把复杂度和质量画等号,是选指标时容易踩进去的一处偏差。指标公式越复杂越好吗,这个问题换个问法会清楚:这段公式交给另一个人接手,能不能读懂、能不能改对、出问题时能不能定位到出错的那一层。
这篇不讨论哪种写法更高明,只把复杂度拆成看得见的部分,再给几条可以逐条核对的判据。判断的依据放在可维护性上,参数个数只是其中一个线索。
一、复杂度的三个来源
指标公式越复杂越好吗,先看复杂度从哪来。把它拆开,来源有三处:参数数量、函数嵌套层数、引用其他周期的数据。三处叠加,读公式的负担就上来了。
参数数量这一处。一段公式里可调参数从两个涨到八个,调参时要试的组合变多,判断是哪个参数在起作用也变难。参数之间还可能互相牵制,调大一个,另一个的效果被压住,看到的结果说不清是谁带来的。
函数嵌套层数这一处。平滑里套位移、位移里套条件,读的时候要在脑子里叠栈,每读到一层都要记住上一层的输入是什么。层数一多,中间量的意义就不容易说清,改其中一处也会牵动别的层。
引用其他周期的数据这一处。在日线公式里取周线值,这类跨周期取数会让同一根 K 线在不同时刻的取值,依赖另一周期数据的完整性。周期切换、数据起点不足,都会让这一层返回和预期不一样的数。
嵌套示例(通达信公式,以个人版为准) A1:MA(CLOSE,20); A2:REF(A1,1); SIGNAL:IF(CLOSE>A2,A1-A2,0);
这段示例里,SIGNAL 依赖 A2,A2 依赖 A1,A1 又依赖收盘价序列。三层串起来,改 A1 的周期,A2 与 SIGNAL 的输出跟着变。层数越多,这种牵连越难在改动前说清。
三处来源可以分开数。参数个数直接数,嵌套层数从里往外数括号,跨周期引用看公式里有没有出现带周期的取数写法。数一遍,比凭感觉说这段公式复杂要可靠。
参数数量这一处还有一层:参数本身会互相影响。均线周期调大,信号的触发点跟着挪,另一个判断阈值的参数在旧周期下合适,换到新周期就不合适了。调参时要把一组参数放在一起看,不要单看一个参数的效果。
二、复杂度带来的三笔成本
复杂度上来之后,成本分三笔记,分别落在调试、维护、失效排查上。
- 调试成本:公式算错时,要在多层里找出是哪一层先偏的
- 维护成本:换软件版本、换数据源之后,要重读一遍才知道哪些地方受影响
- 失效排查成本:条件该成立时没有成立,要逐层判断是哪一层返回了空值
三笔成本里,第三笔最隐蔽。前两笔在改动时出现,改动的人会主动去看;第三笔在公式没有信号的时候出现,屏幕上什么都没有,判断要从最外层往里收,一层一层确认输入还在不在。公式越复杂,往回收的步数越多。
调试成本的记法可以更具体。公式算错时,先把每一句单独跑一遍,看第一处对不上的位置;找到那一句之后,再看它的输入来自哪一句,顺着往回走,直到找到最里层的来源。
维护成本在换版本时才显出来。软件更新之后,个别函数的参数顺序或字段口径可能调整,公式本身不报错,但算出的值变了。重读一遍公式,把每个函数的名字与版本说明对一遍,能提前发现这类偏差。
三、可维护性的三条判据
指标公式越复杂越好吗,在能不能维护这一段上,可以拆成三条可以逐条核对的判据。
- 能否逐句读:按分号把公式断成若干句,每一句都能说清输入是什么、输出是什么
- 能否单独测试一段:把中间量单独挂到副图,看它的曲线是否符合预期
- 换版本后能否定位:版本更新后公式报错,能不能立刻指到具体是哪一句、哪个函数
三条判据都能在公式管理器里当场验证。把公式挂上主图或副图,看中间量的曲线,再把参数逐个调整,观察曲线怎么变。看不懂的那一处,就是需要动的地方。
三条判据的走法是从句到段再到版本。逐句读解决的是看得懂,单独测试解决的是测得准,换版本后定位解决的是改得动。三关都过,这段公式才谈得上可以长期维护。
能否单独测试一段,靠的是把中间量暴露出来。把中间量写成独立的一行,挂到副图上,它就是一条曲线,能看出它在哪个区间跳动、在哪些位置断掉。藏在表达式里的中间量看不见,也就测不了。
| 现象/提示 | 含义 | 处理 |
|---|---|---|
| 打开公式看不出哪句在算哪个量 | 变量命名与层次不清 | 给中间量单独命名,逐个挂副图观察 |
| 改一个参数,曲线变化看不懂 | 参数之间互相牵制 | 固定其余参数,逐个调整并记录变化 |
| 版本更新后公式报错 | 依赖的函数或字段发生了变化 | 在公式管理器里逐句测试,定位到报错的那一行 |
| 条件该成立时没有信号 | 某一层的输入为空或条件过窄 | 把中间层展开挂图,从最外层逐层往回收 |
四、能落地的简化动作
简化不改变判断的意图,只改变表达的方式。三条动作都能在公式管理器里直接落地。
- 合并重复计算:同一段子表达式在公式里出现多次,就提成一个中间变量,后面引用这个名字
- 把常量提到参数:散在各处的阈值收成参数,改一处就够,不必逐个替换
- 拆成两段公式:把算中间量与出信号拆开,中间量单独挂副图,信号段只引用它
简化前 S1:IF(MA(CLOSE,20)>MA(CLOSE,60),MA(CLOSE,20)-MA(CLOSE,60),0); 简化后 快线:MA(CLOSE,20); 慢线:MA(CLOSE,60); 差离:快线-慢线; S1:IF(差离>0,差离,0);
简化后的写法把重复的两处计算收成了一个变量。改周期时只动快线与慢线两行,信号段不用碰。差离这一行还能单独挂到副图,看它自己是不是在按预期的方式变化。
简化还有一个副作用要留意。把常量收成参数之后,参数变多了,前一处复杂度被压下去,后一处复杂度升上来。收哪些常量要挑改动意义大的,比如隔一段时间调一次的周期值,意义不大的固定值就留在原位。
拆成两段公式之后,中间量那一段可以复用。换一个信号条件,只改信号段,中间量段不用动。复用的前提是中间量的口径固定,周期、数据源不变,否则两段之间的约定就失效了。
五、复杂度要服务于讲得清
指标公式越复杂越好吗,把尺子放在讲得清上。一段公式里,能逐句讲清输入输出的部分留下,讲不清的部分要么拆开挂图看清楚,要么去掉。复杂度本身不产生价值,它只是让一件原本说不清的事变得说得清。
把这条尺子落成动作:拿到一段公式,先按分号断句,能读通的留下;读不通的地方,把中间量挂上副图看一眼,看得懂就继续,看不懂就简化或拆开。走完这一遍,这段公式适不适合长期放在自选里,判断就有依据了。
表达是否清楚,还可以用一个更朴素的办法测:把公式放一段时间不动,隔一阵再打开。断句还能顺着读下来,中间量的名字还能对上它算的量,说明这段表达没有跑偏;读起来要重新推一遍才明白的,就是下一次需要动的地方。
本文只作技术研究口径,不涉及也不构成对任何标的的判断。指标公式越复杂越好吗,抛开参数个数不谈,你手上那段公式,能逐句讲给旁边的同事听吗?
