未使用Ibpy的ibapi Python示例

未使用Ibpy的ibapi Python示例,python,api,tws,Python,Api,Tws,有人能帮我弄清楚如何使用IB-API-pythonsocket进行基本请求吗?(我使用的是最新的ibapi,它似乎支持Python,因此不需要人们使用的Ibpy) 我这样的代码可以简单地工作并使其连接到TWS。 问题是:我不知道如何“看到”IB发回的消息 from ibapi import wrapper from ibapi.client import EClient from ibapi.contract import * w = wrapper.EWrapper() myTWS = E

有人能帮我弄清楚如何使用IB-API-pythonsocket进行基本请求吗?(我使用的是最新的ibapi,它似乎支持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中实现它。有人能帮我举个简单的例子吗?提前谢谢

您必须子类化/重写/实现wrapper.EWrapper。这就是您告诉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()
后,程序将启动一个几乎无限的循环来读取消息,因此,由于必须启动循环,因此您需要一些其他方法来构造程序。

我已经找到了如何处理app对象之外的请求序列的方法

这是我对Brian代码的一点修改(感谢Brian介绍了如何使用它),它得到了两个合同细节,首先它请求MSFT的contractdetails,然后是IBM的contractdetails

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

  • 之后,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秒。twsapi消息存储在appinstance中,当响应准备好处理时,会发出简单的信号量信号

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

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()
来自ibapi导入包装器的

从ibapi.client导入EClient
从ibapi.utils导入iswrapper#仅用于装饰器
来自ibapi.common导入*
来自ibapi.contract import*
从ibapi.ticktype导入*
#从OrderSamples导入OrderSamples
导入线程
导入时间
类myThread(threading.Thread):
def u u init u;(self、app、threadID、name):
threading.Thread.\uuuuu init\uuuuuu(自)
self.threadID=threadID
self.name=名称
self.app=app
def运行(自):
打印(“在单独的线程中启动应用程序:”,self.name,“threadID:”,self.threadID)
self.app.run()
打印(“退出”+自身名称)
类TestApp(wrapper.EWrapper,EClient):
定义初始化(自):
wrapper.EWrapper.\uuuuu init\uuuuuuu(self)
EClient.\uuuuu初始化(self,wrapper=self)
self.start=False
self.nextValidOrderId=0
self.reqData={}#存储请求返回的数据
self.reqStatus={}#请求的信号量-status End将指示请求已完成
@iswrapper
def nextValidId(self,orderId:int):
打印(“设置nextValidOrderId:%d”,订单ID)
self.nextValidOrderId=orderId
@iswrapper
def错误(self,requid:TickerId,errorCode:int,errorString:str):
打印(“Error.Id:,reqId,“Code:,errorCode,”Msg:,errorString)
@iswrapper
# ! [合约详情]
def合同详细信息(self,需求ID:int,合同详细信息:合同详细信息):
super().contractDetails(请求ID,contractDetails)
#将响应存储在reqData dict中,对于每个请求,会将多个对象追加到列表中
如果self.reqData中没有reqId:
self.reqData[reqId]=“[]
self.reqData[reqId].append(contractDetails)#将返回的数据放入数据存储目录
# ! [合约详情]
@iswrapper
# ! [合同详情发送]
def contractDetailsEnd(自身,需求ID:int):
super().contractDetailsEnd(请求ID)
打印(“ContractDetailsEnd.”,reqId,“\n”)#仅显示信息
self.reqStatus[reqId]=“End”#表示响应已准备好进行进一步处理
# ! [合同详情发送]
def main():
app=TestApp()
app.connect(“127.0.0.1”,4001,clientId=123)
打印(“服务器版本:%s连接时间:%s%”(app.serverVersion(),
app.twsConnectionTime())
thread1App=myThread(应用程序,1,“线程1”)#为sunning应用程序定义线程
thread1App.start()#启动app.run(]作为独立线程中的infitnite循环
打印('请求MSFT合同详细信息:')
合同
contract.symbol=“MSFT”
contract.secttype=“STK”
contract.currency=“USD”
contract.exchange=“”
app.reqStatus[210]=“已发送”#将请求状态设置为“已发送到TWS”
附录REQ合同详情(210,合同)
打印('请求IBM合同详细信息:')
contract.symbol=“IBM”
app.reqStatus[211]=“已发送”
附录reqContractDetails(211,合同)
打印('请求IBM合同详细信息:')
contract.symbol=“GE”
app.reqStatus[212]=“已发送”
附录reqContractDetails(212,合同)
打印('请求IBM合同详细信息:')
contract.symbol=“GM”
app.reqStatus[213]=“已发送”
附录REQ合同详情(213,合同)
打印('请求IBM合同详细信息:')
contract.symbol=“BAC”
应用程序需求状态[214]
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()
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']])