コード例 #1
0
ファイル: orders.py プロジェクト: maxima-us/noobit-markets
async def get_closedorders_kraken(
    client: ntypes.CLIENT,
    symbol: ntypes.SYMBOL,
    symbols_resp: NoobitResponseSymbols,
    # prevent unintentional passing of following args
    *,
    logger: typing.Optional[typing.Callable] = None,
    auth=KrakenAuth(),
    base_url: pydantic.AnyHttpUrl = endpoints.KRAKEN_ENDPOINTS.private.url,
    endpoint: str = endpoints.KRAKEN_ENDPOINTS.private.endpoints.closed_orders,
) -> Result[NoobitResponseClosedOrders, Exception]:

    # format: "ETHUSD"
    symbol_from_exchange = lambda x: {
        f"{v.noobit_base}{v.noobit_quote}": k
        for k, v in symbols_resp.asset_pairs.items()
    }[x]

    req_url = urljoin(base_url, endpoint)
    # Kraken Doc : Private methods must use POST
    method = "POST"
    data = {"nonce": auth.nonce, "trades": True}

    valid_kraken_req = _validate_data(KrakenRequestClosedOrders, pmap(data))
    if valid_kraken_req.is_err():
        return valid_kraken_req

    if logger:
        logger(f"Closed Orders - Parsed Request : {valid_kraken_req.value}")

    headers = auth.headers(endpoint, valid_kraken_req.value.dict())

    result_content = await get_result_content_from_req(client, method, req_url,
                                                       valid_kraken_req.value,
                                                       headers)
    if result_content.is_err():
        return result_content

    if logger:
        logger(f"Closed Orders - Result content : {result_content.value}")

    valid_result_content = _validate_data(KrakenResponseClosedOrders,
                                          result_content.value)
    if valid_result_content.is_err():
        return valid_result_content

    parsed_result_data = parse_result_closedorders(
        valid_result_content.value.closed, symbol_from_exchange, symbol)

    valid_parsed_result_data = _validate_data(
        NoobitResponseClosedOrders,
        pmap({
            "orders": parsed_result_data,
            "rawJson": result_content.value,
            "exchange": "KRAKEN",
        }),
    )
    return valid_parsed_result_data
コード例 #2
0
ファイル: trades.py プロジェクト: maxima-us/noobit-markets
async def get_usertrades_kraken(
    client: ntypes.CLIENT,
    symbol: ntypes.SYMBOL,
    symbols_resp: NoobitResponseSymbols,
    # prevent unintentional passing of following args
    *,
    logger: typing.Optional[typing.Callable] = None,
    auth=KrakenAuth(),
    base_url: pydantic.AnyHttpUrl = endpoints.KRAKEN_ENDPOINTS.private.url,
    endpoint: str = endpoints.KRAKEN_ENDPOINTS.private.endpoints.
    trades_history,
) -> Result[NoobitResponseTrades, pydantic.ValidationError]:

    # format: "DOTUSD" or "XETHZUSD" (doc incorrect on this one)
    symbol_from_exchange = lambda x: {
        v.exchange_pair: k
        for k, v in symbols_resp.asset_pairs.items()
    }[x]

    req_url = urljoin(base_url, endpoint)
    method = "POST"
    data = {"nonce": auth.nonce, "type": "all", "trades": True}

    valid_kraken_req = _validate_data(KrakenRequestUserTrades, pmap(data))
    if valid_kraken_req.is_err():
        return valid_kraken_req

    if logger:
        logger(f"User Trades - Parsed Request : {valid_kraken_req.value}")

    headers = auth.headers(endpoint, valid_kraken_req.value.dict())

    result_content = await get_result_content_from_req(client, method, req_url,
                                                       valid_kraken_req.value,
                                                       headers)
    if result_content.is_err():
        return result_content

    if logger:
        logger(f"User Trades - Result content : {result_content.value}")

    valid_result_content = _validate_data(KrakenResponseUserTrades,
                                          result_content.value)
    if valid_result_content.is_err():
        return valid_result_content

    parsed_result_data = parse_result(valid_result_content.value.trades,
                                      symbol_from_exchange, symbol)

    valid_parsed_result_data = _validate_data(
        NoobitResponseTrades,
        pmap({
            "trades": parsed_result_data,
            "rawJson": result_content.value,
            "exchange": "KRAKEN",
        }),
    )
    return valid_parsed_result_data
コード例 #3
0
async def get_balances_binance(
    client: ntypes.CLIENT,
    symbols_resp: NoobitResponseSymbols,
    # prevent unintentional passing of following args
    *,
    logger: typing.Optional[typing.Callable] = None,
    auth=BinanceAuth(),
    base_url: pydantic.AnyHttpUrl = endpoints.BINANCE_ENDPOINTS.private.url,
    endpoint: str = endpoints.BINANCE_ENDPOINTS.private.endpoints.balances
) -> Result[NoobitResponseBalances, ValidationError]:

    asset_from_exchange = lambda x: {
        v: k
        for k, v in symbols_resp.assets.items()
    }[x]

    req_url = urljoin(base_url, endpoint)
    method = "GET"
    headers: typing.Dict = auth.headers()

    nonce = auth.nonce
    data = {"timestamp": nonce}
    signed_params = auth._sign(data)

    valid_binance_req = _validate_data(BinancePrivateRequest,
                                       pmap(signed_params))

    if logger:
        logger(f"Balances - Parsed Request : {valid_binance_req.value}")

    result_content = await get_result_content_from_req(client, method, req_url,
                                                       valid_binance_req.value,
                                                       headers)
    if result_content.is_err():
        return result_content

    if logger:
        logger(f"Balances - Result Content : {result_content.value}")

    valid_result_content = _validate_data(BinanceResponseBalances,
                                          result_content.value)
    if valid_result_content.is_err():
        return valid_result_content

    parsed_result = parse_result(valid_result_content.value,
                                 asset_from_exchange,
                                 exclude=["TWT"])

    valid_parsed_response_data = _validate_data(
        NoobitResponseBalances,
        pmap({
            "balances": parsed_result,
            "rawJson": result_content.value,
            "exchange": "BINANCE"
        }))
    return valid_parsed_response_data
コード例 #4
0
ファイル: balances.py プロジェクト: maxima-us/noobit-markets
async def get_balances_kraken(
    client: ntypes.CLIENT,
    symbols_resp: NoobitResponseSymbols,
    # prevent unintentional passing of following args
    *,
    logger: typing.Optional[typing.Callable] = None,
    auth=KrakenAuth(),
    base_url: pydantic.AnyHttpUrl = endpoints.KRAKEN_ENDPOINTS.private.url,
    endpoint: str = endpoints.KRAKEN_ENDPOINTS.private.endpoints.balances,
) -> Result[NoobitResponseBalances, Exception]:

    asset_from_exchange = lambda x: {
        v: k
        for k, v in symbols_resp.assets.items()
    }[x]

    req_url = urljoin(base_url, endpoint)
    # Kraken Doc : Private methods must use POST
    method = "POST"
    data = {"nonce": auth.nonce}

    valid_kraken_req = _validate_data(KrakenPrivateRequest, pmap(data))
    if valid_kraken_req.is_err():
        return valid_kraken_req

    if logger:
        logger(f"Balances - Parsed Request : {valid_kraken_req.value}")

    headers = auth.headers(endpoint, valid_kraken_req.value.dict())

    result_content = await get_result_content_from_req(client, method, req_url,
                                                       valid_kraken_req.value,
                                                       headers)
    if result_content.is_err():
        return result_content

    if logger:
        logger(f"Balances - Result Content : {result_content.value}")

    valid_result_content = _validate_data(
        KrakenResponseBalances, pmap({"balances": result_content.value}))
    if valid_result_content.is_err():
        return valid_result_content

    parsed_result_data = parse_result(valid_result_content.value.balances,
                                      asset_from_exchange)

    valid_parsed_result_data = _validate_data(
        NoobitResponseBalances,
        pmap({
            "balances": parsed_result_data,
            "rawJson": result_content.value,
            "exchange": "KRAKEN",
        }),
    )
    return valid_parsed_result_data
