未使用 Ibpy 的 IB API Python 示例



有人可以帮助我弄清楚如何使用IB API Python套接字进行基本请求吗? (我正在使用最新的IB API,似乎它支持Python,所以不应该需要人们过去使用的Ibpy)

我这样的代码可以简单地工作并使其连接到TWS。 问题是:我不知道如何"看到"从IB发回的消息。

from ibapi import wrapper
from ibapi.client import EClient
from ibapi.contract import *

w = wrapper.EWrapper()
myTWS = EClient(w)
myTWS.connect(host='localhost', port=7496, clientId=100)
print("serverVersion:%s connectionTime:%s" % (myTWS.serverVersion(),
myTWS.twsConnectionTime()))
myTWS.startApi()

c = Contract()
c.m_symbol = "AAPL"
c.m_secType = "STK"
c.m_exchange = "ISLAND"
c.m_currency = "USD"

myTWS.reqRealTimeBars(999, c, 5, "MIDPOINT", True, [])

我知道之前使用IBPy 就像 Register() 一样。我只是不知道如何在当前的IB原始python API中做到这一点。有人可以帮我举一个简单的例子吗?提前谢谢。

有一个新项目简化了Python TWS API的工作。

它被称为IB-insync,它允许同步和异步处理。对于TWS API的新手来说,它看起来非常棒。链接到项目页面

使用 IB 不同步请求历史数据的示例:

from ib_insync import *
ib = IB()
ib.connect('127.0.0.1', 7497, clientId=1)
contract = Forex('EURUSD')
bars = ib.reqHistoricalData(contract, endDateTime='', durationStr='30 D',
barSizeSetting='1 hour', whatToShow='MIDPOINT', useRTH=True)
# convert to pandas dataframe:
df = util.df(bars)
print(df[['date', 'open', 'high', 'low', 'close']])

你必须子类/覆盖/实现包装器。说唱歌手。 这就是您告诉EClient发送从TWS收到的数据的地方。

我从示例程序中删除了几乎所有内容,然后运行。

from ibapi import wrapper
from ibapi.client import EClient
from ibapi.utils import iswrapper #just for decorator
from ibapi.common import *
from ibapi.contract import *
from ibapi.ticktype import *
class TestApp(wrapper.EWrapper, EClient):
def __init__(self):
wrapper.EWrapper.__init__(self)
EClient.__init__(self, wrapper=self)
@iswrapper
def nextValidId(self, orderId:int):
print("setting nextValidOrderId: %d", orderId)
self.nextValidOrderId = orderId
#here is where you start using api
contract = Contract()
contract.symbol = "AAPL"
contract.secType = "STK"
contract.currency = "USD"
contract.exchange = "SMART"
self.reqMktData(1101, contract, "", False, None)
@iswrapper
def error(self, reqId:TickerId, errorCode:int, errorString:str):
print("Error. Id: " , reqId, " Code: " , errorCode , " Msg: " , errorString)
@iswrapper
def tickPrice(self, reqId: TickerId , tickType: TickType, price: float,
attrib:TickAttrib):
print("Tick Price. Ticker Id:", reqId, "tickType:", tickType, "Price:", price)
#this will disconnect and end this program because loop finishes
self.done = True
def main():
app = TestApp()
app.connect("127.0.0.1", 7496, clientId=123)
print("serverVersion:%s connectionTime:%s" % (app.serverVersion(),
app.twsConnectionTime()))
app.run()
if __name__ == "__main__":
main()

一旦你调用app.run()程序就会启动一个几乎无限的循环来读取消息,所以你需要一些其他方法来构建你的程序,因为循环必须启动。

我一直在寻找如何在应用程序对象之外处理请求序列的方法。

这是我对 Brian 代码的小修改(感谢 Brian 介绍如何使用它),它获得了两个合同详细信息,首先它请求 MSFT 的合同详细信息,然后是 IBM。

  • app.run() 在收到所有 contractDetails 消息后完成,方法是在 contractDetailsEnd() 方法中设置 app.done = True
  • 当 app.done 设置为 True 时,客户端在 EClient.run() 方法中断开连接。我没有弄清楚如何在不断开连接的情况下退出 EClient.run() 方法,所以我在 client.py EClient.run() 方法的源代码中更改了退出:

    finally:
    #self.disconnect() # Myk prevent disconnect
    return  #Myk instead of disconnect return
    
  • 之后 app.run() 完成且没有断开连接并且可以再次调用,但必须先将 app.done 设置为 False,否则 run() 方法退出
  • 最后你必须自己断开连接
  • disconnect() 方法抛出错误,但正如有人所说,您似乎可以忽略它,尤其是在代码末尾断开连接时

如果有人知道更好的方法而不更改API源代码,如果您给我建议,我会很高兴。

这是代码:

