一段公式在历史图上回看时,标记每次落在低点附近;把本地数据往后补一段再回看同一根 K 线,标记的位置挪了。这不是源码写错了符号,是它在计算那根 K 线时读了当时还不存在的数据。通达信未来函数检测要处理的,就是这类引用位置的问题。

下面按判断标准、常见写法、三步检测法、替换思路四层展开,每一层都给可动手核对的动作。全文只讨论公式语言与数据引用的口径,不评价任何公式的效果,也不给出操作结论。文中出现的函数名以通达信金融终端个人版自带的函数说明为准,版本号可以在「帮助 → 关于」里核对。

一、判断依据是引用位置,不是函数名

以正在计算的那根 K 线为界,公式能引用的数据分成两段:界之前已经落地的,和界之后还没有产生的。一段源码只要引用了界之后的数据,它就含未来函数。判断依据在这里,与函数名听起来是否可疑无关。

按这个依据分,情形有两类。一类是函数在设计上就向后读,比如直接取当前之后第若干根的写法。另一类是算法要确认一个区域内的极值,而区域的边界要等区域走完才能确定。第二类更隐蔽,因为源码里可能只出现了看起来很普通的统计函数。

由此还能推出一个现象:同一段源码在只看历史的那段区间上表现平稳,问题只在处理最后一根 K 线时暴露。这也是为什么只在历史图上检验,很难发现问题。

二、可疑写法集中在三族

按用途归类,通达信公式里需要重点核对的写法集中在三族。函数名的拼写以你所用版本自带的函数列表为准,不同版本收词并不完全一致。

族别 典型写法 为什么会读到界之后的数据
峰谷定位类 ZIG、ZIGZAG、PEAK、TROUGH 及同名加 BARS 后缀的写法 要确认一个高点,需要等后面出现足够低的点来把它固定下来
回填类 BACKSET 按条件反向修改前面若干根 K 线上的取值
向后引用类 REFX 直接取当前之后第 N 根的值

跨周期引用是另一处需要单独看的地方,它不属于上面三族,但可能落到同一类问题上。日线公式里引用本周的周线数据,在本周走完之前,这个周线值会随着本周行情推进而变化。判断办法在后文第三步。

三、重绘会让回看结果与使用结果错位

峰谷定位类函数在历史回看时的表现,和它在处理最新一根 K 线时不一样,原因在数据是否齐全。

回看历史时,一根低点后面的数据已经全部存在,函数能在整段数据上一次性找出拐点,标记落在低点上。处理最新一根时,它后面的数据还没有,函数无法判断当前这根是不是拐点,只能等到后面的点走出来、条件成立之后,再在那个确认位置上给出标记。两个位置之间的差,就是这个函数带来的错位。

这个错位对回测的影响很直接。回测使用的历史数据是齐全的,所以含未来函数的公式在回测里给出的标记,落在条件确认之前的位置上。回测结果因此显得比使用时的表现更好。这是机制层面的直接结果,与回测软件无关。

把含未来函数的公式拿去回测,得到的不只是偏乐观的数字,而是一份无法在使用中重现的信号序列。核对回测口径时,这一项应排在未来函数检查之前。

四、通达信未来函数检测的三步做法

三步做完,通达信未来函数检测的结论才落到具体的一行上:是某一个函数读到了界之后的数据,还是某个窗口的边界要等后续才能确定。第一步是函数名对照。把源码里用到的函数逐个抄出来,对着公式编辑器里的函数说明或帮助菜单里的函数列表,逐条看它引用了哪一段数据。这一步能把上面三族的写法直接筛出来。

第二步是时间切片对照。选一根 K 线,把与它相关的输出在收盘后记一次,在盘中再记一次。两次一致,说明这一段没有读取未完成的数据;两次不一致,公式里就含未来函数。这一步不需要函数表知识,是动手成本最低的一步,建议放在最先做。

