ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

狂牛启动副图指标源码拆解:打分制公式编写与信号校验

狂牛启动副图指标源码拆解:打分制公式编写与信号校验

副图指标这个词在行情终端里出现的频率极高,但真正能把一份指标源码读懂、改到适配自己使用习惯的人并不多。“狂牛启动”这个名字一听就知道属于哪一类:它想捕捉的是横盘末端、量能异动、均线由纠缠转向发散的那一刻,然后把这种启动信号用柱子或文字在副图上标出来。我做过不少类似的公式拆解,也帮人改过一堆从各处收来的指标,发现绝大多数“启动型”副图指标的骨架高度雷同——差别主要在阈值、平滑方式和标注方式上。这篇内容就把这套骨架拆开揉碎,从命名套路、语法结构、打分制设计、参数标定,一直讲到用脚本做信号密度校验和未来函数排查,适合刚接触公式编写的新手,也适合写了很多年公式但总被信号闪烁困扰的老手参考。文中所有代码都是我自己重写的演示版本,不涉及任何第三方软件包的二次修改。

1. 副图指标到底在画什么:从“狂牛启动”的命名套路说起

1.1 主图与副图的分工差异

先把这个最基本的分工讲清楚,后面所有设计都建立在这上面。主图承载的是价格本身——K线、均线、通道线,纵轴刻度是价格或指数点位,坐标系是被价格“锚定”的。副图不一样,副图的纵轴是自定义的,可以是0到100的分数、可以是成交量倍数、也可以是任意无量纲的数值,它本质上是一个附加维度,用来把主图上肉眼看不出来的信息单独开辟一块空间画出来。

这个差异带来一个很实际的后果:主图指标和副图指标不能互相抄公式。你从别人的主图指标里抄一段均线变色逻辑放进副图,往往画不出来,因为主图用价格做纵轴,输出值是价格量级;副图如果输出一个20日均价,而你的副图范围设成0到100,那根线会直接飞出画面顶部。我见过太多人卡在这一步,以为公式写错了,其实是输出量纲和副图坐标范围不匹配。

所以设计副图指标的第一个决策不是“用什么函数”,而是“我要输出什么量纲”。输出0到100的打分、输出0到1的布尔标记、输出成交量倍数、输出差值百分比,这四种量纲的画法和后续标注方式完全不同。我个人偏好打分制(0到100),原因是它可以分级显示强弱,而不是只有一个“有信号/没信号”的二值状态,信息密度高得多。

1.2 一个“启动型”指标通常由哪几块拼成

把市面上流传的各类启动型副图拆开,内核基本逃不出四个模块的组合。

第一个是趋势确认模块,负责判断当前是不是已经处于多头结构,最常见的写法就是短中长三条均线的多头排列,或者收盘价站上某条中期均线并且该均线本身在向上。第二个是量能异动模块,负责判断有没有资金参与的迹象,典型写法是当日成交量相对过去N日均量的倍数超过某个阈值。第三个是突破模块,负责判断价格有没有脱离前期的横盘区间,通常是收盘价创出过去N日新高,或者突破某个箱体上沿。第四个是蓄势模块,反过来判断启动之前是不是真的“安静”过——振幅收窄、波动率下降、成交量萎缩,这一块最容易被漏掉,但恰恰是区分“启动”和“追高”的关键。

这四块拼在一起,用逻辑与(AND)连接,就得到了一个最朴素的启动信号。名字起得响一点,就叫“狂牛启动”;起得学术一点,就叫“多因子共振”。内核是一样的。我把这个拆解过程放在最前面,是想说明一件事:你看到的那些花哨名字背后,没有神秘算法,只有这四块积木的不同组合方式和不同阈值。

1.3 为什么很多人拿到源码还是用不明白

这是我在实际交流中遇到最多的情况:拿到一份源码,复制粘贴进去,能编译通过,图上也有柱子冒出来,但完全不知道那些柱子为什么在那个位置出现,调一个参数信号全没了,再调回来又满屏都是。问题出在三个地方。

一是参数没有语义。很多流传的公式参数名就叫N1、N2、N3、M,不告诉你N1代表什么周期。你把它从20改成30,不知道自己在改的是“平台统计窗口”还是“均线周期”,只能瞎试。二是阈值被硬编码在公式里,比如直接写了V>MA(V,5)*2,你看着这个2不知道该不该动。三是条件用AND硬连接,四个条件全满足才出信号,任何一个条件稍微苛刻一点,信号就归零;稍微宽松一点,信号就糊成一片。这种“全有或全无”的结构对参数极度敏感,是很多人用不下去的根本原因。