コード例 #5
0
async def get_usertrades_binance(
        client: ntypes.CLIENT,
        symbol: ntypes.SYMBOL,
        symbols_resp: NoobitResponseSymbols,
        # prevent unintentional passing of following args
        *,
        logger: typing.Optional[typing.Callable] = None,
        auth=BinanceAuth(),
        base_url: pydantic.AnyHttpUrl = endpoints.BINANCE_ENDPOINTS.private.url,
        endpoint: str = endpoints.BINANCE_ENDPOINTS.private.endpoints.trades_history
    ) -> Result[NoobitResponseTrades, ValidationError]:

    symbol_to_exchange = lambda x: {k: v.exchange_pair for k, v in symbols_resp.asset_pairs.items()}[x]
    symbol_from_exchange= lambda x: {v.exchange_pair: k for k, v in symbols_resp.asset_pairs.items()}[x]

    req_url = urljoin(base_url, endpoint)
    method = "GET"
    headers: typing.Dict = auth.headers()

    valid_noobit_req = _validate_data(NoobitRequestTrades, pmap({"symbol": symbol, "symbols_resp": symbols_resp, "since": None}))
    if isinstance(valid_noobit_req, Err):
        return valid_noobit_req

    if logger:
        logger(f"User Trades - Noobit Request : {valid_noobit_req.value}")

    parsed_req = parse_request(valid_noobit_req.value, symbol_to_exchange)

    parsed_req["timestamp"] = auth.nonce
    signed_req = auth._sign(parsed_req)

    valid_binance_req = _validate_data(BinanceRequestUserTrades, pmap(signed_req))
    if valid_binance_req.is_err():
        return valid_binance_req

    if logger:
        logger(f"User Trades - Parsed Request : {valid_binance_req.value}")

    result_content = await get_result_content_from_req(client, method, req_url, valid_binance_req.value, headers)
    if result_content.is_err():
        return result_content

    valid_result_content = _validate_data(BinanceResponseTrades, pmap({"trades": result_content.value}))
    if valid_result_content.is_err():
        return valid_result_content

    if logger:
        logger(f"User Trades - Result Content : {result_content.value}")

    parsed_result = parse_result(valid_result_content.value, symbol, symbol_from_exchange)

    # filled_orders = [item for item in parsed_result if item["ordStatus"] in ["filled"]]

    valid_parsed_response_data = _validate_data(NoobitResponseTrades, pmap({"trades": parsed_result, "rawJson": result_content.value, "exchange": "BINANCE"}))
    return valid_parsed_response_data
コード例 #6
0
async def _get_all_orders(
        client: ntypes.CLIENT,
        symbol: ntypes.SYMBOL,
        symbols_resp: NoobitResponseSymbols,
        # prevent unintentional passing of following args
        *,
        logger: typing.Optional[typing.Callable] = None,
        auth=BinanceAuth(),
        base_url: pydantic.AnyHttpUrl = endpoints.BINANCE_ENDPOINTS.private.url,
        endpoint: str = endpoints.BINANCE_ENDPOINTS.private.endpoints.closed_orders
    ) -> Result[_AllOrders, ValidationError]:


    symbol_to_exchange = lambda x: {k: v.exchange_pair for k, v in symbols_resp.asset_pairs.items()}[x]
    symbol_from_exchange = lambda x: {f"{v.noobit_base}{v.noobit_quote}": k for k, v in symbols_resp.asset_pairs.items()}[x]

    req_url = urljoin(base_url, endpoint)
    method = "GET"
    headers: typing.Dict = auth.headers()

    valid_noobit_req = _validate_data(NoobitRequestClosedOrders, pmap({"symbol": symbol, "symbols_resp": symbols_resp}))
    if valid_noobit_req.is_err():
        return valid_noobit_req

    if logger:
        logger(f"Closed Orders - Noobit Request : {valid_noobit_req.value}")

    parsed_req = parse_request(valid_noobit_req.value, symbol_to_exchange)

    parsed_req["timestamp"] = auth.nonce
    signed_req = auth._sign(parsed_req)

    valid_binance_req = _validate_data(BinanceRequestClosedOrders, pmap(signed_req))
    if valid_binance_req.is_err():
        return valid_binance_req

    if logger:
        logger(f"Closed Orders - Parsed Request : {valid_binance_req.value}")

    result_content = await get_result_content_from_req(client, method, req_url, valid_binance_req.value, headers)
    if result_content.is_err():
        return result_content

    if logger:
        logger(f"Closed Orders - Result Content : {result_content.value}")

    valid_result_content = _validate_data(BinanceResponseOrders, pmap({"orders": result_content.value}))
    if valid_result_content.is_err():
        return valid_result_content

    parsed_result = parse_result(valid_result_content.value, symbol_from_exchange)
    return Ok({"orders": parsed_result, "rawJson": result_content.value})
コード例 #7
0
async def get_instrument_binance(
        client: ntypes.CLIENT,
        symbol: ntypes.SYMBOL,
        symbols_resp: NoobitResponseSymbols,
        # prevent unintentional passing of following args
        *,
        logger: typing.Optional[typing.Callable] = None,
        base_url: pydantic.AnyHttpUrl = endpoints.BINANCE_ENDPOINTS.public.url,
        endpoint: str = endpoints.BINANCE_ENDPOINTS.public.endpoints.instrument,
    ) -> Result[NoobitResponseInstrument, ValidationError]:


    symbol_to_exchange = lambda x : {k: v.exchange_pair for k, v in symbols_resp.asset_pairs.items()}[x]
    
    req_url = urljoin(base_url, endpoint)
    method = "GET"
    headers: typing.Dict = {}

    valid_noobit_req = _validate_data(NoobitRequestInstrument, pmap({"symbol": symbol, "symbols_resp": symbols_resp}))
    if isinstance(valid_noobit_req, Err):
        return valid_noobit_req
    
    if logger:
        logger(f"Instrument - Noobit Request : {valid_noobit_req.value}")

    parsed_req = parse_request(valid_noobit_req.value, symbol_to_exchange)

    valid_binance_req = _validate_data(BinanceRequestInstrument, pmap(parsed_req))
    if valid_binance_req.is_err():
        return valid_binance_req
    
    if logger:
        logger(f"Instrument - Parsed Request : {valid_binance_req.value}")

    result_content = await get_result_content_from_req(client, method, req_url, valid_binance_req.value, headers)
    if result_content.is_err():
        return result_content
    
    if logger:
        logger(f"Instrument - Result Content : {result_content.value}")

    valid_result_content = _validate_data(BinanceResponseInstrument, result_content.value)
    if valid_result_content.is_err():
        return valid_result_content

    parsed_result = parse_result(valid_result_content.value, symbol)

    valid_parsed_response_data = _validate_data(NoobitResponseInstrument, pmap({**parsed_result, "rawJson": result_content.value, "exchange": "BINANCE"}))
    return valid_parsed_response_data
