【问题标题】:how to get series of requests in ibapi on python如何在python上的ibapi中获取一系列请求
【发布时间】:2018-01-29 07:01:29
【问题描述】:

我是 Python 和 ibapi 的新手,我问过盈透证券本身,他们只告诉我:

self.done 最初是在父类 EClient 中定义的 用于表示当前 API 连接“完成”。你应该 不要将其用作停止您自己构建的循环的指标。 在完成之前,您可以保持一个 API 客户端连接处于活动状态 下载了您需要的所有历史数据。如果你需要减速 请求数据的速度,可以使用其他线程控制 python,例如 sleep() 函数,在您的 循环,因此它不会发送所有合约的历史数据请求 一次。

所以我认为错误来自

self.done = True

这是我的代码

from ibapi import wrapper
from ibapi.client import EClient
from ibapi.wrapper import EWrapper
from ibapi.contract import Contract as IBcontract
from threading import Thread
import queue
import datetime
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 historicalData(self, reqId:int, bar: BarData):
    print("HistoricalData. ", reqId, " Date:", bar.date, "Open:", bar.open,
          "High:", bar.high, "Low:", bar.low, "Close:", bar.close, "Volume:", bar.volume,
          "Count:", bar.barCount, "WAP:", bar.average)
    if  all_data.iloc[reqId,7] == 0:
        all_data.iloc[reqId,7] = bar.close
    self.done = True

@iswrapper
def historicalDataEnd(self, reqId: int, start: str, end: str):
    super().historicalDataEnd(reqId, start, end)
    print("HistoricalDataEnd ", reqId, "from", start, "to", end)

@iswrapper
def historicalDataUpdate(self, reqId: int, bar: BarData):
    print("HistoricalDataUpdate. ", reqId, " Date:", bar.date, "Open:", bar.open,
          "High:", bar.high, "Low:", bar.low, "Close:", bar.close, "Volume:", bar.volume,
          "Count:", bar.barCount, "WAP:", bar.average)

def main():
    t = time()
    max_amount_per_Iter = 70 #max number per iter to save cost
    max_Iter = ceil(len(all_data)/max_amount_per_Iter)
    for i in range (0,max_Iter):
        print('====================round : ',i+1,'===============================')
        app = TestApp()
        app.connect("127.0.0.1", 7496, clientId=i)
        print("serverVersion:%s connectionTime:%s" % (app.serverVersion(),app.twsConnectionTime()))
        for j in range (0,min(max_amount_per_Iter,len(all_data)-i*max_amount_per_Iter)):
            print(j+i*70)
        app.i = j+i*max_amount_per_Iter

        contract = Contract()
        contract.symbol = all_data.iloc[app.i,0]
        contract.secType = all_data.iloc[app.i,1]
        contract.currency = all_data.iloc[app.i,3]
        contract.exchange = all_data.iloc[app.i,2]            

        app.reqHistoricalData(app.i, contract, "","1 W", "1 day", "Adjusted_Last", 1, 1, False, []) 

        app.run()

    sleep(1)
    app.disconnect()
    sleep(0.02)
    print('=========End round : ',i+1,'with time :',time() - t,'==============')

if __name__ == "__main__":
    main()

我希望看到一个建议,如何在不使用 self.done 或断开我的 TWS 的情况下传递到下一个迭代。如果我不包括 self.done 程序将在第一次 i=0,j=0 迭代时无限循环运行,没有人告诉它退出。

所以如果你不知道可以解决我的直接答案,你可以建议:

  1. 在这种情况下还有其他可以使用的流量控制吗?

  2. 或者cancelHistoricalData命令,如果它可以用于这种情况?

  3. 或者有什么方法可以在 Class 中构建 Class 并只在子类中执行 self.done = True 而不会断开我在 Class 中的 ID?

PS。我对 requestMarketData 有同样的问题

更新 V2 这是我尝试打印的一些结果

