修改返回日期
formatDate 用来控制历史行情回调里日期字段的返回格式。它不会改变请求范围,也不会改变行情本身,只改变返回给程序的时间表示方式。
官方参考:Historical Bar Data
app.reqHistoricalData( reqId, contract, endDateTime, durationStr, barSizeSetting, whatToShow, useRTH, formatDate, # 控制返回日期格式 keepUpToDate, chartOptions,)reqHeadTimeStamp() 也有 formatDate:
app.reqHeadTimeStamp( reqId, contract, whatToShow, useRTH, formatDate, # 控制最早时间戳返回格式)formatDate | 返回形式 | 适合场景 |
|---|---|---|
1 | 可读日期字符串,例如 20260612 09:30:00 US/Eastern | 文档示例、人工检查、日志排查 |
2 | Unix 秒级时间戳,例如 1781271000 | 程序入库、统一转 UTC、跨市场处理 |
新手调试时建议先用 1,因为肉眼能看懂。等字段和时区都确认后,再考虑用 2 做系统存储层存储。
下面两个请求只有 formatDate 不同:
# 返回可读日期字符串app.reqHistoricalData( 97101, contract, "20260612 15:59:00 US/Eastern", "1 D", "1 hour", "TRADES", 1, 1, False, [],)
# 返回 Unix 秒级时间戳app.reqHistoricalData( 97102, contract, "20260612 15:59:00 US/Eastern", "1 D", "1 hour", "TRADES", 1, 2, False, [],)AAPL、1 D、1 hour、TRADES 请求的返回结果:
CONNECTED=TrueFORMAT_DATE_1_ROWS=20260612 09:30:00 US/Eastern|20260612 10:00:00 US/Eastern|20260612 11:00:00 US/EasternFORMAT_DATE_2_ROWS=1781271000|1781272800|1781276400DONE_FLAGS=97101,97102NON_INFO_ERROR_COUNT=0可以看到,两个请求对应的是同一组 K 线,只是日期字段的表达方式不同。
回调处理示例
Section titled “回调处理示例”from datetime import datetime, timezone
def historicalData(self, reqId, bar): """接收历史 K 线,并兼容两种日期格式。""" raw_date = bar.date
if str(raw_date).isdigit(): # formatDate=2:TWS 返回 Unix 秒级时间戳 bar_time = datetime.fromtimestamp(int(raw_date), tz=timezone.utc) else: # formatDate=1:TWS 返回可读字符串,建议连同原始字符串一起保存 bar_time = raw_date
print(bar_time, bar.open, bar.high, bar.low, bar.close)| 场景 | 建议 |
|---|---|
| 给新手看日志 | formatDate=1 |
| 写文档或排查日志 | formatDate=1 |
| 存数据库主时间字段 | formatDate=2 或自行转换成 UTC |
| 同时需要复盘原始 TWS 输出 | 保存 raw_date 字段 |
无论选择哪种格式,都要在项目里保持一致。最怕的是一部分数据按字符串解析,一部分数据按时间戳解析,后面回测时才发现时间轴混乱。