简介:针对网格交易中网格大小固定导致过早满仓或空仓的痛点,这份文档系统介绍了自动调整网格大小的实用方法。内容以魔灯策略为例,结合收盘价、最高价与最低价的标准差衡量市场波动,并引入KDJ指标中的RSV值,对买入网格与卖出网格进行差异化设置。文档包含具体计算公式和示例,例如当初始网格为0.5元、RSV值为0.85时,买入网格设为0.15元、卖出网格设为0.85元,便于读者直接理解与迁移应用。资源为单个docx文档,压缩包仅165KB,适合量化投资初学者、Python股票分析开发者及希望在实战中优化网格策略的投资者。目前已吸引6360人学习浏览,文档内容源于作者实战总结,既提供了可落地的策略改进思路,也附带魔灯股票分析软件的开源项目介绍,便于进一步探索Python量化分析技术并构建自己的分析工具。
1. 网格交易不是不行,是固定网格不行
网格交易大概是散户最容易上手、也最容易在红绿 K 线里找到存在感的一类量化策略。它的逻辑朴素得不像策略:价格在某个区间里来回震荡,你按固定间隔挂买单和卖单,跌一格买一份、涨一格卖一份,不预测方向,只赚波动本身。魔灯的思路更大胆,它把网格大小从固定值改成动态值——用标准差衡量波动烈度,用 RSV 值判断当下该多买还是多卖,让网格自己适应行情。只要价格还在波动,这个策略就不会彻底空仓或满仓。对想学 Python 量化分析的初学者来说,魔灯源码是一个难得的可读性极高的实战样本;对已经跑过固定网格的熟手来说,它正好补上“网格参数固化”这块短板。
2. 固定网格为什么翻车:资金闲置与过早满仓的数学直觉
2.1 网格交易的本质:把震荡市变成可重复收割的现金流
网格交易赚的不是趋势的钱,是波动的钱。以魔灯文档里平安银行的例子为参照:股价在 7 元到 15 元之间震荡,网格大小设成 0.5 元,母仓在 11 元建仓,之后每涨 0.5 元卖出一部分,每跌 0.5 元买入一部分。表面上看,你只是在 11 元这个中枢位置两侧,每隔 0.5 元挂了一排订单,但实际上你构建的是一个“价格波动即产生现金流”的机器。
为什么说它是机器?因为每一次完整的“买入-卖出”循环,也就是价格从 11 元跌到 10.5 元触发买入,再从 10.5 元涨回 11 元触发卖出,这一来一回你就赚到了 0.5 元的差价。只要价格还在震荡,这个循环就会反复发生。09 年平安银行 11 元,19 年平安银行还是 11 元,普通持有者十年白忙,网格交易在这十年里却通过反复收割波动积累了可观收益。
这背后的数学直觉很简单:固定网格的盈利来源是“波动次数 × 网格间距”。波动次数越多、网格间距越大,单次收割利润越厚,但网格间距变大意味着价格需要走得足够远才能触发下一次交易,持有时间变长。这里存在一个平衡问题,后面会详细展开。
2.2 资金利用率低与极端行情:固定网格的两个死穴
网格交易有两个绕不开的缺陷,魔灯文档里讲得很直白。第一个是资金利用率低。假设你准备 50 万资金,网格交易通常需要留出 20 万做母仓,剩下 30 万用于下跌时补仓。价格上涨时卖出会回收现金,但这个过程是渐进的,大多数时候你的资金有一半以上是“趴着不动”的。资金利用率低,在牛市里意味着收益率被明显摊薄。
第二个缺陷更致命:网格大小是固定的,遇到极端行情容易过早满仓或过早空仓。这里的数学很直观:网格间距 0.5 元,母仓在 11 元建立,如果价格从 11 元一路跌到 9 元,你会触发(11-9)/0.5 = 4 次买入。更极端一点,价格跌到 7 元,你会触发 8 次买入。如果补仓资金只够支撑 6 次买入,第 7 次就只能看着价格继续下跌而无钱可加,更糟的是你已经满仓,账面上全是浮亏。
过早空仓的逻辑完全对称:价格上涨时每涨 0.5 元卖出一部分,价格一路涨到 15 元,你的仓位会全部卖光,后面的大行情与你无关。固定网格的问题是它假设价格始终围绕一个中枢震荡,但真实市场里趋势和震荡是交替出现的,一旦趋势走单边,固定网格就从一个机器变成了一台“给市场送钱”的机器。
这里我给一个可以马上动手验证的模拟表格。假设基准价为 11 元,网格间距 0.5 元,看看价格走到不同位置时网格被触发了多少次:
| 价格位置 | 相较基准价波动幅度 | 买入触发次数 | 卖出触发次数 | 仓位神态 |
|---|---|---|---|---|
| 9.5 元 | -1.5 元 | 3 次 | 0 次 | 补仓 3 份,仓位加重 |
| 8.0 元 | -3.0 元 | 6 次 | 0 次 | 补仓 6 份,接近满仓 |
| 7.0 元 | -4.0 元 | 8 次 | 0 次 | 补仓 8 份,若资金不足则满仓 |
| 12.5 元 | +1.5 元 | 0 次 | 3 次 | 卖出 3 份,回收现金 |
| 15.0 元 | +4.0 元 | 0 次 | 8 次 | 卖出 8 份,仓位可能空掉 |
看到规律没有?固定网格在单边行情里做不了任何主动防御,它的买入和卖出触发逻辑是对称的,价格朝哪个方向走,它就不停地朝哪个方向加码,直到仓位归零或者资金耗尽。这就是魔灯要解决的问题:能不能让网格大小跟着波动幅度走?
3. 魔灯的自适应网格算法:用标准差和 RSV 值驱动网格变形
3.1 用布林逻辑量化波动率:标准差为什么能当网格标尺
魔灯对“极端行情导致爆仓或空仓”的归因是:网格大小没有跟随股价变化自动调整。这句话本质上是说,网格的“胃口”是固定的。波动剧烈的时候,价格随便动一下就是 1 元,固定 0.5 元的网格会被瞬间击穿好几层,导致快速买入或卖出;而波动平缓的时候,0.5 元的网格可能挂一周都不成交一次。
解决办法的第一条是:网格大小与近一段时期收盘价、最高价、最低价的标准差挂钩。标准差是衡量数据离散程度的统计量,股价序列的标准差越大,说明价格分布越分散、波动越剧烈。布林线指标就是按这个逻辑构建的:中轨是移动平均线,上下轨是均线加减若干倍标准差,布林带宽度随价格波动自动收窄或扩张。
应用到网格上,逻辑就变成了:标准差的放大意味着市场波动剧烈,这时把网格调大,让策略的“胃口”变大,避免在剧烈波动中被同一方向的连续击穿打满或打空仓位。反过来,标准差缩小意味着市场趋于平静,这时把网格调小,让策略能吃进那些小幅波动。
这本质上是给网格装了一个“波动率调节器”。注意这里的标准差不是用单根 K 线算的,而是取近一段时期的收盘价、最高价和最低价分别计算,再综合成一个波动度量值。魔灯的实际实现里,通常使用过去 N 日的价格序列。N 的取值是个关键参数,后面讲避坑时专门展开。
3.2 标准差到网格间距的换算:给“胃口”一个具体数字
有了标准差,怎么换算成网格大小?这里需要说清楚,魔灯文档给出的是思路框架,并没有把整套公式锁死在某个固定系数上,这也是它留给使用者二次开发的空间。我根据文档描述给出一套可复现的核心换算逻辑,思路与文档完全一致:以标准差为基准缩放基准网格。
import numpy as np def calc_vol_grid(close_price, high_price, low_price, period=20, base_grid=0.5): """ 根据近 period 日的价格标准差,计算当前应使用的基准网格大小。 核心思想:标准差放大,网格同步放大;标准差缩小,网格同步缩小。 """ # 取近 period 日的收盘价、最高价、最低价 close_win = close_price[-period:] high_win = high_price[-period:] low_win = low_price[-period:] # 三组价格各自的标准差 std_close = np.std(close_win) std_high = np.std(high_win) std_low = np.std(low_win) # 综合波动率取三者的平均值 avg_std = (std_close + std_high + std_low) / 3.0 # 以 base_grid 为基准,按标准差缩放 # 常见做法是网格 = 基准网格 * (当前标准差 / 历史均值标准差) # 这里给出一个简化版本:标准差每达到一个基准单位,网格放大一档 grid = base_grid * (1.0 + avg_std / base_grid) return round(grid, 2)这段代码的逻辑线很清楚:先取过去 20 日的三组价格,分别求标准差,再取平均值作为当前波动率的综合度量。网格大小的计算公式是基准网格乘以「1 + 当前标准差/基准网格」的缩放因子。当标准差是基准网格的两倍时,实际网格变成三倍大;当标准差趋近于零时,网格趋近于基准网格。这个公式不是魔灯的官方代码,而是按文档思想重建的最小可复现版本,区别只在于缩放系数,核心的“标准差驱动网格大小”逻辑是忠实于原文的。
实际使用中,我一般会把 period 设为 9 或 20。9 日更灵敏,适合短线网格;20 日更平滑,适合波段网格。这个参数直接决定了网格调整的节奏,调小则反应快、噪音大,调大则反应慢、延迟明显。
3.3 买入卖出网格差异化:RSV 值告诉策略该偏向哪一侧
标准差只解决了“网格该多大”的问题,还没解决“买卖是否对称”的问题。魔灯的第二个改进是:买入网格和卖出网格大小不一样。这个想法直指一个容易被忽略的事实——上涨趋势中你希望多买少卖,下跌趋势中你希望少买多卖,但固定网格的买卖间距是对称的,根本没有趋势倾向。
用什么来判断趋势倾向?魔灯选的是 RSV 值,公式如下:
RSV = (收盘价 - 最低价) / (最高价 - 最低价)这个公式是 KDJ 指标的一部分,中文叫“未成熟随机值”。它做的事很直接:把当前收盘价放在最近一段时间的最高价和最低价之间,看它处于哪个相对位置。价格收在最高价附近,RSV 接近 1;收在最低价附近,RSV 接近 0;收在中段,RSV 接近 0.5。
魔灯在这里做了不对称设计的核心推理:当 RSV 接近 1 时,说明股价处于上涨趋势中,收盘价经常贴近最高价。这时你希望多买少卖,囤积筹码等后续拉升。反映到网格上就是买入网格变小(更容易触发买入)、卖出网格变大(更不容易触发卖出)。对称地,RSV 接近 0 时应该少买多卖,买入网格变大、卖出网格缩小。
魔灯文档给了一个计算例子,我完整重述一遍:基准网格大小为 0.5 元时,买入网格和卖出网格之和为 1 元,也就是 2 倍基准网格。当前 RSV 值为 0.85,说明处于上涨趋势。买入网格 = 1 * (1 - 0.85) = 0.15 元,卖出网格 = 1 * 0.85 = 0.85 元。股价每下跌 0.15 元就买入一部分,每上涨 0.85 元才卖出一部分。这样,在上涨趋势中,你会越买越密、越卖越稀,筹码自然越攒越多。
我把它整理成一个参数表,方便对照使用:
| RSV 值 | 趋势含义 | 买入网格(元) | 卖出网格(元) | 交易倾向 |
|---|---|---|---|---|
| 0.85 | 强上涨 | 0.15 | 0.85 | 易买难卖,囤积筹码 |
| 0.65 | 弱上涨 | 0.35 | 0.65 | 略偏买入 |
| 0.50 | 震荡 | 0.50 | 0.50 | 买卖对称(等同固定网格) |
| 0.35 | 弱下跌 | 0.65 | 0.35 | 略偏卖出 |
| 0.15 | 强下跌 | 0.85 | 0.15 | 难买易卖,回收现金 |
这个表有一个很关键的观察:买入网格和卖出网格之和恒等于 1 元。这是魔灯策略的隐藏约束,它保证了无论网格怎么变形,“一轮完整买卖”的平均利润空间不变。真正变化的是触发交易的难度——上涨时更难卖出、更容易买入,下跌时则完全反过来。这样做的好处是母仓会随价格趋势动态浮动:趋势向上时母仓越滚越大,趋势向下时母仓自动收缩,从而降低了满仓或空仓的概率。
4. 把思想翻译成 Python:魔灯核心逻辑的最小复现
4.1 数据准备与 RSV 计算
要实现魔灯的完整逻辑,第一步是准备行情数据并计算 RSV。这里用 Python 写一个完整的核心计算模块。注意下面的代码不是魔灯源码的照搬,而是根据文档描述整理出的最小可复现版本——数据结构上完全按文档公式实现,跑通后你再拿源码对照参数细节,会很容易定位到差异。
import pandas as pd import numpy as np def calc_rsv(df, period=9): """ 计算 RSV(未成熟随机值)。 RSV = (收盘价 - 最低价) / (最高价 - 最低价) """ # 用 rolling 窗口取最近 period 日的最高价和最低价 high_n = df['high'].rolling(window=period, min_periods=period).max() low_n = df['low'].rolling(window=period, min_periods=period).min() # 核心公式:收盘价在窗口内的相对位置 rsv = (df['close'] - low_n) / (high_n - low_n) return rsv这里有两个容易出错的细节。第一个是 rolling 窗口的边界处理,min_periods=period 表示前 period-1 行的 RSV 都是空值,因为数据不够。实战中我习惯在计算前用 dropna() 把前面的空行清掉,否则后面算出来的网格包含了 NaN。第二个是窗口大小 period 的选取,魔灯文档里没有固化成某个数字,但 KDJ 指标的标准参数是 9 日,这也是我推荐初学者从 9 日起步的原因。
4.2 自适应网格生成函数
有了 RSV 和标准差,接下来把它们合并进一个网格计算函数。这个函数要回答一个具体问题:在当前这个时刻,下一格买入价和下一格卖出价是多少?下面代码的核心逻辑来自魔灯文档的描述,标准差负责决定基准网格的大小,RSV 负责决定买入网格和卖出网格的分配比例。
def compute_adaptive_grids(df, base_grid=0.5, std_period=20, rsv_period=9): """ 根据标准差和 RSV 计算动态买入/卖出网格大小。 返回 DataFrame,包含:基准网格、买入网格、卖出网格、RSV。 """ # 计算标准差(近 std_period 日收盘价的波动率) df['std'] = df['close'].rolling(window=std_period).std() # 计算 RSV(近 rsv_period 日的相对强弱值) df['rsv'] = calc_rsv(df, period=rsv_period) # 基准网格 = base_grid 按标准差缩放(简化版) # 这里用 std / base_grid 作为缩放系数,std 远大于 base_grid 时网格变大 df['base_grid'] = base_grid * (1.0 + df['std'] / base_grid) # 买入卖出网格差异化:总和等于 2 倍基准网格 total_grid = df['base_grid'] * 2.0 # RSV 接近 1(上涨趋势):买入网格小,卖出网格大 df['buy_grid'] = total_grid * (1.0 - df['rsv']) df['sell_grid'] = total_grid * df['rsv'] return df.dropna()参数说明:base_grid 是初始网格大小,魔灯文档例子中取 0.5 元,对应平安银行这种价格区间在 7 到 15 元的标的;std_period 是计算标准差用的窗口,取 20 表示用最近 20 日价格波动衡量当前波动烈度;rsv_period 是 RSV 的窗口,取 9 与 KDJ 指标一致。
计算买入网格时用 (1 - rsv) 作为权重,卖出网格用 rsv 作为权重,二者的和恒等于 1,因此买入网格加卖出网格恒等于 2 倍基准网格。这个校验关系很实用,调试时可以随手打印一行buy_grid + sell_grid,如果结果不是 2 倍基准网格,说明公式哪里写错了。
实际执行时,我建议在 df 的最后一行取值作为“下一个时刻的挂单参数”。比如 df 最后一行的 buy_grid 是 0.15 元,意味着当前价格每下跌 0.15 元买入一档,sell_grid 是 0.85 元则意味着当前价格每上涨 0.85 元卖出一档。
4.3 参数刻度表:从基准网格到交易频率的换算
参数怎么定,是新手翻车最多的地方。我给一张参考刻度表,这张表以魔灯的例子为基准,覆盖不同价格区间和波动率下的参数选择逻辑:
| 标的价格区间 | 基准网格(元) | 标准差周期 | RSV 周期 | 适用行情 | 备注 |
|---|---|---|---|---|---|
| 7-15 元(平安银行类) | 0.5 | 20 | 9 | 震荡市为主 | 魔灯原例参数 |
| 100-300 元(高价股) | 2.0-3.0 | 20 | 9 | 日振幅 2% 以上 | 网格必须覆盖噪音 |
| 3-10 元(低价股) | 0.1-0.2 | 20 | 9 | 低价股波动小,网格设太小会导致手续费占比过高 | |
| 任意价格区间单边行情 | 基准网格 × 1.5 | 9 | 9 | 趋势中调大网格抗单边 | 用短周期标准差提前应变 |
这张表的逻辑是:基准网格至少要覆盖住股价的噪音波动,否则一天之内触发几十次,手续费全部吞噬收益。标准差周期在震荡市里取 20 日平滑,在趋势市里取 9 日灵敏跟踪。
5. 避坑与参数调试:我在魔灯源码复现时踩过的四个坑
5.1 固定网格的“假优势”陷阱:回测好看,实盘翻车
现象:用固定网格对平安银行的历史数据做回测,跑出来的收益曲线非常平滑,年化收益率看着很不错。但扔进实盘,遇到一段单边下跌行情,账户两天就从浮盈变浮亏,补仓资金迅速耗尽,被迫止损离场。
原因:固定网格回测平滑是幸存者偏差造成的。你选的回测区间如果没有覆盖大级别单边行情,网格的“资金耗尽风险”根本不会暴露。魔灯文档里提到的“过早满仓或空仓”,在短回测区间里是低频事件,容易被漂亮曲线掩盖。
解决:回测时必须强制加入压力测试区间。具体做法是把数据切成三段:震荡区间、上涨趋势区间、下跌趋势区间,分别回测。魔灯的自适应网格在下跌区间会通过 RSV 值持续放大买入网格、缩小卖出网格,效果是下跌时补仓频率明显下降,资金消耗速度变慢,扛单时间拉长。固定网格在同样区间里补仓速度是线性加速的,两种策略在压力测试下的差异非常直观。
5.2 RSV 值在震荡行情中的“假信号”问题
现象:RSV 值在震荡行情中经常一天之内从 0.8 跳到 0.2,买入网格从 0.2 元暴增到 0.8 元,卖出网格反向变化,导致挂单价格频繁变化,最终什么单都没成交,光看行情软件里的挂单价格跳动。
原因:RSV 是一个价格相对位置指标,它的计算只用了收盘价、最高价、最低价,在震荡行情中收盘价在区间内的位置没有明确趋势,RSV 值自然来回摆动。如果直接用它驱动网格,网格大小会跟着剧烈抖动。
解决:给 RSV 值加一层平滑,常见做法是取 3 日移动平均。我看过一个更简单的处理办法,直接用 RSI 的值替代原始 RSV,效果类似。魔灯源码里对 RSV 的处理比文档描述得更细,但核心思路不变——让趋势信号有惯性,而不是每天翻脸。
5.3 标准差周期设太短:网格一天变三次
现象:把 std_period 设为 5,网格大小每天大幅变化,昨天的买入网格是 0.3 元,今天变成 0.7 元,挂单频繁撤换,每撤一次单还要付手续费。
原因:5 日标准差完全被短期噪音主导,波动率信号失真。标准差周期越长,网格越稳定;越短,网格越灵敏。这里有个关键权衡:网格稳定可以降低操作频率,但反应迟缓又会错过行情突变。
解决:我在魔灯项目上试过 5、9、20、30 四组参数,最终保留 20 作为默认值。9 日留给趋势市,20 日留给震荡市。30 日以上不建议,网格大小对行情的响应太慢,差不多等于固定网格。调试时可以写一个参数遍历脚本,分别用不同周期生成网格序列,然后观察网格曲线的平滑度,这是最直接的判断方式。
5.4 母仓比例与自适应网格不匹配:资金还是被打满
现象:自适应网格已经生效,标准差和 RSV 都在动态调整网格大小,但遇到连续下跌,资金还是在 6 次补仓之后耗尽,和第 2 章里固定网格的现象一模一样。
原因:自适应网格改变的是“触发买入的价格间隔”,没有改变“每次买入多少股”。如果每次补仓买入的数量不变,网格间距从 0.5 元压缩到 0.15 元后,同样的下跌幅度会触发更多次买入,资金消耗更快。换句话说,网格缩小会让补仓频率上升,如果持仓量没有同比例缩小,资金会更快耗尽。
解决:魔灯文档对母仓比例的阐述不多,但根据我实盘的经验,正确的做法是让每次买入数量与买入网格大小保持比例关系。具体来说,网格缩小的同时降低每次买入数量,保证“网格间距 × 单次买入数量”对应的资金消耗速度大致稳定。这个参数在代码里对应一个 volume_scale 系数,等于 base_grid / current_buy_grid。当 buy_grid 从 0.5 变成 0.15,volume_scale 约等于 3.3,每次买入量应缩减为原来的 1/3.3,否则资金消耗速度反而更快。
| 核心痛点 | 固定网格表现 | 魔灯自适应网格表现 | 关键差异 |
|---|---|---|---|
| 剧烈波动 | 网格不变,仓位快速打满或清空 | 网格放大,扛单能力增强 | 标准差驱动 |
| 趋势判断 | 无趋势概念,买卖对称 | 买卖网格差异化,跟随 RSV 偏向 | RSV 驱动 |
| 参数调试 | 一个网格间距写到死 | 周期、基准网格、缩放系数可调 | 多参数联动 |
6. 回测验证与实盘习惯:让自适应网格再稳一步
6.1 用历史 K 线回放每一格触发
拿到魔灯策略,别急着上实盘。我的习惯是先做一次“逐格回放”——把历史 K 线按时间顺序逐根喂给策略,打印每一次网格触发时的时间、价格、网格大小、RSV 值。这样做的好处是你能亲眼看到网格是什么时候变大的、RSV 在关键时刻给出了什么信号,而不是只看一个收益曲线。
具体做法是把第 4 章的 compute_adaptive_grids 包进一个循环,每一根 K 线算一次当前网格,然后用当前价格和上一次成交价格做比对。价格跌穿买入网格就记录一次买入,涨破卖出网格就记录一次卖出。魔灯项目本身就是可运行的 Python 代码,你完全可以把它的源码导入自己的回测框架,或者用你自己的数据源替换它内置的行情接口。
6.2 参数收敛习惯与手动干预标准
我从魔灯实战里学到的另一个习惯是:策略只是一个动态的决策参考,不是圣杯。魔灯文档的作者在文中写到,自己操作时也会凭主观感觉买买卖卖,经常过早抄底或过早卖出,回头看魔灯的提示懊恼不已。这段话特别有意思,它说明再好的策略模型也需要执行纪律支撑。从那以后,我每次调整网格参数,都强制走一遍下面的流程:先用三组不同市场状态的数据回放网格触发点,再核对资金消耗速度是否在可控范围内,最后模拟一段单边行情看看策略会不会被打满仓或打空仓。完成这三步,才允许自己开始实盘。
魔灯这套自适应网格思想的真正价值,不在于让策略包赚不赔,而在于它给网格交易装了一个根据市场状态自动调节“胃口”的调节器,配合活跃的社区和完整开源的 Python 源码,无论你是想学习量化分析还是直接拿它作为交易参考工具,都能在这套思路上找到可以持续迭代的切入点。希望这套复盘思路能帮到你。
本文还有配套的精品资源,点击获取