def test_update_details(): t = MixinFixture() t.version = 110 instrument = Instrument(t) instrument.symbol = 'AAPL' instrument.security_ids = {SecurityIdentifierType.ISIN: 'US0378331005'} fut = t.refresh_instrument(instrument) assert not fut.done() t.assert_message_sent(9, 8, 43, 0, 'AAPL', '', '', 0.0, '', '', '', '', '', '', '', False, 'ISIN', 'US0378331005') t.dispatch_message(["10", "1", "43", # CONTRACT_DATA "AAPL", "STK", "", "", "", "NASDAQ", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "0", ""]) assert not fut.done() assert instrument.symbol == 'AAPL' assert instrument.exchange == 'NASDAQ' t.dispatch_message(["52", "1", "43"]), # CONTRACT_DATA_END assert fut.done() assert fut.result() is instrument
def subscribe_market_depth(self, instrument: Instrument, num_rows: int): if instrument._market_depth_request_id: request_id = instrument._market_depth_request_id else: request_id, future = self.make_future() self.resolve_future(request_id, None) self.send_message( Outgoing.REQ_MKT_DEPTH, 5, request_id, # We cannot use the instrument serialization, as this specific message has different fields instrument.contract_id, instrument.symbol, instrument.security_type, instrument.contract_month or instrument.last_trade_date, instrument.strike, instrument.right, instrument.multiplier, instrument.exchange, instrument.currency, instrument.local_symbol, instrument.trading_class, num_rows, {}) # options. Undocumented self.__instruments[request_id] = instrument instrument._market_depth_request_id = request_id
def subscribe_realtime_bars( self, instrument: Instrument, what_to_show=BarType.Midpoint, regular_trading_hours=True) -> typing.Awaitable[None]: """Requests real time bars Currently, only 5 seconds bars are provided. This request is subject to the same pacing as any historical data request: no more than 60 API queries in more than 600 seconds. Real time bars subscriptions are also included in the calculation of the number of Level 1 market data subscriptions allowed in an account. """ request_id, future = self.make_future() message = OutgoingMessage(Outgoing.REQ_REAL_TIME_BARS, 3, request_id) message.add( instrument, 1, # bar size, currently ignored what_to_show, regular_trading_hours, None) # realtime bars options, undocumented self.send(message) self._realtime_bar_instruments[request_id] = instrument instrument._realtime_bars_request_id = request_id return future
def _handle_position_data(self, account_id: str, message: IncomingMessage): instrument = Instrument.get_instance_from(message) instrument.contract_id = message.read(int) instrument.symbol = message.read(str) instrument.security_type = message.read(str) instrument.last_trade_date = instrument.contract_month = message.read( datetime.date) instrument.strike = message.read(float) instrument.right = message.read(str) instrument.multiplier = message.read(int) instrument.exchange = message.read(str) instrument.currency = message.read(str) instrument.local_symbol = message.read(str) if message.message_version >= 2: instrument.trading_class = message.read(str) try: account = self.accounts[account_id] except KeyError: account = self.accounts[account_id] = Account(account_id) size = account.positions[instrument] = message.read(float) if message.message_version >= 3: average_cost = account.avg_position_cost[ instrument] = message.read(float) else: average_cost = None self.on_position(PositionEvent(account, instrument, size, average_cost))
def cancel_market_data(self, instrument: Instrument): """Cancels a RT Market Data request.""" message = OutgoingMessage( Outgoing.CANCEL_MKT_DATA, version=2, request_id=instrument._market_data_request_id) self.send(message) instrument._market_data_request_id = None
def get_market_data( self, instrument: Instrument, tick_types: typing.Iterable[TickTypeGroup] = (), snapshot=False, regulatory_snapshot=False, market_data_options: typing.Dict[str, str] = None ) -> typing.Awaitable[None]: if regulatory_snapshot: self.check_feature(ProtocolVersion.REQ_SMART_COMPONENTS, "regulatory snapshots") if snapshot: request_id, future = self.make_future() elif instrument._market_data_request_id: request_id = instrument._market_data_request_id future = asyncio.Future() else: request_id, future = self.make_future() message = OutgoingMessage(Outgoing.REQ_MKT_DATA, version=11, request_id=request_id, protocol_version=self.version) message.add(instrument) if instrument.security_type == 'BAG': raise UnsupportedFeature( "BAG orders") # We're currently missing serialization for BAG if instrument.underlying_component: message.add(True, instrument.underlying_component) else: message.add(False) # convert to integers using getattr with default. This way the en user can provide integers instead of # GenericTickType values. tick_type_ids = (getattr(tick_type, "value", tick_type) for tick_type in tick_types) message.add(','.join(str(tick_type) for tick_type in tick_type_ids)) message.add(snapshot) message.add(regulatory_snapshot, min_version=ProtocolVersion.REQ_SMART_COMPONENTS) message.add(market_data_options) self.send(message) self.__instruments[request_id] = instrument if not snapshot: instrument._market_data_request_id = request_id # subscriptions are complete as soon as the request is sent. self.resolve_future(request_id, instrument) return future
def subscribe_market_depth(self, instrument: Instrument, num_rows: int): if instrument._market_depth_request_id: request_id = instrument._market_depth_request_id else: request_id, future = self.make_future() self.resolve_future(request_id, None) self.send_message(Outgoing.REQ_MKT_DEPTH, 5, request_id, instrument, num_rows, {}) # options. Undocumented self.__instruments[request_id] = instrument instrument._market_depth_request_id = request_id
def test_get_executions(): client = MixinFixture() client.version = ProtocolVersion.MIFID_EXECUTION client.on_execution = cli_exec = MagicMock() order_fut = client.create_market_order(client.test_instrument, 1) client.fake_incoming(Incoming.ORDER_STATUS, 1, 'Submitted', 0, 1, 0, 176952797, 0, 0, 1, '', 0) client.sent = [] order = order_fut.result() order.on_execution = ord_exec = MagicMock() instrument = Instrument(client) instrument.contract_id = 265598 instrument.on_execution = inst_exec = MagicMock() fut = client.get_executions() client.assert_one_message_sent(Outgoing.REQ_EXECUTIONS, 3, 43, 0, '', '', '', '', '', '') assert not fut.done() client.fake_incoming(Incoming.EXECUTION_DATA, 43, 1, 265598, 'AAPL', 'STK', '', '0.0', '', '', 'IBKRATS', 'USD', 'AAPL', 'NMS', '0001b25e.5af587e4.01.01', '20180511 19:17:00', 'DU226959', 'IBKRATS', 'BOT', 1, '188.46', 2037003807, 0, 0, 1, '188.46', '', '', '', '', 2) assert not fut.done() assert ord_exec.call_count == 1 assert cli_exec.call_count == 1 assert inst_exec.call_count == 1 client.fake_incoming(Incoming.EXECUTION_DATA_END, 1, 43) assert fut.done() assert len(fut.result()) == 1 assert fut.result()[0].instrument is instrument
def _handle_symbol_samples(self, request_id: RequestId, num_contracts: int, message: IncomingMessage): result = [] for _ in range(num_contracts): contract = Instrument(self) contract.contract_id = message.read(int) contract.symbol = message.read(str) contract.security_type = SecurityType(message.read(str)) contract.primary_exchange = message.read(str) contract.currency = message.read(str) message.read(typing.List[str]) # derivative_security_types result.append(contract) self.resolve_future(request_id, result)
def _handle_contract_data(self, request_id: RequestId, message: IncomingMessage): contract = self._pending_contract_updates.get(request_id) if not contract: contract = self._pending_contract_updates[request_id] = Instrument(self) contract.symbol = message.read(str) contract.security_type = message.read(SecurityType) contract.last_trade_date = message.read(str) contract.strike = message.read(float) contract.right = message.read(str) contract.exchange = message.read(str) contract.currency = message.read(str) contract.local_symbol = message.read(str) contract.market_name = message.read(str) contract.trading_class = message.read(str) contract.contract_id = message.read(int) contract.minimum_tick = message.read(float) contract.market_data_size_multiplier = message.read(str, min_version=ProtocolVersion.MD_SIZE_MULTIPLIER) contract.multiplier = message.read(str) contract.order_types = message.read(str).split(',') contract.valid_exchanges = message.read(str).split(',') contract.price_magnifier = message.read(int) contract.underlying_contract_id = message.read(int) contract.long_name = message.read(str) contract.primary_exchange = message.read(str) contract.contract_month = message.read(str) contract.industry = message.read(str) contract.category = message.read(str) contract.subcategory = message.read(str) contract.time_zone = message.read(str) contract.trading_hours = message.read(str) contract.liquid_hours = message.read(str) contract.ev_rule = message.read(str) contract.ev_multiplier = message.read(str) contract.security_ids = message.read(typing.Dict[SecurityIdentifierType, str]) contract.aggregated_group = message.read(str, min_version=ProtocolVersion.AGG_GROUP) contract.underlying_symbol = message.read(str, min_version=ProtocolVersion.UNDERLYING_INFO) contract.underlying_security_type = message.read(SecurityType, min_version=ProtocolVersion.UNDERLYING_INFO) contract.market_rule_ids = message.read(str, min_version=ProtocolVersion.MARKET_RULES) contract.real_expiration_date = message.read(str, min_version=ProtocolVersion.REAL_EXPIRATION_DATE)
def unsubscribe_market_depth(self, instrument: Instrument): if instrument._market_depth_request_id: self.send_message(Outgoing.CANCEL_MKT_DEPTH, 0, instrument._market_depth_request_id) self.__instruments.pop(instrument._market_depth_request_id, None) instrument._market_depth_request_id = None
def _handle_contract_data(self, request_id: RequestId, message: IncomingMessage): # fast forward to instrument id position, so that we avoid making new contracts when existing ones can be # reused. This is required for proper event routing elsewhere instrument = self._pending_instrument_updates.get(request_id) if not instrument: message.idx += 10 instrument = Instrument.get_instance_from(message) self._pending_instrument_updates[request_id] = instrument message.idx -= 10 instrument.symbol = message.read(str) instrument.security_type = message.read(SecurityType) instrument.last_trade_date = message.read(datetime.datetime) instrument.strike = message.read(float) instrument.right = message.read(str) instrument.exchange = message.read(str) instrument.currency = message.read(str) instrument.local_symbol = message.read(str) instrument.market_name = message.read(str) instrument.trading_class = message.read(str) instrument.contract_id = message.read(int) instrument.minimum_tick = message.read(float) instrument.market_data_size_multiplier = message.read( str, min_version=ProtocolVersion.MD_SIZE_MULTIPLIER) instrument.multiplier = message.read(str) instrument.order_types = message.read(str).split(',') instrument.valid_exchanges = message.read(str).split(',') instrument.price_magnifier = message.read(int) instrument.underlying_contract_id = message.read(int) instrument.long_name = message.read(str) instrument.primary_exchange = message.read(str) instrument.contract_month = message.read(str) instrument.industry = message.read(str) instrument.category = message.read(str) instrument.subcategory = message.read(str) instrument.time_zone = message.read(str) instrument.trading_hours = message.read(str) instrument.liquid_hours = message.read(str) instrument.ev_rule = message.read(str) instrument.ev_multiplier = message.read(str) instrument.security_ids = message.read( typing.Dict[SecurityIdentifierType, str]) instrument.aggregated_group = message.read( str, min_version=ProtocolVersion.AGG_GROUP) instrument.underlying_symbol = message.read( str, min_version=ProtocolVersion.UNDERLYING_INFO) instrument.underlying_security_type = message.read( SecurityType, min_version=ProtocolVersion.UNDERLYING_INFO) instrument.market_rule_ids = message.read( str, min_version=ProtocolVersion.MARKET_RULES) instrument.real_expiration_date = message.read( datetime.datetime, min_version=ProtocolVersion.REAL_EXPIRATION_DATE) self.resolve_future(request_id, instrument)