def trade_pre_cancel(contract=None, order: IBOrder = None) -> Trade: contract = contract or IBTestStubs.contract_details("AAPL").contract order = order or IBExecTestStubs.ib_order() return Trade( contract=contract, order=order, orderStatus=OrderStatus( orderId=41, status="PreSubmitted", filled=0.0, remaining=1.0, avgFillPrice=0.0, permId=189868420, parentId=0, lastFillPrice=0.0, clientId=1, whyHeld="", mktCapPrice=0.0, ), fills=[], log=[ TradeLogEntry( time=datetime.datetime( 2022, 3, 6, 2, 17, 18, 455087, tzinfo=datetime.timezone.utc ), status="PendingCancel", message="", errorCode=0, ) ], )
def fill_trade(trade: Trade, exec_id: int, date: pd.datetime, price: float) -> Trade: quantity = trade.order.totalQuantity execution = Execution(execId=exec_id, time=date, acctNumber='', exchange=trade.contract.exchange, side=trade.order.action, shares=quantity, price=price, permId=trade.order.permId, orderId=trade.order.orderId, cumQty=quantity, avgPrice=price, lastLiquidity=quantity) commission = CommissionReport() fill = Fill(time=date, contract=trade.contract, execution=execution, commissionReport=commission) trade.fills.append(fill) trade.orderStatus = OrderStatus(status=OrderStatus.Filled, filled=quantity, remaining=0, avgFillPrice=price, lastFillPrice=price) trade.log.append(TradeLogEntry(time=date, status=trade.orderStatus, message=f'Fill @{price}')) return trade
def trade_pending_submit(contract=None, order: IBOrder = None) -> Trade: contract = contract or IBTestStubs.contract_details("AAPL").contract order = order or IBExecTestStubs.ib_order() return Trade( contract=contract, order=order, orderStatus=OrderStatus( orderId=41, status="PendingSubmit", filled=0.0, remaining=0.0, avgFillPrice=0.0, permId=0, parentId=0, lastFillPrice=0.0, clientId=0, whyHeld="", mktCapPrice=0.0, ), fills=[], log=[ TradeLogEntry( time=datetime.datetime( 2022, 3, 5, 3, 6, 23, 492613, tzinfo=datetime.timezone.utc ), status="PendingSubmit", message="", errorCode=0, ), ], )
def placeOrder(self, contract: Contract, order: Order) -> Trade: orderId = order.orderId or next(self.id) now = self.market.date trade = self.market.get_trade(order) if trade: # this is a modification of an existing order assert trade.orderStatus.status not in OrderStatus.DoneStates logEntry = TradeLogEntry(now, trade.orderStatus.status, 'Modify') trade.log.append(logEntry) trade.modifyEvent.emit(trade) self.orderModifyEvent.emit(trade) else: # this is a new order assert order.totalQuantity != 0, 'Order quantity cannot be zero' order.orderId = orderId order.permId = orderId if order.parentId: # this is for bracket order implementation TODO orderStatus = OrderStatus(status=OrderStatus.PreSubmitted, remaining=order.totalQuantity) log.error('Why the f**k are we here?') else: orderStatus = OrderStatus(status=OrderStatus.Submitted, remaining=order.totalQuantity) logEntry = TradeLogEntry(now, orderStatus, '') trade = Trade(contract, order, orderStatus, [], [logEntry]) self.newOrderEvent.emit(trade) self.market.append_trade(trade) return trade
def test_cancel_order(self): # Arrange instrument = IBTestStubs.instrument("AAPL") contract_details = IBTestStubs.contract_details("AAPL") contract = contract_details.contract order = IBTestStubs.create_order() self.instrument_setup(instrument=instrument, contract_details=contract_details) self.exec_client._ib_insync_orders[ TestIdStubs.client_order_id()] = Trade(contract=contract, order=order) # Act command = TestCommandStubs.cancel_order_command( instrument_id=instrument.id) with patch.object(self.exec_client._client, "cancelOrder") as mock: self.exec_client.cancel_order(command=command) # Assert expected = { "contract": Contract( secType="STK", conId=265598, symbol="AAPL", exchange="SMART", primaryExchange="NASDAQ", currency="USD", localSymbol="AAPL", tradingClass="NMS", ), "order": LimitOrder(action="BUY", totalQuantity=100_000, lmtPrice=105.0), }
def cancel_trade(self, trade: Trade) -> None: log.debug(f'will cancel trade: {trade}') now = self.date if not trade.isDone(): newStatus = OrderStatus.Cancelled logEntry = TradeLogEntry(now, newStatus, '') trade.log.append(logEntry) trade.orderStatus.status = newStatus trade.cancelEvent.emit(trade) trade.statusEvent.emit(trade) trade.cancelledEvent.emit(trade) log.debug(f'cancelled trade: {trade}') log.debug(f'isDone: {trade.isDone()}')
def monitor(self, trade: Trade) -> bool: c = 0 while c < 5: c += 1 self._trader.ib.sleep(15) if trade.isDone(): return True else: log.debug(f'{trade.contract.localSymbol} attempt {c} to amend ' f'{trade.order.orderType}') trade.order.limitPrice = self.price(trade.order.action, trade.contract) self.trade(trade.contract, trade.order) return False
def test_update_order(self): # Arrange instrument = IBTestStubs.instrument("AAPL") contract_details = IBTestStubs.contract_details("AAPL") contract = contract_details.contract order = IBTestStubs.create_order() self.instrument_setup(instrument=instrument, contract_details=contract_details) self.exec_client._ib_insync_orders[ TestIdStubs.client_order_id()] = Trade(contract=contract, order=order) # Act command = TestCommandStubs.modify_order_command( instrument_id=instrument.id, price=Price.from_int(10), quantity=Quantity.from_str("100"), ) with patch.object(self.exec_client._client, "placeOrder") as mock: self.exec_client.modify_order(command=command) # Assert expected = { "contract": Contract( secType="STK", conId=265598, symbol="AAPL", exchange="SMART", primaryExchange="NASDAQ", currency="USD", localSymbol="AAPL", tradingClass="NMS", ), "order": LimitOrder(action="BUY", totalQuantity=100, lmtPrice=10.0), } name, args, kwargs = mock.mock_calls[0] # Can't directly compare kwargs for some reason? assert kwargs["contract"] == expected["contract"] assert kwargs["order"].action == expected["order"].action assert kwargs["order"].totalQuantity == expected["order"].totalQuantity assert kwargs["order"].lmtPrice == expected["order"].lmtPrice
def trade_canceled(contract=None, order: IBOrder = None) -> Trade: contract = contract or IBTestStubs.contract_details("AAPL").contract order = order or IBExecTestStubs.ib_order() return Trade( contract=contract, order=order, orderStatus=OrderStatus( orderId=41, status="Cancelled", filled=0.0, remaining=1.0, avgFillPrice=0.0, permId=189868420, parentId=0, lastFillPrice=0.0, clientId=1, whyHeld="", mktCapPrice=0.0, ), fills=[], log=[ TradeLogEntry( time=datetime.datetime( 2022, 3, 6, 2, 17, 18, 455087, tzinfo=datetime.timezone.utc ), status="PendingCancel", message="", errorCode=0, ), TradeLogEntry( time=datetime.datetime(2022, 3, 6, 2, 23, 2, 847, tzinfo=datetime.timezone.utc), status="Cancelled", message="Error 10148, reqId 45: OrderId 45 that needs to be cancelled cannot be cancelled, state: PendingCancel.", errorCode=10148, ), ], )
async def wait_for_fill(self, trade: ibs.Trade): while not trade.isDone(): await self.ib.updateEvent # noinspection PyUnresolvedReferences return trade.orderStatus.status == 'Filled'