问题描述
purchase(security, cash, pindex=0)
成交价能指定到下单当日吗?
解决方案
基金申购成交价为前一天的原因解析
在量化回测或模拟交易中,如果您发现申购基金(尤其是场外基金)的成交价是前一天的价格,通常是由以下几个核心原因造成的:
1. 基金净值公布的 T+1 规则与防未来函数机制
场外基金(如开放式基金、联接基金等)的交易价格是基于T日(交易日)收盘后的基金净值。然而,在 T 日的盘中(如 09:30 - 15:00),T 日的净值尚未计算出来(通常在当晚或 T+1 日凌晨公布)。
为了严格防止未来函数(即在盘中使用了收盘后才能知道的数据),回测引擎在盘中撮合时,只能获取到最新已知的净值数据,也就是 T-1 日(前一天)的净值。因此,系统会按照前一天的价格进行撮合显示。
2. 真实价格模式(use_real_price)未开启
如果您没有在 initialize 函数中开启真实价格模式,回测引擎可能会使用基于某个基准日的复权价格,导致您看到的价格与实际净值存在时间错位或数值差异。
成交价能指定到下单当日吗?
在真实的基金交易中,只要您在 T 日 15:00 之前下单,最终的成交价一定是 T 日的净值。但在回测系统中,要模拟这一行为,您可以采取以下解决方案:
解决方案一:调整下单时间至收盘或盘后
如果您希望在回测中以 T 日的净值成交,可以尝试将下单逻辑放在接近收盘或收盘后的函数中执行。例如,在 14:50 或 after_trading_end 中进行结算逻辑的模拟,此时系统可能已经能够获取到当天的收盘数据进行撮合。
解决方案二:开启真实价格模式(强烈建议)
确保在 initialize 函数中开启了动态复权(真实价格)模式。这能保证您在回测和模拟中使用的价格逻辑最贴近真实市场:
def initialize(context):
# 开启动态复权模式(真实价格)
set_option('use_real_price', True)
解决方案三:使用 JoinQuant 标准下单 API
需要注意的是,在 JoinQuant 官方标准 API 中,买入基金通常使用 order_value 或 order_target_value,而不是 purchase。如果您使用的是 order_value,引擎会根据设定的滑点和撮合机制自动处理:
# 按金额申购基金(例如申购 10000 元的某基金)
order_value('519671.OF', 10000)
总结:回测中显示前一天的价格是引擎为了避免“未来函数”而做出的合理妥协。在实盘中,只要在 15:00 前申购,券商/基金公司会自动以当日收盘净值给您确认份额,您无需在代码层面强行指定成交价。