后面我会用打分制替代AND硬连接,把“全有或全无”变成“加权求和再卡线”,这是解决参数敏感问题最直接的办法。

2. 公式语言的骨架:五行结构拆解

2.1 参数行、变量行、计算行、输出行、绘图行

不管哪家的公式语言,一份完整的副图指标代码都可以切成五层。理解了这五层,你读任何陌生公式都能快速定位到关键逻辑。

参数层是写在代码最前面的一组可调变量,通常带默认值和取值范围。变量层用中间变量把复杂计算拆成一步步的中间结果,用:=这种“只赋值不输出”的符号。计算层是真正的逻辑运算,各种比较、与或非、条件判断。输出层用:单冒号,表示这个值要画到图上。绘图层是STICKLINE、DRAWTEXT、DRAWICON这类专门控制视觉呈现的函数。

新手最容易犯的错是把该用:=的地方写成:,结果副图上冒出一堆乱七八糟的线。记住一条规则:中间过程一律用:=,只有最终想看到的那个值才用:。一份写得干净的公式,输出行通常只有一到三条。

2.2 必须搞清楚的八个基础函数

下面这张表是我认为写副图指标绕不开的八个函数,按使用频率排序。表里只讲语义和坑,具体语法各家略有差异,以你所用终端的函数说明为准。

函数语义典型用法最容易踩的坑
MA(X,N)简单移动平均MA(C,20)N设太小噪声大,设太大钝化严重
EMA(X,N)指数移动平均EMA(C,12)与MA混用会导致两条线量纲感不一致
REF(X,N)取N周期前的值REF(C,1)N=0时返回当前值,容易写出逻辑死循环
HHV/LLV(X,N)N周期内最高/最低HHV(H,20)含当前K线,做突破判断时要REF一层
COUNT(COND,N)N周期内条件成立次数COUNT(C>O,10)N为0表示从第一根K线起算,性能差
BARSLAST(COND)距上次条件成立的天数BARSLAST(信号)首次出现前返回无效值,需处理
CROSS(A,B)A上穿BCROSS(MA5,MA10)只在上穿那根为真,连续走强不会再触发
SUM(X,N)N周期累加SUM(V,5)与COUNT区别:一个是求和一个是计数

这里重点说HHV这个坑,因为它在突破模块里几乎必用。HHV(H,20)统计的是包含当前K线在内的20根最高价,如果你直接写C>HHV(H,20),这个条件永远不成立——因为当前K线的收盘价不可能大于包含它自己在内的最高价。正确写法必须往前挪一根:C>REF(HHV(H,20),1)。这一个字的差别,能让整个指标从“从不触发”变成“正常工作”。我在帮人看公式的时候,这类错误占了相当大的比例。

2.3 绘图函数与颜色控制

副图的价值一半在数值,一半在呈现。数值对了但画得糊,用起来照样难受。常用的绘图手段就三种:柱状(STICKLINE)、文字(DRAWTEXT)、图标(DRAWICON)。

柱状用于表达强度,比如打分越高柱子越高、颜色越深。这里有个实用技巧:同一根柱子用两段STICKLINE叠画,先画一根宽的浅色做底,再画一根窄的深色做芯,视觉上就有立体感,比单色柱子清楚得多。文字标注适合标关键节点,但要注意位置参数,标注位置如果设在固定值上,当副图纵轴范围变化时会飘出画面,稳妥的做法是把标注位置写成“当前值 + 一个固定的偏移量”。

颜色控制上,我建议只保留两到三种语义色:强势一种、弱势一种、中性一种。有些人喜欢把每个条件配一种颜色,最后副图变成调色盘,反而看不出重点。颜色是信息层级的表达工具,不是装饰。

3. 从零手写一个打分制启动副图指标

3.1 第一步:把模糊描述翻译成分项打分

“启动”这个词是模糊的,落到代码里必须变成可计算的东西。我的做法是先做一次翻译:把“我觉得它要启动了”这个直觉,拆成几个可以独立验证的分项,再给每个分项分配权重。

