股票信号晚一天参数还有效吗:对候选做延迟压力测试
延迟压力测试问的是:已经冻结的股票候选,比基线执行政策再晚行动,会发生什么。必须把引擎原有延后和额外延迟分列。如果把原有下一期规则替换成零延迟,所谓压力情景反而可能更早成交,比较就失去意义。
本文在三个额外延迟下重放固定合成买卖信号,逐腿追踪数据末尾边界。方法是外部研究扩展,不承诺真实执行速度,也不核实CoTrading功能。全部价格虚构,费用零,研究保持单一市场和币种,不把交易日偏移等同于网络延迟模型。
捕获真正的基线时序
记录信息何时可得、策略何时发出信号、现有引擎何时允许成交。信息形成、订单释放和市场执行是不同阶段。只写“延迟一天”没有说明从哪一个时点开始算,也没有说明使用哪份交易会话日历,不能作为可复现规则。
backtesting.py官方API文档说明其默认下一根开盘市价成交及可选收盘成交设置。这里是需要检查的参考行为,并不证明CoTrading或其他引擎相同。实际研究必须核对自己所用引擎的基线,再决定额外施加什么变化。
本例基线为信号后一个合成会话,额外延迟为零、一、二,总延后就是一、二、三。额外零列复现基线,而不是取消原有延后。每个执行事件都同时保存两个字段,避免汇总时只剩一个含义不清的delay数字。
冻结候选与压力政策
候选参数应在查看压力结果之前选好,信号机会、数据快照、仓位、成本和末期政策保持固定。事先确定进出两腿是否都移位、订单是否过期,以及旧单等待时出现反向信号如何处理。不同政策是不同实验,不应在结果出来后选最有利的一种。
小样例对一股往返的买卖两腿施加相同额外延迟,没有部分成交、订单竞争、现金不足或过期。这让时序计算可检查。真实候选若存在组合资金交互,需要完整重跑订单和账户状态,不能只移动一张已实现交易利润表,然后假设原股数仍然可行。
先规定降级含义,可以是低于最低净结果、失去要求的排名,或者未匹配机会太多。这几种判定应分开。排名变化不等于收益为负;剩下的完整交易好看,也不能让候选自动通过完整性要求。本文只展示可复算的变化,不代替读者制定实际投资门槛。
建立合成机会账
索引零到七的成交及估值价格为[100,101,103,100,106,104,108,107]。A在零发买入、三发卖出;B在一买、四卖;用于测试末尾边界的C在五买、六卖。信号保持原样,不因后续价格重新生成或回选。
每腿使用成交索引=信号索引+基线延后+额外延迟,保留原信号键以匹配同一次机会。断言所有允许成交都严格晚于信号,不会在后续价格缺失时改用信号价。索引代表合成会话,真实市场应按交易日历移动,而不是直接加自然日。
| 额外延迟 | A成交索引 | A已闭合利润 | B成交索引 | B已闭合利润 |
|---|---|---|---|---|
| 0 | 1、4 | 5 | 2、5 | 1 |
| 1 | 2、5 | 1 | 3、6 | 8 |
| 2 | 3、6 | 8 | 4、7 | 1 |
基线A领先,额外一期后B领先,再多一期A又领先。虚构路径中的延迟影响并不单调,不能强行讲成越晚必然越差。测试目标是在指定情景下量化敏感性,改善的情景也应保留,不能只挑最糟或最好的一列。
逐腿记录,而不是删掉不完整交易
核心事件记录保留两个延后组件,并明确末尾越界:
fill_t = signal_t + baseline_lag + extra_lag
leg = {
'signal_t': signal_t, 'fill_t': fill_t,
'status': 'filled' if fill_t < len(prices) else 'out_of_range',
}
完整例还保存方向、价格和情景。组合两腿后,结果可能为闭合往返、末期仍持仓,或根本没有开仓,这是不同账户状态。退出缺失不能抹掉已经买入、占用资金并产生敞口的事实。即使完整往返利润不可用,已执行腿也仍然属于交付账。
匹配依据是冻结候选和信号身份,不是寻找日期附近最赚钱的一笔。多个事件同日时保留稳定序号和订单引用,避免把旧入场与另一笔退出错误配对。否则报告所谓延迟敏感性,可能实际来自机会连接错误,而不是策略时效。
不同机制反例:末尾裁剪改变了状态
C额外零期时,在索引六以一百零八买入,七以一百零七卖出,闭合利润负一。额外一期时,买入移至七、价格一百零七,计划卖出移至八,超出数据;因此账户持一股,期末未实现损益零,但没有完成往返利润。
额外两期时,入场八、退出九,两腿都越界,根本没有开仓。这与上一情景的一股开放敞口不同。脚本分别记录closed、open_at_end、no_entry,后两者的闭合利润都不可用,而不是零。
不能把C缺失的闭合结果填零,与A、B排名。若比较完整组合净值,可以按声明的期末估值政策评价开放持仓,但账户回报应与闭合交易利润分列。如果研究要求完整机会跟踪,就按冻结更新政策延长数据或报告覆盖不足,不能虚构未来退出价。
还有一个实际检查点:额外一期的C已经有买入,未来数据补全后应该承接这一股;额外两期的C没有买入,不能承接一股。恢复或续算时若只保存一个“未匹配”标签,可能把两种情景混成同一状态,因此需要股数、现金与每腿引用共同保存。
按预定规则解释降级
A在额外一期从五降至一,B从一升至八。原要求若是保持基线领先,A在该列被标记;原要求若只是非负,两者都没有触发负收益门槛。报告应写出具体规则对应的状态,而不是把所有改变都叫失败。
基线为零或负数时,百分比恶化率可能没有稳定分母。优先展示金额、敞口、完整机会数和明确门槛。不要看完结果才选延迟长度,然后称它为预先规定的压力检查;新增情景需要更新实验记录,不能偷偷加入或删除某列。
延后信号不会清除所有前视。如果指标已经用了未来价格,多等一天仍然污染。输入时点正确性与成交压力要分别检查;一个合成会话的移动,也不模拟盘中网络延迟、点差不确定性或成交保障,更不能被用来承诺实盘时效。
核验情景完整性
交接时保存原始机会总数,每个候选每个情景都必须有唯一去向,包括完整、末期持仓和未开仓。不要只对闭合交易计数,再把消失机会从分母里删掉。矩阵每格应连接到逐腿账和末期状态,检查者能确认差异来自价格、边界还是执行政策。
同时检查额外延迟零列与原基线逐腿相同。若连这列都无法复现,后面排名翻转可能来自实现偏差。增加延迟时,原有基线组件保持一,不能被覆盖。负的额外延迟不属于本文压力范围,应拒绝,避免出现提前成交却仍被命名为延迟测试的错误。
可以按原机会键再输出一张匹配表,列明各情景的入场价、出场价、闭合利润和期末股数。A同一机会在三列都闭合,因而能够直接比较五、一、八;C不能采用相同解释,其后两列分别是仍持仓和未入场。把这种可比性列出来,比只画三条利润曲线更清楚。若真实候选有多个机会,还需检查延迟是否使两个往返重叠,从而违反单仓或现金限制。发生这种交互时,应重跑账户执行,不可独立平移每个往返后直接求和。本例每个候选只有一组买卖,因此没有检验这种多机会竞争。
实际运行和更新条件
下载完整示例。使用Python 3.12或更新版本,运行python R613.py。标准库脚本输出A的[5,1,8]、B的[1,8,1]及C三种不同状态。断言检查排名翻转、时序公式、额外一期一股未平,以及额外两期两腿越界。
数据尾部延长、基线规则或压力政策改变时重新运行。说明C后来闭合是因为新增了后续观测,并保留之前被裁剪的结果。合成样例只检验时序和边界记账,不提供真实历史收益、产品支持或实际执行保障。成本、手数、资金和部分成交等简化,需要在扩展真实研究之前落实。
常见问题
额外零期就是当期成交吗?
不是。仍保留基线延后,本例为一期。
未完成往返可以填零利润吗?
不能作为闭合利润。保留开放或未开仓状态,期末估值另列。