基本原理 该指标背后的基本原理是:当资产价格达到极限时,无论趋势如何,都会出现(可能不相等,但)相反的反应。
设置 无论您选择什么时间段,默认设置都不是最好的。我个人认为,JMA的长度最好比“正常”长。
JMA来源:Jurik移动平均线计算基于的来源。 JMA长度:控制Jurik移动平均线的长度。 JMA阶段:各种各样的滞后控制器。增加相位会增加过冲,但会减少滞后,减少相位会减少过冲,但会增加滞后。
ATR长度:计算平均真实范围值的长度。 ATR乘数:该乘数控制信封或极端频带的“宽度”。
学分 @gorx1用于改进和更精确(?)Jurik移动平均值计算。 @用于ATR包络计算的redktrader。
回测测试
/*backtest start: 2021-10-01 09:00:00 end: 2022-06-06 15:00:00 period: 1d basePeriod: 1h exchanges: [{"eid":"Futures_CTP","currency":"FUTURES"}] */ // This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/ // © multigrain //@version=5 indicator('baguette by multigrain', 'baguette', overlay = true) //NAME TYPE DEFVAL TITLE MIN MAX GROUP jmaSrc = input.source (hlc3, 'JMA 数据源', group='JMA') jmaLen = input.int (144, 'JMA 周期', group='JMA') jmaPhs = input.int (34, 'JMA 阶', -100, 100, group='JMA') atrLen = input.int (34, 'ATR 周期', group='Envelope') atrMul = input.float (3, 'ATR 乘数', group='Envelope') // Jurik Moving Average // credit to @gorx1 f_jma(_src, _length, _phase) => lower_band = _src upper_band = _src del2 = math.abs(_src - lower_band[1]) del1 = math.abs(_src - upper_band[1]) vola = del1 == del2 ? 0 : math.max(del1, del2) vola_sum = 0.0 vola_sum := nz(vola_sum[1]) + 0.1 * (vola - vola[10]) avg_len = 65 y = bar_index + 1 avg_vola = 0.0 avg_vola := if y <= avg_len + 1 nz(avg_vola[1]) + 2.0 * (vola_sum - nz(avg_vola[1])) / (avg_len + 1) else ta.sma(vola_sum, avg_len) len = 0.5 * (_length - 1) len1 = math.max(math.log(math.sqrt(len)) / math.log(2) + 2, 0) pow1 = math.max(len1 - 2, 0.5) r_vola = avg_vola > 0 ? vola / avg_vola : 0 r_vola := if r_vola > math.pow(len1, 1 / pow1) math.pow(len1, 1 / pow1) else if r_vola < 1 1 else r_vola pow2 = math.pow(r_vola, pow1) len2 = math.sqrt(len) * len1 bet = len2 / (len2 + 1) kv = math.pow(bet, math.sqrt(pow2)) lower_band := y == 1 ? _src : del2 < 0 ? _src : _src - kv * del2 upper_band := y == 1 ? _src : del1 < 0 ? _src : _src + kv * del1 beta = 0.45 * (len - 1) / (0.45 * (len - 1) + 2) pr = _phase < -100 ? 0.5 : _phase > 100 ? 2.5 : _phase / 100 + 1.5 alpha = math.pow(beta, pow2) ma1 = 0.0 det0 = 0.0 jma = 0.0 det1 = 0.0 ma1 := (1 - alpha) * _src + alpha * nz(ma1[1]) det0 := (_src - ma1) * (1 - beta) + beta * nz(det0[1]) ma2 = ma1 + pr * det0 det1 := (ma2 - nz(jma[1])) * math.pow(1 - alpha, 2) + math.pow(alpha, 2) * nz(det1[1]) jma := nz(jma[1]) + det1 jma // Jurik Moving Average Envelope // credit to @redktrader f_atrEnv(_src, _length, _multiplier) => atr = ta.atr(_length) * _multiplier atr_us = atr atr_ls = atr atr_us := ta.change(_src) != 0 ? atr : atr_us[1] atr_ls := ta.change(_src) != 0 ? atr : atr_ls[1] atr_upper = _src + atr_us atr_lower = _src - atr_ls [atr_upper, atr_lower] // Calculations j = f_jma(jmaSrc, jmaLen, jmaPhs) [j_up, j_low] = f_atrEnv(j, atrLen, atrMul) long = ta.crossover(hlc3, j_low) ? close : na short = ta.crossunder(hlc3, j_up) ? close : na // Colors green = #0F7173 red = #F05D5E tan = #D8A47F white = #FFFFFF // Plots plot (j, 'JMA Centerline', tan, display=display.none) plot (j_up, 'ATR Upper', green) plot (j_low, 'ATR Lower', red) // Alerts if long strategy.entry("Enter Long", strategy.long) else if short strategy.entry("Enter Short", strategy.short)