同一只标的在两处显示,日涨跌幅对不上:行情列表里读到的比值是 -0.0342,用算式算出来是 -0.0351。两个数都不是软件算错,差别落在通达信涨跌幅公式把哪个价当成了基准。列表那一列、交易所公布的数值、你自己写的算式,三处对基准的取法不一样,同一根 K 线就能给出三个数。

下面按基准、分母、复权、分档数字、停牌与除权、记录表六步展开。函数名与参数取值以本机公式编辑器里的函数列表为准。

一、基准取谁:前收、开盘与前结算

日线涨跌幅的骨架是 (C - REF(C,1)) / REF(C,1) * 100,REF(C,1) 取上一根 K 线的收盘价。式子里基准只有一处,换成谁就换一个含义。基准取 REF(C,1),算的是相对前一根收盘的变化;基准取 O,也就是当日开盘价,算的是相对当日开盘的变化。跳空开盘的根上,这两个结果分叉得最开。

{ 基准换一下,同一根的涨跌幅就换一个数 }
BAS1 := REF(C, 1);                    { 基准:前收盘价 }
BAS2 := O;                            { 基准:当日开盘价 }
ZF_A : (C - BAS1) / BAS1 * 100;
ZF_B : (C - BAS2) / BAS2 * 100;
{ 跳空开盘的根上,两条线分开 }

前结算价是另一个字段。股票日线里它与前收取到的是同一个数,期货与期权的行情把结算价单独给出,与前收不是一个值。把股票的写法搬到期货品种上,基准取错,整条线的数值都不对。

分母跟着基准一起换,两个输出不是同一个量,比较前要先对齐基准,给一个算式准备的阈值不能套到另一个算式上。

分钟周期上还有一处:基准取上一根收盘价还是当日开盘价,得到的是两条不同的线,周期越短分得越明显。核对前先把基准写进公式注释。

二、涨跌额与振幅的分母落在别处

写通达信涨跌幅公式时容易把三个数混成一个:涨跌幅、涨跌额、振幅,它们的分母各不相同。

涨跌额是价格差,写成分数时分母按 1 计,量纲是价格;涨跌幅的分母是基准价,量纲是比例,乘 100 之后才写成百分数;振幅的分子取当根的最高与最低,分母落在基准一侧,取法另有规定。这里只指出三者分母不同这一点,振幅本身的算法不展开。

{ 三个数,三种分母 }
BAS := REF(C, 1);                 { 基准:前收盘价 }
CHA : C - BAS;                    { 涨跌额,量纲是价格 }
ZF  : (C - BAS) / BAS * 100;      { 涨跌幅,量纲是比例 }
{ 分母不同,两个数不能互相代入 }

分母不同,两个数就不能互相代入。把一个 0.35 的价格差当成 0.0035 的比例来读,或者把 3.5 的比值当成 0.35 的价格差,都是分母看错了。两个数摆进一张表,量纲要分开标注,单位栏不能省。

涨跌额的数值随价格水平走,按涨跌额排序与按涨跌幅排序得到的次序不一样,横向对比之前先决定按哪一个排。

三、复权设置改了 REF(C,1) 的取值

复权处理改的是历史价格序列本身。C 是被改过的值,REF(C,1) 从这条序列上取数,前收跟着变,涨跌幅跟着变。通达信在 K 线图的右键菜单里给出「复权处理」,前复权把除权之前的价格按比例调整到与最新价衔接,后复权保持上市初期的价格不动、把之后的价格往上调整。

{ 复权方式改变的是 C 序列,公式一个字不用改 }
BAS : REF(C, 1);            { 前收随复权设置变化 }
ZF  : (C - BAS) / BAS * 100;
{ 同一条公式挂在不同复权方式的图上,读数不同 }

同一段行情,两种复权方式下的收盘价序列不同,前收不同,算出的涨跌幅也不同。这一点在除权日附近显出来:不复权口径下,除权日那根的 REF(C,1) 是除权前一根的收盘价,当日按除权参考价开盘,两个价之间夹着分红与送股,算式把这段缺口记成一根很大的跌幅;前复权把除权前后的价格接顺,这根上的涨跌幅回到与相邻根同一个量级。两条线上的数都对,回答的问题不同。

复权方式属于图表设置,不写在公式里。同一条公式挂在不同复权方式的图上读数不同,复制到另一台机器也会不同,那台机器上的设置说了算。

图表上的复权设置与公式里的取数是两件事:前者决定序列,后者决定用序列里的哪一项。设置改了而公式没动,输出照样会变。核对数值之前先确认图上用的是哪一种复权方式,开关就在 K 线图的右键菜单里。

四、分档数字是设定值,不是统计结论

通达信涨跌幅公式里写的分档数字,例如按比值口径填的 0.1 与 0.05,是使用者填进去的设定值,不是从行情数据里算出来的统计结论。

