「我已经测试过了」这句话在讨论公式时会指向两件不同的事。一件是点一下测试公式、提示通过;另一件是让它在历史数据上跑一遍、看给出什么结果。如何用通达信测试指标公式,先要把这两层分开。
本文按两层测试的分工、各自的操作、都不能回答的问题、样本区间与函数核对四个部分展开。文中的菜单项与函数名以通达信金融终端个人版为准,券商定制版的功能入口可能有差异。全文只讨论测试过程与结果口径,不涉及任何标的的判断。
一、测试不是一个动作,是两层
两层测试的输入、输出与耗时都不一样。混在一起谈,就会出现「测试通过但结果不对」这种说不清的情况。
| 层级 | 输入 | 输出 | 看什么 |
|---|---|---|---|
| 语法测试 | 公式正文 | 能否编译 | 下方是否出现红字提示 |
| 历史回测 | 公式正文加一段历史数据 | 在指定区间上产生的信号与统计 | 区间、信号数量、统计口径 |
语法测试的结果只有两种:通过,或者不通过并给出提示。它不产生任何数值。历史回测的结果是一组数值,它依赖选定的区间与参与的范围。
两层之间存在先后关系。语法不通的公式,回测跑不起来;语法通了,回测也未必有意义,因为回测还要求数据完整、区间合适。反过来则不成立:回测跑得起来,不代表语法层已经被认真核对过。
把这层关系落到操作上,就是先做便宜的检查、再做昂贵的检查。语法测试几秒钟就能完成,回测要跑一段区间。顺序颠倒过来先跑回测,遇到编译问题时得到的是空白结果,还得回头再走一遍。
二、语法测试:它只回答能不能编译
语法测试的入口在公式编辑窗口。写完正文之后点「测试公式」,软件把正文交给编译器解析一遍。解析通过会给出提示通过的反馈;解析不通过会在下方列出提示,指向出问题的位置。
这一步的作用是隔离问题。一份公式在图上不显示,原因可能是语法不通过、挂载位置不对、或者数据缺失。先把语法这一层排掉,剩下两种可能就容易分辨了。
{ 一段会因为缺少分号而不通过的写法 }
A:=MA(C,N)
B:=REF(A,1);
差:A-B;
{ 补上分号后通过 }
A:=MA(C,N);
B:=REF(A,1);
差:A-B;
上面这段示例的差别只有一个字符,提示的位置却可能落在下一行。编译器读到下一句时才判断出上一句没有结束,所以提示指向的行号与真正需要改的地点之间可能差一行。看到提示之后回到上一行末尾检查,是处理这类提示的方式。
语法测试的边界要记住:它不检查逻辑是否符合预期,也不检查取值是否落在合理范围。一份语法完全正确、逻辑写反的公式,测试照样会通过。
三、历史回测:它回答历史上出现过什么
如何用通达信测试指标公式的第二层,是让公式在一段历史数据上求值,看它产生了什么。这一层要手动指定三件事。
- 参与的范围。在哪些品种上求值。范围越大,跑一遍越久。
- 样本区间。从哪一天到哪一天。区间长度决定结果里包含多少个观察点。
- 参与的方式。是让公式输出信号并列出清单,还是把信号代入后续的统计口径。
三项里最容易忽略的是区间。区间选得不同,同一份公式的信号数量会不同,这是数据层面的直接结果,不是公式不稳定。记录结果时把区间一起记下来,两次结果才有比较的基础。
范围的选取同样影响读数。同一份公式在小范围上跑出的信号数量,与在全市场上跑出的数量不在一个量级,两次数值直接相比没有意义。做对比时把范围固定住,只改一项,结论才落到那一项上。
范围之外还有一项要一并记录:区间内是否包含全部交易日。中间有停牌或者本地数据缺失的品种,会以空值的形式进入统计,读数时要把这部分单独标出来,否则数量对不上时会误以为是表达式的问题。
四、两层都不能回答的问题
把两层合起来,仍然有一批问题是它们回答不了的。把这条边界认清楚,可以避免把测试通过当成结论。
| 不能回答的问题 | 原因 |
|---|---|
| 它在以后会不会继续给出信号 | 回测只覆盖历史区间,区间之外没有数据 |
| 信号出现之后会怎样 | 公式计算的是表达式的取值,不含后续结果 |
| 同一根 K 线上信号是否稳定 | 取决于公式是否引用了会被后续数据改写的量 |
| 换个软件是否一致 | 取决于函数集合与数据口径是否一致 |
第三项单独说明一下。如果公式引用了会被后续数据改写的量,那么在历史区间上跑出来的信号,与当时实时看到的信号,可能不是同一批。测试时看到的是用完整数据算出的结果,这与当时的可见状态不同。
五、样本区间与函数核对
如何用通达信测试指标公式,落到操作上就是两件核对工作:区间是否合适,函数是否被正确理解。
区间方面要确认三件事:起点是否早于公式需要的最长回溯窗口;区间内是否包含本地数据缺失的段落;区间的长度是否足以覆盖多次同类情形。第三项决定了结果的可比性,一个过短的区间里,结果容易受个别位置影响。
函数方面要确认的是求值方式。有一类函数的取值依赖「当前是哪一根 K 线」,把这类函数用在回测里,得到的结果与实时运行的结果不同。核对办法是查函数说明里有没有相关标注,再按上面说的方法做一次前后对比。
{ 依赖最后一根 K 线状态的写法 }
当前:ISLASTBAR;
{ 依赖整段历史的写法,取值随区间长度变化 }
位置:BARSCOUNT(C)-BARSLAST(C>0);
上面两种写法在图上都画得出东西,但在回测里的表现不同。前一种直方在最后一根 K 线上有值,回测跑到历史区间时它取不到;后一种的取值与区间的起点绑在一起,区间一变,同一个位置的数值就变。把这类语句挑出来单独确认,是回测前的一项准备工作。
六、结论怎么读
两层测试都给不出「这份公式能不能用」这样的结论,它们给出的是两类事实:语法能不能编译,以及在指定区间与范围内出现过什么。这两类事实是判断的输入,不是判断本身。
如何用通达信测试指标公式,回答到操作层面是三句话:先用语法测试把编译问题排掉,再用回测拿到一段区间上的事实,最后把区间、范围与函数求值方式一并记下来。本文只讲测试的两层分工与结果口径,不涉及具体标的的判断,也不涉及任何效果承诺。回测数值取决于区间、范围与函数求值方式,换一个区间结果就会不同。站内另有 指标回测与风险验证 里讲统计口径分歧的条目、公式编写教程 里讲语法与函数结构的条目、公式报错与卡顿排查 里讲编译提示原文的条目,可对照查看。