コード例 #8
0
async def get_openorders_binance(
        client: ntypes.CLIENT,
        symbol: ntypes.SYMBOL,
        symbols_resp: NoobitResponseSymbols,
        # prevent unintentional passing of following args
        *,
        logger: typing.Optional[typing.Callable] = None,
        auth=BinanceAuth(),
        base_url: pydantic.AnyHttpUrl = endpoints.BINANCE_ENDPOINTS.private.url,
        endpoint: str = endpoints.BINANCE_ENDPOINTS.private.endpoints.closed_orders
    ) -> Result[NoobitResponseOpenOrders, ValidationError]:


    parsed_result = await _get_all_orders(
        client,
        symbol,
        symbols_resp,
        logger=logger,
        auth=auth,
        base_url=base_url,
        endpoint=endpoint
    )
    if isinstance(parsed_result, Ok):
        closed_orders = [item for item in parsed_result.value["orders"] if item["ordStatus"] in ["NEW", "PENDING-NEW", "PARTIALLY-FILLED"]]

        valid_parsed_response_data = _validate_data(NoobitResponseOpenOrders, pmap({"orders": closed_orders, "rawJson": parsed_result.value["rawJson"], "exchange": "BINANCE"}))
        return valid_parsed_response_data
    else:
        return parsed_result
コード例 #9
0
async def get_exposure_kraken(
    client: ntypes.CLIENT,
    symbols_resp: typing.Optional[
        NoobitResponseSymbols
    ] = None,  # only there to have consistent signature with binance
    # prevent unintentional passing of following args
    *,
    logger: typing.Optional[typing.Callable] = None,
    auth=KrakenAuth(),
    base_url: pydantic.AnyHttpUrl = endpoints.KRAKEN_ENDPOINTS.private.url,
    endpoint: str = endpoints.KRAKEN_ENDPOINTS.private.endpoints.exposure,
) -> Result[NoobitResponseExposure, Exception]:

    req_url = urljoin(base_url, endpoint)
    # Kraken Doc : Private methods must use POST
    method = "POST"
    data = {"nonce": auth.nonce}

    valid_kraken_req = _validate_data(KrakenPrivateRequest, pmap(data))
    if valid_kraken_req.is_err():
        return valid_kraken_req

    if logger:
        logger(f"Exposure - Parsed Request : {valid_kraken_req.value}")

    headers = auth.headers(endpoint, valid_kraken_req.value.dict())

    result_content = await get_result_content_from_req(
        client, method, req_url, valid_kraken_req.value, headers
    )
    if result_content.is_err():
        return result_content

    if logger:
        logger(f"Exposure - Result content : {result_content.value}")

    valid_result_content = _validate_data(KrakenResponseExposure, result_content.value)
    if valid_result_content.is_err():
        return valid_result_content

    parsed_result = parse_result(valid_result_content.value)

    valid_parsed_result_data = _validate_data(
        NoobitResponseExposure,
        pmap({**parsed_result, "rawJson": result_content.value, "exchange": "KRAKEN"}),
    )
    return valid_parsed_result_data
コード例 #10
0
async def get_balances_ftx(
    client: ntypes.CLIENT,
    symbols_resp: NoobitResponseSymbols,
    #  prevent unintentional passing of following args
    *,
    logger: typing.Optional[typing.Callable] = None,
    auth=FtxAuth(),
    base_url: pydantic.AnyHttpUrl = endpoints.FTX_ENDPOINTS.private.url,
    endpoint: str = endpoints.FTX_ENDPOINTS.private.endpoints.balances,
) -> Result[NoobitResponseBalances, pydantic.ValidationError]:

    asset_from_exchange = lambda x: {v: k for k, v in symbols_resp.assets.items()}[x]

    req_url = "/".join([base_url, "wallet", "balances"])
    method = "GET"
    headers = auth.headers(method, "/api/wallet/balances")

    valid_ftx_req = Ok(FtxPrivateRequest())

    result_content = await get_result_content_from_req(
        client, method, req_url, valid_ftx_req.value, headers
    )
    if isinstance(result_content, Err):
        return result_content

    valid_result_content = _validate_data(
        FtxResponseBalances, pmap({"balances": result_content.value})
    )
    if valid_result_content.is_err():
        return valid_result_content

    parsed_result_balances = parse_result(valid_result_content.value)

    valid_parsed_response_data = _validate_data(
        NoobitResponseBalances,
        pmap(
            {
                "balances": parsed_result_balances,
                "rawJson": result_content.value,
                "exchange": "FTX",
            }
        ),
    )
    return valid_parsed_response_data
コード例 #11
0
async def get_symbols_ftx(
    client: ntypes.CLIENT,
    #  prevent unintentional passing of following args
    *,
    logger: typing.Optional[typing.Callable] = None,
    base_url: pydantic.AnyHttpUrl = endpoints.FTX_ENDPOINTS.public.url,
    endpoint: str = endpoints.FTX_ENDPOINTS.public.endpoints.symbols,
) -> Result[NoobitResponseSymbols, pydantic.ValidationError]:

    # ftx has variable urls besides query params
    # format: https://ftx.com/api/markets/
    req_url = "/".join([base_url, endpoint])
    method = "GET"
    headers: typing.Dict = {}

    # no query params but needs to wrapped in a result that contains an instance of FrozenBaseModel
    valid_ftx_req = Ok(FrozenBaseModel())
    result_content = await get_result_content_from_req(client, method, req_url,
                                                       valid_ftx_req.value,
                                                       headers)
    if isinstance(result_content, Err):
        return result_content

    if logger:
        logger(f"Symbols - Result Content : {result_content.value}")

    valid_result_content = _validate_data(
        FtxResponseSymbols, pmap({"symbols": result_content.value}))
    if valid_result_content.is_err():
        return valid_result_content

    parsed_result = parse_result(valid_result_content.value)

    valid_parsed_response_data = _validate_data(
        NoobitResponseSymbols,
        pmap({
            **parsed_result, "rawJson": result_content.value,
            "exchange": "FTX"
        }),
    )
    return valid_parsed_response_data
コード例 #12
0
ファイル: symbols.py プロジェクト: maxima-us/noobit-markets
async def get_symbols_binance(
    client: ntypes.CLIENT,
    # prevent unintentional passing of following args
    *,
    logger: typing.Optional[typing.Callable] = None,
    base_url: pydantic.AnyHttpUrl = endpoints.BINANCE_ENDPOINTS.public.url,
    endpoint: str = endpoints.BINANCE_ENDPOINTS.public.endpoints.symbols
) -> Result[NoobitResponseSymbols, Exception]:

    req_url = urljoin(base_url, endpoint)
    method = "GET"
    headers: typing.Dict = {}

    # no query params but needs to wrapped in a result that contains an instance of FrozenBaseModel
    valid_binance_req = Ok(FrozenBaseModel())

    result_content = await get_result_content_from_req(client, method, req_url,
                                                       valid_binance_req.value,
                                                       headers)
    if result_content.is_err():
        return result_content

    if logger:
        logger(f"Symbols - Result Content : {result_content.value}")

    valid_result_content = _validate_data(BinanceResponseSymbols,
                                          result_content.value)
    if valid_result_content.is_err():
        return valid_result_content

    parsed_result = parse_result(valid_result_content.value)

    valid_parsed_response_data = _validate_data(
        NoobitResponseSymbols,
        pmap({
            **parsed_result, "rawJson": result_content.value,
            "exchange": "BINANCE"
        }))
    return valid_parsed_response_data
