通达信无未来函数公式,指的是这段代码在被逐根重算时,同一根上的输出不会因为之后才出现的数据而改变。判断一段写法有没有这个问题,不看名字,也不看作者在说明里怎么写,看的是把它挂到图上逐根走一遍,同一根上的读数会不会跟着后面的 K 线跳动。
下面按四件事讲:未来函数引用的是什么、常见清单里落着哪几个函数、逐根回放的验证怎么做、回测口径怎么定。内容以通达信金融终端个人版为准,公式管理器里的入口位置与按钮措辞在不同版本里可能有差异。
一、未来函数引用的是当前根尚未产生的数据
一根 K 线的数据在收盘之后才定型,盘中还会继续变动。公式在计算第 N 根时,正常只能读到第 N 根以及之前的历史值;一旦代码逻辑让第 N 根的输出用上了第 N+1 根及之后的信息,这一根的输出就不再是当时能算出来的结果,而是事后补出来的结果。
这种写法在图上会留下一个可观察的特征:把光标停在第 N 根上不动,输出的数值随着后面几根陆续出现而不断改写。改写之后的数值与那段走势贴合,但它在第 N 根当天并不存在。回看时一条很顺的线,落到当时的时点上对不上,问题就出在这里。
还有一类写法不是直接去读将来,而是把一个后来才确定的点反向标记到过去。为了确定某个转折的位置,算法要等到后面出现足够的高低点,再把标记回填到更早的那几根上。落在图上,那几根上就多了一个当时还无法确认的记号,看图的人会以为那里在当时已经被识别出来。
这个问题与公式挂在哪里没有关系。挂在主图上、挂在副图上、拿去做条件选股,只要代码里引用了将来的数据,读数一样会随后面的行情改写。把公式换一个挂载位置,或者换一个周期,都换不掉它内部那一步对将来数据的依赖。
二、常见清单里落在这一类的函数
通达信公式语言里有几个函数属于这一类,写公式时遇到它们要单独处理。下面这份清单按函数名与它引用的数据位置列出来,括号里的参数用公式里的写法。
ZIG(K,N) 确定转折位置时用到后续高低点,转折点被回填到更早的根上 PEAK(K,N,M) 取前若干个转折里的波峰值,值随后续数据改写 TROUGH(K,N,M) 取前若干个转折里的波谷值,值随后续数据改写 BACKSET(X,N) 条件成立后向前回填 N 根,成立之前的那几根一并被标成成立 REFX(X,A) 取当前根之后第 A 根的值,直接读到尚未产生的数据
这份清单不是判定的全部。有的写法把未来函数藏在被调用的自定义公式里,主公式的表面看不出异常;有的用 REF 与循环组合出跨根取值的等价效果。清单覆盖得住的是明确命名的几个,覆盖不到的部分要靠下一节的逐根回放来看。
反过来也要说清:BARSLAST、COUNT、SUM 这类对历史做统计的函数不在清单里,它们只回看已经出现过的根。看到名字里带计数、累计,不必先入为主地判成未来函数;看到清单里的函数名,也不该直接判定整段代码作废,判定要落到读数会不会变这一条上。
三、把公式挂到副图,逐根回放看同一根的读数
要确认一段通达信无未来函数公式,做法是把代码挂到副图,再一根一根往前推演。Ctrl+F 打开公式管理器,新建一个副图指标,把代码贴进编辑框,点「测试公式」先过语法这一关,再点「确定」保存,回到图上就能看到这条线。
回放的动作是按住键盘上的右方向键,让光标一根一根向前推进,同时盯住已经走过的那一根。没有引用将来的写法,读数定住之后不再改动;引用了将来数据的写法,光标停在原来那一根不动,屏幕上它的读数也会随新出现的 K 线跳动。这个跳动就是直接的证据,把它所在的那一根记下来,再回到代码里找是哪一个函数在起作用。
另一种做法更适合试算:先写一段只用历史值的对照代码,把同一组参数代进去,得到一条基准线,再和原来那段并排挂在同一个副图上。两条线在已经走完的根上重合,在最后若干根上分开,分开的位置就是原代码依赖将来数据的位置。
{只用历史值的对照写法}
MA20:=MA(CLOSE,20);
COND:=CLOSE < MA20;
CNT:=COUNT(COND,20);
条件成立根数:CNT;
还有一种看周期差异的办法:把同一段代码先挂在日线副图上截取一段,再换到更小的周期挂一次,对比同一个时点的输出。周期变小,一根之内可见的数据变短,若输出跟着周期一起变形,说明这段逻辑对尚未走完的那一段有依赖。两种办法合用,一个定位到根,一个定位到周期间的口径差。
| 现象 | 含义 | 处理 |
|---|---|---|
| 光标停在某一根不动,该根读数随新 K 线出现而改写 | 该根的输出引用了之后才产生的数据 | 回到代码里找到引用将来数据的那一步,换成只用历史值的写法 |
| 换到更小的周期后,同一时点的输出形态改变 | 输出与当前可见的未来数据长度相关 | 把跨周期引用限制在已经收盘的周期上 |
| 条件成立的那一根上,它之前若干根同时出现标记 | 代码里有把结果回填到过去的写法 | 去掉回填,只保留条件成立当根的标记 |
| 把公式贴进编辑框后按下测试按钮,提示通过 | 语法层通过,函数语义没有被检查 | 再按前面的动作走一遍逐根回放 |
四、官方的测试公式按钮只做语法检查
「测试公式」这个按钮解决的是能不能编译通过的问题。它检查括号是否配对、函数名是否写对、参数个数是否匹配,不检查某个函数是否引用了将来的数据。语法通过的公式照样可以带未来函数,这一层要分清楚,否则按下按钮看到测试通过,会把语法问题当成已经排除了语义问题。
验证因此分成两层来做。语法层交给测试按钮,拼错的函数名、缺掉的括号在这一层拦住;语义层交给逐根回放,读数会不会随后面的数据跳动在这一层看。两层都过,才谈得上这段代码在当时的时点上能算出来。顺序上语法在前,因为编译不过的代码挂不到图上。
五、回测口径:逐根重算,样本内外分开
确认了通达信无未来函数公式之后,回测才有可以站住的前提。回测要按逐根重算的口径来做:计算第 N 根时,只允许读到第 1 根到第 N 根的数据,在这一段上算出的条件与结果记录下来,然后把窗口往下一根推进。整段统计由每一次只看见过去的计算拼起来,而不是拿全段数据一次性算完再分段读。
口径里还有两件事要分开写清楚。样本内的那一段用来确定参数,样本外的那一段用来观察同一组参数换到新数据上是什么样;两段混在一起算,得出的数字同时受参数与选段影响,事后分不清是哪一项在起作用。分段的位置、每一段的起止日期、参数是在哪一段上定下来的,这三样都要落成文字,跟着记录一起存档。
记录里建议保留这几列:样本段标识、起止日期、逐根重算用到的参数快照、该段内条件成立的根数、条件成立之后若干根上的偏离幅度,以及数据缺失的位置。偏离幅度那一列要注明取几根,取三根和取十根是两个数,不注明就没法在两版记录之间对照。
样本外的一段要不要复权、遇到停牌怎么处理、数据不足时前面几根怎么算,这些属于口径本身,写进记录里,改口径时一并改。口径不落成文字,换一个人重算同一段,数字对不上时无从查起。
六、下一步动作
下一步动作是把手里这段通达信无未来函数公式按上面的顺序过一遍:先挂到副图上逐根回放,把读数会跳动的根找出来并记下位置;再换一个周期复核,看输出是否随周期变形;确认通过之后,按逐根重算的口径分段回测,把样本内与样本外的记录分开放。改过一版的代码,把公式名、导出文件名与参数值一起记在旁边,下一次重算时才有东西可以对照。
本文只作技术研究口径,不涉及也不构成对任何标的的判断,也不涉及任何收益层面的结论。
站内还有 指标回测与风险验证 的其他条目,通达信公式编写教程 里讲函数与语法怎么写,公式报错排查 里讲编译不通过时怎么定位,可对照查看。