把 0.1 写成常量,是给输出加一个分档标记。以 -9.8 作下档边界、把小于等于这个数的根记成一档,这个 -9.8 是你选的数,换一个数,同一段行情会被切成不同的段。统计口径的结论来自样本计算:先把一段时间里所有根的涨跌幅算出来,再看某个数值落在分布里的哪个位置。设定值先定,统计值后算,两者不能互相充当证据。

{ 常量是设定值,写进注释 }
UP := 9.8;                          { 设定的上档边界,不是统计结果 }
DN := -9.8;                         { 设定的下档边界 }
MARK : IF(ZF >= UP, 1, IF(ZF <= DN, -1, 0));

边界数值与分档标记分开写:边界放在公式开头的注释或者参数位置,标记写成独立的一支输出。改边界的时候只动一个地方,其余部分不用跟着改,脚本也便于复算。

本篇不写什么:不写任何价格限制幅度的判定条件与容差给法,不写振幅与波动率的算法,不写选股条件怎么组合。这三块各自要单独立题,塞进这一篇会把基准与复权这条主线冲散。

五、停牌与除权日的跳空缺口

停牌期间不生成 K 线,复牌首根的 REF(C,1) 接的是停牌前那一根的收盘价,中间隔过的交易日不计入分母,复牌跳空的部分被整根写进这一根的涨跌幅。首根的数值看着比相邻根大,原因在数据这一侧,不在行情当天的波动。

{ 缺口核算:基准与当根一起输出 }
BAS : REF(C, 1);
GAP : O - BAS;                     { 开盘缺口,量纲是价格 }
ZF  : (C - BAS) / BAS * 100;
{ 停牌段的基准跨了若干交易日,与相邻根不等价 }

除权日的缺口按复权口径处理:不复权留在图上,前复权被接顺。同一段行情,两种口径下这一根的数不同,记录里必须写明当时用的是哪一种,否则两次统计的涨跌幅不可比。

停牌段的影响不止一根:复牌之后的一段时间里,前收可能取到停牌前的价格,首根的涨跌幅同时含停牌段的变化与当日的变化,这两部分在数据里拆不开,只能靠标记与交易日历去识别。

核对停牌与除权按这个顺序走:先看本地数据里这根 K 线之前有没有缺失的交易日;再看 REF(C,1) 取到的数值与停牌前那一根的收盘价是否相同;最后看这一根的除权标记有没有打开。

本地数据的下载与更新也会影响这几根:数据重新下载之后,除权处理的数值可能改变,同一天的涨跌幅跟着变。记录里补一列数据下载日期,回溯时能对上。

六、把口径写进复盘记录表

复盘统计做的是同一口径下的横比与纵比,口径不写进表里,两次统计的数就对不上。记录表要能回答三个问题:这一根的周期是什么、序列是哪一种复权、基准取到的是哪个价。

字段 取值示例 为什么要留这一列
证券代码 六位代码加市场后缀 对齐标的,避免同名混淆
交易日期 年月日 对齐交易日历,识别停牌缺口
K 线周期 日线 / 60 分钟线 同一根在不同周期上的基准不同
复权方式 不复权 / 前复权 / 后复权 决定 C 序列,也就决定了 REF(C,1)
基准价 REF(C,1) 的数值 让涨跌幅能被复算,分母可核
收盘价 当日收盘的数值 与基准价配对才能还原算式
涨跌幅 百分数 统计对象本身
停牌 / 除权标记 是 / 否 标出缺口根,剔除或单列
数据下载日期 年月日 数据版本变化后能追溯

表里省掉两列会直接影响复算。「复权方式」省掉,两次统计跑在不同复权方式的图上,差的落在设置上;「基准价」省掉,涨跌幅只剩一个百分数,复算时分不出分母取的是哪一个价。

{ 导出这一行时一起写出的三个值 }
BAS : REF(C, 1);                  { 基准价 }
ZF  : (C - BAS) / BAS * 100;      { 涨跌幅 }
{ 随行记录:K 线周期、复权方式、基准价 }

记录表落成一份本地表格文件就够用。自编公式与备份在安装目录的 T0002 下,公式文件是 PriGS.dat,备份目录是 gs_bak,记录表在同层另建一个文件夹存放,恢复公式备份时不会把它一起覆盖。公式本身在「公式管理器」里维护,路径在功能菜单的公式系统下面。

同一根 K 线给出两个涨跌幅,源头在基准取谁与复权口径这两处设置;把口径写进复盘记录,通达信涨跌幅公式算出的数才可复算,也可横比。

站内还有 复盘方法与数据工具 的条目,指标原理与参数 讲取数与分母的口径,选股公式与预警 讲把条件写成公式时的字段对应,可对照查看。

本文只作技术研究口径,不涉及也不构成对任何标的的判断。

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