Установка переменных для ответов API Interactive Brokers в Python

У меня есть код, в котором я запрашиваю рыночные данные в реальном времени для фьючерсного контракта, используя Interactive Brokers API и Python, в данном случае контракт VIX. Я получаю обратно поток данных, который печатается через пропатченные обертки. Здесь используется реальный Python API от IB, а не сторонняя библиотека.

Я хотел бы сделать два раза: во-первых, установить переменную на последнюю цену, которая имеет значение tickType 4 в ответе (13.0). Во-вторых, я хотел бы затем остановить потоковую передачу данных для текущего контракта и запросить данные для другого контракта (например, дата истечения срока действия, 20170816). В противном случае, если бы я мог одновременно запросить оба набора данных и установить для них переменную, тогда прекратить стримить, это тоже было бы потрясающе. Это код, который у меня есть до сих пор, который делает успешный запрос от IB. Предполагая, что API включен и у вас есть доступ к данным рынка фьючерсов VIX (биржа CFE), ответ будет таким:

from ibapi.wrapper import EWrapper
from ibapi.client import EClient
from ibapi.utils import iswrapper
from ibapi.common import *
from ibapi.contract import *
from ibapi.ticktype import *
# Request IB Data in less than 50 lines of code
class BasicApp(EWrapper, EClient):
  def __init__(self):
    EClient.__init__(self,self)

  def error(self, reqId: TickerId, errorCode:int, errorString:str):
    print('Error:', reqId, " ", errorCode, " ", errorString)

  @iswrapper
  def tickPrice(self, reqId: TickerId, tickType: TickType, price: float, attrib: TickAttrib):
    super().tickPrice(reqId, tickType, price, attrib)
    print("Tick Price. Ticker Id:", reqId, "tickType:", tickType, "Price:", price, "CanAutoExecute:", attrib.canAutoExecute, "PastLimit", attrib.pastLimit)

  @iswrapper
  def tickSize(self, reqId: TickerId, tickType: TickType, size: int):
    super().tickSize(reqId, tickType, size)
    print("Tick Size. Ticker Id:", reqId, "tickType:", tickType, "Size:", size)

  @iswrapper
  def tickString(self, reqId: TickerId, tickType: TickType, value: str):
    super().tickString(reqId, tickType, value)
    print("Tick string. Ticker Id:", reqId, "Type:", tickType, "Value:", value)

  @iswrapper
  def tickGeneric(self, reqId: TickerId, tickType: TickType, value: float):
    super().tickGeneric(reqId, tickType, value)
    print("Tick Generic. Ticker Id:", reqId, "tickType:", tickType, "Value:", value)

def main():
  app = BasicApp()
  app.connect("127.0.0.1", 4001, 0)
  contract = Contract();
  contract.symbol = "VIX";
  contract.secType = "FUT";
  contract.exchange = "CFE";
  contract.currency = "USD";
  contract.lastTradeDateOrContractMonth = "20170719";
  app.reqMktData(1001, contract, "", False, False, [])
  app.run()

if __name__ == '__main__':
  main()

Это обертки выше, печатающие ответ от IB:

Error: -1   2119   Market data farm is connecting:usfuture.us
Error: -1   2104   Market data farm connection is OK:usfuture.us
Tick string. Ticker Id: 1001 Type: 45 Value: 1499398651
Tick Price. Ticker Id: 1001 tickType: 4 Price: 13.0 CanAutoExecute: False PastLimit False
Tick Size. Ticker Id: 1001 tickType: 5 Size: 1
Tick Size. Ticker Id: 1001 tickType: 5 Size: 1
Tick Size. Ticker Id: 1001 tickType: 8 Size: 3072
Tick Price. Ticker Id: 1001 tickType: 6 Price: 13.15 CanAutoExecute: False PastLimit False
Tick Price. Ticker Id: 1001 tickType: 7 Price: 12.95 CanAutoExecute: False PastLimit False
Tick Price. Ticker Id: 1001 tickType: 9 Price: 13.0 CanAutoExecute: False PastLimit False
Tick Price. Ticker Id: 1001 tickType: 14 Price: 12.3 CanAutoExecute: False PastLimit False
Tick Price. Ticker Id: 1001 tickType: 1 Price: 12.95 CanAutoExecute: True PastLimit False
Tick Size. Ticker Id: 1001 tickType: 0 Size: 140
Tick Price. Ticker Id: 1001 tickType: 2 Price: 13.0 CanAutoExecute: True PastLimit False
Tick Size. Ticker Id: 1001 tickType: 3 Size: 138
Tick Size. Ticker Id: 1001 tickType: 0 Size: 140
Tick Size. Ticker Id: 1001 tickType: 3 Size: 138