コード例 #13
0
async def get_exposure_binance(
    client: ntypes.CLIENT,
    symbols_resp: NoobitResponseSymbols,
    # prevent unintentional passing of following args
    *,
    logger: typing.Optional[typing.Callable] = None,
    auth=BinanceAuth()
) -> Result[NoobitResponseExposure, ValidationError]:
    """
    Binance does not have an endpoint for this, so we have to check fiat value
    of each asset in balances individually ==> slow
    """

    totalNetValue = Decimal(0)
    bals = await get_balances_binance(client,
                                      symbols_resp,
                                      logger=logger,
                                      auth=auth)

    if isinstance(bals, Err):
        return bals

    else:
        for asset, amount in bals.value.balances.items():
            if not asset in ["USDT", "USD", "TWT"]:
                symbol = str(f"{asset}-USDT")
                price = await get_instrument_binance(
                    client=client,
                    symbol=ntypes.PSymbol(symbol),
                    # symbol_to_exchange=symbol_to_exchange
                    symbols_resp=symbols_resp)
                if price.is_err():
                    raise price.value
                net_v = amount * price.value.last
                totalNetValue += net_v
            else:
                totalNetValue += amount

    valid_response = _validate_data(
        NoobitResponseExposure,
        pmap({
            "totalNetValue": totalNetValue,
            "cashOutstanding": None,
            "marginExcess": 0,  #TODO check what this corresponds to
            "exchange": "BINANCE",
            "rawJson": bals.value.
            rawJson  #! isnt really corresponding json resp, but more relevant
        }))
    return valid_response
コード例 #14
0
ファイル: ws_auth.py プロジェクト: maxima-us/noobit-markets
async def get_wstoken_kraken(
    client: ntypes.CLIENT,
    # prevent unintentional passing of following args
    *,
    logger: typing.Optional[typing.Callable] = None,
    auth=KrakenAuth(),
    base_url: pydantic.AnyHttpUrl = endpoints.KRAKEN_ENDPOINTS.private.url,
    # intentionally not typed
    endpoint=endpoints.KRAKEN_ENDPOINTS.private.endpoints.ws_token,
) -> Result[KrakenResponseWsToken, pydantic.ValidationError]:

    req_url = urljoin(base_url, endpoint)
    # Kraken Doc : Private methods must use POST
    method = "POST"
    data = {"nonce": auth.nonce}

    valid_kraken_req = _validate_data(KrakenPrivateRequest, pmap(data))
    if valid_kraken_req.is_err():
        return valid_kraken_req

    if logger:
        logger(f"Ws Token - Parsed Request : {valid_kraken_req.value}")

    headers = auth.headers(endpoint, valid_kraken_req.value.dict())

    result_content = await get_result_content_from_req(
        client, method, req_url, valid_kraken_req.value, headers
    )
    if result_content.is_err():
        return result_content

    if logger:
        logger(f"Ws Token - Result content : {result_content.value}")

    valid_result_content = _validate_data(KrakenResponseWsToken, result_content.value)
    return valid_result_content
コード例 #15
0
async def get_exposure_ftx(
        client: ntypes.CLIENT,
        symbols_resp: NoobitResponseSymbols,
        # prevent unintentional passing of following args
        *,
        logger: typing.Optional[typing.Callable] = None,
        auth=FtxAuth(),
) -> Result[NoobitResponseExposure, ValidationError]:

    totalNetValue = Decimal(0)
    bals = await get_balances_ftx(client,
                                  symbols_resp,
                                  logger=logger,
                                  auth=auth)

    if isinstance(bals, Err):
        return bals

    else:
        for asset, amount in bals.value.balances.items():
            if not asset in ["USDT", "USD"]:
                symbol = str(f"{asset}-USD")
                trades = await get_trades_ftx(client,
                                              symbol,
                                              symbols_resp,
                                              None,
                                              logger=logger)
                if trades.is_err():
                    raise trades.value
                last_price = trades.value.trades[-1].avgPx
                net_v = amount * last_price
                totalNetValue += net_v
            else:
                totalNetValue += amount

    valid_response = _validate_data(
        NoobitResponseExposure,
        pmap({
            "totalNetValue": totalNetValue,
            "cashOutstanding": None,
            "marginExcess": 0,
            "exchange": "FTX",
            "rawJson": bals.value.rawJson,
        }),
    )

    return valid_response
コード例 #16
0
ファイル: ws_auth.py プロジェクト: maxima-us/noobit-markets
async def get_wstoken_binance(
    client: ntypes.CLIENT,
    # prevent unintentional passing of following args
    *,
    auth=BinanceAuth(),
    base_url: pydantic.AnyHttpUrl = endpoints.BINANCE_ENDPOINTS.private.url,
    endpoint: str = endpoints.BINANCE_ENDPOINTS.private.endpoints.ws_token
) -> Result[BinanceResponseWsToken, pydantic.ValidationError]:

    req_url = urljoin(base_url, endpoint)
    method = "POST"
    headers: typing.Dict = auth.headers()

    result_content = await get_result_content_from_req(client, method, req_url,
                                                       FrozenBaseModel(),
                                                       headers)
    if result_content.is_err():
        return result_content

    valid_result_content = _validate_data(BinanceResponseWsToken,
                                          result_content.value)
    return valid_result_content
コード例 #17
0
async def cancel_openorder_kraken(
    client: ntypes.CLIENT,
    symbol: ntypes.SYMBOL,
    symbols_resp: NoobitResponseSymbols,
    orderID: str,
    # prevent unintentional passing of following args
    *,
    logger: typing.Optional[typing.Callable] = None,
    auth=KrakenAuth(),
    base_url: pydantic.AnyHttpUrl = endpoints.KRAKEN_ENDPOINTS.private.url,
    endpoint: str = endpoints.KRAKEN_ENDPOINTS.private.endpoints.remove_order,
) -> Result[NoobitResponseItemOrder, Exception]:

    symbol_to_exchange = lambda x: {
        k: v.exchange_pair
        for k, v in symbols_resp.asset_pairs.items()
    }[x]

    req_url = urljoin(base_url, endpoint)
    method = "POST"

    payload = {"txid": orderID}
    data = {"nonce": auth.nonce, **payload}

    valid_kraken_req = _validate_data(KrakenRequestCancelOpenOrder, pmap(data))
    if valid_kraken_req.is_err():
        return valid_kraken_req

    headers = auth.headers(endpoint, data)

    result_content = await get_result_content_from_req(client, method, req_url,
                                                       valid_kraken_req.value,
                                                       headers)
    if result_content.is_err():
        return result_content

    if logger:
        logger(f"Cancel Open Order - Result content : {result_content.value}")

    valid_result_content = _validate_data(KrakenResponseCancelOpenOrder,
                                          result_content.value)
    if valid_result_content.is_err():
        return valid_result_content

    cl_ord = await get_closedorders_kraken(client,
                                           symbol,
                                           symbols_resp,
                                           logger=logger,
                                           auth=auth)

    if isinstance(cl_ord, Ok):
        try:
            [order_info] = [
                order for order in cl_ord.value.orders
                if order.orderID == orderID
            ]
            return Ok(order_info)
        except ValueError as e:
            return Err(e)
        except Exception as e:
            return Err(e)
    else:
        return cl_ord
