接收历史 K 线
历史 K 线通过回调返回,不是 reqHistoricalData() 的函数返回值。每收到一根 bar,TWS API 会调用一次 historicalData()。
def historicalData(self, reqId, bar): """接收单根历史 K 线。""" print( reqId, bar.date, bar.open, bar.high, bar.low, bar.close, bar.volume, )
def historicalDataEnd(self, reqId, start, end): """历史 K 线请求结束。""" print(f"历史 K 线结束:reqId={reqId}, start={start}, end={end}")historicalDataEnd() 很重要。没有它,程序很难知道“这次请求是不是已经返回完了”。
BarData 字段
Section titled “BarData 字段”| 字段 | 中文解释 |
|---|---|
date | K 线时间。格式受 formatDate 影响。 |
open | 开盘价。 |
high | 最高价。 |
low | 最低价。 |
close | 收盘价。 |
volume | 成交量。 |
wap | 加权平均价。Python ibapi.common.BarData 字段名是 wap。 |
barCount | 该 bar 内包含的成交笔数或数据点数量。 |
AAPL 验证样本
Section titled “AAPL 验证样本”date=20260612 09:30:00 US/Easternopen=295.9high=297.14low=294.89close=295.35volume=1472090wap=295.893barCount=10645这是一根 5 分钟 K 线,表示美股东部时间 09:30:00 开始的这 5 分钟内,AAPL 的开高低收和成交量。
日线的特殊点
Section titled “日线的特殊点”日线和更大周期的 bar 不一定像分钟线那样带完整时分秒。期货日线还可能使用交易所结算价作为收盘价,结算价有时会在交易时段结束后几个小时才更新。跨自然日的交易时段,日线日期通常以该交易时段结束的日期为准。
调试时可以直接打印。正式程序里建议整理成字典或数据库行:
bars = []
def historicalData(self, reqId, bar): """先收集原始 K 线。""" bars.append( { "reqId": reqId, "date": bar.date, "open": float(bar.open), "high": float(bar.high), "low": float(bar.low), "close": float(bar.close), "volume": int(bar.volume), "wap": float(bar.wap), "barCount": int(bar.barCount), } )保存时建议额外记录这些请求参数:
| 字段 | 为什么要保存 |
|---|---|
symbol / conId | 知道是哪一个合约。 |
durationStr | 方便复现请求窗口。 |
barSizeSetting | 知道每根 K 线周期。 |
whatToShow | 区分成交价、买卖中间价、买价、卖价等口径。 |
useRTH | 区分是否只包含常规交易时段。 |
timeZoneId | 避免跨时区回测错位。 |
如果 historicalDataEnd() 一直没到,要同时检查连接状态、错误回调和 pacing 限制。