Pandas DataFrame 和系列 - IB TWS HistoricalData [英] Pandas DataFrame and Series - IB TWS HistoricalData

查看:23
本文介绍了Pandas DataFrame 和系列 - IB TWS HistoricalData的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试将 pandas 模块应用到我的代码中,以便重新组织从 IB TWS 服务器收到的消息.

I am trying to apply the pandas module to my code in order to re-organize the messages received back from IB TWS server.

代码是

from ibapi.client import EClient
from ibapi.wrapper import EWrapper
from ibapi.contract import Contract


class MyWrapper(EWrapper):

    def nextValidId(self, orderId:int):
        print("Setting nextValidOrderId: %d", orderId)
        self.nextValidOrderId = orderId
        self.start()

    def historicalData(self, reqId, bar):
        print("HistoricalData. ", reqId, "Date:", bar.date, "Open:", bar.open, "High:", bar.high, "Low:", bar.low, "Close:", bar.close, "Volume:", bar.volume, "Average:", bar.average, "Count:", bar.barCount)

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

    def error(self, reqId, errorCode, errorString):
        print("Error. Id: " , reqId, " Code: " , errorCode , " Msg: " , errorString)

    def start(self):
        queryTime = ""

        contract = Contract()
        contract.secType = "STK"
        contract.symbol = "NIO"
        contract.currency = "USD"
        contract.exchange = "SMART"

        app.reqHistoricalData(1, contract, queryTime, "1 D", "5 secs", "TRADES", 0, 1, True, [])

app = EClient(MyWrapper())
app.connect("127.0.0.1", 7496, clientId=123)
app.run()

此代码检索给定股票的历史数据,然后返回最新更新.

This code retrives historical data for a given stock, then returns the most current updates.

我面临的问题是返回的消息是这样组织的

The problem that I am facing is that the messages returned are organized as such

HistoricalDataUpdate.  1 Date: 20200708  08:31:00 Open: 14.17 High: 14.17 Low: 14.17 Close: 14.17 Volume: -1 Average: 14.15 Count: -1

虽然我试图以重新组织的方式检索数据,例如

While I am trying to retrieve the data in a re-organized manner such as

HistoricalDataUpdate.  1 Date:            Open:  High:  Low:   Close:  Volume:  Average:  Count:
                       20200708  08:31:00 14.17  14.17  14.17  14.17   -1       14.15     -1

将不胜感激.

推荐答案

回调为您提供 ibapi.common.BarData,您可以读取它的 vars 以获得像 {date:..., open:123 这样的 dict...}

The callback gives you ibapi.common.BarData which you can read it's vars to get a dict like {date:..., open:123...} etc.

Pandas 可以从一个字典列表中创建一个数据框,因此将它们存储在一个列表中

Pandas can make a dataframe from a list of dicts so store them in a list

也许您想要日期作为索引,pandas 也可以这样做,令人惊讶的是它可以读取格式.

Maybe you want date as an index, pandas can do that as well, surprisingly it can read the format.

完成后,您可以将数据保存在 csv 文件中.

You can save the data when you are done in a csv file.

from ibapi.client import EClient
from ibapi.wrapper import EWrapper
from ibapi.contract import Contract
import pandas as pd

class MyWrapper(EWrapper):
    def __init__(self):
        self.data = []
        self.df=None
        
    def nextValidId(self, orderId:int):
        print("Setting nextValidOrderId: %d", orderId)
        self.nextValidOrderId = orderId
        self.start()

    def historicalData(self, reqId, bar):
        self.data.append(vars(bar));
        
    def historicalDataUpdate(self, reqId, bar):
        line = vars(bar)
        # pop date and make it the index, add rest to df
        # will overwrite last bar at that same time
        self.df.loc[pd.to_datetime(line.pop('date'))] = line
        
    def historicalDataEnd(self, reqId: int, start: str, end: str):
        print("HistoricalDataEnd. ReqId:", reqId, "from", start, "to", end)
        self.df = pd.DataFrame(self.data)
        self.df['date'] = pd.to_datetime(self.df['date'])
        self.df.set_index('date', inplace=True)
        
    def error(self, reqId, errorCode, errorString):
        print("Error. Id: " , reqId, " Code: " , errorCode , " Msg: " , errorString)

    def start(self):
        queryTime = ""
        
        # so everyone can get data use fx
        fx = Contract()
        fx.secType = "CASH" 
        fx.symbol = "USD"
        fx.currency = "JPY"
        fx.exchange = "IDEALPRO"
        
        # setting update to 1 minute still sends an update every tick? but timestamps are 1 min
        # I don't think keepUpToDate sends a realtimeBar every 5 secs, just updates the last bar.
        app.reqHistoricalData(1, fx, queryTime, "1 D", "1 min", "MIDPOINT", 0, 1, True, [])

wrap = MyWrapper()        
app = EClient(wrap)
app.connect("127.0.0.1", 7497, clientId=123)

#I just use this in jupyter so I can interact with df
import threading
threading.Thread(target = app.run).start()

#this isn't needed in jupyter, just run another cell
import time
time.sleep(300) # in 5 minutes check the df and close

print(wrap.df)
wrap.df.to_csv("myfile.csv")#save in file
app.disconnect()

#in jupyter to show plot
%matplotlib inline 
wrap.df.close.plot()

我使用 jupyter notebook,所以我添加了线程,这样我仍然可以交互.

I use jupyter notebook so I added threading so I can still interact.

这是一些输出.接收和打印的第一个数据来自historyDataEnd.数据帧由带有日期时间索引的变量组成,因此可以按时间添加条形.

Here is some output. The first data received and printed comes from historicalDataEnd. A dataFrame gets made from the variables with a datetime index so bars can be added by time.

历史数据结束.ReqId:1 从 20200707 14:23:19 到 20200708 14:23:19

然后在 300 秒后我打印数据帧.检查 ohlc 是否合乎逻辑,并每分钟注意一个新的柱线.14:28 栏只是我假设的前 19 秒,因为我的五分钟(300 秒)从 14:23:19 开始.这正是您希望和期望保持图表最新的行为.

Then later after 300 secs I print the dataframe. Check that ohlc is logical and notice a new bar every minute. The 14:28 bar is only the first 19 seconds I assume since my five minutes (300 secs) started at 14:23:19. This is exactly the behaviour you would want and expect for keeping a chart up to date.

2020-07-08 14:24:00  107.231  107.236  107.231  107.233     -1       -1   
2020-07-08 14:25:00  107.233  107.234   107.23  107.232     -1       -1   
2020-07-08 14:26:00  107.232  107.232  107.225  107.232     -1       -1   
2020-07-08 14:27:00  107.232  107.239  107.231  107.239     -1       -1   
2020-07-08 14:28:00  107.239  107.239  107.236  107.236     -1       -1   

您可以看到它获取所有条形(仅在图形中关闭)并使其保持最新状态.

You can see that it gets all the bars (close only in graph) and keeps it up to date.

这篇关于Pandas DataFrame 和系列 - IB TWS HistoricalData的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