解决SMI指标应用Ehlers Roofing Filter的Pine Script报错问题
问题解决:Pine Script中"Could not find function or function reference 'roof'"错误
错误原因
第56行的roof(sm, erflen)是错误操作——你之前定义的roof是一个序列变量(通过roof = erf(src, hp_per, lp_per)计算得到的针对src的滤波结果),并非可调用的函数,因此Pine Script无法识别这个函数调用。
修复方案
将Ehlers Roofing Filter封装为可复用的函数,这样就能对不同序列(比如这里的sm)灵活应用滤波。修改后的完整代码如下:
//@version=5 indicator(title="Stochastic Momentum Index", shorttitle="SMI", overlay=false) // Ehlers Roofing Filter - 封装为可复用函数 ehlersRoofingFilter(x, t_hp, t_lp)=> omega1 = 4*math.asin(1)/t_hp omega2 = 4*math.asin(1)/t_lp alpha = (math.cos((math.sqrt(2)/2)*omega1) + math.sin((math.sqrt(2)/2)*omega1) - 1)/math.cos((math.sqrt(2)/2)*omega1) hp = 0.0 hp := math.pow(1 - alpha/2, 2)*(x - 2*x[1] + x[2]) + 2*(1 - alpha)*nz(hp[1]) - math.pow(1 - alpha, 2)*nz(hp[2]) a1 = math.exp(-math.sqrt(2)*2*math.asin(1)/t_lp) b1 = 2*a1*math.cos((math.sqrt(2)/2)*omega2) c2 = b1 c3 = -math.pow(a1, 2) c1 = 1 - c2 - c3 erf = 0.0 erf := c1*hp + c2*nz(erf[1]) + c3*nz(erf[2]) erf src = input(defval=close, title="Source") lp_per = input.int(defval=10, minval=2, title="Low Pass Cutoff Period") hp_per = input.int(defval=30, minval=2, title="High Pass Cutoff Period") applyerf = input.bool(true, title="Apply Ehlers Roofing?") // 为Roofing Filter添加独立周期参数,也可直接复用hp_per/lp_per erf_hp_per = input.int(defval=30, minval=2, title="Roofing Filter High Pass Period") erf_lp_per = input.int(defval=10, minval=2, title="Roofing Filter Low Pass Period") // Ehler's Smoother Filter PI=3.14159265359 EhlersSuperSmootherFilter(price, lower) => var filt=0.0 a1 = math.exp(-PI * math.sqrt(2) / lower) coeff2 = 2 * a1 * math.cos(math.sqrt(2) * PI / lower) coeff3 = - math.pow(a1,2) coeff1 = 1 - coeff2 - coeff3 filt := coeff1 * (price + nz(price[1])) / 2 + coeff2 * nz(filt[1]) + coeff3 * nz(filt[2]) applyes = input.bool(true, title="Apply Ehlers Smoother?") eslen = input.int(10, title="Ehlers Smoother Length") // Input q = input.int(title="Stochastic Lookback", defval=13, minval=1) r = input.int(title="1st Smoothing Length", defval=25, minval=1) s = input.int(title="2nd Smoothing Length", defval=2, minval=1) signalLength = input.int(title="Signal Length", defval=12, minval=1) showsignals = input.bool(defval=true, title="Buy/Sell Signals") // Calculation hh = ta.highest(q) ll = ta.lowest(q) numerator = ta.ema(ta.ema(src - 0.5 * (hh + ll), r), s) denominator = 0.5 * ta.ema(ta.ema(hh - ll, r), s) sm = 100 * numerator / denominator // 修复函数调用:使用封装好的Roofing Filter函数 smrf = applyerf ? ehlersRoofingFilter(sm, erf_hp_per, erf_lp_per) : sm smi = applyes ? EhlersSuperSmootherFilter(smrf, eslen) : smrf signal = ta.ema(smi, signalLength) hist = smi - signal // Hist-Color col_grow_above = input(#26A69A, "Above Grow", group="Histogram", inline="Above") col_fall_above = input(#B2DFDB, "Fall", group="Histogram", inline="Above") col_grow_below = input(#FFCDD2, "Below Grow", group="Histogram", inline="Below") col_fall_below = input(#FF5252, "Fall", group="Histogram", inline="Below") // Plotting plot(hist, title="Histogram", style=plot.style_columns, color=(hist>=0 ? (hist[1] < hist ? col_grow_above : col_fall_above) : (hist[1] < hist ? col_grow_below : col_fall_below))) plot(smi, title="SMI", color=color.green, transp=0) plot(signal, title="Signal", color=color.red, transp=0) maxLevel = hline(+75, title="Max Level", color=color.black) obLevel = hline(+40, title="Overbought Level", color=#00796b) median = hline(0, title="Zero Level", color=#989898) osLevel = hline(-40, title="Oversold Level", color=#f57f17) minLevel = hline(-75, title="Min Level", color=color.black) fill(obLevel, osLevel, title="SMI Background Fill", color=color.purple, transp=95)
关键修改点
- 将原
erf函数重命名为ehlersRoofingFilter,语义更清晰,避免和内置函数混淆 - 移除原代码中
roof = erf(src, hp_per, lp_per)的变量定义,改为在需要时直接调用函数 - 为Roofing Filter添加独立的周期输入参数,支持单独控制对SMI序列的滤波周期(若需和src滤波周期一致,直接替换为
hp_per和lp_per即可) - 修复第56行的错误调用:将
roof(sm, erflen)改为ehlersRoofingFilter(sm, erf_hp_per, erf_lp_per)
内容的提问来源于stack exchange,提问作者Krishnendu Bhattacharyya
相关产品推荐
相关产品推荐