from ibapi import wrapper
from ibapi.client import EClient
from ibapi.utils import iswrapper #just for decorator
from ibapi.common import *
from ibapi.contract import *
from ibapi.ticktype import *
class TestApp(wrapper.EWrapper, EClient):
def __init__(self):
wrapper.EWrapper.__init__(self)
EClient.__init__(self, wrapper=self)
self.reqIsFinished = True
self.started = False
self.nextValidOrderId = 0
@iswrapper
def nextValidId(self, orderId:int):
print("setting nextValidOrderId: %d", orderId)
self.nextValidOrderId = orderId
# we can start now
@iswrapper
def error(self, reqId:TickerId, errorCode:int, errorString:str):
print("Error. Id: " , reqId, " Code: " , errorCode , " Msg: " ,     errorString)
@iswrapper
# ! [contractdetails]
def contractDetails(self, reqId: int, contractDetails: ContractDetails):
super().contractDetails(reqId, contractDetails)
print("ContractDetails. ReqId:", reqId, contractDetails.summary.symbol,
contractDetails.summary.secType, "ConId:", contractDetails.summary.conId,
"@", contractDetails.summary.exchange)
# ! [contractdetails]
@iswrapper
# ! [contractdetailsend]
def contractDetailsEnd(self, reqId: int):
super().contractDetailsEnd(reqId)
print("ContractDetailsEnd. ", reqId, "n")
self.done = True  # This ends the messages loop
# ! [contractdetailsend]
def main():
app = TestApp()
app.connect("127.0.0.1", 4001, clientId=123)
print("serverVersion:%s connectionTime:%s" % (app.serverVersion(),
app.twsConnectionTime()))
print('MSFT contract details:')
contract = Contract()
contract.symbol = "MSFT"
contract.secType = "STK"
contract.currency = "USD"
contract.exchange = ""
app.reqContractDetails(210, contract)
app.run()
print('IBM contract details:')
contract.symbol = "IBM"
app.done = False # must be set before next run
app.reqContractDetails(210, contract)
app.run()
app.disconnect() 
if __name__ == "__main__":
main()

这是如何使用多线程处理 API 消息的示例。app.run() 作为单独的线程启动,它正在侦听 TWS API 响应。然后,主程序发送 5 个 ContractDetails 请求,然后主程序等待响应 10 秒。TWS API消息存储在应用程序实例中,当响应准备好处理时,会发出简单的信号量信号。

这是我的第一个多线程程序,欢迎任何评论。

from ibapi import wrapper
from ibapi.client import EClient
from ibapi.utils import iswrapper #just for decorator
from ibapi.common import *
from ibapi.contract import *
from ibapi.ticktype import *
#from OrderSamples import OrderSamples
import threading
import time
class myThread (threading.Thread):
def __init__(self, app, threadID, name):
threading.Thread.__init__(self)
self.threadID = threadID
self.name = name
self.app = app
def run(self):
print ("Starting application in separate thread:", self.name,     "threadID:", self.threadID  )
self.app.run()
print ("Exiting " + self.name)
class TestApp(wrapper.EWrapper, EClient):
def __init__(self):
wrapper.EWrapper.__init__(self)
EClient.__init__(self, wrapper=self)
self.started = False
self.nextValidOrderId = 0
self.reqData = {}       # store data returned by requests
self.reqStatus = {}     # semaphore of requests - status End will indicate request is finished

@iswrapper
def nextValidId(self, orderId:int):
print("setting nextValidOrderId: %d", orderId)
self.nextValidOrderId = orderId

@iswrapper
def error(self, reqId:TickerId, errorCode:int, errorString:str):
print("Error. Id: " , reqId, " Code: " , errorCode , " Msg: " , errorString)
@iswrapper
# ! [contractdetails]
def contractDetails(self, reqId: int, contractDetails: ContractDetails):
super().contractDetails(reqId, contractDetails)
# store response in reqData dict, for each request several objects are appended into list
if not reqId in self.reqData:
self.reqData[reqId] = []
self.reqData[reqId].append(contractDetails) # put returned data into data storage dict
# ! [contractdetails]
@iswrapper
# ! [contractdetailsend]
def contractDetailsEnd(self, reqId: int):
super().contractDetailsEnd(reqId)
print("ContractDetailsEnd. ", reqId, "n")  # just info
self.reqStatus[reqId] = 'End'               # indicates the response is ready for further processing
# ! [contractdetailsend]

def main():
app = TestApp()
app.connect("127.0.0.1", 4001, clientId=123)
print("serverVersion:%s connectionTime:%s" % (app.serverVersion(),
app.twsConnectionTime()))
thread1App = myThread(app, 1, "Thread-1")  # define thread for sunning app
thread1App.start()                         # start app.run(] as infitnite loop in separate thread
print('Requesting MSFT contract details:')
contract = Contract()
contract.symbol = "MSFT"
contract.secType = "STK"
contract.currency = "USD"
contract.exchange = ""
app.reqStatus[210] = 'Sent'   # set request status to "sent to TWS"
app.reqContractDetails(210, contract)
print('Requesting IBM contract details:')
contract.symbol = "IBM"
app.reqStatus[211] = 'Sent'          
app.reqContractDetails(211, contract)
print('Requesting IBM contract details:')
contract.symbol = "GE"
app.reqStatus[212] = 'Sent'
app.reqContractDetails(212, contract)
print('Requesting IBM contract details:')
contract.symbol = "GM"
app.reqStatus[213] = 'Sent'
app.reqContractDetails(213, contract)
print('Requesting IBM contract details:')
contract.symbol = "BAC"
app.reqStatus[214] = 'Sent'
app.reqContractDetails(214, contract)
i = 0
while i < 100:         # exit loop after 10 sec (100 x time.sleep(0.1)
i = i+1
for reqId in app.reqStatus:
if app.reqStatus[reqId] == 'End':
for contractDetails in app.reqData[reqId]:
print("ContractDetails. ReqId:", reqId, contractDetails.summary.symbol,
contractDetails.summary.secType, "ConId:", contractDetails.summary.conId,
"@", contractDetails.summary.exchange)
app.reqStatus[reqId] = 'Processed'
time.sleep(0.1)
app.done = True             # this stops app.run() loop
if __name__ == "__main__":
main()

相关内容

  • 没有找到相关文章

最新更新