Ejemplo n.º 1
0
def validate_data_against(data: dict, model: FrozenBaseModel):
    try:
        validated = model(**data)  #type: ignore
        return Ok(validated)
    except ValidationError as e:
        return Err(e)
    except Exception as e:
        raise e
Ejemplo n.º 2
0
def validate_parsed(msg, parsed_msg):

    try:
        validated_msg = NoobitResponseTrades(trades=parsed_msg,
                                             rawJson=msg,
                                             exchange="BINANCE")
        return Ok(validated_msg)

    except ValidationError as e:
        return Err(e)
Ejemplo n.º 3
0
def validate_parsed(msg, parsed_msg):

    try:
        validated_msg = NoobitResponseSpread(spread=(parsed_msg, ),
                                             rawJson=msg,
                                             exchange="KRAKEN")
        return Ok(validated_msg)

    except ValidationError as e:
        print(e)
        return Err(e)
Ejemplo n.º 4
0
def validate_parsed(msg, parsed_msg):

    try:
        validated_msg = NoobitResponseOhlc(ohlc=parsed_msg,
                                           rawJson=msg,
                                           exchange="KRAKEN")
        return Ok(validated_msg)

    except ValidationError as e:
        # print(e)
        return Err(e)
Ejemplo n.º 5
0
def _validate_data(
    model: typing.Type[BaseModel],
    fields: pyrsistent.PMap  # PRecord sublasses PMap so its also acceptable
) -> Result:

    try:
        validated = model(**fields)  #type: ignore
        return Ok(validated)
    except ValidationError as e:
        return Err(e)
    except Exception as e:
        raise e
Ejemplo n.º 6
0
def validate_parsed(msg: BinanceBookMsg, parsed_msg: dict):

    try:
        validated_msg = NoobitResponseOrderBook(
            rawJson=msg,
            exchange="BINANCE",
            **parsed_msg
            )
        return Ok(validated_msg)

    except ValidationError as e:
        return Err(e)
Ejemplo n.º 7
0
async def result_or_err(resp_obj: httpx.Response) -> Result:

    content = await resp_json(resp_obj)

    errors: list = content.get("error", None)

    if errors:
        err_dict = {err: err.split(":")[1] for err in errors}
        return Err(err_dict)
    else:
        # no error
        return Ok(content["result"])
Ejemplo n.º 8
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})
Ejemplo n.º 9
0
def validate_parsed(msg, parsed_msg):

    try:
        validated_msg = NoobitResponseOrderBook(
            **parsed_msg,
            utcTime=time.time() * 10**3,
            rawJson=msg,
            exchange="KRAKEN"
        )
        return Ok(validated_msg)

    except ValidationError as e:
        return Err(e)
Ejemplo n.º 10
0
async def result_or_err(resp_obj: httpx.Response) -> Result:
    # example of ftx error response content:
    #  {"error":"Not logged in","success":false}

    # example of ftx orderbook response content
    # {"success": true, "result": {"asks": [[4114.25, 6.263]], "bids": [[4112.25, 49.]]}}

    content = await resp_json(resp_obj)

    if content["success"]:
        return Ok(content["result"])
    else:
        # needs to be a dict
        return Err({"error": content})
Ejemplo n.º 11
0
async def result_or_err(resp_obj: httpx.Response) -> Result:

    # Example of error content (note no key to indicate it is an error)
    # {"code":-1105,"msg":"Parameter \'startTime\' was empty."}

    content = await resp_json(resp_obj)

    if "code" in content:
        # we have an error message
        error_msg = content.get("msg", None)
        error_key = int(content["code"]) * -1
        return Err({error_key: error_msg})
    else:
        # no error
        return Ok(content)
Ejemplo n.º 12
0
def validate_nreq_trades(
    symbol: ntypes.SYMBOL, symbol_mapping: ntypes.SYMBOL_TO_EXCHANGE,
    since: typing.Optional[ntypes.TIMESTAMP]
) -> Result[NoobitRequestTrades, ValidationError]:

    try:
        valid_req = NoobitRequestTrades(symbol=symbol,
                                        symbol_mapping=symbol_mapping,
                                        since=since)
        return Ok(valid_req)

    except ValidationError as e:
        return Err(e)

    except Exception as e:
        raise e