Ответы (2)


Чтобы остановить потоковую передачу данных для текущего контракта, вызовите

app.cancelMktData(tickerId); 

Для tickerId используйте то же значение, что и в app.reqMktData (1001 в вашем примере).

Сохранение последней цены не должно быть проблемой. Вставлять

lastPrice = price;

в методе tickPrice.

Вы можете получать рыночные данные по нескольким инструментам параллельно, вызвав app.reqMktData с другим тикером. В этом случае lastprice может храниться в коллекции (например, в словаре, который использует тиккерId в качестве ключа).

person Janos    schedule 20.07.2017
comment
Это ты хотел узнать? - person Janos; 24.07.2017
comment
Не совсем, потому что тогда следующая цена, которую я назначу, заменит последнюю цену. По сути, я хотел бы, чтобы последняя цена нескольких контрактов сохранялась как переменная одновременно. - person Jeremy; 27.07.2017
comment
Используйте словарь: lastPrice[tickerId]=price; - person Janos; 28.07.2017
comment
Есть ли способ получить цену вне функции tickPrice? Как внутри def main():? - person Jeremy; 01.08.2017
comment
Нет, всю информацию вы получаете через функции интерфейса Ewrapper. Цена поступает в tickPrice. Это не должно вызвать никаких проблем, вы можете хранить информацию в коллекции, которая видна везде. - person Janos; 03.08.2017

Цель 1: может быть достигнута с помощью приведенного ниже кода:

class BasicApp(EWrapper, EClient):
  def __init__(self):
    EClient.__init__(self,self)
    self.reqId_last_price_dict = {}  # This dictionary uses reqId as key, last price as value

  @iswrapper
  def tickPrice(self, reqId: TickerId, tickType: TickType, price: float, attrib: TickAttrib):
    super().tickPrice(reqId, tickType, price, attrib)
    print("Tick Price. Ticker Id:", reqId, "tickType:", tickType, "Price:", price, "CanAutoExecute:", attrib.canAutoExecute, "PastLimit", attrib.pastLimit)
    self.reqId_last_price_dict[reqId] = price  # This line updates the dictionary value with the same reqId whenever a new price returned.

Цель 2:
IB разрешает 3 одновременных запроса данных о рыночных тиках, если вы подписались на одну из их прямых трансляций, как в их документах ниже:

Ограничения Учитывая потенциально большой объем отправляемых данных, запросы на анализ рынка гораздо более ограничены. Как и в случае с запросами исторических данных, количество активных запросов глубины связано с количеством строк рыночных данных, минимум три и максимум 60:

Технических сложностей нет, достаточно запросить тиковые данные по 3-м контрактам одновременно с 3-мя разными reqIds. Мне также нравится инициализировать словарь для хранения информации о контракте для удобства записи данных в базу данных, но не забудьте добавить reqId и контракт в словарь перед запросом данных.

class BasicApp(EWrapper, EClient):
  def __init__(self):
    EClient.__init__(self,self)
    self.reqId_last_price_dict = {}  # This dictionary uses reqId as key, last price as value
    self.reqId_contract_dict = {}  # This dictionary uses reqId as key, contract as value

  @iswrapper
  def tickPrice(self, reqId: TickerId, tickType: TickType, price: float, attrib: TickAttrib):
    super().tickPrice(reqId, tickType, price, attrib)
    print("Tick Price. Ticker Id:", reqId, "tickType:", tickType, "Price:", price, "CanAutoExecute:", attrib.canAutoExecute, "PastLimit", attrib.pastLimit)
    self.reqId_last_price_dict[reqId] = price  # This line updates the dictionary value with the same reqId whenever a new price returned.
    print('last price for {} is {}.'.format(self.reqId_contract_dict[reqId].symbol, price))
person Rosie C    schedule 04.02.2021