3 分钟快速生成代码
输入想法,AI 即刻生成可运行代码
在量化交易中,“回测是上帝,实盘是地狱”。当您的策略在聚宽(JoinQuant)上跑出异常高的收益时,绝大多数情况下并非发现了“圣杯”,而是触发了某种回测陷阱。以下是系统排查和修正策略的四大步骤:
未来函数是指在回测历史的某一时刻,使用了该时刻之后(未来)才发生的数据。这是导致回测收益虚高的最常见原因。
排查与解决方法:
initialize 中加入以下代码。开启后,若策略在运行中尝试获取当前逻辑时间(context.current_dt)之后的数据,系统会直接抛出 FutureDataError 异常。def initialize(context):
# 开启避免未来数据模式
set_option("avoid_future_data", True)
get_price / get_bars:检查 end_date 或 end_dt 是否传入了大于 context.current_dt 的值。如果不设限制,默认可能会取到当天的收盘价,而在开盘时使用收盘价交易即引入了未来函数。get_fundamentals:查询财务数据时,若传入 statDate(如指定季度 2023q1),由于上市公司财报披露存在滞后性,直接在季度结束日获取该数据会引入未来函数。建议使用 date 参数,系统会自动查找该日期前已发布的最新财报。get_call_auction:集合竞价数据在当日 9:28 之前无法获取,若在 9:00 运行的函数中调用并据此交易,即为未来函数。传统的“前复权”回测模式会使用未来的复权因子对历史价格进行调整,这在回测中会引入隐蔽的未来函数,导致买入数量和价格不真实。
排查与解决方法:
initialize 中调用 set_option('use_real_price', True)。开启后:
def initialize(context):
# 强烈建议开启真实价格(动态复权)模式
set_option('use_real_price', True)
history 等 API 拿到的仍是基于当天日期的前复权价格,但不同日期看到的前复权价格不同。切勿跨日期缓存 API 返回的价格数据。如果您的策略只在当前存活的股票池(如当前的沪深300成分股)中进行历史回测,就会漏掉历史上已经退市或被 ST 的股票,从而产生严重的“幸存者偏差”。
排查与解决方法:
# 获取历史特定日期的指数成分股,避免幸存者偏差
stocks = get_index_stocks('000300.XSHG', date=context.current_dt)
get_current_data() 检查标的是否停牌或被 ST,实盘中停牌股是无法交易的:current_data = get_current_data()
if current_data[security].paused or current_data[security].is_st:
# 停牌或ST股不操作
return
回测中默认的成交极其理想,而实盘中由于冲击成本、盘口深度不足,会产生明显的滑点和手续费,高频调仓策略若不设置合理的摩擦,回测收益会严重失真。
排查与解决方法:
PriceRelatedSlippage(0.00246)。对于小市值或流动性差的股票,应调高滑点:# 设置股票固定滑点,买入加0.01元,卖出减0.01元
set_slippage(FixedSlippage(0.02), type='stock')
# 设定成交量比例,单笔成交量不超过本日真实成交量的 25%
set_option('order_volume_ratio', 0.25)
set_order_cost(OrderCost(close_tax=0.001, open_commission=0.0003, close_commission=0.0003, min_commission=5), type='stock')
通过以上四个步骤的系统排查,您可以挤掉回测中的“虚胖”水分,获得一个真正具备实盘指导意义的量化策略净值曲线。