====================round :  1 ===============================
step2
serverVersion:124 connectionTime:b'20170821 22:34:09 ICT'
0
ERROR:root:ERROR -1 2104 Market data farm connection is OK:hfarm
ERROR:root:ERROR -1 2104 Market data farm connection is OK:jfarm
ERROR:root:ERROR -1 2104 Market data farm connection is OK:usfuture
ERROR:root:ERROR -1 2104 Market data farm connection is OK:eufarm
ERROR:root:ERROR -1 2104 Market data farm connection is OK:cashfarm
ERROR:root:ERROR -1 2104 Market data farm connection is OK:usfarm.us
ERROR:root:ERROR -1 2104 Market data farm connection is OK:usfarm
ERROR:root:ERROR -1 2106 HMDS data farm connection is OK:ilhmds
ERROR:root:ERROR -1 2106 HMDS data farm connection is OK:euhmds
ERROR:root:ERROR -1 2106 HMDS data farm connection is OK:fundfarm
ERROR:root:ERROR -1 2106 HMDS data farm connection is OK:ushmds
HistoricalData.  0  Date: 20170815 Open: 67.2 High: 68.24 Low: 66.99 Close: 68.02 Volume: 13268 Count: 9453 WAP: 67.8105
HistoricalData.  0  Date: 20170816 Open: 68.28 High: 68.91 Low: 67.45 Close: 68.01 Volume: 11950 Count: 9723 WAP: 68.457
HistoricalData.  0  Date: 20170817 Open: 67.8 High: 68.53 Low: 66.83 Close: 66.89 Volume: 11407 Count: 9432 WAP: 67.504
HistoricalData.  0  Date: 20170818 Open: 66.91 High: 67.25 Low: 66.57 Close: 66.78 Volume: 12091 Count: 9637 WAP: 66.8445
HistoricalData.  0  Date: 20170821 Open: 66.9 High: 66.96 Low: 66.14 Close: 66.28 Volume: 3317 Count: 2541 WAP: 66.3425
HistoricalDataEnd  0 from 20170814  22:34:14 to 20170821  22:34:14
ERROR:root:ERROR 1 504 Not connected
ERROR:root:ERROR 2 504 Not connected
ERROR:root:ERROR 3 504 Not connected
ERROR:root:ERROR 4 504 Not connected
ERROR:root:ERROR 5 504 Not connected
ERROR:root:ERROR 6 504 Not connected
ERROR:root:ERROR 7 504 Not connected
ERROR:root:ERROR 8 504 Not connected
ERROR:root:ERROR 9 504 Not connected
ERROR:root:ERROR 10 504 Not connected
ERROR:root:ERROR 11 504 Not connected
ERROR:root:ERROR 12 504 Not connected
ERROR:root:ERROR 13 504 Not connected
ERROR:root:ERROR 14 504 Not connected
ERROR:root:ERROR 15 504 Not connected
ERROR:root:ERROR 16 504 Not connected
ERROR:root:ERROR 17 504 Not connected
ERROR:root:ERROR 18 504 Not connected
ERROR:root:ERROR 19 504 Not connected
ERROR:root:ERROR 20 504 Not connected
ERROR:root:ERROR 21 504 Not connected
ERROR:root:ERROR 22 504 Not connected
ERROR:root:ERROR 23 504 Not connected
ERROR:root:ERROR 24 504 Not connected
ERROR:root:ERROR 25 504 Not connected
ERROR:root:ERROR 26 504 Not connected
ERROR:root:ERROR 27 504 Not connected
ERROR:root:ERROR 28 504 Not connected
ERROR:root:ERROR 29 504 Not connected
ERROR:root:ERROR 30 504 Not connected
ERROR:root:ERROR 31 504 Not connected
ERROR:root:ERROR 32 504 Not connected
ERROR:root:ERROR 33 504 Not connected
ERROR:root:ERROR 34 504 Not connected
ERROR:root:ERROR 35 504 Not connected
ERROR:root:ERROR 36 504 Not connected
ERROR:root:ERROR 37 504 Not connected
ERROR:root:ERROR 38 504 Not connected
ERROR:root:ERROR 39 504 Not connected
ERROR:root:ERROR 40 504 Not connected
ERROR:root:ERROR 41 504 Not connected
ERROR:root:ERROR 42 504 Not connected
ERROR:root:ERROR 43 504 Not connected
ERROR:root:ERROR 44 504 Not connected
ERROR:root:ERROR 45 504 Not connected
ERROR:root:ERROR 46 504 Not connected
ERROR:root:ERROR 47 504 Not connected
ERROR:root:ERROR 48 504 Not connected
ERROR:root:ERROR 49 504 Not connected
ERROR:root:ERROR 50 504 Not connected
ERROR:root:ERROR 51 504 Not connected
ERROR:root:ERROR 52 504 Not connected
ERROR:root:ERROR 53 504 Not connected
ERROR:root:ERROR 54 504 Not connected
ERROR:root:ERROR 55 504 Not connected
ERROR:root:ERROR 56 504 Not connected
ERROR:root:ERROR 57 504 Not connected
ERROR:root:ERROR 58 504 Not connected
ERROR:root:ERROR 59 504 Not connected
ERROR:root:ERROR 60 504 Not connected
ERROR:root:ERROR 61 504 Not connected
ERROR:root:ERROR 62 504 Not connected
ERROR:root:ERROR 63 504 Not connected
ERROR:root:ERROR 64 504 Not connected
ERROR:root:ERROR 65 504 Not connected
ERROR:root:ERROR 66 504 Not connected
ERROR:root:ERROR 67 504 Not connected
ERROR:root:ERROR 68 504 Not connected
ERROR:root:ERROR 69 504 Not connected
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
=========End round :  1 with time : 7.807971477508545 ==============
====================round :  2 ===============================
step2
ERROR:root:ERROR -1 2104 Market data farm connection is OK:hfarm
ERROR:root:ERROR -1 2104 Market data farm connection is OK:jfarm
ERROR:root:ERROR -1 2104 Market data farm connection is OK:usfuture
ERROR:root:ERROR -1 2104 Market data farm connection is OK:eufarm
ERROR:root:ERROR -1 2104 Market data farm connection is OK:cashfarm
ERROR:root:ERROR -1 2104 Market data farm connection is OK:usfarm.us
ERROR:root:ERROR -1 2104 Market data farm connection is OK:usfarm
ERROR:root:ERROR -1 2106 HMDS data farm connection is OK:ilhmds
ERROR:root:ERROR -1 2106 HMDS data farm connection is OK:euhmds
ERROR:root:ERROR -1 2106 HMDS data farm connection is OK:fundfarm
ERROR:root:ERROR -1 2106 HMDS data farm connection is OK:ushmds
serverVersion:124 connectionTime:b'20170821 22:34:17 ICT'
70
HistoricalData.  70  Date: 20170815 Open: 117.23 High: 117.62 Low: 116.58 Close: 117.43 Volume: 7232 Count: 6205 WAP: 117.1295
HistoricalData.  70  Date: 20170816 Open: 117.49 High: 119.59 Low: 117.03 Close: 119.25 Volume: 16468 Count: 11498 WAP: 118.8035
HistoricalData.  70  Date: 20170817 Open: 119.19 High: 119.48 Low: 116.46 Close: 116.47 Volume: 12285 Count: 10072 WAP: 117.4645
HistoricalData.  70  Date: 20170818 Open: 116.0 High: 117.84 Low: 115.46 Close: 116.88 Volume: 14917 Count: 10824 WAP: 116.9795
HistoricalData.  70  Date: 20170821 Open: 116.85 High: 117.4 Low: 116.15 Close: 116.77 Volume: 3471 Count: 2599 WAP: 116.5535
HistoricalDataEnd  70 from 20170814  22:34:19 to 20170821  22:34:19
ERROR:root:ERROR 71 504 Not connected
ERROR:root:ERROR 72 504 Not connected

