问题描述
/
解决方案
在 ptrade 量化平台中,同一个策略在回测环境和实盘交易环境中获取的交易日期不同,通常是由于日期获取函数的默认基准时间不同导致的。
问题原因解析
ptrade 提供了多个获取交易日期的 API,如 get_trading_day、get_all_trades_days 和 get_trade_days。当这些函数不传入具体的日期参数时,它们会使用默认的基准时间:
- 回测环境:默认基准时间为策略当前运行到的回测日期(即
context.blotter.current_dt)。例如,回测运行到 2020年1月5日,默认基准就是 2020年1月5日。 - 实盘/研究环境:默认基准时间为系统的当前真实日期(即今天的日期)。
因此,如果你在回测中调用 get_trading_day(-1),它返回的是回测当前日期的前一个交易日;而在实盘中调用,返回的是今天的前一个交易日。这就是导致结果不同的根本原因。
核心 API 行为对比
| API 接口 | 回测环境默认基准 | 实盘/研究环境默认基准 |
|---|---|---|
get_trading_day(day) |
回测当前日期 | 系统当前日期 |
get_all_trades_days(date=None) |
回测当前日期 | 系统当前日期 |
get_trade_days(start_date, end_date, count) |
end_date 默认为回测当前日期 |
end_date 默认为系统当前日期 |
如何保证回测和实盘的一致性?
为了保证策略在回测和实盘中逻辑一致,建议采取以下最佳实践:
1. 依赖框架的默认行为(推荐)
如果你只是想获取“策略运行当天”的前后交易日,直接使用默认参数即可。框架会自动在回测时使用回测日期,在实盘时使用真实日期,这正是量化策略所需要的“所见即所得”逻辑。
def handle_data(context, data):
# 获取前一个交易日
# 回测时:返回回测日期的前一交易日
# 实盘时:返回真实日期的前一交易日
prev_day = get_trading_day(-1)
log.info("前一交易日: %s" % prev_day)
2. 显式传入日期参数
如果你需要获取某个特定历史日期前后的交易日,请务必显式传入日期参数,而不要依赖默认值。
def handle_data(context, data):
# 明确获取 2022年1月1日 之前的所有交易日
# 无论在回测还是实盘,结果都是一致的
days = get_all_trades_days('20220101')
log.info("20220101之前的交易日: %s" % days)
3. 使用 context 获取当前策略时间
如果你需要在代码中明确知道当前策略运行到了哪一天,并基于此进行计算,可以使用 context.blotter.current_dt。这个属性在回测中代表回测时间,在实盘中代表真实时间。
def handle_data(context, data):
# 获取当前策略运行的日期
current_date = context.blotter.current_dt.strftime('%Y%m%d')
# 显式传入当前日期获取 A 股列表
# 这样写在回测和实盘中逻辑完全一致
ashares = get_Ashares(date=current_date)
log.info("%s A股数量为: %s" % (current_date, len(ashares)))
总结
理解 ptrade 中日期函数的默认基准是解决此类问题的关键。在编写策略时,明确你的需求是“相对于策略运行日”还是“相对于某个固定历史日”,并据此选择是否传入具体的日期参数,即可完美保证回测与实盘的一致性。