在 Python 中为 Interactive Brokers API 响应设置变量
Setting variables to Interactive Brokers API responses in Python
我有一些代码,我使用 Interactive Brokers API 和 Python 请求期货合约的实时市场数据,在本例中是 VIX 合约。我收到了通过修补后的包装器打印的数据流。这是使用来自 IB 的实际 Python API,而不是第三方库。
我想做两件事:首先,将变量设置为最后价格,即响应 (13.0) 中的 tickType 4。其次,我想停止当前合同的流数据并请求另一个合同的数据(例如,下一个到期日,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
要停止当前合约的流数据,请调用
app.cancelMktData(tickerId);
对于 tickerId 使用与 app.reqMktData 中相同的值(在您的示例中为 1001)。
保持最后的价格应该不是问题。插入
lastPrice = price;
在 tickPrice 方法中。
您可以通过使用不同的 tickerId 调用 app.reqMktData 来并行接收多个工具的市场数据。在这种情况下,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 个同时的市场报价数据请求,如下面的文件所示:
限制
鉴于发送的数据量可能很大,市场深度请求的限制要大得多。与历史数据请求一样,活跃深度请求的数量与行情数据线数量有关,最少3条,最多60条:
没有技术上的困难,只需要用3个不同的reqId同时请求3个合约的分时数据。
我也喜欢初始化一个字典来存放合约信息,方便写数据到数据库的时候,但是不要忘记在请求数据之前把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))
我有一些代码,我使用 Interactive Brokers API 和 Python 请求期货合约的实时市场数据,在本例中是 VIX 合约。我收到了通过修补后的包装器打印的数据流。这是使用来自 IB 的实际 Python API,而不是第三方库。
我想做两件事:首先,将变量设置为最后价格,即响应 (13.0) 中的 tickType 4。其次,我想停止当前合同的流数据并请求另一个合同的数据(例如,下一个到期日,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
要停止当前合约的流数据,请调用
app.cancelMktData(tickerId);
对于 tickerId 使用与 app.reqMktData 中相同的值(在您的示例中为 1001)。
保持最后的价格应该不是问题。插入
lastPrice = price;
在 tickPrice 方法中。
您可以通过使用不同的 tickerId 调用 app.reqMktData 来并行接收多个工具的市场数据。在这种情况下,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 个同时的市场报价数据请求,如下面的文件所示:
限制 鉴于发送的数据量可能很大,市场深度请求的限制要大得多。与历史数据请求一样,活跃深度请求的数量与行情数据线数量有关,最少3条,最多60条:
没有技术上的困难,只需要用3个不同的reqId同时请求3个合约的分时数据。 我也喜欢初始化一个字典来存放合约信息,方便写数据到数据库的时候,但是不要忘记在请求数据之前把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))