【问题讨论】:

  • 你能告诉我到底是什么问题吗?我看到你想下载历史数据,但你没有告诉你出了什么问题。你没拿到数据吗?还是出错了?您也可以分享您发送给 IB 的问题。我无法从答案中弄清楚。
  • 我已经添加了结果。谢谢你的建议!
  • 您是否正确缩进了这个示例代码?
  • 我认为 self.done=true 会断开客户端的连接。如果您只是注释掉该行,您的输出是什么?我预计起搏违规错误。
  • 是的,Janos 我只是评论那行,抱歉我的英语不好。

标签: python wrapper quantitative-finance interactive-brokers


【解决方案1】:

非常感谢 Janos 真正帮助我改变了这一点,它的工作!

谢谢你的想法,我会改进的

由于您的代码有一些错误,所以我使它可以运行。

from ibapi import wrapper
from ibapi.client import EClient
from ibapi.wrapper import EWrapper
from ibapi.contract import Contract as IBcontract
from threading import Thread
import queue
import datetime
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 historicalData(self, reqId:int, bar: BarData):
        print("HistoricalData. ", reqId, " Date:", bar.date, "Open:", bar.open,
              "High:", bar.high, "Low:", bar.low, "Close:", bar.close, "Volume:", bar.volume,
          "Count:", bar.barCount, "WAP:", bar.average)
        if  all_data.iloc[reqId,7] == 0:
            all_data.iloc[reqId,7] = bar.close
    # the line below is not necessary
    #self.done = True

    @iswrapper
    def historicalDataEnd(self, reqId: int, start: str, end: str):
        super().historicalDataEnd(reqId, start, end)
        print("HistoricalDataEnd ", reqId, "from", start, "to", end)
        print('=========End round : ',self.i+1,'with time :',time() - self.t,'==============')

        self.i = self.i+1
        if self.i==len(all_data):
            self.disconnect() # Disconnect here: get out of app.run() when all data processed
        else:
        # add some sleep here if necessary
            reqNext(self.i,self)


    @iswrapper
    def historicalDataUpdate(self, reqId: int, bar: BarData):
        print("HistoricalDataUpdate. ", reqId, " Date:", bar.date, "Open:", bar.open,
              "High:", bar.high, "Low:", bar.low, "Close:", bar.close, "Volume:", bar.volume,
              "Count:", bar.barCount, "WAP:", bar.average)


