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
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)
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)
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)
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
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)
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"])
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})
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)
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})
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)
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
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
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
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
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
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
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
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)))
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
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
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)
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
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
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
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)
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)
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)