Ejemplo n.º 13
0
def validate_nreq_orderbook(
        symbol: ntypes.SYMBOL, symbol_mapping: ntypes.SYMBOL_TO_EXCHANGE,
        depth: ntypes.DEPTH
) -> Result[NoobitRequestOrderBook, ValidationError]:

    try:
        valid_req = NoobitRequestOrderBook(symbol=symbol,
                                           symbol_mapping=symbol_mapping,
                                           depth=depth)
        return Ok(valid_req)

    except ValidationError as e:
        return Err(e)

    except Exception as e:
        raise e
Ejemplo n.º 14
0
def validate_nreq_ohlc(
        symbol: ntypes.SYMBOL, symbol_mapping: ntypes.SYMBOL_TO_EXCHANGE,
        timeframe: ntypes.TIMEFRAME,
        since: ntypes.TIMESTAMP) -> Result[NoobitRequestOhlc, ValidationError]:

    try:
        valid_req = NoobitRequestOhlc(symbol=symbol,
                                      symbol_mapping=symbol_mapping,
                                      timeframe=timeframe,
                                      since=since)
        return Ok(valid_req)

    except ValidationError as e:
        return Err(e)

    except Exception as e:
        raise e
Ejemplo n.º 15
0
def validate_nreq_instrument(
    symbol: ntypes.SYMBOL,
    symbol_mapping: ntypes.SYMBOL_TO_EXCHANGE,
) -> Result[NoobitRequestInstrument, ValidationError]:

    try:
        valid_req = NoobitRequestInstrument(
            symbol=symbol,
            symbol_mapping=symbol_mapping,
        )
        return Ok(valid_req)

    except ValidationError as e:
        return Err(e)

    except Exception as e:
        raise e
Ejemplo n.º 16
0
def validate_sub(symbol_to_exchange: SYMBOL_TO_EXCHANGE,
                 symbol: SYMBOL) -> Result[BinanceSubModel, ValidationError]:

    msg = {
        "id": 1,
        "method": "SUBSCRIBE",
        "params": (f"{symbol_to_exchange(symbol)}@aggTrade", )
    }

    try:
        submodel = BinanceSubModel(exchange="binance", feed="trade", msg=msg)
        return Ok(submodel)

    except ValidationError as e:
        return Err(e)

    except Exception as e:
        raise e
Ejemplo n.º 17
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
Ejemplo n.º 18
0
def validate_sub(token) -> Result[KrakenSubModel, Exception]:
    msg = {
        "event": "subscribe", 
        "pair": None,
        "subscription": {"name": "openOrders", "token": token} 
    }
    try:
        submodel = KrakenSubModel(
            exchange="kraken",
            feed="user_orders",
            msg=msg
        )
        return Ok(submodel)

    except ValidationError as e:
        return Err(e)

    except Exception as e:
        raise e
Ejemplo n.º 19
0
def get_response_status_code(
        resp_obj: httpx.Response) -> Result[pydantic.PositiveInt, BaseError]:
    # status_code = response_json.status_code
    # err_msg = f"HTTP Status Error: {status_code}"
    # return Ok(status_code) if status_code == 200 else Err(err_msg)

    status_keys = [k for k in resp_obj.__dict__.keys() if "status" in k]

    if len(status_keys) > 1:
        raise KeyError(
            f"Found multiple <status> keys in {resp_obj.__dict__.keys()}")

    status = getattr(resp_obj, status_keys[0])

    if status == 200:
        return Ok(status)
    else:
        msg = f"Http Status Error: {status}"
        return Err(
            BadRequest(raw_error=msg, sent_request=get_sent_request(resp_obj)))
