问题描述
策略中 datetime.date.today()取得是编译或则回测当天的数据,比如今天编译它数据就是一直5月29日,即使回测4月1日到5月20日,每天运行中datetime.date.today()还是 5月29日,怎么避免
解决方案
在 JoinQuant(聚宽)量化平台进行策略回测时,这是一个非常常见且容易踩坑的问题。
原因分析
datetime.date.today() 和 datetime.datetime.now() 是 Python 标准库的方法,它们获取的是运行代码的服务器的系统当前真实时间。当你点击“运行回测”时,代码是在现实世界的今天(例如5月29日)执行的,因此无论你的回测区间设置在过去的哪个月份,这两个函数永远返回现实中的今天。
这会导致严重的未来函数问题或逻辑错误,因为你的策略在历史回测中使用了未来的日期。
解决方法
在 JoinQuant 策略中,必须使用平台提供的上下文对象 context 来获取回测的逻辑时间(即策略穿越回历史的那一刻的时间)。
1. 获取当前逻辑时间:context.current_dt
context.current_dt 是一个 datetime.datetime 对象,代表当前单位时间(按天回测就是当天的开盘时间,按分钟回测就是当前分钟)的开始时间。
- 获取当前日期 (等同于正确的 today):
current_date = context.current_dt.date() - 获取当前时间的字符串格式:
date_str = context.current_dt.strftime("%Y-%m-%d")
2. 获取前一个交易日:context.previous_date
如果你需要获取昨天的日期,平台直接提供了一个属性,返回的是 datetime.date 对象:
prev_date = context.previous_date
代码示例
以下是如何在策略中正确替换 datetime.date.today() 的示例:
import jqdata
import datetime
def initialize(context):
set_benchmark('000300.XSHG')
set_option('use_real_price', True)
run_daily(market_open, time='09:30')
def market_open(context):
# 错误做法:获取的是现实世界的今天
# wrong_today = datetime.date.today()
# 正确做法:获取回测逻辑中的今天
correct_today = context.current_dt.date()
# 获取回测逻辑中的昨天(上一个交易日)
yesterday = context.previous_date
log.info("当前回测逻辑日期是: %s" % correct_today)
log.info("上一个交易日是: %s" % yesterday)
# 使用正确的逻辑日期去获取数据,避免未来函数
# 例如获取某只股票在逻辑日期当天的某些信息
# ...
总结
在编写量化回测策略时,绝对不要使用 datetime.date.today() 或 datetime.datetime.now() 来决定交易逻辑或获取数据。始终依赖 context.current_dt 和 context.previous_date,这样你的策略才能在历史回测和未来的模拟/实盘交易中保持时间逻辑的一致性。