コード例 #18
0
async def cancel_openorder_binance(
    client: ntypes.CLIENT,
    symbol: ntypes.SYMBOL,
    symbols_resp: NoobitResponseSymbols,
    orderID: str,
    # prevent unintentional passing of following args
    *,
    logger: typing.Optional[typing.Callable] = None,
    auth=BinanceAuth(),
    base_url: pydantic.AnyHttpUrl = endpoints.BINANCE_ENDPOINTS.private.url,
    endpoint: str = endpoints.BINANCE_ENDPOINTS.private.endpoints.remove_order
) -> Result[NoobitResponseItemOrder, ValidationError]:

    symbol_to_exchange = lambda x: {
        k: v.exchange_pair
        for k, v in symbols_resp.asset_pairs.items()
    }[x]
    symbol_from_exchange = lambda x: {
        f"{v.noobit_base}{v.noobit_quote}": k
        for k, v in symbols_resp.asset_pairs.items()
    }[x]

    req_url = urljoin(base_url, endpoint)
    method = "DELETE"
    headers: typing.Dict = auth.headers()

    valid_noobit_req = _validate_data(
        NoobitRequestCancelOpenOrder,
        pmap({
            "exchange": "BINANCE",
            "symbol": symbol,
            "symbols_resp": symbols_resp,
            "orderID": orderID
        }))
    if valid_noobit_req.is_err():
        return valid_noobit_req

    if logger:
        logger(
            f"Cancel Open Order - Noobit Request : {valid_noobit_req.value}")

    parsed_req = parse_request(valid_noobit_req.value, symbol_to_exchange)

    parsed_req["timestamp"] = auth.nonce
    signed_req = auth._sign(parsed_req)

    valid_binance_req = _validate_data(BinanceRequestCancelOpenOrder,
                                       pmap(signed_req))
    if valid_binance_req.is_err():
        return valid_binance_req

    if logger:
        logger(
            f"Cancel Open ORder - Parsed Request : {valid_binance_req.value}")

    result_content = await get_result_content_from_req(client, method, req_url,
                                                       valid_binance_req.value,
                                                       headers)
    if result_content.is_err():
        return result_content

    if logger:
        logger(f"Cancel Open Order - Result Content : {result_content.value}")

    valid_result_content = _validate_data(BinanceResponseCancelOpenOrder,
                                          result_content.value)
    if valid_result_content.is_err():
        return valid_result_content

    parsed_result = parse_result(valid_result_content.value,
                                 symbol_from_exchange)
    return Ok(parsed_result)
コード例 #19
0
async def get_closedorders_ftx(
    client: ntypes.CLIENT,
    symbol: ntypes.SYMBOL,
    symbols_resp: NoobitResponseSymbols,
    #  prevent unintentional passing of following args
    *,
    logger: typing.Optional[typing.Callable] = None,
    auth=FtxAuth(),
    base_url: pydantic.AnyHttpUrl = endpoints.FTX_ENDPOINTS.private.url,
    endpoint: str = endpoints.FTX_ENDPOINTS.private.endpoints.closed_orders,
) -> Result[NoobitResponseClosedOrders, pydantic.ValidationError]:

    symbol_from_exchange = lambda x: {
        f"{v.noobit_base}{v.noobit_quote}": k
        for k, v in symbols_resp.asset_pairs.items()
    }[x]
    symbol_to_exchange = lambda x: {
        k: v.exchange_pair
        for k, v in symbols_resp.asset_pairs.items()
    }[x]

    req_url = "/".join([base_url, "orders/history"])
    method = "GET"

    valid_noobit_req = _validate_data(
        NoobitRequestClosedOrders,
        pmap({
            "symbol": symbol,
            "symbols_resp": symbols_resp
        }),
    )
    if valid_noobit_req.is_err():
        return valid_noobit_req

    parsed_req = parse_request(valid_noobit_req.value, symbol_to_exchange)

    valid_ftx_req = _validate_data(FtxRequestClosedOrder, pmap(parsed_req))
    if valid_ftx_req.is_err():
        return valid_ftx_req

    querystr = f"?market={valid_ftx_req.value.market}"
    req_url += querystr
    headers = auth.headers(method, f"/api/orders/history{querystr}")

    if logger:
        logger(f"Closed Orders - Parsed Request : {valid_ftx_req.value}")

    result_content = await get_result_content_from_req(client, method, req_url,
                                                       FrozenBaseModel(),
                                                       headers)
    if result_content.is_err():
        return result_content

    if logger:
        logger(f"Open Orders - Result content : {result_content.value}")

    valid_result_content = _validate_data(
        FtxResponseOrder, pmap({"orders": result_content.value}))
    if valid_result_content.is_err():
        return valid_result_content

    parsed_result_data = parse_result(valid_result_content.value,
                                      symbol_from_exchange, symbol)

    valid_parsed_response = _validate_data(
        NoobitResponseClosedOrders,
        pmap({
            "orders": parsed_result_data,
            "rawJson": result_content.value,
            "exchange": "FTX",
        }),
    )
    return valid_parsed_response
コード例 #20
0
async def get_spread_kraken(
    client: ntypes.CLIENT,
    symbol: ntypes.SYMBOL,
    symbols_resp: NoobitResponseSymbols,
    # prevent unintentional passing of following args
    *,
    logger: typing.Optional[typing.Callable] = None,
    base_url: pydantic.AnyHttpUrl = endpoints.KRAKEN_ENDPOINTS.public.url,
    # intentionally not typed
    endpoint=endpoints.KRAKEN_ENDPOINTS.public.endpoints.spread,
) -> Result[NoobitResponseSpread, ValidationError]:

    symbol_to_exchange = lambda x: {
        k: v.exchange_pair
        for k, v in symbols_resp.asset_pairs.items()
    }[x]

    req_url = urljoin(base_url, endpoint)
    method = "GET"
    headers: typing.Dict = {}

    valid_noobit_req = _validate_data(
        NoobitRequestSpread,
        pmap({
            "symbol": symbol,
            "symbols_resp": symbols_resp
        }))
    if isinstance(valid_noobit_req, Err):
        return valid_noobit_req

    if logger:
        logger(f"Spread - Noobit Request : {valid_noobit_req.value}")

    parsed_req = parse_request(valid_noobit_req.value, symbol_to_exchange)

    valid_kraken_req = _validate_data(KrakenRequestSpread, pmap(parsed_req))
    if valid_kraken_req.is_err():
        return valid_kraken_req

    if logger:
        logger(f"Spread - Parsed Request : {valid_kraken_req.value}")

    result_content = await get_result_content_from_req(client, method, req_url,
                                                       valid_kraken_req.value,
                                                       headers)
    if result_content.is_err():
        return result_content

    if logger:
        logger(f"Spread - Result Content : {result_content.value}")

    valid_result_content = _validate_data(
        make_kraken_model_spread(symbol, symbol_to_exchange),
        result_content.value)
    if valid_result_content.is_err():
        return valid_result_content

    parsed_result_spread = parse_result(
        getattr(valid_result_content.value, symbol_to_exchange(symbol)),
        symbol)

    valid_parsed_response_data = _validate_data(
        NoobitResponseSpread,
        pmap({
            "spread": parsed_result_spread,
            "rawJson": result_content.value,
            "exchange": "KRAKEN",
        }),
    )
    return valid_parsed_response_data
