如何归一化TradingView多零交叉指标并保留零交叉特性?
问题描述
在TradingView中整合Coppock Curve、QQE、PMI三类零交叉指标时,因指标原生值域差异大,使用自定义历史极值归一化函数将其统一至[-100,100]区间后,指标的零交叉点出现偏移,无法在原应交叉0线的位置准确对齐。需要找到既能统一缩放范围,又能严格保留零交叉一致性的方案。
原因分析
原normalize函数基于历史极值线性映射,公式为:_min + (_max - _min) * (_src - _historicMin) / (_historicMax - _historicMin)
这种方式会将原指标的整个值域从[_historicMin, _historicMax]强制拉伸到[-100,100],但原指标的0点并非历史极值的中点,因此映射后0点会偏移到非零位置,破坏了零交叉的一致性。
解决方案:中心化比例缩放
采用以0为中心的比例缩放,核心逻辑是:
- 计算指标历史数据的绝对值最大值(确保正负方向缩放比例一致)
- 将原指标值乘以
100 / max_abs_value,把值域缩放到[-100,100]区间 - 保留原指标的0点不变,确保零交叉位置完全对齐
这种方式既统一了指标的显示范围,又严格保留了零交叉的一致性,同时避免了历史极值漂移导致的缩放比例突变。
修改后的完整代码
//@version=4 study("QQE, CC, PMI (Normalized with Zero-Cross Preserve)", shorttitle="QQE/CC/PMI Norm", precision=4, resolution="") // 中心化归一化函数:保留零交叉,缩放到[-100,100] normalize_preserve_zero(_src) => var float max_abs = 0.0 current_abs = abs(nz(_src)) max_abs := max(max_abs, current_abs) // 避免除以0,最小用0.0001 scale_factor = 100 / max(max_abs, 0.0001) _src * scale_factor // ------------------------------ // Coppock Curve // ------------------------------ section1 = input(false, 'Coppock Curve') length = input(title="Smoothing Length", type=input.integer, defval=10) longRocLength = input(title="Long ROC Length", type=input.integer, defval=14) shortRocLength = input(title="Short ROC Length", type=input.integer, defval=11) src = input(title="Source", type=input.source, defval=close) coppock = wma(roc(src, longRocLength) + roc(src, shortRocLength), length) normalized_coppock = normalize_preserve_zero(coppock) coppockColor = normalized_coppock > 0 ? #0ebb23 : color.red plot(normalized_coppock, title="Coppock", linewidth=2, color=coppockColor, transp=0) // ------------------------------ // QQE // ------------------------------ section2 = input(false, 'QQE') src2=input(close) length2 = input(14,"RSI Length", minval=1) SSF=input(5, "SF RSI SMoothing Factor", minval=1) showsignals = input(title="Show Crossing Signals?", type=input.bool, defval=true) highlighting = input(title="Highlighter On/Off ?", type=input.bool, defval=true) RSII=ema(rsi(src2,length2),SSF) TR=abs(RSII-RSII[1]) wwalpha = 1/ length2 WWMA = 0.0 WWMA := wwalpha*TR + (1-wwalpha)*nz(WWMA[1]) ATRRSI=0.0 ATRRSI := wwalpha*WWMA + (1-wwalpha)*nz(ATRRSI[1]) QQEF=ema(rsi(src2,length2),SSF) QUP=QQEF+ATRRSI*4.236 QDN=QQEF-ATRRSI*4.236 QQES=0.0 QQES:=QUP<nz(QQES[1]) ? QUP : QQEF>nz(QQES[1]) and QQEF[1]<nz(QQES[1]) ? QDN : QDN>nz(QQES[1]) ? QDN : QQEF<nz(QQES[1]) and QQEF[1]>nz(QQES[1]) ? QUP : nz(QQES[1]) QQF_raw = (QQEF-50)*3 normalized_QQF = normalize_preserve_zero(QQF_raw) QQS_raw = (QQES-50)*3 normalized_QQS = normalize_preserve_zero(QQS_raw) plot(normalized_QQF, "FAST", color.maroon, 2) plot(normalized_QQS, "SLOW", color=color.blue, linewidth=1) longFillColor = highlighting ? (QQEF>QQES ? color.green : na) : na shortFillColor = highlighting ? (QQEF<QQES ? color.red : na) : na fill(normalized_QQF, normalized_QQS, title="UpTrend Highligter", color=longFillColor) fill(normalized_QQF, normalized_QQS, title="DownTrend Highligter", color=shortFillColor) // ------------------------------ // Basic Polychromatic Momentum Indicator (PMI) // ------------------------------ section3 = input(false, 'PMI') len = input(14, title="Length", minval=1) smoothing = input(2, title="Smoothing", minval=1) mom = src - src[len] pmi = (mom - (mom - mom[len]) / len) * 130 sm_pmi = sma(pmi, smoothing) normalized_sm_pmi = normalize_preserve_zero(sm_pmi) plot(normalized_sm_pmi, title="PMI", color=color.blue, linewidth=2) // 零参考线 hline(0, title="Zero Level", linestyle=hline.style_dotted)
关键说明
- 新的
normalize_preserve_zero函数会持续跟踪指标的历史绝对值最大值,动态调整缩放比例,确保指标始终在[-100,100]范围内 - 原指标的0点经过缩放后仍为0,完美保留零交叉信号的一致性
- 所有指标的正负方向缩放比例对称,不会扭曲原指标的波动幅度比例
内容的提问来源于stack exchange,提问作者vulcan4d
相关产品推荐
相关产品推荐