权重分配不是拍脑袋,要按“这个条件对结论的贡献度”来。以启动判断为例,量能异动是最难伪装的,权重给最高;趋势确认是基础门槛,权重次之;突破是触发条件,权重再低一档;蓄势是加分项,权重最低。我给的一个参考配比是量能30分、趋势30分、突破25分、蓄势15分,加起来100分,方便读数。

为什么用加权求和而不是AND?因为AND的本质是权重无限大——任何一个条件不满足直接判0分。而现实中经常出现“量能很猛但趋势还没完全转好”这种半启动状态,AND会把它全部丢掉,打分制可以保留成60分、65分,让你看到“正在酝酿”的中间态。这个差别在实际使用中非常明显。

3.2 第二步:分项公式逐条落地

下面是我按这个思路写的一份演示代码,参数全部命名成有语义的英文缩写,方便你后续调整。这段代码用的是常见的类Pascal风格公式语法,各家终端大同小异。

{============ 参数区 ============} {TREND_N : 趋势均线组合的长周期, 默认20} {PLAT_N : 平台统计窗口, 默认20} {VOL_N : 量能基准均线周期, 默认5} {VOL_K : 量能放大倍数阈值, 默认1.8} {AMP_MAX : 蓄势振幅上限(百分比), 默认12} {============ 趋势分 ============} MA5 := MA(C,5); MA10 := MA(C,10); MAL := MA(C,TREND_N); UP_TREND := MA5 > MA10 AND MA10 > MAL AND MAL > REF(MAL,1); S_TREND := IF(UP_TREND, 30, IF(MA5>MA10, 18, IF(C>MAL, 10, 0))); {============ 量能分 ============} VMA := MA(V,VOL_N); VRAT := V / VMA; S_VOL := IF(VRAT >= VOL_K, 30, IF(VRAT >= VOL_K*0.75, 22, IF(VRAT >= 1.2, 12, IF(VRAT >= 1.0, 6, 0)))); {============ 突破分 ============} PLAT_H := REF(HHV(H,PLAT_N),1); BRK := C > PLAT_H; S_BRK := IF(BRK, 25, IF(C > PLAT_H*0.97, 12, 0)); {============ 蓄势分 ============} AMP := (HHV(H,PLAT_N)-LLV(L,PLAT_N))/LLV(L,PLAT_N)*100; S_AMP := IF(AMP <= AMP_MAX, 15, IF(AMP <= AMP_MAX*1.5, 8, 0)); {============ 总分与输出 ============} SCORE := S_TREND + S_VOL + S_BRK + S_AMP; 启动分: SCORE, COLORWHITE; 警戒线: 70, COLORGRAY;

这份代码有几个设计上的用意值得说一下。分项打分用的是嵌套IF做阶梯,而不是简单的0/满分二值,这样每一项都能贡献中间值。比如趋势项给了30、18、10、0四档,量能项给了30、22、12、6、0五档。阶梯越细,总分的分辨率越高,用起来越能看出“接近了”和“还早得很”的区别。

另外注意PLAT_H那一行,我特意用了REF(HHV(...),1),就是前面提到的那个坑。突破判断必须是“今天的收盘价超过了昨天为止的N日最高”,否则条件恒假。

3.3 第三步:输出层与信号标注

数值算出来只是第一步,怎么画决定了它好不好用。我的画法是三层:底层画一个0到100的浅色柱体做背景刻度感,中层画实际打分柱,顶层在超过警戒线时叠加强调色并加文字。

{基础柱: 用浅灰表示0-100的完整刻度} STICKLINE(1, 0, 100, 8, 0), COLOR404040; {打分柱: 不足70用中性色, 超过70用强调色} STICKLINE(SCORE>0 AND SCORE<70, 0, SCORE, 6, 0), COLOR808080; STICKLINE(SCORE>=70, 0, SCORE, 6, 0), COLORRED; STICKLINE(SCORE>=85, 0, SCORE, 3, 0), COLORYELLOW; {分项堆叠显示, 便于判断是哪一项在拉分} STICKLINE(1, 0, S_TREND, 2, 1), COLORBLUE; STICKLINE(1, S_TREND, S_TREND+S_VOL, 2, 1), COLORMAGENTA; {信号文字标注} DRAWTEXT(CROSS(SCORE,70), SCORE+8, '启动');