コード例 #21
0
async def get_orderbook_ftx(
    client: ntypes.CLIENT,
    symbol: ntypes.SYMBOL,
    symbols_resp: NoobitResponseSymbols,
    depth: ntypes.DEPTH,
    #  prevent unintentional passing of following args
    *,
    logger: typing.Optional[typing.Callable] = None,
    base_url: pydantic.AnyHttpUrl = endpoints.FTX_ENDPOINTS.public.url,
    endpoint: str = endpoints.FTX_ENDPOINTS.public.endpoints.orderbook,
) -> Result[NoobitResponseOrderBook, pydantic.ValidationError]:

    symbol_to_exchange = lambda x: {
        k: v.exchange_pair
        for k, v in symbols_resp.asset_pairs.items()
    }[x]

    # ftx has variable urls besides query params
    # format: https://ftx.com/api/markets/{market_name}/candles
    req_url = "/".join(
        [base_url, "markets",
         symbol_to_exchange(symbol), endpoint])
    method = "GET"
    headers: typing.Dict = {}

    valid_noobit_req = _validate_data(
        NoobitRequestOrderBook,
        pmap({
            "symbol": symbol,
            "symbols_resp": symbols_resp,
            "depth": depth
        }),
    )
    if isinstance(valid_noobit_req, Err):
        return valid_noobit_req

    if logger:
        logger(f"Orderbook - Noobit Request : {valid_noobit_req.value}")

    parsed_req = parse_request(valid_noobit_req.value)

    valid_ftx_req = _validate_data(FtxRequestOrderBook, pmap(parsed_req))
    if valid_ftx_req.is_err():
        return valid_ftx_req

    if logger:
        logger(f"Orderbook - Parsed Request : {valid_ftx_req.value}")

    result_content = await get_result_content_from_req(client, method, req_url,
                                                       valid_ftx_req.value,
                                                       headers)
    if result_content.is_err():
        return result_content

    if logger:
        logger(f"Orderbook - Result Content : {result_content.value}")

    valid_result_content = _validate_data(FtxResponseOrderBook,
                                          result_content.value)
    if valid_result_content.is_err():
        return valid_result_content

    parsed_result = parse_result(valid_result_content.value, symbol)

    valid_parsed_response_data = _validate_data(
        NoobitResponseOrderBook,
        pmap({
            **parsed_result, "rawJson": result_content.value,
            "exchange": "FTX"
        }),
    )
    return valid_parsed_response_data
コード例 #22
0
async def post_neworder_kraken(
    client: ntypes.CLIENT,
    symbol: ntypes.SYMBOL,
    symbols_resp: NoobitResponseSymbols,
    side: ntypes.ORDERSIDE,
    ordType: ntypes.ORDERTYPE,
    clOrdID: str,
    orderQty: Decimal,
    price: Decimal,
    timeInForce: ntypes.TIMEINFORCE,
    stopPrice: typing.Optional[Decimal] = None,
    # until kraken enables use of `viqc` flag, always pass in None
    quoteOrderQty: typing.Optional[Decimal] = None,
    # prevent unintentional passing of following args
    *,
    logger: typing.Optional[typing.Callable] = None,
    auth=KrakenAuth(),
    base_url: pydantic.AnyHttpUrl = endpoints.KRAKEN_ENDPOINTS.private.url,
    endpoint: str = endpoints.KRAKEN_ENDPOINTS.private.endpoints.new_order,
    **kwargs,
) -> Result[NoobitResponseItemOrder, Exception]:

    symbol_to_exchange = lambda x: {
        k: v.exchange_pair
        for k, v in symbols_resp.asset_pairs.items()
    }[x]

    req_url = urljoin(base_url, endpoint)
    method = "POST"

    valid_noobit_req = _validate_data(
        NoobitRequestAddOrder,
        pmap({
            "exchange": "KRAKEN",
            "symbol": symbol,
            "symbols_resp": symbols_resp,
            "side": side,
            "ordType": ordType,
            "clOrdID": clOrdID,
            "orderQty": orderQty,
            "price": price,
            "timeInForce": timeInForce,
            "quoteOrderQty": quoteOrderQty,
            "stopPrice": stopPrice,
            **kwargs,
        }),
    )

    if valid_noobit_req.is_err():
        return valid_noobit_req

    if logger:
        logger(f"New Order - Noobit Request : {valid_noobit_req.value}")

    parsed_req = parse_request(valid_noobit_req.value, symbol_to_exchange)
    data = {"nonce": auth.nonce, **parsed_req}

    valid_kraken_req = _validate_data(
        KrakenRequestNewOrder, pmap({
            "nonce": data["nonce"],
            **parsed_req
        }))
    if valid_kraken_req.is_err():
        return valid_kraken_req

    if logger:
        logger(f"New Order - Parsed Request : {valid_kraken_req.value}")

    headers = auth.headers(endpoint,
                           valid_kraken_req.value.dict(exclude_none=True))

    result_content = await get_result_content_from_req(client, method, req_url,
                                                       valid_kraken_req.value,
                                                       headers)
    if result_content.is_err():
        return result_content

    if logger:
        logger(f"New Order - Result content : {result_content.value}")

    valid_result_content = _validate_data(KrakenResponseNewOrder,
                                          result_content.value)
    if valid_result_content.is_err():
        return valid_result_content

    parsed_result = parse_result(valid_result_content.value)

    valid_parsed_response_data = _validate_data(
        NoobitResponseNewOrder,
        pmap({
            "descr": parsed_result["descr"],
            "txid": parsed_result["txid"],
            "rawJson": result_content.value,
            "exchange": "KRAKEN",
        }),
    )
    if valid_parsed_response_data.is_err():
        return valid_parsed_response_data
    # return valid_parsed_response_data

    [newOrderID] = valid_parsed_response_data.value.txid

    # # TODO we want to return a more complete info on the trade:
    # # ?     ==> should we fetch the order corresponding to the txid we get back ?
    # tx_info = await get_usertrades_kraken(client, symbol, lambda x : {"DOTUSD": ntypes.PSymbol("DOT-USD")}, auth)
    # return [trade for trade in tx_info.value.trades if trade.orderID == valid_parsed_response_data.value.txid]

    if ordType == "MARKET":
        # FIXME symbol_from_exchange lambda isnt entirely accurate
        # will be ok for most pairs but some have 4/5 letters for base
        cl_ord = await get_closedorders_kraken(client,
                                               symbol,
                                               symbols_resp,
                                               logger=logger,
                                               auth=auth)
        if isinstance(cl_ord, Ok):
            [order_info] = [
                order for order in cl_ord.value.orders
                if order.orderID == newOrderID
            ]
        else:
            return cl_ord

    else:
        await asyncio.sleep(0.1)
        # FIXME symbol_from_exchange lambda isnt entirely accurate
        # will be ok for most pairs but some have 4/5 letters for base
        op_ord = await get_openorders_kraken(client,
                                             symbol,
                                             symbols_resp,
                                             logger=logger,
                                             auth=auth)
        if isinstance(op_ord, Ok):
            [order_info] = [
                order for order in op_ord.value.orders if order.orderID ==
                newOrderID  #FIXME this causes errors because false sometimes
            ]
        else:
            return op_ord
    # return type will be : NoobitResponseItemOrder, same as binance trading.py, so should be ok
    return Ok(order_info)