Ejemplo n.º 20
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
Ejemplo n.º 21
0
def validate_sub(symbol_to_exchange: SYMBOL_TO_EXCHANGE, symbol: SYMBOL, depth: DEPTH) -> Result[KrakenSubModel, ValidationError]:

    msg = {
        "event": "subscribe",
        "pair": [symbol_to_exchange(symbol), ],
        "subscription": {"name": "book", "depth": depth}
    }

    try:
        submodel = KrakenSubModel(
            exchange="kraken",
            feed="orderbook",
            msg=msg
        )
        return Ok(submodel)

    except ValidationError as e:
        return Err(e)

    except Exception as e:
        raise e
Ejemplo n.º 22
0
def validate_sub(
        symbol_to_exchange: SYMBOL_TO_EXCHANGE, symbol: SYMBOL,
        timeframe: TIMEFRAME) -> Result[KrakenSubModel, ValidationError]:

    msg = {
        "event": "subscribe",
        "pair": [
            symbol_to_exchange(symbol),
        ],
        "subscription": {
            "name": "ohlc",
            "interval": K_TIMEFRAME_FROM_N[timeframe]
        }
    }

    try:
        submodel = KrakenSubModel(exchange="kraken", feed="trade", msg=msg)
        return Ok(submodel)

    except ValidationError as e:
        return Err(e)
Ejemplo n.º 23
0
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
Ejemplo n.º 24
0
    async def create_neworder(
        self,
        exchange: str,
        symbol: str,
        ordType: str,
        clOrdID,
        orderQty: float,
        price: float,
        timeInForce: str = "GOOD-TIL-CANCEL",
        quoteOrderQty: typing.Optional[float] = None,
        stopPrice: typing.Optional[float] = None,
        *,
        side: str,
        blind: bool,
        split: typing.Optional[int] = None,
        delay: typing.Optional[int] = None,
        step: typing.Optional[float] = None,
    ):
        from noobit_markets.base.models.rest.response import NSingleOrder

        self.log_field.log("CALLED create_neworder") 

        if not symbol: 
            if not settings.SYMBOL or settings.SYMBOL.isspace(): 
                return Err("Please set or pass <symbol> argument")
            else: symbol = settings.SYMBOL
        else: symbol=symbol.upper()

        if not ordType:
            if not settings.ORDTYPE or settings.ORDTYPE.isspace(): 
                return Err("Please set or pass <ordType> argument")
            else: ordType = settings.ORDTYPE
        # TODO be consistent: either all noobit types in capital or in lowercase
        else: ordType = ordType.upper()

        if not orderQty:
            if not settings.ORDQTY: 
                return Err("Please set or pass <orderQty> argument")
            else: orderQty = settings.ORDQTY

        if not timeInForce and ordType in ["LIMIT", "STOP-LOSS-LIMIT", "TAKE-PROFIT-LIMIT"]:
            self.log("WARNING : <timeInForce> not provided, defaulting to <GOOD-TIL-CANCEL>")
            timeInForce = "GOOD-TIL-CANCEL"

        
        interface = globals()[exchange]

        if split:
            # step is only for limit orders
            if step:
                if not ordType in ["LIMIT", "STOP_LIMIT", "TAKE_PROFIT"]:
                    return Err(f"Argument <step>: Ordertype can not be {ordType}")
            
            # only one of delay or step
            if not any([delay, step]) or all([delay, step]):
                return Err("Please set only one of <delay> or <step> argument to split orders")
            else: 
                _acc = []
                acc_price = price

                for i in range(split):
                    _res = await interface.rest.private.new_order(
                        client=self.client,
                        symbol=symbol, 
                        symbols_resp=self.symbols[exchange].value, 
                        side=side, 
                        ordType=ordType, 
                        clOrdID=clOrdID, 
                        # orderQty=round(orderQty/split, self.symbols[exchange].value.asset_pairs[symbol].volume_decimals), # TODO atm we limit to 2 decimal places, could check max decimals for pair, ALSO this can lead to keyerror if symbol is not on exchange
                        orderQty=round(orderQty/split, 2), # TODO atm we limit to 2 decimal places, could check max decimals for pair, ALSO this can lead to keyerror if symbol is not on exchange
                        price=acc_price, 
                        timeInForce=timeInForce, 
                        quoteOrderQty=quoteOrderQty, 
                        stopPrice=stopPrice
                        )
                    if _res.is_ok():
                        if blind:
                            _res.value.price = None
                        _acc.append(_res.value)
                        self.log_field.log(f"Successful order, count {len(_acc)}")
                    else:
                        self.log_field.log(f"Failed order")
                        return _res
                    
                    if step:
                        acc_price = round(float(acc_price + step), 2) # FIXME this will create decimal place precision errors sometimes, we need to round somehow (use context ??) 
                        await asyncio.sleep(1)
                    else:
                        await asyncio.sleep(delay)  # avoid rate limiting


                try:
                    
                    if blind:
                        self.log("Argument <blind>: Setting Order Price to <None>")
                    
                    _splitorders = NoobitResponseClosedOrders(
                        exchange="KRAKEN",
                        rawjson={},
                        orders=_acc
                    )
                    # request coros always return a result
                    # so we wrap the validated model in an OK container
                    
                    _nords = NOrders(Ok(_splitorders))
                    return _nords
                except ValidationError as e:
                    return Err(e)


        else:

            if any([delay, step]):
                self.log_field.log("Argument <delay> or <step> require <split>")    
                return Err("Argument <delay> or <step> require <split>")    

            _res = await interface.rest.private.new_order(
                client=self.client,
                symbol=symbol, 
                symbols_resp=self.symbols[exchange].value, 
                side=side, 
                ordType=ordType, 
                clOrdID=clOrdID, 
                orderQty=orderQty, 
                price=price, 
                timeInForce=timeInForce, 
                quoteOrderQty=quoteOrderQty, 
                stopPrice=stopPrice
                )

            if blind:
                self.log("Argument <blind>: Setting Order Price to <None>")
                if _res.is_ok():
                    _res.value.price = None

            _nord = NSingleOrder(_res)
        
            return _nord
