Skip to content

9.1 回测最小模型

课前导读

本节目标

学完能解决什么困惑:回测为什么不是一张“历史赚钱截图”,而是一套从信号到资金曲线的实验流程。

适合基础:已经学完因子、选股名单、Python 与 pandas,知道 shift、收益率和交易成本的读者。

难度:intermediate

预计用时:约 40 分钟

你可以把回测想成一次“模拟考试”。

真正的模拟考试不是把答案抄在卷子上,再宣布自己满分。

它要按考试时间、题目顺序、可用资料和评分规则来做。

回测也是如此。

它不是把历史上已经涨过的股票圈出来,再截图说“如果当时买入就赚了”。

它要站在过去每一个交易日,只使用当时已经能看到的信息。

然后把信号、仓位、交易、成本和资金变化一步一步记录下来。

本节只搭最小模型。

不追求复杂系统。

先让你看清一件事:回测的核心是流程,而不是神奇按钮。


知识正文

一、先用“沙盘演练”理解回测

沙盘演练常用于训练应急决策。

桌面上摆着地图、队伍、补给和规则。

参演者不能说“如果我提前知道敌人从东边来,我就一定赢”。

他只能按当时可见的信息做决定。

交易回测也是一张投资沙盘。

历史行情是地图。

因子或技术条件是侦察信息。

仓位是你投入多少兵力。

交易规则是你怎么下达买卖指令。

交易成本是路上的油费、损耗和摩擦。

资金曲线则是整场演练结束后留下的路线图。

关键直觉

回测不是证明“过去能赚钱”,而是检查“如果严格按这套规则走,过去的资金路径会长什么样”。

二、最小回测的五个零件

最小回测不需要一开始就很大。

但它必须把五个零件接起来。

零件通俗类比在回测里回答的问题
信号老师发出的做题提示今天是否满足买入、持有或卖出条件
仓位这道题投入多少时间账户资金中有多少比例放在股票上
交易真正写到答题卡上从目标仓位变化成实际买卖动作
成本考试扣分和路费佣金、印花税、过户费、滑点等摩擦
资金曲线模拟考试成绩轨迹每个交易日结束后账户价值是多少

这五个零件缺一不可。

只有信号,没有仓位,无法知道买多少。

只有仓位,没有交易,无法知道何时从现金变成股票。

只有交易,不扣成本,结果往往过于乐观。

只有最后收益,没有资金曲线,看不到中途是否很难坚持。

三、流程图:从想法到资金曲线

下面这张图是最小模型的骨架。

它适合新手先背下来。

mermaid
flowchart TD
    A["准备历史数据"] --> B["生成交易信号"]
    B --> C["把信号延后到可交易日期"]
    C --> D["计算目标仓位"]
    D --> E["形成买卖交易"]
    E --> F["扣除成本和滑点"]
    F --> G["更新每日资金曲线"]
    G --> H["检查收益与风险"]

注意中间的“延后到可交易日期”。

这是很多新手回测最容易出错的地方。

如果你用今天收盘价计算信号,就不能假设今天收盘前已经知道结果并完成买入。

在日线入门模型中,更稳妥的做法是:今天收盘后产生信号,下一交易日再执行。

这也是 shift(1) 在 pandas 回测里经常出现的原因。

四、A 股边界:信号不等于一定成交

A 股市场有一些现实规则。

这些规则会让“纸面信号”和“实际交易”之间出现距离。

第一,普通股票买入后通常不能当天卖出。

这就是你前面学过的 T+1。

如果模型周一买入,周一盘中看到不对也不能马上卖掉这笔新买入的股票。

第二,涨跌停会限制成交。

如果模型给出买入信号,但下一天股票一字涨停,可能买不到。

如果模型给出卖出信号,但下一天股票一字跌停,可能卖不出。

第三,停牌期间不能交易。

停牌不是价格不动这么简单。

它意味着你的交易动作需要等待复牌后才可能发生。

第四,滑点会让成交价偏离你想象中的价格。

例如你以为可以按 10.00 元买入,实际成交可能是 10.03 元。

这 0.03 元看起来很小,但频繁交易时会不断累积。

风险提醒

回测里如果默认所有信号都能按理想价格成交,就会把 A 股的 T+1、涨跌停、停牌和滑点边界全部忽略,结果容易虚高。

五、一个最小 A 股案例

假设你研究一只主板股票。

你先不关心公司名称。

只用收盘价和 5 日均线做练习。

规则非常简单。

当收盘价站上 5 日均线时,次日持有 100% 仓位。

当收盘价跌破 5 日均线时,次日空仓。

这个例子不是推荐策略。

它只是用来练流程。

你需要问五个问题。

第一个问题:信号何时出现?

第二个问题:信号何时可以用于交易?

第三个问题:目标仓位是多少?

第四个问题:为了到达目标仓位,需要买入还是卖出?

第五个问题:扣完成本后,资金曲线如何变化?

六、pandas 最小示例

下面这段代码只演示思路。

它不依赖外部数据。

你可以把它当成一张小型练习表。

python
import pandas as pd