コード例 #23
0
ファイル: api.py プロジェクト: maxima-us/noobit-markets
    async def orderbook(
        self,
        symbols_resp: NoobitResponseSymbols,
        symbol: ntypes.PSymbol,
        depth: ntypes.DEPTH,
        aggregate: bool = False
    ) -> typing.AsyncIterable[Result[NoobitResponseOrderBook,
                                     ValidationError]]:

        super()._ensure_dispatch()

        symbol_to_exchange = lambda x: {
            k: f"{v.noobit_base}/{v.noobit_quote}"
            for k, v in symbols_resp.asset_pairs.items()
        }[x]
        valid_sub_model = orderbook.validate_sub(symbol_to_exchange, symbol,
                                                 depth)

        if isinstance(valid_sub_model, Err):
            yield valid_sub_model
        #! replace with: below

        sub_result = await subscribe(self.client,
                                     valid_sub_model.value)  #type: ignore
        # subscription status is checked by a watcher coro

        await asyncio.sleep(1)
        if not symbol_to_exchange(symbol) in self._subd_feeds["orderbook"]:
            return

        self._subd_feeds["orderbook"].add(symbol_to_exchange(symbol))

        #? should we stream full orderbook ?
        if not aggregate:
            # # stream udpates
            # async for msg in self.iterq(self._data_queues, "orderbook"):
            #     if self._terminate: break
            #     yield msg
            pass

        else:
            # reconstruct orderbook
            _count = 0
            # async for msg in self.iterq(self._data_queues, "orderbook"):
            async for msg in self.aiter_book():

                # print("From iterq :", msg)

                # !!!! this means if we are not subbed to spread feed, we will stall here
                sp_q: Result[
                    NoobitResponseSpread,
                    Exception] = await self._data_queues["spread_copy"].get()

                if isinstance(sp_q, Ok):
                    spreads = sp_q
                else:
                    #? how should we handle this
                    raise ValueError("Error in Spread")

                pair = msg.value.symbol  #type: ignore
                pair_key = ntypes.PSymbol(pair)

                # only way to make mypy understand that `msg.value` is `Ok`
                #   (msg.is_ok() will not work)
                # see: https://github.com/dbrgn/result/issues/17#issue-502950927
                if isinstance(msg, Ok):

                    if _count == 0:
                        # snapshot
                        print("orderbook snapshot")
                        # TODO exchange shoudl be dynamic (add to model ?)
                        self._full_books[pair_key] = {"asks": {}, "bids": {}}
                        self._full_books[pair_key]["asks"] = msg.value.asks
                        self._full_books[pair_key]["bids"] = msg.value.bids
                    else:
                        print("orderbook update")
                        # update
                        (self._full_books[pair_key]["asks"]).update(
                            msg.value.asks)
                        self._full_books[pair_key]["bids"].update(
                            msg.value.bids)

                        # filter out 0 values and bids/asks outside of spread
                        self._full_books[pair_key]["asks"] = {
                            k: v
                            for k, v in self._full_books[pair]["asks"].items()
                            if v > 0
                            and k >= spreads.value.spread[0].bestAskPrice
                        }
                        self._full_books[pair_key]["bids"] = {
                            k: v
                            for k, v in self._full_books[pair]["bids"].items()
                            if v > 0
                            and k <= spreads.value.spread[0].bestBidPrice
                        }

                    _count += 1

                    valid_book = _validate_data(
                        NoobitResponseOrderBook,
                        pmap({
                            "exchange": "KRAKEN",
                            "symbol": msg.value.symbol,
                            "utcTime": msg.value.utcTime,
                            "rawJson": msg.value.rawJson,
                            "asks": self._full_books[pair_key]["asks"],
                            "bids": self._full_books[pair_key]["bids"]
                        }))
                    yield valid_book

                else:
                    #? or log it ?
                    yield msg
コード例 #24
0
ファイル: trades.py プロジェクト: maxima-us/noobit-markets
def validate_parsed(msg, parsed_msg):
    return _validate_data(NoobitResponseTrades, {
        "trades": parsed_msg,
        "rawJson": msg
    })
コード例 #25
0
async def post_neworder_binance(
    client: ntypes.CLIENT,
    symbol: ntypes.SYMBOL,
    symbols_resp: NoobitResponseSymbols,
    side: ntypes.ORDERSIDE,
    ordType: ntypes.ORDERTYPE,
    clOrdID: str,
    orderQty: Decimal,
    price: Decimal,
    timeInForce: ntypes.TIMEINFORCE,
    stopPrice: typing.Optional[Decimal] = None,
    quoteOrderQty: typing.Optional[Decimal] = None,
    # prevent unintentional passing of following args
    *,
    logger: typing.Optional[typing.Callable] = None,
    auth=BinanceAuth(),
    base_url: pydantic.AnyHttpUrl = endpoints.BINANCE_ENDPOINTS.private.url,
    endpoint: str = endpoints.BINANCE_ENDPOINTS.private.endpoints.new_order,
) -> Result[NoobitResponseItemOrder, ValidationError]:

    symbol_to_exchange = lambda x: {
        k: v.exchange_pair
        for k, v in symbols_resp.asset_pairs.items()
    }[x]

    req_url = urljoin(base_url, endpoint)
    method = "POST"
    headers: typing.Dict = auth.headers()

    valid_noobit_req = _validate_data(
        NoobitRequestAddOrder,
        pmap({
            "exchange": "BINANCE",
            "symbol": symbol,
            "symbols_resp": symbols_resp,
            "side": side,
            "ordType": ordType,
            "clOrdID": clOrdID,
            "orderQty": orderQty,
            "price": price,
            "timeInForce": timeInForce,
            "quoteOrderQty": quoteOrderQty,
            "stopPrice": stopPrice,
        }))

    if valid_noobit_req.is_err():
        return valid_noobit_req

    if logger:
        logger(f"New Order - Noobit Request : {valid_noobit_req.value}")

    parsed_req = parse_request(valid_noobit_req.value, symbol_to_exchange)
    parsed_req["timestamp"] = auth.nonce

    valid_binance_req = _validate_data(BinanceRequestNewOrder,
                                       pmap({**parsed_req}))
    if valid_binance_req.is_err():
        return valid_binance_req

    if logger:
        logger(f"New Order - Parsed Request : {valid_binance_req.value}")

    #! sign after validation, otherwise we aill get all the non values too
    signed_req: dict = auth._sign(
        valid_binance_req.value.dict(exclude_none=True))

    #! we should not pass in "params" to the client, but construct the whole url + query string ourself, so we can make sure its sorted properly

    #! ====>
    qstrings = sorted([(k, v)
                       for k, v in signed_req.items() if not "signature" in k],
                      reverse=True)
    qstrings_join = urlencode(qstrings)
    full_url = "?".join([req_url, qstrings_join])
    full_url += f"&signature={signed_req['signature']}"
    #! <=====

    result_content = await get_result_content_from_req(client, method,
                                                       full_url,
                                                       FrozenBaseModel(),
                                                       headers)
    if result_content.is_err():
        return result_content

    if logger:
        logger(f"New Order - Result Content : {result_content.value}")

    valid_result_content = _validate_data(BinanceResponseNewOrder,
                                          result_content.value)
    if valid_result_content.is_err():
        return valid_result_content

    parsed_result = parse_result(valid_result_content.value, symbol)

    valid_parsed_response_data = _validate_data(
        NoobitResponseItemOrder,
        pmap({
            **parsed_result, "rawJson": result_content.value,
            "exchange": "BINANCE"
        }))
    return valid_parsed_response_data