def reqNext(i,app):
        print('====================round : ',i+1,'===============================')
        contract = Contract()
        contract.symbol = all_data.iloc[i,0]
        contract.secType = all_data.iloc[i,1]
        contract.currency = all_data.iloc[i,3]
        contract.exchange = all_data.iloc[i,2]
        app.reqHistoricalData(i, contract, "","1 W", "1 day", "Adjusted_Last", 1, 1, False, []) 


def main():
    app = TestApp()
    app.connect("127.0.0.1", 7496, clientId=1234)
    print("serverVersion:%s connectionTime:%s" % (app.serverVersion(),app.twsConnectionTime()))
    app.i = 0
    app.t = time()
    reqNext(app.i,app)
    app.run()
    # when we arrive here, app is disconnected already


if __name__ == "__main__":
    main()

【讨论】:

  • 抱歉,我没有使用 Python。我只是展示了我的概念。
  • 不用抱歉,你帮了我很多。我是这个领域的新手,你的方法打开了我的世界,拓宽了我对 def/class 的视野,我什至不知道如何开始搜索,因为我在这近一个月的挣扎中,IOU 很重要。跨度>
【解决方案2】:

我建议在这里重新设计一下。

在您的示例中,您在获得第一个数据后立即使用 self.done=True 断开与 API 的连接。由于请求的数据以非常快的速度到达,因此您在此之前获取请求的所有数据。在您的输出中看到的结果:您获得并处理了第一个请求的所有数据,然后您发现自己断开了连接。这重复了 for i...

  1. 删除“self.done=True”行。这没有什么好处,你不想那样。

  2. 重构您的代码,使其在向 API 发送下一个请求之前等待 historyDataEnd 事件。 API 可以处理并行请求,但服务器不能容忍非常频繁的历史数据请求。如果您发送请求的速度过快,您将收到节奏违规错误。请求之间也可能需要一些 sleep()。

  3. 我假设 app.run() 等待断开连接,这就是您需要“完成”标志操作的原因。也删除该行。如果确实需要此调用来捕获消息(我不知道您的 TestApp 类及其基类),请确保在所有请求的数据到达并处理后调用 disconnect() ,实际上是在 historyDataEnd() 中。在这种情况下,在下一个循环之前需要重新连接,现在在 app.run() 调用 for j 之后丢失了...

