Установка переменных для ответов API Interactive Brokers в Python
У меня есть некоторый код, где я запрашиваю рыночные данные в реальном времени для фьючерсного контракта, используя API Interactive Brokers и Python, в данном случае VIX-контракт. Я получаю обратно поток данных, который печатается через исправленные обертки. Это использует настоящий API Python от 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 с другим tickerId. В этом случае lastprice может храниться в коллекции (например, в словаре, который использует tickerId в качестве ключа).
Цель 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))