历史行情
历史行情用于一次性查询某个合约过去一段时间的数据。它和实时行情不同:实时行情是持续推送,历史行情是发出请求后返回一批结果,结束后通过回调通知本次请求完成。
历史行情最常见的用途包括:
- 拉取 K 线,用于图表、回测和策略信号计算。
- 查询某个合约最早可用历史数据时间。
- 获取历史逐笔成交或历史 bid/ask。
- 检查不同
whatToShow数据类型的返回差异。 - 理解时间格式、交易所时区和 UTC 存储口径。
| 目标 | 方法 | 主要回调 |
|---|---|---|
| 历史 K 线 | reqHistoricalData() | historicalData()、historicalDataEnd() |
| 取消历史 K 线 | cancelHistoricalData() | 无固定结束回调,通常由程序清理状态 |
| 最早可用数据点 | reqHeadTimeStamp() | headTimestamp() |
| 取消最早时间请求 | cancelHeadTimeStamp() | 无固定结束回调 |
| 历史逐笔数据 | reqHistoricalTicks() | historicalTicks()、historicalTicksBidAsk()、historicalTicksLast() |
| 直方图数据 | reqHistogramData() | histogramData() |
大多数开发者会先从 reqHistoricalData() 开始,因为它最容易理解,也最常用于图表和回测。
历史 K 线请求要点
Section titled “历史 K 线请求要点”reqHistoricalData() 的核心参数是:
| 参数 | 中文含义 | 示例 |
|---|---|---|
contract | 要查询的合约 | AAPL 股票 Contract |
endDateTime | 结束时间 | "" 表示使用 TWS 可用的最新时间 |
durationStr | 向前查询多长时间 | 1 D、1 W、1 M |
barSizeSetting | 每根 bar 的周期 | 5 mins、1 hour、1 day |
whatToShow | 数据口径 | TRADES、MIDPOINT、BID、ASK |
useRTH | 是否只要常规交易时段 | 1 常规时段,0 包含盘前盘后 |
formatDate | 返回时间格式 | 1 可读字符串,2 Unix 时间戳 |
keepUpToDate | 是否持续更新最后一根 bar | 历史回填用 False |
新手最容易错的是把 durationStr 和 barSizeSetting 组合得过大。例如请求很长时间范围的 1 秒线,容易触发历史数据限制或等待很久。应先用小范围确认字段,再扩大请求范围。
历史行情不等于完全绕过行情权限。不同产品、交易所、数据类型和账户订阅状态都会影响返回结果。
| 现象 | 常见原因 |
|---|---|
返回 200 | 合约定义不准确,或 TWS 找不到该证券定义。 |
返回 162 | 历史数据服务拒绝请求,常见于权限、范围、限频或无数据。 |
返回 10089 | API 行情需要额外订阅。 |
| 返回空数组 | 该时间范围、数据类型或产品没有可用数据。 |
| 只返回部分数据 | 请求范围过大、数据被过滤,或产品历史数据不完整。 |
如果普通模拟账户遇到权限不足,不要把示例改成假成功。文档和程序都应说明:合约能识别、连接正常,但账户缺少对应数据权限。
时间格式建议
Section titled “时间格式建议”历史行情一定要重视时区。TWS 可能返回交易所时区、操作员时区或 UTC 相关格式。正式系统建议:
- 展示给用户时,使用交易所时区或用户选择的时区。
- 写入数据库时,保存 UTC 或明确带时区的时间。
- 回测时固定
useRTH、formatDate、whatToShow,避免不同数据口径混用。
推荐学习顺序
Section titled “推荐学习顺序”- 先用
reqContractDetails()确认合约。 - 用
reqHistoricalData()请求 AAPL 这类高流动性股票的1 D + 5 mins + TRADES。 - 等
historicalDataEnd()后再处理结果。 - 对比
useRTH=1和useRTH=0。 - 再学习
whatToShow、历史逐笔、最早可用数据点和限频规则。