以下是我建议的修改:

from ibapi import wrapper
from ibapi.client import EClient
from ibapi.wrapper import EWrapper
from ibapi.contract import Contract as IBcontract
from threading import Thread
import queue
import datetime
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 historicalData(self, reqId:int, bar: BarData):
    print("HistoricalData. ", reqId, " Date:", bar.date, "Open:", bar.open,
          "High:", bar.high, "Low:", bar.low, "Close:", bar.close, "Volume:", bar.volume,
          "Count:", bar.barCount, "WAP:", bar.average)
    if  all_data.iloc[reqId,7] == 0:
        all_data.iloc[reqId,7] = bar.close
    # the line below is not necessary
    #self.done = True

@iswrapper
def historicalDataEnd(self, reqId: int, start: str, end: str):
    super().historicalDataEnd(reqId, start, end)
    print("HistoricalDataEnd ", reqId, "from", start, "to", end)
    print('=========End round : ',app.i+1,'with time :',time() - app.t,'==============')

    app.i++
    if app.i==len(all_data):
        app.disconnect() # Disconnect here: get out of app.run() when all data processed
    else:
        # add some sleep here if necessary
        reqNext()


@iswrapper
def historicalDataUpdate(self, reqId: int, bar: BarData):
    print("HistoricalDataUpdate. ", reqId, " Date:", bar.date, "Open:", bar.open,
          "High:", bar.high, "Low:", bar.low, "Close:", bar.close, "Volume:", bar.volume,
          "Count:", bar.barCount, "WAP:", bar.average)


def reqNext():
    print('====================round : ',app.i+1,'===============================')
    contract = Contract()
    contract.symbol = all_data.iloc[app.i,0]
    contract.secType = all_data.iloc[app.i,1]
    contract.currency = all_data.iloc[app.i,3]
    contract.exchange = all_data.iloc[app.i,2]
    app.reqHistoricalData(app.i, contract, "","1 W", "1 day", "Adjusted_Last", 1, 1, False, []) 


def main():
    app = TestApp()
    app.connect("127.0.0.1", 7496, clientId=1234)
    print("serverVersion:%s connectionTime:%s" % (app.serverVersion(),app.twsConnectionTime()))

    app.i = 0
    app.t = time()
    reqNext()
    app.run()
    # when we arrive here, app is disconnected already


if __name__ == "__main__":
    main()

【讨论】:

  • 我已经用self.done = True 尝试过这个,它可以工作,但是它浪费了大量的时间来重新连接。这使得代码花费超过 10 分钟,这在我的模型时间范围内是不切实际的。
  • 当然,这就是我建议重组你的程序的原因。最好有 one 的 TestApp 实例,调用 connect() once,在 main() 方法中调用 reqHistoricalData() once,并在你的 historyDataEnd() 方法中再次调用它,直到你得到你需要的所有数据。
  • 非常感谢,我会试试这个
  • '-/\-' 谢谢你的想法!我对其进行了一些更改以使其可运行。 ==========在下一条评论中。
【解决方案3】:

您需要使用另一个标志来终止历史数据获取,而不是 self.done,正如 IB 所指出的那样,它是“保留的”。

如果您print x.__dict__ 其中xTestApp 的一个实例,您将看到基类已经使用的内容,并且不应被覆盖,除非您对此处显示的方法所做的那样。

此外,如果您想存储结果,而不仅仅是打印它们;最好像我在这里一样使用队列:

https://gist.github.com/robcarver17/f50aeebc2ecd084f818706d9f05c1eb4

【讨论】:

  • 是的,如果需要一个标志,它必须是另一个。但是你怎么能解释他为什么需要那个标志:“如果我不包括 self.done 程序将在无限循环中运行”。我想知道示例代码是否正确缩进...
  • Janos,我不知道它只是简单地不要停止,所以我必须像互联网上的其他示例一样将 self.done 放在。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-06-20
  • 2019-02-05
  • 1970-01-01
  • 1970-01-01
  • 2016-10-09
  • 2019-11-19
  • 1970-01-01
相关资源
最近更新 更多