基本原理 该指标背后的基本原理是:当资产价格达到极限时,无论趋势如何,都会出现(可能不相等,但)相反的反应。
设置 无论您选择什么时间段,默认设置都不是最好的。我个人认为,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)