这里STICKLINE的第一个参数是条件,后面依次是“起点值、终点值、宽度、是否空心”。最后那个分项堆叠是我个人觉得很实用的一个技巧——把趋势分和量能分画成堆叠的细条,一眼就能看出这波分数是均线撑起来的还是量能撑起来的。趋势高量能低说明是慢牛型,量能高趋势低说明是脉冲型,两种情况下后续的应对方式完全不同。

DRAWTEXT的CROSS(SCORE,70)也值得说一下。这里用CROSS而不是SCORE>=70,是为了只在上穿那根K线标一次文字,避免连续十几根K线叠出一串重复文字把图糊满。CROSS 的语义是“前一根不满足、这一根满足”,正好符合“首次触发”的需求。

3.4 第四步:参数标定与信号密度检查

代码写完不能直接就用了,必须做参数标定。标定的核心指标是信号密度——在足够长的历史区间里,信号出现的频率。我的经验基准是:日线级别的启动型信号,一年出现15到40次比较合理,平均到每个月1到3次。低于10次,说明条件太苛刻,参数过拟合了历史,样本外基本全是遗漏;高于80次,说明条件太松,信号失去区分度,跟随机撒点没区别。

标定的方法是单参数扫描。固定其他参数,把VOL_K从1.2往上每次加0.1扫到3.0,记录每个取值下的信号次数,画一张表。你会看到信号次数随阈值上升单调下降,中间通常有一段“下降很平缓”的区间,说明这个区间内信号对参数不敏感,是最稳健的选择。如果找不到这段平缓区间,说明你的条件之间高度冗余——两个条件在描述同一件事,删掉一个。

AMP_MAX这个参数要特别小心。蓄势振幅上限设得太严(比如8%),会漏掉大量温和波动的标的,因为不同标的的波动率天然不同,用一个绝对值卡所有标的是不合理的。更稳的做法是改成相对值:用当前振幅除以过去一年的平均振幅,得到振幅的收缩比,收缩比小于0.6算蓄势。这样跨标的可比,也不用天天调参数。

4. 用 Python 把公式“验一遍”

4.1 数据对齐与复权

公式在终端里画出来,你只能看到图和信号位置,看不到信号数量和分布的统计。想知道这个指标到底出了多少次信号、信号之后走势分布如何,得把公式搬到脚本里跑一遍。这不是为了做决策,纯粹是公式校验。

第一步是数据准备,这里有个必须处理的问题:复权。终端里的图表默认是复权显示的,但你自己导出的原始数据往往是未复权的,两者算出来的均线和信号位置会对不上。建议直接导出复权后的日线数据,字段至少包含日期、开、高、低、收、量。如果只有未复权数据,那就需要在除权日前后做前复权处理,否则除权当天会出现一个巨大的假跳空,把突破条件全部触发。

第二个问题是数据对齐。成交量单位和价格单位不在一个量级,计算量比时要做除法而不是比较绝对值。另外停牌日的处理要提前想好:是剔除还是填充?我建议剔除,因为停牌日没有真实成交,填出来的量比是假的。

4.2 公式翻译对照

把公式翻成脚本时,逐个函数对着翻译,别自己发挥。下面是对照关系,用常见的表格处理库来写。

公式写法脚本等价实现
MA(C,N)df['close'].rolling(N).mean()
REF(X,N)df['X'].shift(N)
HHV(H,N)df['high'].rolling(N).max()
CROSS(A,B)(A > B) & (A.shift(1) <= B.shift(1))
IF(COND,A,B)np.where(COND, A, B)
COUNT(COND,N)COND.rolling(N).sum()

翻译时有两点要特别注意。一是rolling的默认窗口是包含当前行的,所以REF(HHV(H,20),1)要写成df['high'].rolling(20).max().shift(1),先滚动再位移,顺序不能反。二是np.where返回的是数组不是序列,记得带上下标重建,否则后续的布尔运算会出莫名其妙的错。

4.3 信号密度与分布统计

把打分算出来之后,做三件事:数信号次数、看信号的时间分布、看信号的后续统计特征。

import numpy as np # 打分计算(省略中间分项, 与公式一一对应) df['score'] = df['s_trend'] + df['s_vol'] + df['s_brk'] + df['s_amp'] # 上穿70作为信号 df['sig'] = (df['score'] > 70) & (df['score'].shift(1) <= 70) # 1. 信号密度: 按年统计 df['year'] = df.index.year density = df.groupby('year')['sig'].sum() print(density) # 2. 时间分布: 看看是不是集中堆在某几个月 df['month'] = df.index.to_period('M') print(df[df['sig']].groupby('month').size().describe()) # 3. 后续统计: 仅用于校验信号是否扎堆在特定形态 for n in [5, 10, 20]: df[f'fwd_{n}'] = df['close'].shift(-n) / df['close'] - 1 print(df.loc[df['sig'], ['fwd_5','fwd_10','fwd_20']].describe())

