回测要回答的是:一组明确定义的交易规则,在特定的一组历史观测数据上、在特定的执行模型下,会有怎样的表现。这项工作在出现第一张业绩曲线图之前就已经开始:写下一条有可能被证伪的规则,核实每一次决策时究竟有哪些价格可用,并把假设与结果放在一起。

“图表看起来很强就买入”无法被复现。“在小时收盘价完成并高于此前 20 根 K 线高点后,按下一根可用 K 线的开盘价模拟入场”则具体到足以检验。它仍然需要出场条件、市场定义、成本和基准,但另一位研究者能够判断,什么样的证据会改变这一结论。

按时间顺序划分的研究窗口按时间顺序进行的测试会切分历史数据,使未来的评估区间不参与更早参数的选取;但后续信息仍可能影响研究者的反复决策。较早的观测在此指定并估计参数留出集评估一次较晚后续复核最早时间 →留出集能减少一种形式的复用;但它无法消除反复的研究选择,也不能保证未来表现
按时间顺序进行的测试会切分历史数据,使未来的评估区间不参与更早参数的选取;但后续信息仍可能影响研究者的反复决策。 教学示意图 · 非实时市场数据
加密货币策略回测研究流程可复现的回测始于一个可证伪的问题和冻结的规则,需核查数据与时间戳,对执行与成本进行建模,在更晚的观测数据上评估,随后报告失败之处与局限。流程本身并不能消除研究者的挑选偏差。结果是否清晰,取决于产生它的那些决策问题哪些环节可能出问题?规则冻结时点数据来源 + 缺口执行成交 + 成本评估后续样本报告局限修改会让证据链重新开始 · 反复选择可能污染留出样本回测是有条件的历史研究,不是预测
可复现的回测始于一个可证伪的问题和冻结的规则,需核查数据与时间戳,对执行与成本进行建模,在更晚的观测数据上评估,随后报告失败之处与局限。流程本身并不能消除研究者的挑选偏差。 教学说明图 · 非实时市场数据

1. 冻结假设与规则

写下标的与合约、交易所或数据提供方、K 线周期、时区、入场事件、出场与失效条件、方向、数量规则、最长持仓时间和基准。说明这条规则为什么可能有效,以及出现什么样的形态会构成反证。如果收盘价很快回到原区间内,突破可能失败;如果价格持续偏离均值,均值回归规则可能失败。

为每条规则保留带日期的版本。如果您测试了 20 组回看窗口与出场条件的组合,就把这 20 组全部记录下来,并说明为什么选择它们。在大规模搜索中表现最好的那一行,并不能证明该参数是事先选定的。Probability of Backtest Overfitting paper on its publisher’s page 解释了为什么反复挑选最佳候选,会让样本内结果看起来比其后续表现更有说服力。

2. 审查每根 K 线实际告诉了您什么

把数据提供方、产品、交易对、合约类型、请求的日期、获取时间、K 线周期、原始时间戳、成交量单位以及任何变换,与数据集一并保存。检查是否存在重复或缺失的区间、异常的最高价/最低价、交易对突然变更,以及获取时尚未收盘的最后一根 K 线。保留原始文件或稳定的指纹,以便复现输入。

例如,设想一根虚构的小时 K 线:开盘价 $100、最高价 $108、最低价 $97、收盘价 $105。规则要求:当已收盘的收盘价高于此前 20 根 K 线高点 $104.50 时入场。该信号只有在这根 K 线收盘时才可知。如果测试看到了这个收盘价,却按同一根 K 线的 $100 开盘价成交,那就是用更晚的信息去选择一个更早的价格。符合因果关系的 K 线模型可以使用下一根 K 线虚构的 $105.20 开盘价,同时仍应把该开盘价标注为价格代理,而非保证成交。K 线内部的止损或突破,需要足够精细的数据才能确定事件发生的先后顺序。

K线收盘信号只能在更晚的可成交时点建模虚构的12:00至13:00 K线穿过此前20根K线的最高价104.50,收于105。该信号在13:00才已知晓;图中13:00开盘价105.20是更晚的模型价格。若以12:00的开盘价100成交,就过早使用了已完成K线所包含的信息。核查信号何时已知 · 虚构小时K线此前区间20根K线最高价 · $104.50仅限更早的已完成K线12:00–13:00 UTC K线开 $100 · 高 $108 · 低 $97收盘价 $10513:00 时交叉已可确认后续模型价格13:00 开盘 · $105.20假设的开仓价代理值以 12:00 开盘价成交会过早使用随后的收盘价所有价格均为虚构 · OHLC 无法揭示 K线内的队列排队位置,也不保证成交
虚构的12:00至13:00 K线穿过此前20根K线的最高价104.50,收于105。该信号在13:00才已知晓;图中13:00开盘价105.20是更晚的模型价格。若以12:00的开盘价100成交,就过早使用了已完成K线所包含的信息。 教学说明图 · 非实时市场数据