コード例 #26
0
async def post_neworder_ftx(
    client: ntypes.CLIENT,
    symbol: ntypes.SYMBOL,
    symbols_resp: NoobitResponseSymbols,
    side: ntypes.ORDERSIDE,
    ordType: ntypes.ORDERTYPE,
    clOrdID: str,
    orderQty: Decimal,
    price: Decimal,
    timeInForce: ntypes.TIMEINFORCE,
    stopPrice: typing.Optional[Decimal] = None,
    quoteOrderQty: typing.Optional[Decimal] = None,
    # prevent unintentional passing of following args
    *,
    logger: typing.Optional[typing.Callable] = None,
    auth=FtxAuth(),
    base_url: pydantic.AnyHttpUrl = endpoints.FTX_ENDPOINTS.private.url,
    endpoint: str = endpoints.FTX_ENDPOINTS.private.endpoints.new_order,
) -> Result[NoobitResponseItemOrder, pydantic.ValidationError]:

    symbol_from_exchange = lambda x: {
        f"{v.noobit_base}{v.noobit_quote}": k
        for k, v in symbols_resp.asset_pairs.items()
    }[x]
    symbol_to_exchange = lambda x: {
        k: v.exchange_pair
        for k, v in symbols_resp.asset_pairs.items()
    }[x]

    req_url = "/".join([base_url, "orders"])
    method = "POST"

    valid_noobit_req = _validate_data(
        NoobitRequestAddOrder,
        pmap({
            "exchange": "FTX",
            "symbol": symbol,
            "symbols_resp": symbols_resp,
            "side": side,
            "ordType": ordType,
            "clOrdID": clOrdID,
            "orderQty": orderQty,
            "price": price,
            "timeInForce": timeInForce,
            "quoteOrderQty": quoteOrderQty,
            "stopPrice": stopPrice,
        }))
    if valid_noobit_req.is_err():
        return valid_noobit_req

    # if logger:
    #     logger(f"New Order - Noobit Request : {valid_noobit_req.value}")

    parsed_req = parse_request(valid_noobit_req.value, symbol_to_exchange)

    valid_ftx_req = _validate_data(FtxRequestNewOrder, pmap(parsed_req))
    if valid_ftx_req.is_err():
        return valid_ftx_req

    # ? should be more elegant way to do this
    querystr = f"?market={valid_ftx_req.value.market}"
    req_url += querystr
    headers = auth.headers(method, f"/api/orders{querystr}")

    if logger:
        logger(f"New Order - Parsed Request : {valid_ftx_req.value}")

    result_content = await get_result_content_from_req(client, method, req_url,
                                                       FrozenBaseModel(),
                                                       headers)
    if result_content.is_err():
        return result_content

    if logger:
        logger(f"New Order - Result content : {result_content.value}")

    valid_result_content = _validate_data(FtxResponseNewOrder,
                                          result_content.value)
    if valid_result_content.is_err():
        return valid_result_content

    parsed_result = parse_result(valid_result_content.value,
                                 symbol_from_exchange)

    valid_parsed_response = _validate_data(
        NoobitResponseNewOrder,
        pmap({
            **parsed_result,
            "rawJson": result_content.value,
            "exchange": "FTX",
        }),
    )
    return valid_parsed_response
コード例 #27
0
async def get_ohlc_kraken(
    client: ntypes.CLIENT,
    symbol: ntypes.SYMBOL,
    symbols_resp: NoobitResponseSymbols,
    timeframe: ntypes.TIMEFRAME,
    since: ntypes.TIMESTAMP,
    # prevent unintentional passing of following args
    *,
    logger: typing.Optional[typing.Callable] = None,
    base_url: pydantic.AnyHttpUrl = endpoints.KRAKEN_ENDPOINTS.public.url,
    endpoint: str = endpoints.KRAKEN_ENDPOINTS.public.endpoints.ohlc,
) -> Result[NoobitResponseOhlc, ValidationError]:

    symbol_to_exchange = lambda x: {
        k: v.exchange_pair
        for k, v in symbols_resp.asset_pairs.items()
    }[x]

    req_url = urljoin(base_url, endpoint)
    method = "GET"
    headers: typing.Dict = {}

    valid_noobit_req = _validate_data(
        NoobitRequestOhlc,
        pmap({
            "symbol": symbol,
            "symbols_resp": symbols_resp,
            "timeframe": timeframe,
            "since": since,
        }),
    )
    if isinstance(valid_noobit_req, Err):
        return valid_noobit_req

    if logger:
        logger(f"Ohlc - Noobit Request : {valid_noobit_req.value}")

    parsed_req = parse_request(valid_noobit_req.value, symbol_to_exchange)

    valid_kraken_req = _validate_data(KrakenRequestOhlc, pmap(parsed_req))
    if valid_kraken_req.is_err():
        return valid_kraken_req

    if logger:
        logger(f"Ohlc - Parsed Request : {valid_kraken_req.value}")

    result_content = await get_result_content_from_req(client, method, req_url,
                                                       valid_kraken_req.value,
                                                       headers)
    if result_content.is_err():
        return result_content

    if logger:
        logger(f"Ohlc - Result Content : {result_content.value}")

    valid_result_content = _validate_data(
        make_kraken_model_ohlc(symbol, symbol_to_exchange),
        pmap({
            symbol_to_exchange(symbol):
            result_content.value[symbol_to_exchange(symbol)],
            "last":
            result_content.value["last"],
        }),
    )
    if valid_result_content.is_err():
        return valid_result_content

    parsed_result = parse_result(
        getattr(valid_result_content.value, symbol_to_exchange(symbol)),
        symbol)

    valid_parsed_response_data = _validate_data(
        NoobitResponseOhlc,
        pmap({
            "ohlc": parsed_result,
            "rawJson": result_content.value,
            "exchange": "KRAKEN",
        }),
    )
    return valid_parsed_response_data
コード例 #28
0
ファイル: orders.py プロジェクト: maxima-us/noobit-markets
def validate_parsed(msg, parsed_msg):
    return _validate_data(
        NoobitResponseOpenOrders,
        {"orders": parsed_msg, "rawJson": msg}
    )