跳转到内容

接收最早数据点

headTimestamp()reqHeadTimeStamp() 的结果回调。它只返回一行核心数据:请求编号和最早时间。

官方参考:Head Timestamp

Python API 中的回调方法在 EWrapper 里:

def headTimestamp(self, reqId: int, headTimestamp: str):
"""接收最早可用历史数据时间。"""
print("headTimestamp", reqId, headTimestamp)
字段中文解释
reqId请求时传入的编号,用来对应是哪一个合约或哪一种 whatToShow
headTimestamp最早可用时间,格式由请求参数 formatDate 决定。

formatDate=1 时,TWS 通常返回可读字符串:

HEAD=reqId=3001;name=aapl_trades_rth_string;timestamp=19801212-14:30:00

formatDate=2 时,返回 Unix 时间戳风格的数值:

HEAD=reqId=3003;name=aapl_trades_rth_unix;timestamp=345479400

这个时间可以理解为“该请求组合下的最早可用历史数据边界”。它不是行情本身,也不包含开高低收和成交量。

AAPL TRADES 的同一组参考里,formatDate=1formatDate=2 都正常返回,且没有业务错误:

HEAD_ROWS=3
HEAD=reqId=3001;name=aapl_trades_rth_string;timestamp=19801212-14:30:00
HEAD=reqId=3002;name=aapl_trades_all_string;timestamp=19801212-14:30:00
HEAD=reqId=3003;name=aapl_trades_rth_unix;timestamp=345479400
NON_INFO_ERROR_COUNT=0
from datetime import datetime, timezone
def parse_head_timestamp(value, format_date):
"""按 formatDate 解析 headTimestamp。"""
if format_date == 1:
return datetime.strptime(value, "%Y%m%d-%H:%M:%S")
if format_date == 2:
return datetime.fromtimestamp(int(value), tz=timezone.utc)
raise ValueError(f"不支持的 formatDate: {format_date}")

formatDate=1 返回的字符串没有显式时区。实际使用时,应结合请求合约、TWS 登录地区、交易所时区和后续 K 线返回格式一起处理。

步骤说明
记录 reqId 和参数知道这个时间对应哪个合约、whatToShowuseRTH
解析 headTimestampformatDate 分别处理字符串和 Unix 时间戳。
调用 cancelHeadTimeStamp(reqId)清理该请求,避免批量任务中请求状态混乱。
写入合约元数据批量回测或补数时可直接读取缓存,减少重复请求。
现象可能原因处理方式
没有收到 headTimestamp()连接断开、合约错误、权限不足或请求还没完成先检查 error() 回调和连接状态。
返回时间比预期晚很多合约上市晚、数据类型不支持更早历史、账户权限不足whatToShow 或先确认合约详情。
不同 whatToShow 起点不同成交、报价、中点价的数据来源不同每种策略用到的数据类型都单独查询。
RTH 和全时段结果不同useRTH=1 会按常规交易时段过滤回测和实盘信号保持同一口径。

收到最早时间后,不建议只存在内存里。回测系统可以把它写入合约元数据或本地缓存:

historical_meta = {
"symbol": "AAPL",
"secType": "STK",
"whatToShow": "TRADES",
"useRTH": 1,
"earliest": "19801212-14:30:00",
}

下次启动时可以先用缓存决定请求范围,再定期重新查询一次,兼顾速度和准确性。