//@version=6
indicator('<[Расширенный двойной конверт HL MTF]>', '<[ADHL-Env-MTF]>', true)
// Настройки МТФ
mtf = input.timeframe('', 'Таймфрейм')
// ВЫБОР ТИПА МУВИНГА
ma_type = input.string('EMA', 'Тип мувинга', options = ['SMA', 'EMA', 'WMA', 'Hull MA', 'VWMA', 'TEMA', 'JMA', 'LSMA', 'ALMA', 'Vidya', 'ZLEMA', 'FRAMA'])
ma_length = input.int(9, 'Период мувинга')
ma_source = input.source(hl2, 'Источник для MA')
// Дополнительные параметры для некоторых MA
ma_offset = input.int(0, 'Смещение MA')
jma_power = input.float(2.0, 'JMA: Мощность', minval = 1, maxval = 10, step = 0.1)
alma_offset = input.float(0.85, 'ALMA: Смещение', minval = 0, maxval = 1, step = 0.01)
alma_sigma = input.float(6.0, 'ALMA: Сигма', minval = 1, maxval = 10, step = 0.1)
// Настройки конвертов
lookback1 = input.int(5, 'Период волатильности 1')
mult1 = input.float(1.0, 'Множитель 1', step = 0.1)
lookback2 = input.int(10, 'Период волатильности 2')
mult2 = input.float(1.0, 'Множитель 2', step = 0.1)
// Получаем данные с нужного ТФ
src = request.security(syminfo.tickerid, mtf, ma_source)
high_mtf = request.security(syminfo.tickerid, mtf, high)
low_mtf = request.security(syminfo.tickerid, mtf, low)
// ФУНКЦИИ РАСЧЕТА РАЗНЫХ MA
// Hull Moving Average
hma(_src, _length) =>
_wma1 = ta.wma(_src, _length / 2)
_wma2 = ta.wma(_src, _length)
2 * _wma1 - _wma2
// Volume Weighted Moving Average
vwma(_src, _length) =>
_sum = math.sum(_src * volume, _length)
_vol = math.sum(volume, _length)
_sum / _vol
// Triple Exponential Moving Average
tema(_src, _length) =>
_ema1 = ta.ema(_src, _length)
_ema2 = ta.ema(_ema1, _length)
_ema3 = ta.ema(_ema2, _length)
3 * _ema1 - 3 * _ema2 + _ema3
// Jurik Moving Average (упрощенная версия)
jma(_src, _length, _power) =>
_beta = 0.45 * (_length - 1) / (0.45 * (_length - 1) + 2)
_alpha = math.pow(_beta, _power)
_jma = 0.0
_jma := _alpha * _src + (1 - _alpha) * nz(_jma[1])
_jma
// Least Squares Moving Average
lsma(_src, _length) =>
_sum_x = _length * (_length - 1) / 2
_sum_x2 = _length * (_length - 1) * (2 * _length - 1) / 6
_sum_xy = 0.0
_sum_y = 0.0
for i = 0 to _length - 1 by 1
_sum_xy := _sum_xy + i * _src[i]
_sum_y := _sum_y + _src[i]
_sum_y
_slope = (_length * _sum_xy - _sum_x * _sum_y) / (_length * _sum_x2 - _sum_x * _sum_x)
_intercept = (_sum_y - _slope * _sum_x) / _length
_intercept + _slope * (_length - 1)
// Arnaud Legoux Moving Average
alma(_src, _length, _offset, _sigma) =>
_m = math.floor(_offset * (_length - 1))
_s = _length / _sigma
_weights = array.new_float(0)
_norm = 0.0
for i = 0 to _length - 1 by 1
_w = math.exp(-math.pow(i - _m, 2) / (2 * math.pow(_s, 2)))
array.push(_weights, _w)
_norm := _norm + _w
_norm
_sum = 0.0
for i = 0 to _length - 1 by 1
_sum := _sum + _src[i] * array.get(_weights, i)
_sum
_sum / _norm
// Variable Index Dynamic Average
vidya(_src, _length) =>
_cmos = math.abs(ta.change(_src, 9)) / ta.atr(9)
_alpha = 2.0 / (_length + 1)
_vidya = 0.0
_vidya := _alpha * _cmos * _src + (1 - _alpha * _cmos) * nz(_vidya[1])
_vidya
// Zero-Lag EMA
zlema(_src, _length) =>
_lag = math.round((_length - 1) / 2)
_zlsrc = _src + _src - _src[_lag]
ta.ema(_zlsrc, _length)
// Fractal Adaptive Moving Average
frama(_src, _length) =>
float _n1 = math.max(ta.highest(_length), ta.lowest(_length))
float _n2 = math.max(ta.highest(_length / 2), ta.lowest(_length / 2))
float _n3 = math.max(ta.highest(_length / 2), ta.lowest(_length / 2))
float _dimen = 1.0
if _n1 > 0 and _n2 > 0 and _n3 > 0
float _temp1 = math.log(_n1 + _n2)
float _temp2 = math.log(_n3)
_dimen := (_temp1 - _temp2) / math.log(2)
_dimen
float _alpha = math.exp(-4.6 * (_dimen - 1))
_alpha := math.max(math.min(_alpha, 1), 0.01)
float _frama = 0.0
_frama := _alpha * _src + (1 - _alpha) * nz(_frama[1])
_frama
// ВЫБОР ТИПА MA
get_ma() =>
switch ma_type
'SMA' => ta.sma(src, ma_length)
'EMA' => ta.ema(src, ma_length)
'WMA' => ta.wma(src, ma_length)
'Hull MA' => hma(src, ma_length)
'VWMA' => vwma(src, ma_length)
'TEMA' => tema(src, ma_length)
'JMA' => jma(src, ma_length, jma_power)
'LSMA' => lsma(src, ma_length)
'ALMA' => alma(src, ma_length, alma_offset, alma_sigma)
'Vidya' => vidya(src, ma_length)
'ZLEMA' => zlema(src, ma_length)
'FRAMA' => frama(src, ma_length)
// Расчет центральной линии
center_line = get_ma()
// ПЕРВЫЙ конверт: Суммарная волатильность
total_hl_diff = 0.0
for i = 0 to lookback1 - 1 by 1
total_hl_diff := total_hl_diff + high_mtf[i] - low_mtf[i]
total_hl_diff
upper_band1 = center_line + total_hl_diff * mult1
lower_band1 = center_line - total_hl_diff * mult1
// ВТОРОЙ конверт: Общий диапазон
overall_high = ta.highest(high_mtf, lookback2)
overall_low = ta.lowest(low_mtf, lookback2)
hl_range = overall_high - overall_low
upper_band2 = center_line + hl_range * mult2
lower_band2 = center_line - hl_range * mult2
// Отрисовка
plot(center_line, 'Мувинг', #ff9800, 2)
// Конверт 1
u1 = plot(upper_band1, 'Верх Суммарный', #ff5252, 2)
l1 = plot(lower_band1, 'Низ Суммарный', #ff5252, 2)
fill(u1, l1, color.new(color.red, 90), 'Конверт 1')
// Конверт 2
u2 = plot(upper_band2, 'Верх Общий', #4caf50, 2)
l2 = plot(lower_band2, 'Низ Общий', #4caf50, 2)
fill(u2, l2, color.new(color.green, 90), 'Конверт 2')
// Общие High/Low
plot(overall_high, 'Общий High', #ff0057, 1, plot.style_circles)
plot(overall_low, 'Общий Low', #00ffff, 1, plot.style_circles)
var table logo = table.new(position.bottom_right, 1, 1)
table.cell(logo, 0, 0, 'DM', text_size = size.normal, text_color = #00897b)
//===========================================================================//