Pine Script获取RSI背离点bar索引时计数器始终返回固定值问题
RSI背离指标首个背离点bar索引定位异常问题分析
问题描述
基于公开脚本开发RSI背离检测指标时,需要定位构成背离形态的两个K线中第一个背离点的bar索引(即该点距当前K线已走过的K线根数):
- 已通过
Y=ta.valuewhen(plFound, rsi[lbR], 1)语句成功获取第一个点的RSI数值 - 后续尝试使用
ta.barssince函数、for循环回溯遍历K线,查找RSI值等于Y的K线位置时逻辑失效,计数器q始终返回固定值51
涉及代码如下:
//@version=5 indicator(title="RSI Divergence Indicator w/Alerts", format=format.price,overlay=true) len = input.int(title="RSI Period", minval=1, defval=14) src = input.source(title="RSI Source", defval=close) lbR = input.int(title="Pivot Lookback Right", defval=5) lbL = input.int(title="Pivot Lookback Left", defval=5) rangeUpper = input.int(title="Max of Lookback Range", defval=60) rangeLower = input.int(title="Min of Lookback Range", defval=5) plotBull = input.bool(title="Plot Bullish", defval=true) plotHiddenBull = input.bool(title="Plot Hidden Bullish", defval=false) plotBear = input.bool(title="Plot Bearish", defval=true) plotHiddenBear = input.bool(title="Plot Hidden Bearish", defval=false) rsi = ta.rsi(src, len) plot(rsi, title="RSI", linewidth=2, color=#8D1699) hline(50, title="Middle Line", linestyle=hline.style_dotted) obLevel = hline(70, title="Overbought", linestyle=hline.style_dotted) osLevel = hline(30, title="Oversold", linestyle=hline.style_dotted) fill(obLevel, osLevel, title="Background", color=#9915FF, transp=90) plFound = na(ta.pivotlow(rsi, lbL, lbR)) ? false : true phFound = na(ta.pivothigh(rsi, lbL, lbR)) ? false : true _inRange(cond) => bars = ta.barssince(cond == true) rangeLower <= bars and bars <= rangeUpper //------------------------------------------------------------------------------ // Regular Bullish // Osc: Higher Low oscHL = rsi[lbR] > ta.valuewhen(plFound, rsi[lbR], 1) and _inRange(plFound[1]) // Price: Lower Low priceLL = low[lbR] < ta.valuewhen(plFound, low[lbR], 1) bullCond = plotBull and priceLL and oscHL and plFound plot( plFound ? osc[lbR] : na, offset=-lbR, title="Regular Bullish", linewidth=2, color=(bullCond ? bullColor : noneColor), transp=0 ) Y=ta.valuewhen(plFound, rsi[lbR], 1) plot(Y,color=color.yellow,offset=-lbR)// THIS SHOWS THE RSI'S FIRST POINT VALUE q=0 if bullCond for i=0 to 50 q:=q+1 if ta.rsi(close,14)[i]==Y break plot(bullCond?q:na,color=color.orange,offset=-lbR)// IT ALWAYS SHOWS 51 !
故障原因
q固定返回51是三个逻辑错误共同导致的:
- 浮点数相等判断永远不成立:RSI是经过平滑、除法运算得到的浮点型数值,哪怕视觉上两个值看起来一致,实际存储时小数末尾会存在极细微的精度误差,直接用
==做绝对相等判断几乎不可能命中。循环内的break条件永远不会触发,代码会跑完0到50的全部51次循环,q从0开始每次循环加1,最终结果固定为51。 - 遍历逻辑和pivot的偏移规则不匹配:
plFound标记的pivot点,实际对应的K线位置是信号出现位置往左偏移lbR根K线,不是信号出现的当根K线。循环从i=0(当前K线)开始回溯找RSI等于Y的位置,本身就找错了搜索范围。 - 重复计算RSI放大精度误差:循环内每次重新调用
ta.rsi(close,14)[i]计算RSI,和全局提前计算好的rsi序列在回溯时会产生额外的精度偏差,进一步降低相等判断的命中概率。
修正方案
不需要通过遍历匹配RSI值的方式找pivot位置,直接通过pivot信号的时间偏移计算bar索引即可:
- 利用
ta.barssince直接获取上一次plFound成立的位置距离当前K线的根数,叠加lbR偏移量就能得到第一个背离点的准确bar索引 - 如果需要做值校验,用差值阈值判断代替绝对相等判断,规避浮点数精度问题
修正后的核心代码替换原有的q计算逻辑即可:
Y=ta.valuewhen(plFound, rsi[lbR], 1) plot(Y,color=color.yellow,offset=-lbR) q = 0 if bullCond // 上一个plFound信号距离当前的bar数 + pivot右偏移量 = 第一个背离点的bar索引 lastPivotSignalBar = ta.barssince(plFound[1]) q := lastPivotSignalBar + lbR // 可选精度校验,差值小于0.0001即认为匹配,过滤异常值 // if math.abs(rsi[q] - Y) > 0.0001 // q := na plot(bullCond?q:na,color=color.orange,offset=-lbR)
内容的提问来源于stack exchange,提问作者konkoori
相关产品推荐
相关产品推荐

