很多回测失败,并不是策略本身不行,而是“历史数据这一步就已经偏了”。

在加密货币市场里,这个问题会更明显:价格 24 小时连续跳动、不同交易所存在价差、成交结构高度碎片化。如果用一份不干净或者不完整的数据去做回测,本质上是在用“失真的市场”验证“真实策略”。

回测真正做的事情,其实不是验证赚钱能力,而是回答一个更基础的问题:如果策略在历史的市场结构中运行,它的行为是否稳定、是否可解释。

一、回测的本质不是赚钱模拟,而是行为重建

很多人理解回测时,会默认它是“历史赚钱测试器”,但从工程角度看,它更接近一个“市场行为重放系统”。

你需要做的不是预测收益,而是还原三件事:

  • 在某个时间点,市场真实能成交的价格范围
  • 策略在这个价格结构下会如何挂单/撤单
  • 成交是否真实发生,以及滑点如何分布

尤其在加密货币(Cryptocurrency Market)中,这三点非常关键,因为市场结构变化极快,同一策略在不同波动阶段,表现可能完全不同。

二、历史数据不是“价格序列”,而是事件序列

如果只拿 OHLC K线去做回测,其实已经丢掉了大量信息。

更接近真实市场的数据结构应该包括:

  • Tick 级成交数据(price / volume / timestamp)
  • 或至少包含高频 K线(1s / 100ms)
  • 订单簿快照(如果做做市或高频策略)

在微观结构层面,市场不是“每分钟一根K线”,而是连续发生的交易事件流。

举个简单例子:

同样是一根 1分钟上涨K线:

  • 情况A:缓慢上涨 + 持续放量
  • 情况B:前10秒暴力拉升 + 后50秒横盘

表面一样,但策略表现可能完全不同。

三、历史数据获取:决定回测上限的第一步

加密市场的数据来源很多,但差异主要不在“有没有”,而在:

  • 是否连续
  • 是否对齐时间戳
  • 是否包含真实成交结构
  • 是否支持多市场统一规范

在工程实践中,如果需要覆盖多品种(BTC、ETH、主流山寨币甚至外汇/黄金等跨资产对比),通常会用统一数据接口来降低数据拼接成本。

例如通过 AllTick 提供的历史 tick / K线数据能力,可以在同一时间轴下获取多个市场的结构化数据,用于后续策略对比与回测建模。

关键点不在“数据多”,而在“结构一致”。

四、回测系统的最小闭环结构

一个可运行的量化回测系统,通常只需要四层:

1. 数据层(Data Layer)

负责读取历史数据:

  • tick 数据
  • K线数据
  • 或 order book(如果有)

2. 策略层(Strategy Layer)

生成交易信号,例如:

  • 做市报价
  • 趋势判断
  • 均值回归

3. 撮合层(Execution Simulator)

模拟真实成交:

  • 是否成交(fill or not)
  • 滑点(slippage)
  • 手续费(fee)

4. 账户层(Portfolio Layer)

记录:

  • 持仓
  • 盈亏
  • 风险暴露

这四层的关系,本质是一个闭环:

数据驱动策略 → 策略生成行为 → 行为在市场中撮合 → 撮合影响资金状态

五、一个简单的 tick 数据回测框架(Python示意)

下面是一个非常简化的结构,用于说明回测逻辑如何串起来:

import pandas as pd

class SimpleBacktest:
    def __init__(self, data, fee=0.0005):
        self.data = data
        self.fee = fee
        self.position = 0
        self.cash = 10000
        self.entry_price = 0

    def signal(self, row):
        # 示例策略:简单动量
        if row["price"] > row["ma"]:
            return 1
        elif row["price"] < row["ma"]:
            return -1
        return 0

    def run(self):
        for _, row in self.data.iterrows():
            sig = self.signal(row)

            price = row["price"]

            # 开多
            if sig == 1 and self.position == 0:
                self.position = 1
                self.entry_price = price
                self.cash -= price * self.fee

            # 平仓
            elif sig == -1 and self.position == 1:
                pnl = price - self.entry_price
                self.cash += pnl
                self.cash -= price * self.fee
                self.position = 0

        return self.cash

这个结构虽然简单,但已经包含回测的核心逻辑:

  • 信号生成
  • 仓位变化
  • 成交成本
  • 资金更新

真实系统只是在这些基础上增加更复杂的撮合与数据精度。

六、回测最容易被忽略的三个问题

1. 滑点不是常数,而是状态变量

很多回测默认固定滑点,但在真实市场:

  • 流动性越差 → 滑点越大
  • 波动越剧烈 → 滑点越不稳定

更合理的方式是让滑点和波动率、成交量挂钩。

2. 时间对齐比价格更重要

在加密市场中,不同数据源常见问题:

  • tick 延迟
  • 时间戳乱序
  • 不同交易所时间不同步

如果时间轴错位,即使价格正确,策略行为也会完全失真。

3. 成交模拟比策略本身更重要

很多策略在“理想成交”环境下表现很好,但一旦加入:

  • 部分成交
  • 撮合延迟
  • 队列优先级

收益曲线会明显变化。

换句话说:

回测结果的可信度,很大程度取决于你如何模拟“没成交的那一部分”。

七、从单资产回测到多市场结构回测

当策略不再局限于 BTC 或 ETH,而是扩展到多资产时,回测复杂度会上升一个层级。

你会开始看到一些新的结构性问题:

  • BTC 与 ETH 的联动滞后
  • 加密市场与黄金/外汇的风险传导
  • 波动率在不同资产之间的迁移

此时回测不再只是“单策略验证”,而更像是在验证一个“市场系统模型”。

例如:

  • BTC 上涨 + ETH 滞后 → 可能存在资金轮动
  • 黄金上涨 + 美元走弱 → 宏观风险偏好变化

这些关系在回测阶段就可以被结构化验证,而不仅仅是观察收益曲线。

八、回测结果真正该看的不是收益曲线

很多人第一眼看 PnL 曲线,但更关键的指标其实是:

  • 回撤结构是否稳定
  • 不同市场阶段表现差异
  • 交易频率与滑点关系
  • 胜率是否依赖少数极端行情

一个健康的策略,不一定曲线最漂亮,但一定具备:

  • 行为稳定
  • 风险可控
  • 对市场状态变化不过度敏感

九、历史数据的价值不在“复现过去”,而在“暴露结构”

回测最终的意义,其实不是告诉你“过去能不能赚钱”,而是:

  • 策略在哪种市场结构下会失效
  • 风险在什么阶段集中爆发
  • 是否存在隐藏的依赖关系(例如流动性或波动率)

当你把历史数据从“价格记录”重新理解为“市场行为轨迹”,回测的价值才真正开始显现。