prices = pd.DataFrame(
    {
        "close": [10.00, 10.20, 10.10, 10.50, 10.80, 10.40, 10.60],
    },
    index=pd.to_datetime(
        [
            "2024-01-02",
            "2024-01-03",
            "2024-01-04",
            "2024-01-05",
            "2024-01-08",
            "2024-01-09",
            "2024-01-10",
        ]
    ),
)

prices["ma3"] = prices["close"].rolling(3).mean()
prices["signal"] = prices["close"] > prices["ma3"]
prices["position"] = prices["signal"].shift(1).fillna(False).astype(int)
prices["stock_return"] = prices["close"].pct_change().fillna(0)
prices["strategy_return_before_cost"] = prices["position"] * prices["stock_return"]
prices["trade"] = prices["position"].diff().abs().fillna(prices["position"])
prices["cost"] = prices["trade"] * 0.001
prices["strategy_return"] = prices["strategy_return_before_cost"] - prices["cost"]
prices["equity"] = (1 + prices["strategy_return"]).cumprod()

print(prices)

这里最重要的不是代码长度。

最重要的是 position = signal.shift(1)

它提醒你:今天收盘后才知道的信号,不能倒回今天去成交。

trade 表示仓位变化。

仓位从 0 变成 1,代表买入。

仓位从 1 变成 0,代表卖出。

cost 是一个简化成本。

真实 A 股还要区分买入佣金、卖出佣金、卖出印花税、过户费和滑点。

新手先把成本作为“每次换仓扣一点”来理解即可。

七、资金曲线才是回测主角

很多人喜欢盯着最终收益。

例如从 1.00 变成 1.20,就说赚了 20%。

但资金曲线会告诉你中间发生了什么。

如果它先从 1.00 跌到 0.70,再涨到 1.20,你可能很难坚持。

如果它从 1.00 稳稳涨到 1.12,虽然最终收益小一些,但过程更容易执行。

回测最小模型必须每天更新资金。

每天更新,才能看见波动、回撤和成本侵蚀。

只看起点和终点,就像只看考试总分,不看错题分布。

八、常见错误清单

新手写回测时,最常见的错误不是代码语法。

而是流程逻辑。

错误为什么危险修正思路
当天收盘信号当天成交偷看了收盘后的答案shift(1) 延后执行
不扣交易成本频繁交易会被美化至少加入简化成本
忽略涨跌停假设所有买卖都能完成对不可成交日做限制
忽略停牌把不能交易当成可交易停牌日保持原仓位
只看最终收益看不到中途压力保存每日资金曲线

这些错误会让回测像“改过答案的模拟考试”。

分数漂亮,但不能帮助你面对真实市场。

九、从老师、投资者、开发者三个角度看

从老师角度,回测是一套教学实验。

它帮助你把抽象的因子和规则变成可检查步骤。

从投资者角度,回测是一面风险镜子。

它让你提前看到这套规则可能经历怎样的亏损和等待。

从量化开发角度,回测是一条数据流水线。

每个字段都要说明来源、时间和计算方式。

这三个角度合在一起,才能避免把回测误解成“历史发财截图”。


交互实验室

练习:手工走一遍 5 日最小回测

请你把下面这张表复制到纸上或表格软件中。

目标不是算得很快。

目标是亲手感受“信号、仓位、交易、成本、资金曲线”的顺序。

日期收盘价昨日是否产生买入信号今日仓位今日是否交易简化成本今日资金
第 1 天10.00001.0000
第 2 天10.20001.0000
第 3 天10.50001.0000
第 4 天10.301买入0.0010待填
第 5 天10.6010待填

练习步骤如下。

第一步,假设第 3 天收盘后才知道“买入信号”。

第二步,因此第 4 天才把仓位从 0 调整到 1。

第三步,第 4 天买入时扣 0.0010 的简化成本。

第四步,第 5 天继续持有,资金随收盘价变化。

第五步,在表格旁边写一句话:这个回测有没有偷看未来?

如果你能把这五步讲给别人听,就已经掌握了最小回测的骨架。

可执行小任务

用你自己的 pandas 环境新建一个 DataFrame。

手动输入 7 个交易日的收盘价。

写出 signalpositiontradecostequity 五列。

然后把 shift(1) 去掉再运行一次。

比较两条资金曲线的差异。

你会直观看到:偷看未来的模型通常更漂亮,但也更不真实。


核心复盘

知识清单

  • [ ] 我知道回测不是历史赚钱截图,而是按过去可见信息进行的规则实验。
  • [ ] 我能说出最小回测的五个零件:信号、仓位、交易、成本、资金曲线。
  • [ ] 我理解为什么日线信号通常要延后一日执行,不能把收盘后才知道的信息用于当日成交。
  • [ ] 我能在 A 股语境下主动检查 T+1、涨跌停、停牌和滑点边界。
  • [ ] 我知道资金曲线比单个最终收益更能反映策略过程。

金句总结

回测的价值不是告诉你过去赚了多少钱,而是让你看见一套规则在历史沙盘里如何一步一步走过。

本文档仅供学习交流用途,不构成任何投资建议。股市有风险,入市需谨慎。