async def tick( self) -> AsyncGenerator[Any, Event]: # type: ignore[override] now = self._start for i in range(1000): if self._client_order: self._client_order.filled = self._client_order.volume t = Trade( self._client_order.volume, i, taker_order=self._client_order, maker_orders=[], ) t.taker_order.timestamp = now self._client_order = None yield Event(type=EventType.TRADE, target=t) continue o = Order( 1, i, Side.BUY, self._instrument, self.exchange(), timestamp=now, filled=1, ) t = Trade(1, i, o, []) yield Event(type=EventType.TRADE, target=t) now += timedelta(minutes=30)
async def tick(self): '''return data from exchange''' while True: # clear order events while self._order_event_queue.qsize() > 0: order_data = self._order_event_queue.get() status = order_data['status'] order = self._orders[order_data['orderId']] if status in ('ApiPending', 'PendingSubmit', 'PendingCancel', 'PreSubmitted', 'ApiCancelled', 'Inactive'): # ignore continue elif status in ('Submitted', ): # TODO more granular order events api? # ignore pass elif status in ('Cancelled', ): e = Event(type=EventType.REJECTED, target=order) yield e elif status in ('Filled', ): t = Trade(volume=order_data['filled'], price=order_data['avgFillPrice'], maker_orders=[], taker_order=order) t.my_order = order e = Event(type=EventType.TRADE, target=t) yield e await asyncio.sleep(0)
async def tick(self): '''return data from exchange''' while True: # clear order events while self._order_event_queue.qsize() > 0: order_data = self._order_event_queue.get() status = order_data['status'] order = self._orders[order_data['orderId']] if status in ('ApiPending', 'PendingSubmit', 'PendingCancel', 'PreSubmitted', 'ApiCancelled', 'Inactive'): # ignore continue elif status in ('Submitted',): e = Event(type=EventType.RECEIVED, target=order) yield e elif status in ('Cancelled',): e = Event(type=EventType.CANCELED, target=order) yield e elif status in ('Filled',): # this is the filled from orderStatus, but we # want to use the one from execDetails # From the IB Docs: # "There are not guaranteed to be orderStatus # callbacks for every change in order status" # It is recommended to use execDetails # ignore pass elif status in ('Execution',): # set filled order.filled = order_data['filled'] # create trade object t = Trade(volume=order_data['filled'], price=order_data['avgFillPrice'], maker_orders=[], taker_order=order) # set my order t.my_order = order e = Event(type=EventType.TRADE, target=t) yield e # clear market data events while self._market_data_queue.qsize() > 0: market_data = self._market_data_queue.get() instrument = market_data['instrument'] price = market_data['price'] o = Order(volume=1, price=price, side=Side.BUY, instrument=instrument, exchange=self.exchange()) t = Trade(volume=1, price=price, taker_order=o, maker_orders=[]) yield Event(type=EventType.TRADE, target=t) await asyncio.sleep(0)
async def tick(self): '''return data from exchange''' while True: # clear order events while self._order_event_queue.qsize() > 0: order_data = self._order_event_queue.get() status = order_data['status'] order = self._orders[order_data['orderId']] if status in ('ApiPending', 'PendingSubmit', 'PendingCancel', 'PreSubmitted', 'ApiCancelled', 'Inactive'): # ignore continue elif status in ('Submitted', ): # TODO more granular order events api? # ignore pass elif status in ('Cancelled', ): e = Event(type=EventType.CANCELED, target=order) yield e elif status in ('Filled', ): # set filled order.filled = order_data['filled'] # create trade object t = Trade(volume=order_data['filled'], price=order_data['avgFillPrice'], maker_orders=[], taker_order=order) # set my order t.my_order = order e = Event(type=EventType.TRADE, target=t) yield e # clear market data events while self._market_data_queue.qsize() > 0: market_data = self._market_data_queue.get() instrument = market_data['instrument'] price = market_data['price'] o = Order(volume=1, price=price, side=Side.BUY, instrument=instrument, exchange=self.exchange()) t = Trade(volume=1, price=price, taker_order=o, maker_orders=[]) yield Event(type=EventType.TRADE, target=t) await asyncio.sleep(0)
async def cancelOrder(self, order: Order): '''cancel a previously submitted order to the exchange.''' ret = self._client.cancelOrder(order) if ret: # cancel succesful self._order_events.append( Event(type=EventType.CANCELED, target=order)) else: # cancel rejected self._order_events.append( Event(type=EventType.REJECTED, target=order))
async def newOrder(self, order): '''submit a new order to the exchange. should set the given order's `id` field to exchange-assigned id''' ret = self._client.newOrder(order) if ret: # order succesful self._order_events.append( Event(type=EventType.RECEIVED, target=order)) else: # order failure self._order_events.append( Event(type=EventType.REJECTED, target=order))
async def _onCanceled(self, strategy, order: Order): # push event to loop ev = Event(type=Event.Types.CANCELED, target=order) self._engine.pushTargetedEvent(strategy, ev) # synchronize state when engine processes this self._alerted_events[ev] = (strategy, order)
async def _onReceived(self, strategy: "Strategy", order: Order) -> None: # push event to loop ev = Event(type=Event.Types.RECEIVED, target=order) self._engine.pushTargetedEvent(strategy, ev) # synchronize state when engine processes this self._alerted_events[ev] = (strategy, order)
async def newOrder(self, strategy, order: Order): '''helper method, defers to buy/sell''' # ensure has list if strategy not in self._strategy_open_orders: self._strategy_open_orders[strategy] = [] if strategy not in self._strategy_past_orders: self._strategy_past_orders[strategy] = [] if strategy not in self._strategy_trades: self._strategy_trades[strategy] = [] # append to open orders list self._strategy_open_orders[strategy].append(order) # append to past orders list self._strategy_past_orders[strategy].append(order) # TODO check risk ret, approved = await self._risk_mgr.newOrder(strategy, order) # was this trade allowed? if approved: # send to be executed await self._order_mgr.newOrder(strategy, order) return ret # raise onRejected self._engine.pushEvent(Event(type=Event.Types.REJECTED, target=order)) return None
async def tick(self): now = self._start for i in range(1000): if self._client_order: self._client_order.filled = self._client_order.volume t = Trade(self._client_order.volume, i, [], self._client_order) t.taker_order.timestamp = now self._client_order = None yield Event(type=EventType.TRADE, target=t) continue o = Order(1, i, Side.BUY, self._instrument, self.exchange()) o.filled = 1 o.timestamp = now t = Trade(1, i, [], o) yield Event(type=EventType.TRADE, target=t) now += timedelta(minutes=30)
async def _onSold(self, strategy, trade: Trade): # append to list of trades self._strategy_trades[strategy].append(trade) # push event to loop ev = Event(type=Event.Types.SOLD, target=trade) self._engine.pushTargetedEvent(strategy, ev) # synchronize state when engine processes this self._alerted_events[ev] = (strategy, trade.my_order)
async def _onRejected(self, strategy, order: Order): '''callback method for if your order fails to execute Args: order (Order): the order you attempted to make ''' # push event to loop ev = Event(type=Event.Types.REJECTED, target=order) self._engine.pushTargetedEvent(strategy, ev) # synchronize state when engine processes this self._alerted_events[ev] = (strategy, order)
async def tick(self): for item in self._data: yield Event(EventType.TRADE, item) await asyncio.sleep(0) # save timestamp timestamp = item.timestamp while self._queued_orders: order = self._queued_orders.popleft() order.timestamp = timestamp order.filled = order.volume t = Trade( volume=order.volume, price=order.price, taker_order=order, maker_orders=[], my_order=order, ) yield Event(type=EventType.TRADE, target=t) await asyncio.sleep(0)
async def tick(self): '''return data from exchange''' dfs = [] for i in self._subscriptions: df = self._client.chartDF(i.name, timeframe='6m') df = df[['close', 'volume']] df.columns = ['close:{}'.format(i.name), 'volume:{}'.format(i.name)] dfs.append(df) data = pd.concat(dfs, axis=1) data.sort_index(inplace=True) data = data.groupby(data.index).last() data.drop_duplicates(inplace=True) data.fillna(method='ffill', inplace=True) for index in data.index: for i in self._subscriptions: volume = data.loc[index]['volume:{}'.format(i.name)] price = data.loc[index]['close:{}'.format(i.name)] o = Order(volume=volume, price=price, side=Side.BUY, instrument=i, exchange=self.exchange()) o.timestamp = index.to_pydatetime() t = Trade(volume=volume, price=price, taker_order=o, maker_orders=[]) yield Event(type=EventType.TRADE, target=t) await asyncio.sleep(0) while self._queued_orders: order = self._queued_orders.popleft() order.timestamp = index t = Trade(volume=order.volume, price=order.price, taker_order=order, maker_orders=[]) t.my_order = order yield Event(type=EventType.TRADE, target=t) await asyncio.sleep(0)
async def _onSold(self, strategy, trade: Trade): '''callback method for when/if your order executes. Args: order_or_trade (Union[Order, Trade]): the trade/s as your order completes, and/or a cancellation order ''' # append to list of trades self._strategy_trades[strategy].append(trade) # push event to loop ev = Event(type=Event.Types.SOLD, target=trade) self._engine.pushTargetedEvent(strategy, ev) # synchronize state when engine processes this self._alerted_events[ev] = (strategy, trade.my_order)
async def onTrade(self, event): action, strat, order = False, None, None for order in event.target.maker_orders: if order.id in self._pending_orders: action = True _, strat = self._pending_orders[order.id] break if event.target.taker_order.id in self._pending_orders: action = True order = event.target.taker_order _, strat = self._pending_orders[order.id] if action: # TODO add to event loop event = Event(type=Event.Types.TRADE, target=order) if order.side == Order.Sides.SELL: await strat.onSold(event) else: await strat.onBought(event) del self._pending_orders[order.id]
async def newOrder(self, order): """submit a new order to the exchange. should set the given order's `id` field to exchange-assigned id For MarketData-only, can just return None """ # construct IB contract and order ibcontract, iborder = _constructContractAndOrder(order) # send to IB id = self._api.placeOrder(ibcontract, iborder) # update order id order.id = id self._orders[order.id] = order # set event for later trigerring self._order_received_map[id] = Event() await self._order_received_map[id] res = self._order_received_res[id] del self._order_received_map[id] del self._order_received_res[id] return res
async def tick( self) -> AsyncGenerator[Any, Event]: # type: ignore[override] """return data from exchange""" while True: # clear order events while self._order_event_queue.qsize() > 0: order_data = self._order_event_queue.get() status = order_data["status"] order = self._orders[str(order_data["orderId"])] if status in ( "ApiPending", "PendingSubmit", "PendingCancel", "PreSubmitted", "ApiCancelled", "Inactive", ): # ignore continue elif status in ("Submitted", ): self._order_received_res[order.id] = True self._order_received_map[order.id].set() await asyncio.sleep(0) elif status in ("Cancelled", ): self._order_cancelled_res[order.id] = True self._order_cancelled_map[order.id].set() await asyncio.sleep(0) elif status in ("Filled", ): # this is the filled from orderStatus, but we # want to use the one from execDetails # From the IB Docs: # "There are not guaranteed to be orderStatus # callbacks for every change in order status" # It is recommended to use execDetails # ignore pass elif status in ("Execution", ): # set filled order.filled = order_data["filled"] # create trade object t = Trade( volume=order_data["filled"], # type: ignore price=order_data["avgFillPrice"], # type: ignore maker_orders=[], taker_order=order, ) # set my order t.my_order = order e = Event(type=EventType.TRADE, target=t) yield e # clear market data events while self._market_data_queue.qsize() > 0: market_data = self._market_data_queue.get() instrument: Instrument = market_data[ "instrument"] # type: ignore price: float = market_data["price"] # type: ignore o = AATOrder( volume=1, price=price, side=Side.BUY, instrument=instrument, exchange=self.exchange(), ) t = Trade(volume=1, price=float(price), taker_order=o, maker_orders=[]) yield Event(type=EventType.TRADE, target=t) await asyncio.sleep(0)
async def tick(self): '''return data from exchange''' if self._timeframe == 'live': data = deque() def _callback(record): data.append(record) self._client.tradesSSE(symbols=",".join( [i.name for i in self._subscriptions]), on_data=_callback) while True: while data: record = data.popleft() volume = record['volume'] price = record['price'] instrument = Instrument(record['symbol'], InstrumentType.EQUITY) o = Order(volume=volume, price=price, side=Side.BUY, instrument=instrument, exchange=self.exchange()) t = Trade(volume=volume, price=price, taker_order=o, maker_orders=[]) yield Event(type=EventType.TRADE, target=t) await asyncio.sleep(0) else: dfs = [] insts = set() if self._timeframe != '1d': for i in tqdm(self._subscriptions, desc="Fetching data..."): if i.name in insts: # already fetched the data, multiple subscriptions continue if self._cache_data: # first, check if we have this data and its cached already os.makedirs('_aat_data', exist_ok=True) data_filename = os.path.join( '_aat_data', 'iex_{}_{}_{}_{}.pkl'.format( i.name, self._timeframe, datetime.now().strftime('%Y%m%d'), 'sand' if self._is_sandbox else '')) if os.path.exists(data_filename): print('using cached IEX data for {}'.format( i.name)) df = pd.read_pickle(data_filename) else: df = self._client.chartDF( i.name, timeframe=self._timeframe) df.to_pickle(data_filename) else: df = self._client.chartDF(i.name, timeframe=self._timeframe) df = df[['close', 'volume']] df.columns = [ 'close:{}'.format(i.name), 'volume:{}'.format(i.name) ] dfs.append(df) insts.add(i.name) data = pd.concat(dfs, axis=1) data.sort_index(inplace=True) data = data.groupby(data.index).last() data.drop_duplicates(inplace=True) data.fillna(method='ffill', inplace=True) else: for i in tqdm(self._subscriptions, desc="Fetching data..."): if i.name in insts: # already fetched the data, multiple subscriptions continue date = self._start_date subdfs = [] while date <= self._end_date: if self._cache_data: # first, check if we have this data and its cached already os.makedirs('_aat_data', exist_ok=True) data_filename = os.path.join( '_aat_data', 'iex_{}_{}_{}_{}.pkl'.format( i.name, self._timeframe, date, 'sand' if self._is_sandbox else '')) if os.path.exists(data_filename): print( 'using cached IEX data for {} - {}'.format( i.name, date)) df = pd.read_pickle(data_filename) else: df = self._client.chartDF( i.name, timeframe='1d', date=date.strftime('%Y%m%d')) df.to_pickle(data_filename) else: df = self._client.chartDF( i.name, timeframe='1d', date=date.strftime('%Y%m%d')) if not df.empty: df = df[['average', 'volume']] df.columns = [ 'close:{}'.format(i.name), 'volume:{}'.format(i.name) ] subdfs.append(df) date += timedelta(days=1) dfs.append(pd.concat(subdfs)) insts.add(i.name) data = pd.concat(dfs, axis=1) data.index = [ x + timedelta(hours=int(y.split(':')[0]), minutes=int(y.split(':')[1])) for x, y in data.index ] data = data.groupby(data.index).last() data.drop_duplicates(inplace=True) data.fillna(method='ffill', inplace=True) for index in data.index: for i in self._subscriptions: volume = data.loc[index]['volume:{}'.format(i.name)] price = data.loc[index]['close:{}'.format(i.name)] if volume == 0: continue o = Order(volume=volume, price=price, side=Side.BUY, instrument=i, exchange=self.exchange()) o.filled = volume o.timestamp = index.to_pydatetime() t = Trade(volume=volume, price=price, taker_order=o, maker_orders=[]) yield Event(type=EventType.TRADE, target=t) await asyncio.sleep(0) while self._queued_orders: order = self._queued_orders.popleft() order.timestamp = index order.filled = order.volume t = Trade(volume=order.volume, price=order.price, taker_order=order, maker_orders=[]) t.my_order = order yield Event(type=EventType.TRADE, target=t) await asyncio.sleep(0)
async def tick( self) -> AsyncGenerator[Any, Event]: # type: ignore[override] """return data from exchange""" while True: # clear order events while self._order_event_queue.qsize() > 0: try: order_data = self._order_event_queue.get_nowait() except Empty: await asyncio.sleep(0.1) continue status = order_data["status"] order = self._orders[str(order_data["orderId"])] if status in ( "ApiPending", "PendingSubmit", "PendingCancel", "PreSubmitted", "ApiCancelled", ): # ignore continue elif status in ("Inactive", ): self._finished_orders.add(order.id) self._send_order_received(order.id, False) self._send_cancel_received(order.id, False) elif status in ("Rejected", ): self._finished_orders.add(order.id) self._send_order_received(order.id, False) await asyncio.sleep(0) elif status in ("Submitted", ): self._send_order_received(order.id, True) await asyncio.sleep(0) elif status in ("Cancelled", ): self._finished_orders.add(order.id) self._send_cancel_received(order.id, True) await asyncio.sleep(0) elif status in ("Filled", ): # this is the filled from orderStatus, but we # want to use the one from execDetails # From the IB Docs: # "There are not guaranteed to be orderStatus # callbacks for every change in order status" # It is recommended to use execDetails # ignore pass elif status in ("Execution", ): # set filled order.filled = order_data["filled"] # finish order if fully filled if order.finished(): self._finished_orders.add(order.id) # if it was cancelled but already executed, clear out the wait self._send_cancel_received(order.id, False) # create trade object t = Trade( volume=order_data["filled"], # type: ignore price=order_data["avgFillPrice"], # type: ignore maker_orders=[], taker_order=order, ) # set my order t.my_order = order e = Event(type=EventType.TRADE, target=t) # if submitted was skipped, clear out the wait self._send_order_received(order.id, True) yield e # clear market data events while self._market_data_queue.qsize() > 0: try: market_data = self._market_data_queue.get_nowait() except Empty: await asyncio.sleep(0.1) continue instrument: Instrument = market_data[ "instrument"] # type: ignore price: float = market_data["price"] # type: ignore o = AATOrder( volume=1, price=price, side=Side.BUY, instrument=instrument, exchange=self.exchange(), filled=1, ) t = Trade(volume=1, price=float(price), taker_order=o, maker_orders=[]) yield Event(type=EventType.TRADE, target=t) await asyncio.sleep(0)
async def tick( self) -> AsyncGenerator[Any, Event]: # type: ignore[override] """return data from exchange""" if self._timeframe == "live": data: Deque[dict] = deque() def _callback(record: dict) -> None: data.append(record) self._client.tradesSSE( symbols=",".join([i.name for i in self._subscriptions]), on_data=_callback, ) while True: while data: record = data.popleft() volume = record["volume"] price = record["price"] instrument = Instrument(record["symbol"], InstrumentType.EQUITY) o = Order( volume=volume, price=price, side=Side.BUY, instrument=instrument, exchange=self.exchange(), ) t = Trade(volume=volume, price=price, taker_order=o, maker_orders=[]) yield Event(type=EventType.TRADE, target=t) await asyncio.sleep(0) else: dfs = [] insts = set() if self._timeframe != "1d": for i in tqdm(self._subscriptions, desc="Fetching data..."): if i.name in insts: # already fetched the data, multiple subscriptions continue if self._cache_data: # first, check if we have this data and its cached already os.makedirs("_aat_data", exist_ok=True) data_filename = os.path.join( "_aat_data", "iex_{}_{}_{}_{}.pkl".format( i.name, self._timeframe, datetime.now().strftime("%Y%m%d"), "sand" if self._is_sandbox else "", ), ) if os.path.exists(data_filename): print("using cached IEX data for {}".format( i.name)) df = pd.read_pickle(data_filename) else: df = self._client.chartDF( i.name, timeframe=self._timeframe) df.to_pickle(data_filename) else: df = self._client.chartDF(i.name, timeframe=self._timeframe) df = df[["close", "volume"]] df.columns = [ "close:{}".format(i.name), "volume:{}".format(i.name) ] dfs.append(df) insts.add(i.name) data_frame = pd.concat(dfs, axis=1) data_frame.sort_index(inplace=True) data_frame = data_frame.groupby(data_frame.index).last() data_frame.drop_duplicates(inplace=True) data_frame.fillna(method="ffill", inplace=True) else: for i in tqdm(self._subscriptions, desc="Fetching data..."): if i.name in insts: # already fetched the data, multiple subscriptions continue date = self._start_date subdfs = [] while date <= self._end_date: if self._cache_data: # first, check if we have this data and its cached already os.makedirs("_aat_data", exist_ok=True) data_filename = os.path.join( "_aat_data", "iex_{}_{}_{}_{}.pkl".format( i.name, self._timeframe, date, "sand" if self._is_sandbox else "", ), ) if os.path.exists(data_filename): print( "using cached IEX data for {} - {}".format( i.name, date)) df = pd.read_pickle(data_filename) else: df = self._client.chartDF( i.name, timeframe="1d", date=date.strftime("%Y%m%d")) df.to_pickle(data_filename) else: df = self._client.chartDF( i.name, timeframe="1d", date=date.strftime("%Y%m%d")) if not df.empty: df = df[["average", "volume"]] df.columns = [ "close:{}".format(i.name), "volume:{}".format(i.name), ] subdfs.append(df) date += timedelta(days=1) dfs.append(pd.concat(subdfs)) insts.add(i.name) data_frame = pd.concat(dfs, axis=1) data_frame.index = [ x + timedelta(hours=int(y.split(":")[0]), minutes=int(y.split(":")[1])) for x, y in data_frame.index ] data_frame = data_frame.groupby(data_frame.index).last() data_frame.drop_duplicates(inplace=True) data_frame.fillna(method="ffill", inplace=True) for index in data_frame.index: for i in self._subscriptions: volume = data_frame.loc[index]["volume:{}".format(i.name)] price = data_frame.loc[index]["close:{}".format(i.name)] if volume == 0: continue o = Order( volume=volume, price=price, side=Side.BUY, instrument=i, exchange=self.exchange(), filled=volume, timestamp=index.to_pydatetime(), ) t = Trade(volume=volume, price=price, taker_order=o, maker_orders=[]) yield Event(type=EventType.TRADE, target=t) await asyncio.sleep(0) while self._queued_orders: order = self._queued_orders.popleft() order.timestamp = index order.filled = order.volume t = Trade( volume=order.volume, price=order.price, taker_order=order, maker_orders=[], my_order=order, ) yield Event(type=EventType.TRADE, target=t) await asyncio.sleep(0)
async def tick(self): for item in self._data: yield Event(EventType.TRADE, item)
async def _onRejected(self, strategy, order): # push event to loop ev = Event(type=Event.Types.REJECTED, target=order) self._engine.pushTargetedEvent(strategy, ev)
async def tick(self): '''return data from exchange''' if self._timeframe == 'live': data = deque() def _callback(record): data.append(record) self._client.tradesSSE(symbols=",".join([i.name for i in self._subscriptions]), on_data=_callback) while True: while data: record = data.popleft() volume = record['volume'] price = record['price'] instrument = Instrument(record['symbol'], InstrumentType.EQUITY) o = Order(volume=volume, price=price, side=Side.BUY, instrument=instrument, exchange=self.exchange()) t = Trade(volume=volume, price=price, taker_order=o, maker_orders=[]) yield Event(type=EventType.TRADE, target=t) await asyncio.sleep(0) else: dfs = [] if self._timeframe != '1d': for i in tqdm(self._subscriptions, desc="Fetching data..."): df = self._client.chartDF(i.name, timeframe=self._timeframe) df = df[['close', 'volume']] df.columns = ['close:{}'.format(i.name), 'volume:{}'.format(i.name)] dfs.append(df) data = pd.concat(dfs, axis=1) data.sort_index(inplace=True) data = data.groupby(data.index).last() data.drop_duplicates(inplace=True) data.fillna(method='ffill', inplace=True) else: for i in tqdm(self._subscriptions, desc="Fetching data..."): date = self._start_date subdfs = [] while date <= self._end_date: df = self._client.chartDF(i.name, timeframe='1d', date=date.strftime('%Y%m%d')) if not df.empty: df = df[['average', 'volume']] df.columns = ['close:{}'.format(i.name), 'volume:{}'.format(i.name)] subdfs.append(df) date += timedelta(days=1) dfs.append(pd.concat(subdfs)) data = pd.concat(dfs, axis=1) data.index = [x + timedelta(hours=int(y.split(':')[0]), minutes=int(y.split(':')[1])) for x, y in data.index] data = data.groupby(data.index).last() data.drop_duplicates(inplace=True) data.fillna(method='ffill', inplace=True) for index in data.index: for i in self._subscriptions: volume = data.loc[index]['volume:{}'.format(i.name)] price = data.loc[index]['close:{}'.format(i.name)] if volume == 0: continue o = Order(volume=volume, price=price, side=Side.BUY, instrument=i, exchange=self.exchange()) o.timestamp = index.to_pydatetime() t = Trade(volume=volume, price=price, taker_order=o, maker_orders=[]) yield Event(type=EventType.TRADE, target=t) await asyncio.sleep(0) while self._queued_orders: order = self._queued_orders.popleft() order.timestamp = index t = Trade(volume=order.volume, price=order.price, taker_order=order, maker_orders=[]) t.my_order = order yield Event(type=EventType.TRADE, target=t) await asyncio.sleep(0)