通达信BARSLAST 接收一个条件表达式,返回上一次这个条件成立的那一根,到当前这一根之间隔了多少根。条件在当根成立时返回 0,隔一根返回 1,往后依次加一。这个返回值是一个整数计数,不是一个真假值,把它放到真假判断的位置,得到的结果与条件本身不同。下面把返回值的来源、几个容易混的函数、以及几处常见的用法偏差按顺序讲清楚。
口径以通达信金融终端个人版的公式语言为准,公式管理器里的提示措辞与函数说明在不同版本里可能有差异,以本地版本的实际输出为准。文中的写法都可以放进公式管理器,用「测试公式」按钮先过一遍语法,再挂到图上核对数值。
一、BARSLAST(X) 返回上一次成立到当前的周期数
先看返回值的构成。函数不关心条件在历史上成立过几次,只关心最近的那一次。当前根成立,返回 0;上一根成立,返回 1;上五根成立,返回 5。中间又成立过一次,计数从新的一次重新起算。这个特性决定了它适合回答「距离上一次发生过了多久」,不适合回答「历史上发生过几次」。
COND:=CROSS(MA(CLOSE,5),MA(CLOSE,20)); DIST:=BARSLAST(COND); DRAWTEXT(DIST=0, LOW*0.97, 'CROSS');
上面这段把距离单独存成一列输出。把它挂到副图,纵轴就是一根一根数出来的距离;把它放进 DRAWTEXT 的定位参数,就变成画在价格上的标记。同一段公式换一个挂法,读法完全不同,后面的用法都建立在这个数上。
计数单位是「根」,不是「天」。在日线上,一根就是一天;在 60 分钟线上,一根是一小时。同一个条件在两个周期上算出来的距离数值不同,因为被数的格子大小不一样。跨周期引用的时候,这个差别会被放大。
二、条件从未成立时返回什么
条件在已加载的数据里一次都没有成立,返回值就失去「最近一次」这个参照,转而与数据的起点发生关系:计数从数据起点开始累加,读出来的就是当前这一根距数据起点的距离。换一段加载范围,这个数跟着变。同一个公式,在导出数据长度不同的两台机器上,可能读出两个数。
这种情况在图上留不下标记,判断起来靠旁的线索。把距离挂到副图上,曲线从最左边开始单调上升、中间没有归零的位置,说明条件在这段数据里没有成立过,而不是条件成立得太早。归零的位置就是成立的位置。看到一条一路向上的线,先想到的是条件没触发,而不是公式哪里坏了。
三、BARSCOUNT 与 BARSLAST 的差别在口径
把通达信BARSLAST 与 BARSCOUNT 并排看,两个函数都返回整数,口径不同。BARSLAST 数的是「距离」:最近一次成立的那一根,到现在隔了多少根,起点随条件移动。BARSCOUNT 数的是「累计」:从第一根有效数据起算,到当前一共有多少根,起点由数据本身决定,与条件无关。
VALID:=BARSCOUNT(CLOSE); { 自第一根有效数据起算的根数 }
AT_HEAD:=BARSCOUNT(CLOSE)=1; { 只落在第一根有效数据上 }
RECENT:=BARSLAST(CLOSE>REF(CLOSE,1));
口径的差别带来的后果是:同一个数在两种写法下的含义不可互换。用 BARSCOUNT 的读数去替代距离,等于把数据起点当成条件成立点;用距离去替代累计根数,等于把最近一次当成第一次。需要统计「条件累计成立了多少根」,用的是 COUNT 这一类写法,而不是这两个函数中的一个。
数据的有效起点也会影响读数。停牌段不产生新的根,因此距离只在有交易的那几根上累加。把停牌前后两根当作相邻,计数就会比实际的时间跨度小。核对读数时,先确认这段时间里有没有停牌。
四、COUNT 与 FILTER 组合时的用法
单独一个通达信BARSLAST 的距离数,能表达的信息有限。与 COUNT 组合,可以区分「最近一次」与「这一段里的次数」;与 FILTER 组合,可以先把密集出现的成立点压成一个点,再量距离,得到的数才是两次间隔。
CNT:=COUNT(COND,60); { 最近 60 根里 COND 成立的次数 }
ONLY:=FILTER(COND,10); { COND 成立后 10 根内的重复成立被压掉 }
GAP:=BARSLAST(ONLY); { 相邻两个成立点之间的间隔 }
上面三行的顺序不能换。先 COUNT 再 FILTER,得到的是两组不同口径的数;先 FILTER 再 BARSLAST,量到的是被压缩之后的间隔。函数之间的先后决定了取哪一根作为参照,这一段与信号拆解里讲的条件分层是同一件事,公式里的顺序就是口径。
再往下可以做一个条件式的判读。把距离的数与阈值比较,得到一个状态:距离落在给定的根数以内为一种状态,之外为另一种。这一步只做分类,不涉及对后面走势的看法。
NEAR:=BARSLAST(COND)<=10; FAR:=BARSLAST(COND)>10; STATUS:=IF(NEAR,1,IF(FAR,-1,0));
五、它引用已有数据,与 ZIG、PEAK 不是一类
通达信BARSLAST 的输入与输出都只依赖已经出现的那几根。条件在某一根成立,计数从那一根往后加,后面新来的数据只影响新的读数,不改动已经走过的位置。把公式挂到副图上逐根回放,同一根上的数值不随之后的数据变化,这是它不属于未来函数类写法的判断依据。
ZIG、PEAK、TROUGH 这一类函数相反,它们要等到后续数据确认了转折,才能定下前面某一个点的位置,因而同一个历史点上的输出会随之后的数据改变。两类函数的差别不在写法长短,而在是否引用了当前根尚未产生的数据。把距离类函数与转折类函数混在同一段公式里,回放时看到的稳定性只属于前一部分。
六、两处常见误用与几步判断
第一处误用是把返回值直接放进判断位置。公式语言里的真假判断按「非零为真、零为假」处理,而 BARSLAST 在条件成立的当根返回 0,在不成立时返回正数,方向正好与条件相反。写成条件位置,得到的状态与条件相反。
MISUSE:=IF(BARSLAST(COND),1,0); { 非零即真,方向与 COND 相反 }
OKUSE:=BARSLAST(COND)=0; { 当根成立才为真 }
第二处误用是跨周期取值时的口径不一致。在 30 分钟图上算出的距离与在日线上算出的不是同一个数;用 #DAY、#MIN30 这类格式引用另一个周期的数据时,取回来的序列按被引用周期的格子计数,而当前图的格子是另一套。两个口径的数放在同一段条件里比较,比较的结果没有意义。要比较就先统一到一个周期上算。
| 现象 | 含义 | 处理 |
|---|---|---|
| 副图曲线一路向上不归零 | 条件在已加载的数据里没有成立过,读到的是距数据起点的根数 | 补长数据范围,或核对条件写法是否过严 |
| 计数结果与条件方向相反 | 把返回值当成真假值使用,非零为真 | 改成与 0 比较的写法,明确取哪一根 |
| 两个周期上的数对不上 | 计数单位是「根」,各周期的格子长度不同 | 先统一周期,再比较数值 |
| 距离比实际时间跨度小 | 停牌段不产生新的根,计数只累加有交易的根 | 核对区间内有没有停牌 |
| 回放时读数前后变化 | 同一段公式里混入了转折类函数 | 把距离类输出单独拆出来复核 |
把上面的判读压成几步,用于核对通达信BARSLAST 的返回值:先看曲线有没有归零的位置,确认条件是否成立过;再把返回值与 0 比较,明确取当根还是取间隔;然后确认当前图的周期与引用周期的口径是否一致;最后逐根回放,看同一根的读数稳不稳。四步之外仍对不上的,先把加载的数据范围补长,再看一遍。
本文只作技术研究口径,不涉及也不构成对任何标的的判断。