Binance Spot 当前的 API 参考文档列出了 GET /api/v3/klines,并定义了开盘与收盘时间戳以及 OHLC 和成交量字段。应把这些字段视为需要保留的数据提供方事实,然后判断每根 K 线在您的获取时间点是否已经完整。来自单一交易所的数据并不自动等同于全市场历史,现货 K 线也不能替代永续合约。Binance Spot Kline documentation。

3. 把每一项实质性成本都记入台账

对入场与出场手续费、买卖价差、不利滑点、相关的借币成本或资金费率,以及交易所的数量与价格最小变动单位进行建模。说明手续费假设对应的是哪一账户等级和订单角色。对于永续合约,要把每个仓位与其持仓窗口内实际发生的资金费率结算对应起来,使用这些结算的时间戳和正负号;缺失的区间仍然是未知,而不是零支付。

还要确定:当同一根 OHLC K 线同时触及止损和目标价时会发生什么。K 线数据无法说明哪一个先发生。请采用保守约定、更精细的数据,或将该结果归类为不确定。然后用更高的成本重复测试,并报告表面结果在什么情况下不再成立。单凭一个未加说明的“保守手续费”,并不能让执行模型变得贴近现实。

4. 把规则选择与后续评估分开

用较早的观测数据来构建和调优规则。在调优之前留出一段按时间顺序排列的时期,并且只针对它本应回答的那个问题使用一次。如果您查看了这段时期并修改了某个参数,就把它标记为已使用;一段被反复查看的留出数据,此时已成为研究过程的一部分。

反复划分按时间顺序排列的窗口,可以展示一个固定流程在历史数据不断增多时的表现。在前进式检验中,要定义每个边界处重新拟合什么、哪些设置保持冻结。Scikit-learn 当前的 TimeSeriesSplit 文档提供了扩展的、按时间排序的折,以及一个以样本数计的可选间隔。它还要求样本等间隔,测试折才能代表可比的时长;因此存在缺失区间的小时级加密货币数据需要明确的缺失时间处理策略。该间隔是一个行数,所以应根据您自己的标签中的结果期限和重叠情况来选择,而不是照搬默认值。TimeSeriesSplit documentation。

随时间扩展的时间顺序评估窗口与封存的最终留出集三个示例性的前向滚动折会扩展训练窗口,同时每个验证窗口向前移动。另一个更靠后的留出集在各类选择完成前始终保持封存。只有在观测间隔相等时,相同的 K线数量才代表相同的历时。随时间向前推进 · 最终检验保持封存训练 · 逐步扩展验证 · 下一窗口留出集按时间顺序 · 每项验证结果都在下一项研究选择之前记录第 1 折第 2 折第 3 折第 1–4 根 K线5–6第 1–6 根 K线7–8第 1–8 根 K线9–10第 11–12 根 K线仅在以下之后开仓一次规则选择结束然后标记为已使用仅为示意 · 折的长度应适合规则与评估问题
三个示例性的前向滚动折会扩展训练窗口,同时每个验证窗口向前移动。另一个更靠后的留出集在各类选择完成前始终保持封存。只有在观测间隔相等时,相同的 K线数量才代表相同的历时。 教学说明图 · 非实时市场数据

既要记录交易笔数,也要记录 K 线数量。报告扣除成本后的净结果、回撤路径、最长连续亏损、持仓时间占比,以及最大的几笔交易各自的贡献。如果两笔事件解释了大部分收益,这种集中度就应当写入结论。使用相同的市场、日期和资金约定与基准进行比较。

5. 在相信图表之前先质疑实现

做一次刻意不利的检查:提高成本、平移评估窗口、轻微扰动某个参数,并查看缺失或剧烈波动时期附近的逐笔交易记录。核实未来的观测数据无法改变一个本应已经固定的信号。把失败的检查和负面发现与本次运行一并保留,而不只是保留那张获胜的图表。

把确切的策略版本、数据快照、配置、成本表、基准和结果台账一起保存。一个有用的收尾问题是:“什么会让我不再相信这个结果?”在运行下一个变体之前先写下这个答案。当后续检查改变了您的看法时,请创建一个新版本,而不是改写原始记录。

在历史检验之后,模拟交易或前瞻性观察可以检验不同的问题,例如一条规则是否可以被执行,以及记录的数据是否按时到达。这些练习仍然无法验证交易所是否会按模型中的价格成交一笔实盘订单。

SuperQuant 内置的回测历史数据是合成的。其小时级研究工作流和台账有助于检查软件如何应用一条规则,但该引擎简化的执行与保证金假设,无法复现每个交易所的订单簿深度、部分成交或强平档位。在合成 K 线上可重复运行只是一次软件演练,而不是加密货币市场的实际结果。

请使用回测审计清单,然后阅读关于数据质量、成本敏感性和过拟合的指南。这是一种研究方法,不构成投资建议,也不代表对未来盈利能力的任何主张。