Ejemplo n.º 25
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
Ejemplo n.º 26
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)
Ejemplo n.º 27
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)
Ejemplo n.º 28
0
    async def cancel_order(
        self,
        exchange: str,
        symbol: str,
        slice: str,
        all: bool
    ):
        
        self.log_field.log("CALLED cancel_order") 

        # testlist = [x for x in range(0, 100)]
        # regex = re.compile(r"^\[[-]?[0-9]+:[-]?[0-9]+\]$")
        regex = "^\[[-]?[0-9]+:[-]?[0-9]+:[-]?[0-9]\]$"
        match = re.match(regex, slice)
        
        if not match:
            self.log(match)
            return Err(f"Argument position did not match regex - Given {slice}")
        else:
            # sliced = eval(f"testlist{position}")
            # self.log(sliced)
            # return Ok("SUCCESS")
        
            if not symbol: 
                if not settings.SYMBOL or settings.SYMBOL.isspace(): 
                    return Err("Please set or pass <symbol> argument")
                else: symbol = settings.SYMBOL
            else: symbol=symbol.upper()

            self.log_field.log(f"Requested Symbol : {symbol}")
            self.log_field.log(f"Requested Exchange : {exchange}")
            
            interface = globals()[exchange]
            _res = await interface.rest.private.open_orders(self.client, symbol, self.symbols[exchange].value)

            if _res.is_err():
                return _res.value
            else:
                _acc = []

                _all_orders = sorted([order for order in _res.value.orders], key=lambda x: getattr(x, "price"), reverse=False)
                _sliced_orders = eval(f"_all_orders{slice}") 

                for _order in _sliced_orders:

                    _ord = await interface.rest.private.remove_order(self.client, symbol, self.symbols[exchange].value, _order.orderID)

                    if _ord.is_ok():
                        _acc.append(_ord.value)
                    else:
                        return _ord

                    await asyncio.sleep(1)
                
                try:
                    _canceled_orders = NoobitResponseClosedOrders(
                        exchange="KRAKEN",
                        rawjson={},
                        orders=_acc
                    )
                    # request coros always return a result
                    # so we wrap the validated model in an OK container
                    _nords = NOrders(Ok(_canceled_orders))
                    return _nords
                except ValidationError as e:
                    return Err(e)