//@version=5 indicator("Sigma Bands + RSI Filter MTF + Historical S/R & Trendlines", overlay=true, max_lines_count=500) src = input.source(close, "Источник") lookback = input.int(50, "Период расчёта отклонения", minval=10) maType = input.string("SMA", "Тип средней", options=["SMA", "EMA"]) sigma1 = input.float(1.0, "Множитель σ1 (слабая зона)") sigma2 = input.float(2.0, "Множитель σ2 (основная зона)") sigma3 = input.float(3.0, "Множитель σ3 (экстремум)") minAgree = input.int(3, "Мин. кол-во ТФ для сильного сигнала", minval=1, maxval=5) showWeak = input.bool(false, "Показывать слабые сигналы на графике", group="Отображение") boxWidth = input.int(50, "Ширина зон вправо (баров)", group="Зоны для лимиток") rsiLength = input.int(14, "Период RSI", group="RSI фильтр") rsiOversold = input.int(30, "Уровень перепроданности RSI", group="RSI фильтр") rsiOverbought = input.int(70, "Уровень перекупленности RSI", group="RSI фильтр") pivotLen = input.int(10, "Длина pivot (левая/правая)", group="Уровни S/R и трендлинии") showLevels = input.bool(true, "Показывать уровни на графике", group="Уровни S/R и трендлинии") levelLength = input.int(40, "Длина горизонтальных линий (баров)", group="Уровни S/R и трендлинии") trendExtend = input.int(40, "Длина трендлиний вперёд (баров)", group="Уровни S/R и трендлинии") maxDrawnLines = input.int(150, "Макс. кол-во линий на графике", group="Уровни S/R и трендлинии") mean = maType == "SMA" ? ta.sma(src, lookback) : ta.ema(src, lookback) dev = ta.stdev(src, lookback) up1 = mean + sigma1 * dev dn1 = mean - sigma1 * dev up2 = mean + sigma2 * dev dn2 = mean - sigma2 * dev up3 = mean + sigma3 * dev dn3 = mean - sigma3 * dev pMean = plot(mean, "Средняя", color=color.new(color.gray, 0), linewidth=2) pUp1 = plot(up1, "+1σ", color=color.new(color.red, 60)) pUp2 = plot(up2, "+2σ", color=color.new(color.red, 40)) pUp3 = plot(up3, "+3σ", color=color.new(color.red, 10)) pDn1 = plot(dn1, "-1σ", color=color.new(color.green, 60)) pDn2 = plot(dn2, "-2σ", color=color.new(color.green, 40)) pDn3 = plot(dn3, "-3σ", color=color.new(color.green, 10)) fill(pMean, pUp1, color=color.new(color.red, 93)) fill(pUp1, pUp2, color=color.new(color.red, 87)) fill(pUp2, pUp3, color=color.new(color.red, 75)) fill(pMean, pDn1, color=color.new(color.green, 93)) fill(pDn1, pDn2, color=color.new(color.green, 87)) fill(pDn2, pDn3, color=color.new(color.green, 75)) rsiValue = ta.rsi(src, rsiLength) atrValue = ta.atr(14) f_deviation(tf) => [m, d, s] = request.security(syminfo.tickerid, tf, [maType == "SMA" ? ta.sma(src, lookback) : ta.ema(src, lookback), ta.stdev(src, lookback), close], lookahead = barmerge.lookahead_off) result = 0.0 if d != 0 result := (s - m) / d result dev_M15 = f_deviation("15") dev_H1 = f_deviation("60") dev_H4 = f_deviation("240") dev_D1 = f_deviation("1D") dev_W1 = f_deviation("1W") devCurrent = 0.0 if dev != 0 devCurrent := (src - mean) / dev buyCountTF = (dev_M15 <= -sigma1 ? 1 : 0) + (dev_H1 <= -sigma1 ? 1 : 0) + (dev_H4 <= -sigma1 ? 1 : 0) + (dev_D1 <= -sigma1 ? 1 : 0) + (dev_W1 <= -sigma1 ? 1 : 0) sellCountTF = (dev_M15 >= sigma1 ? 1 : 0) + (dev_H1 >= sigma1 ? 1 : 0) + (dev_H4 >= sigma1 ? 1 : 0) + (dev_D1 >= sigma1 ? 1 : 0) + (dev_W1 >= sigma1 ? 1 : 0) // ---------- Обнаружение pivot-точек (визуальные уровни) ---------- pivotHighVal = ta.pivothigh(high, pivotLen, pivotLen) pivotLowVal = ta.pivotlow(low, pivotLen, pivotLen) var array allDrawnLines = array.new() f_registerLine(newLine) => array.push(allDrawnLines, newLine) if array.size(allDrawnLines) > maxDrawnLines oldLine = array.shift(allDrawnLines) line.delete(oldLine) var float lastResLvl = na var int lastResBar = na var float lastSupLvl = na var int lastSupBar = na if not na(pivotHighVal) and showLevels pivotBar = bar_index - pivotLen newLine = line.new(pivotBar, pivotHighVal, pivotBar + levelLength, pivotHighVal, color=color.new(color.red, 20), width=1, style=line.style_solid) f_registerLine(newLine) if not na(lastResLvl) trendLine = line.new(lastResBar, lastResLvl, pivotBar + trendExtend, pivotHighVal + (pivotHighVal - lastResLvl) * trendExtend / (pivotBar - lastResBar), color=color.new(color.red, 0), width=2, style=line.style_solid) f_registerLine(trendLine) lastResLvl := pivotHighVal lastResBar := pivotBar if not na(pivotLowVal) and showLevels pivotBar = bar_index - pivotLen newLine = line.new(pivotBar, pivotLowVal, pivotBar + levelLength, pivotLowVal, color=color.new(color.green, 20), width=1, style=line.style_solid) f_registerLine(newLine) if not na(lastSupLvl) trendLine = line.new(lastSupBar, lastSupLvl, pivotBar + trendExtend, pivotLowVal + (pivotLowVal - lastSupLvl) * trendExtend / (pivotBar - lastSupBar), color=color.new(color.green, 0), width=2, style=line.style_solid) f_registerLine(trendLine) lastSupLvl := pivotLowVal lastSupBar := pivotBar // ---------- Условия сигналов ---------- inStrongBuyZone = devCurrent <= -sigma2 and buyCountTF >= minAgree and rsiValue < rsiOversold inStrongSellZone = devCurrent >= sigma2 and sellCountTF >= minAgree and rsiValue > rsiOverbought inWeakBuyZone = devCurrent <= -sigma1 and not inStrongBuyZone and devCurrent > -sigma2 and rsiValue < rsiOversold inWeakSellZone = devCurrent >= sigma1 and not inStrongSellZone and devCurrent < sigma2 and rsiValue > rsiOverbought strongBuy = inStrongBuyZone and not inStrongBuyZone[1] strongSell = inStrongSellZone and not inStrongSellZone[1] weakBuy = inWeakBuyZone and not inWeakBuyZone[1] weakSell = inWeakSellZone and not inWeakSellZone[1] plotshape(strongBuy, title="Сильная покупка", location=location.belowbar, style=shape.triangleup, size=size.small, color=color.new(color.green, 0), text="▲") plotshape(strongSell, title="Сильная продажа", location=location.abovebar, style=shape.triangledown, size=size.small, color=color.new(color.red, 0), text="▼") plotshape(showWeak and weakBuy, title="Покупка", location=location.belowbar, style=shape.triangleup, size=size.tiny, color=color.new(color.green, 40)) plotshape(showWeak and weakSell, title="Продажа", location=location.abovebar, style=shape.triangledown, size=size.tiny, color=color.new(color.red, 40)) // ---------- Зоны для лимитных ордеров ---------- var box buyZoneBox = na var box sellZoneBox = na var box buyZoneBoxExt = na var box sellZoneBoxExt = na if barstate.islast box.delete(buyZoneBox) box.delete(sellZoneBox) box.delete(buyZoneBoxExt) box.delete(sellZoneBoxExt) buyZoneBox := box.new(left=bar_index - 20, top=dn2, right=bar_index + boxWidth, bottom=dn3, border_color=color.new(color.green, 0), border_width=1, bgcolor=color.new(color.green, 80), extend=extend.right, text="ЗОНА ПОКУПКИ", text_color=color.white, text_size=size.small) sellZoneBox := box.new(left=bar_index - 20, top=up3, right=bar_index + boxWidth, bottom=up2, border_color=color.new(color.red, 0), border_width=1, bgcolor=color.new(color.red, 80), extend=extend.right, text="ЗОНА ПРОДАЖИ", text_color=color.white, text_size=size.small) buyZoneBoxExt := box.new(left=bar_index - 20, top=dn3, right=bar_index + boxWidth, bottom=dn3 - dev, border_color=color.new(color.green, 30), border_width=1, border_style=line.style_dashed, bgcolor=color.new(color.green, 88), extend=extend.right, text="Экстремальная покупка", text_color=color.white, text_size=size.tiny) sellZoneBoxExt := box.new(left=bar_index - 20, top=up3 + dev, right=bar_index + boxWidth, bottom=up3, border_color=color.new(color.red, 30), border_width=1, border_style=line.style_dashed, bgcolor=color.new(color.red, 88), extend=extend.right, text="Экстремальная продажа", text_color=color.white, text_size=size.tiny) // ---------- Функции статуса и цвета для таблицы ---------- f_status(d) => result = "Нейтрально" if d <= -sigma3 result := "СИЛЬНАЯ ПОКУПКА" else if d <= -sigma2 result := "Покупка" else if d <= -sigma1 result := "Слабая покупка" else if d >= sigma3 result := "СИЛЬНАЯ ПРОДАЖА" else if d >= sigma2 result := "Продажа" else if d >= sigma1 result := "Слабая продажа" result f_color(d) => result = color.new(color.gray, 0) if d <= -sigma1 result := color.new(color.green, 0) else if d >= sigma1 result := color.new(color.red, 0) result // ---------- Таблица мультитаймфрейм ---------- var table t = table.new(position.top_right, 2, 7, bgcolor=color.new(color.black, 70), border_width=1) if barstate.islast table.cell(t, 0, 0, "Таймфрейм", text_color=color.white, bgcolor=color.new(color.blue, 50)) table.cell(t, 1, 0, "Статус", text_color=color.white, bgcolor=color.new(color.blue, 50)) table.cell(t, 0, 1, "M15", text_color=color.white) table.cell(t, 1, 1, f_status(dev_M15), text_color=f_color(dev_M15)) table.cell(t, 0, 2, "H1", text_color=color.white) table.cell(t, 1, 2, f_status(dev_H1), text_color=f_color(dev_H1)) table.cell(t, 0, 3, "H4", text_color=color.white) table.cell(t, 1, 3, f_status(dev_H4), text_color=f_color(dev_H4)) table.cell(t, 0, 4, "D1", text_color=color.white) table.cell(t, 1, 4, f_status(dev_D1), text_color=f_color(dev_D1)) table.cell(t, 0, 5, "W1", text_color=color.white) table.cell(t, 1, 5, f_status(dev_W1), text_color=f_color(dev_W1)) table.cell(t, 0, 6, "RSI", text_color=color.white) table.cell(t, 1, 6, str.tostring(rsiValue, "#.#"), text_color=rsiValue < rsiOversold ? color.new(color.green, 0) : rsiValue > rsiOverbought ? color.new(color.red, 0) : color.new(color.gray, 0)) alertcondition(strongBuy, "Strong Buy", "Вход в зону сильной покупки") alertcondition(strongSell, "Strong Sell", "Вход в зону сильной продажи")