第三步是数据裁断法。把本地日线数据裁到某个日期为止,重跑公式,比较裁断点前后那几根 K 线上的输出,看是否因为后面数据被去掉而变化。

{ 第一步:只输出中间量,便于逐根比对 }
Z1:=ZIG(3,5);
D1:PEAKBARS(3,5,1);

{ 第二步:同一根K线的两次记录 }
{ 收盘后记一次 X 的最后一根值 }
{ 盘中再记一次,两次不一致即含未来数据 }

{ 第三步:把本地数据裁到某日为止后重跑 }
{ 比较裁断点附近输出的变化 }
三步里第二步的适用面最广,也不依赖对函数表的熟悉程度。先把第二步做完,再决定要不要花时间做函数名对照。

五、检测出来之后的替换思路

替换的方向是统一的:把「需要等后续数据确认」的判断,改成「只用界之前的数据就能算出」的判断。改写之后信号会有滞后,但滞后可以用数据说明,重绘没法用数据说明。

峰谷定位类的替换,思路是把依赖后续确认的拐点,改成固定窗口内的极值。窗口长度写成常数,边界就不依赖后续数据。

{ 原写法:拐点位置需要后续数据确认 }
G1:ZIG(3,5);

{ 替换写法:固定窗口内的最低值,边界不依赖未来 }
G2:LLV(LOW,20);

{ 两者都会在图上给出位置,差别在于 }
{ G2 在当前K线上就能确定,G1 要等后续确认 }

回填类的替换,是把「回头修改前面几根」改成「对当前及之后生效」的写法。若原本想表达的是「距上一次条件成立过了多少根」,用只向后看的计数写法即可,不必回头改写历史取值。

替换过程中要留意一处副作用:固定窗口的说法会引入窗口长度这个新参数,而窗口长度的选择本身又会回到参数调整的问题上。窗口长度选定后应当固定下来,不要为了让历史曲线好看而反复改动。

六、这些写法不属于未来函数

核对时也容易把正常写法误判成未来函数,下面几类不属于。

  • 向前取值的引用。取上一根的写法只用到已经落地的数据,不在未来函数的范围内。
  • 固定窗口的统计。窗口长度是常数的极值、均值、计数类写法,边界不依赖后续数据。
  • 已落地字段。成交量、成交额、开高低收这些字段在计算时都已确定。
  • 写在公式里的常数。源码里写死 20、60、250 这类数字,含义是设定的窗口长度,与未来数据无关。

需要单独判断的是跨周期引用。它是否算未来函数,取决于引用的那个周期有没有走完,而不是取决于写法本身。

七、替换之后的复核与记录

替换写完之后,用三项复核确认它真的解决了问题,而不是把问题挪到了别处。

第一项是时间切片复核。对新写法再做一次收盘后与盘中的对照,两次一致才算通过。第二项是位置差复核。把新旧两种写法在同一段历史上并排输出,数出两者信号位置相差多少根 K 线。这个差值是可以用数字写下来的,也正是替换必须付出的代价。第三项是数据起点复核。确认替换后的写法在本地数据的最左端返回空值还是 0,返回 0 的写法会在图上拉出一条水平线。

三项复核做完,建议留一份改动记录,字段写清四处:原来的函数名、替换后的写法、位置相差的根数、复核的日期。记录的作用是在后面的使用中遇到信号位置与预期不符时,能快速判断这是替换带来的滞后,还是又引入了新的引用问题。

文中函数名、目录名与菜单路径以通达信金融终端个人版为参照;不同版本与券商定制版的函数列表可能存在差异,请以你所用版本的「帮助 → 关于」与公式编辑器内的函数说明为准。一次完整的通达信未来函数检测包含函数名对照、时间切片对照与数据裁断三步。站内 公式编写与语法函数 一栏讲函数本身的用法,回测验证与风险控制 一栏讲回测口径与验证顺序,公式报错与卡顿排查 一栏讲编译与显示的提示原文,可对照查看。

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。