예제 #1
0
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
예제 #2
0
    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
예제 #3
0
    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
예제 #4
0
    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))
예제 #5
0
 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
예제 #6
0
    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
예제 #7
0
    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
예제 #8
0
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
예제 #9
0
    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)
예제 #10
0
    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)
예제 #11
0
 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
예제 #12
0
    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)