这段代码最有价值的输出不是第三段的统计描述,而是第一段和第二段。如果某一年的信号次数是其他年份的三倍,说明你的阈值是照着那一年的行情调的,属于典型的过拟合。如果信号集中堆在某两个月,说明你的条件里有一项在描述特定行情状态,换个市场环境就失效。这两种情况比参数本身更值得关注。

提示:第三段的前瞻统计只用于检查信号是否在时间上扎堆,不能当作收益预期。任何单一指标的历史分布都不具备外推性。

5. 绕不开的坑:未来函数、信号闪烁与数据错位

5.1 未来函数的识别与规避

未来函数是公式编写里最需要警惕的问题,它的特征是用了当前K线还无法确定的信息。最典型的一类是对未来数据的引用,另一类是基于全周期极值的回溯计算。

识别方法很简单:把最后一根K线删掉,重新算一遍,看历史信号有没有变化。如果删掉最后一根之后,倒数第二根K线上的信号变了(比如原本是信号,现在变成不是),那就说明公式里存在未来函数。正常的公式,历史信号必须是稳定的,不会因为新数据到来而改变。

常见的未来函数包括各类ZIG、PEAK、TROUGH系列的转向类函数,以及任何REF(X,-N)形式的负向引用。转向类函数在图表上画出来非常漂亮,总能在最低点标出买点,因为它本身就是用后面的高低点回推的。这类函数在事后复盘里无敌,在实时信号里一文不值。我的态度很明确:凡是用了转向类的公式,一律不碰。

5.2 信号闪烁的三种成因

没有未来函数,信号也可能闪烁。我遇到过三种成因。

第一种是边界抖动。打分恰好卡在70附近,量能从1.79变到1.81,分数从69跳到71,信号就闪出来了。解法是加迟滞区间:上穿用70触发,下穿用65才撤销,形成一段缓冲区。第二种是盘中数据未完成。日线指标在盘中会随着价格波动反复变化,收盘前看到的信号和收盘后可能完全不同。解法是只在收盘后确认,或者在公式里显式要求“当前K线已完成”。第三种是多周期数据不对齐。用周线数据和日线数据混合运算时,如果周线的最后一根是不完整的,算出来的结果会随每天变化。

5.3 常见问题速查表

现象最可能的原因排查动作
条件写了但从不触发HHV/LLV含当前K线,需REF一层检查所有突破类条件的窗口起点
信号满屏都是阈值过松或分项权重失效打印各分项得分分布,看哪项恒为满分
历史信号会变存在未来函数删最后一根K线重算,对比历史信号
副图曲线飞出画面输出量纲与坐标范围不匹配检查输出值是否被归一化
与导出数据算的对不上未复权或复权方式不同统一为同一复权口径后重算
回测结果异常好用了转向类函数或用了未来数据逐行检查负向REF和ZIG系列
参数微调信号全变用了AND硬连接改打分制,加阶梯阈值

这张表里最后一条是我最想强调的。参数微调信号全变,本质上不是参数问题,是结构问题。AND连接的结构天然对参数敏感,因为它把每个条件都当成必要条件。改用打分制之后,单个参数变化只影响分数高低,不会让信号从有到无,鲁棒性完全不在一个层次上。

6. 关于“和谐源码”这件事,我的实际建议

6.1 为什么第三方改包不能碰

网上流传的所谓改版、去限制版本、二次打包的指标文件,我一律不建议使用,原因不是道德说教,而是三条实打实的风险。

第一是安全风险。这类文件来源不可追溯,里面夹带什么完全靠运气,你把它放进自己的工作环境里跑,等于给一个陌生程序开了权限。第二是稳定性风险。二次打包会破坏原有的依赖关系和版本校验,短期看着能用,一旦主程序更新就直接崩,而且崩溃的方式往往很隐蔽——不报错,只是算出来的结果悄悄变了,你在错误的数字上做了一堆无效分析。第三是责任风险。使用来源不明的修改版本,一旦出现数据损失或者纠纷,你没有任何追索渠道。

