网格策略审判:赢在哪一步
同一条网格,区间用全样本极值定 vs 用过去 250 日定——年化差 1.80 / 3.16 / 3.64 个百分点
网格策略号称"赚波动的钱""远超定投"。
这一节把它放进 P4 那台带约束的引擎里跑,只改一个地方:网格区间的上下界怎么来。
事后区间 事前区间 差
(全样本极值) (过去250日)
沪深300 指数 3.24% 1.44% +1.80 pp
sh.600000 5.02% 1.87% +3.16 pp
sh.600019 5.68% 2.04% +3.64 pp
同一条策略、同一份数据、同一套成本。唯一的改动是:区间是拿全样本的最高最低价定的,还是拿过去 250 日定的。
前者的意思是——你在 2010 年就知道了 2026 年的最低点。
很多"网格远超定投"的回测,赢在这一步,而不是赢在策略。
有人告诉你他射箭百发百中。
你去看,发现他是先射,再在箭落的地方画靶心。
网格的"区间上下界",就是那个靶心。先看完全部行情再定区间,和先画靶心再射箭,是同一件事。
一、先说清网格是什么
网格没有任何预测成分。它是一个逆势的仓位函数:价格越低,仓位越高。
把"跌一格买一格、涨一格卖一格"写成仓位形式,是同一件事的两种写法:
def make_grid(lo, hi, n=10):
"""价格 ≤ lo → 满仓;≥ hi → 空仓;中间按 n 档阶梯。"""
def f(h):
p = float(h["close"].iloc[-1])
x = (hi - p) / (hi - lo)
return float(np.clip(np.floor(np.clip(x, 0, 1) * n) / n, 0.0, 1.0))
return f
这个写法让本节的问题变得很清楚:lo 和 hi 从哪来?
网格的收益来源只有一个:标的在区间内来回震荡。它不预测方向,也不假装预测。
问题从来不在"网格有没有用",而在"区间是谁定的、什么时候定的"。
二、用全样本极值定区间(几乎人人都在犯的未来函数)
| 标的 | 策略 | 年化% | 最大回撤% | 夏普 | 成交笔数 |
|---|---|---|---|---|---|
| 沪深300 | 网格(事后区间) | 3.24 | -31.4 | 0.320 | 10 |
| 买入持有 | 2.07 | -46.5 | 0.203 | 2 | |
| 定投(仓位版) | 3.03 | -40.8 | 0.268 | 3 | |
| sh.600000 | 网格(事后区间) | 5.02 | -38.0 | 0.383 | 668 |
| 买入持有 | 4.32 | -44.8 | 0.293 | 1 | |
| 定投(仓位版) | 5.74 | -41.1 | 0.368 | 290 | |
| sh.600019 | 网格(事后区间) | 5.68 | -45.7 | 0.377 | 2727 |
| 买入持有 | 1.92 | -56.3 | 0.221 | 1 | |
| 定投(仓位版) | 5.31 | -54.2 | 0.322 | 934 |
看起来网格确实赢了——三个标的里两个跑赢买入持有,回撤也更小。
注意 sh.600000 那一组:即使用了事后区间,网格(5.02%)仍然输给定投(5.74%)。
也就是说,"远超定投"这个说法,在开了未来函数的条件下都不总是成立。
三、只改一个地方:区间换成"只用过去 250 日"
| 标的 | 区间口径 | 年化% | 最大回撤% | 夏普 | 成交笔数 |
|---|---|---|---|---|---|
| 沪深300 | 事后(全样本极值) | 3.24 | -31.4 | 0.320 | 10 |
| 事前(过去 250 日) | 1.44 | -25.8 | 0.182 | 46 | |
| 事前 ±20% 缓冲 | 1.62 | -27.7 | 0.209 | 11 | |
| → 事后减事前 | +1.80 pp | ||||
| sh.600000 | 事后 | 5.02 | -38.0 | 0.383 | 668 |
| 事前 | 1.87 | -25.9 | 0.221 | 1179 | |
| 事前 ±20% 缓冲 | 3.08 | -21.7 | 0.331 | 871 | |
| → 事后减事前 | +3.16 pp | ||||
| sh.600019 | 事后 | 5.68 | -45.7 | 0.377 | 2727 |
| 事前 | 2.04 | -33.4 | 0.205 | 2256 | |
| 事前 ±20% 缓冲 | 3.04 | -31.1 | 0.267 | 2766 | |
| → 事后减事前 | +3.64 pp |
这 1.80 ~ 3.64 个百分点,不是策略赚的,是"提前知道结果"赚的。
换成事前区间之后:
- 沪深300:网格 1.44% vs 买入持有 2.07% → 输了
- sh.600000:网格 1.87% vs 买入持有 4.32% → 大幅输了
- sh.600019:网格 2.04% vs 买入持有 1.92% → 险胜
三个标的里,只剩一个还能勉强跑赢买入持有,而且优势只有 0.12 个百分点。
有一个地方要如实说:事前网格的最大回撤确实更小(-25.8% / -25.9% / -33.4%,对比买入持有的 -46.5% / -44.8% / -56.3%)。
这是真的,而且是网格唯一站得住的优点——它和 p6.4 的定投一样,是一个降低波动、降低回撤的仓位方案,不是一个提高收益的策略。
但"降低回撤"和"远超定投"是两个完全不同的宣传语。
🔧 动手做:网格"远超定投",藏了一个未来函数(6 分钟)
网格策略常被吹"远超定投"。跑 python grid_trial.py——它先用全样本极值定网格区间(几乎人人都这么画),再只改一处:区间换成只用过去 250 日。
你会看到(实测):同一条网格,区间从"事后全样本极值"换成"事前过去 250 日",年化直接掉 1.80 / 3.16 / 3.64 个百分点。
想明白:那个"远超"的漂亮回测,是用了你当时根本不知道的未来最高最低价布网格——典型的未来函数。改成只用历史,优势大半蒸发。任何"网格神话",先问:网格区间怎么定的?用没用到未来价格?
四、成本敏感性:高换手策略绕不开的一关
按 p5.7 的纪律,任何高换手结论都要过成本这一关(事前区间口径):
| 标的 | 零成本 | 默认 2.5bp+5bp | 翻倍 5bp+10bp | 零→翻倍 |
|---|---|---|---|---|
| 沪深300 | 1.20 | 1.44 | 1.13 | -0.07 |
| sh.600000 | 2.59 | 1.87 | 1.32 | -1.27 |
| sh.600019 | 2.87 | 2.04 | 1.45 | -1.42 |
两只个股上,成本从零到翻倍吃掉 1.3~1.4 个百分点——而它们的成交笔数是 1179 和 2256 笔。
沪深300 那一行不是单调的:零成本 1.20%,默认成本反而 1.44%。
这不是算错,是路径依赖:成本改变权益 → 改变每次调仓的股数取整、以及"差额是否超过一手"的判定 → 成交路径分叉。在成交笔数很少(10~46 笔)时,这种分叉足以盖过成本本身的量级。
这也是为什么 p4.10 的单元测试里"成本单调"那一条,测的是固定策略下的同一条路径,而不是"任何策略在任何标的上都单调"。
一个在低换手样本上非单调的成本响应,不是 bug,是提醒你样本量不够。
五、判断一份网格回测是否可信,只问一句
区间上下界是哪一天定的?
如果答案里出现了回测结束之后才知道的信息——全样本最高价、最低价、历史极值分位——后面所有数字都不用看了。
这是 p1.2「未来函数」在网格上的具体形态,而且比均线类策略更隐蔽:
| 未来函数藏在哪 | |
|---|---|
| 均线策略 | 信号本身(用了今日收盘算今日信号) |
| 网格策略 | 不在信号里,在参数里——区间是拿全样本定的 |
信号层面完全干净、每一步都只用历史数据,但参数是从未来借来的。
同类问题在本课出现过两次:p5.4 的"样本内最优参数"、p5.1 的"从 16 种读法里挑最好的"。
它们的共同点是:错误不在计算,在「这个数字是什么时候知道的」。
六、那网格到底能不能用
能用,但要把它当成它本来的样子:
| 它是 | 它不是 |
|---|---|
| 一个逆势的仓位规则 | 一个预测工具 |
| 一个降低回撤的方案(实测 -25.8% vs -46.5%) | 一个提高收益的策略 |
| 依赖标的在区间内震荡的方案 | 在单边行情里也有效的方案 |
单边下跌时它会不断买入并被套满;单边上涨时它会过早卖光。这两个失效条件不是缺陷,是它的定义带来的必然结果。
📌 免责:本课为技术教学,网格与定投均为演示口径,标的按代码取样(非精选),不推荐任何策略或标的;历史模拟不构成投资建议。
四件事:
- 网格没有预测成分,它是一个逆势的仓位函数:价格越低仓位越高。收益来源只有一个——标的在区间内来回震荡
- 未来函数藏在参数里,不在信号里。同一条策略,区间从"全样本极值"换成"过去 250 日",年化差 1.80 / 3.16 / 3.64 pp;换成事前区间后,三个标的里只剩一个还能勉强跑赢买入持有(2.04% vs 1.92%,优势 0.12 pp)
- 但要如实说:事前网格的回撤确实更小(-25.8% / -25.9% / -33.4% vs 买入持有 -46.5% / -44.8% / -56.3%)。这是它唯一站得住的优点——它和定投一样是降低回撤的仓位方案,不是提高收益的策略
- 成本敏感性必须报:两只个股上零成本到翻倍吃掉 1.27 / 1.42 pp;而沪深300 那一行非单调,原因是成交笔数太少(10~46 笔)时路径分叉盖过了成本量级——非单调不是 bug,是提醒你样本量不够
一句可以直接用的追问:区间上下界是哪一天定的? 如果答案里出现了回测结束之后才知道的信息,后面所有数字都不用看了。
下一节检验另一个更精致的版本:"智能定投"——用估值或均线决定每期投多少。它比普通定投多了参数,而多参数意味着多一层过拟合风险(p5.4/p5.5)。
🔎 来源与核验· 4 条,点开核对