替代方案很明确:要么用官方正式渠道的版本和内置公式,要么自己写。前者省事,后者可控。公式语言本身是公开的语法,网络上、官方文档里都有完整的函数说明,写一个副图指标需要的全部信息都能合法获取。你缺的不是那份源码,是读懂源码的能力——而这份能力,读十份别人的代码不如自己完整写一份。

6.2 自己写公式其实比找源码快

这句话不是鼓励,是我真实的效率感受。你花两个小时在各种渠道找一份能用的源码,找到之后还要花三个小时搞清楚它的参数含义、改掉里面的过拟合阈值、验证它有没有未来函数——总耗时五个小时,而且这五个小时的成果你并不完全理解。

自己从零写一份,把所有中间变量用:=拆开,每写一行就在图上输出一行看对不对,全程大概两个到三个小时。关键是这个过程里,每一个参数为什么取这个值、每一个条件为什么这么写,你都是清楚的。后面行情变了要调整,你知道该动哪里。

写公式的顺序我建议固定下来:先写数据层(取值、平滑),再写判断层(各分项),再写合成层(打分或逻辑),最后写呈现层(柱、文字、颜色)。每一层写完立刻输出到副图验证,一层对上了再写下一层。这样出错时定位成本极低,不会出现一整个公式写完不知道错在哪的情况。

6.3 分享与复用的合规姿势

如果你想把自己写的公式分享出去,有几个实践上的建议。一是参数语义化,别叫N1N2N3,叫TREND_N、VOL_K,别人一看就知道调的是什么,这是对使用者最大的善意。二是在代码开头写清适用周期和适用场景,日线用的公式搬到分钟线上参数全部要重标,不写清楚会误导人。三是明确标注公式里用了哪些可能引起争议的函数,如果有,就写明白它的问题在哪。

至于复用别人的公开公式,我的原则是只用逻辑,不用原文。看到一份不错的思路,理解它想解决什么问题,然后用自己的话重写一遍。这个过程里你会自然发现原公式的问题,也会加入自己的改进。直接复制原文贴来贴去,除了堆砌一份自己都不理解的代码库之外,没有别的收获。

7. 实操心得:几个参数级的经验笔记

写到这里,把几个不写在文档里但实际很有用的细节补上。

关于副图坐标范围固定。默认情况下副图纵轴会随数据自适应,导致同一个指标在不同标的上柱子的高度视觉差异巨大。建议在输出层加一条固定为100的水平线作为参照(就是前面代码里那句STICKLINE(1,0,100,...)的作用),把纵轴撑到固定范围,这样不同标的之间的分数高低可以直接横向比较。

关于分项得分的事后追溯。用好这份指标的关键不是看总分,是看分数构成。同样是75分,趋势30加量能30加突破15加蓄势0,和趋势18加量能12加突破25加蓄势15,含义完全不同。前者是趋势和量能双强突破不足,后者是蓄势充分但趋势还没跟上。所以我在输出层坚持做分项堆叠显示,就是为了让这个构成信息随时可见。

关于迟滞区间的具体设置。触发阈值和撤销阈值之间留多少合适?我的经验是留总分的5%到8%。警戒线70,撤销线设在64到66之间。留太窄起不到防抖作用,留太宽信号会拖得很长。

关于跨标的参数复用。绝对量类的参数(振幅百分比、成交量绝对值)跨标的基本不能直接复用,一定要改成相对量(振幅收缩比、量比倍数)。相对量参数虽然也需要标定,但至少在同一类标的之间是可迁移的。这一条我踩过很多次坑,一开始图省事用固定百分比,换一个波动率不同的标的,信号要么全灭要么全亮。

关于版本管理。公式改到第三版之后,你一定会忘记第一版长什么样。建议每次大改之前把旧版另存一份,文件名带上日期和改动摘要。这个习惯看起来笨,但当你需要回溯“上个月那个参数为什么改掉”的时候,能省掉大量时间。

最后分享一个小技巧。当你调参数调到怀疑自己的时候,把整个指标简化到只剩一两个分项,先确认基础逻辑没问题,再一层层加回去。绝大多数“参数怎么调都不对”的情况,根源都在某个分项的条件写错了——比如前面说的HHV含当前K线、或者REF的位移方向反了。把复杂公式拆回最小可运行单元逐层验证,是排查这类问题最快的方法,比盯着几十行代码硬看有效得多。

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进