
SUPERTREND, ATR, ADX, EMA, AI
Самая большая проблема традиционной стратегии SuperTrend? фиксированные параметры сильно различаются в различных рыночных условиях. Эта усовершенствованная версия AI динамически регулирует ATR-множитель, повышая его в 2 раза до базового значения во время высоких колебаний и снижая его до 0,85 раза во время низких колебаний.
Основные новшества заключаются в трехслойной системе фильтрации: распознавание состояния рынка, оценка сигналов ИИ и многократное подтверждение механизма. Теперь не просто цена прорывает линию SuperTrend, чтобы войти в игру, а требует, чтобы рейтинг ИИ достиг 65 или более, чтобы вызвать торговый сигнал. Эта система оценки комплексно учитывает 5 измерений, таких как всплеск объема торговли, степень отклонения цены и согласованность тенденции.
Рейтинговый механизм был разработан так, чтобы набрать 20 баллов за рост объема продаж, 25 баллов за отклонение цены от линии SuperTrend, 20 баллов за соответствие тренду EMA, 15 баллов за качество состояния рынка и 20 баллов за расстояние между ценой и линией тренда. В общей сложности 100 баллов, а по умолчанию 65-балльный порог означает, что только высококачественные сигналы могут пройти фильтрацию.
В частности, полный балл 20 баллов получается, когда объем сделок превышает среднее значение 20-ти циклов в 2,5 раза, а полный балл 25 баллов получается, когда цена отклоняется от линии SuperTrend более чем в 1,5 раза ATR. Такая количественная оценка позволяет избежать субъективного суждения, и каждый сигнал имеет четкую поддержку данных. В практическом использовании рекомендуется адаптировать минимальные требования к баллам в зависимости от характеристик различных сортов.
Стратегия использует коэффициент ATR и показатель ADX для выявления трех видов состояний рынка: период тренда (режим = 1), период высокой волатильности (режим = 2) и период колебаний (режим = 0). Высокий волатильный период определяется, когда коэффициент ATR превышает 1,4.
Логика самостоятельной корректировки коэффициентов: увеличение коэффициента во время высоких колебаний на 40% при соотношении ATR -1,0 и снижение коэффициента во время шока до 85% от базового значения. Это означает, что коэффициент в период шока 3.0 может быть скорректирован до 4,2 при крайних колебаниях, а во время шока - до 2,55. Такой динамический механизм корректировки значительно повышает адаптивность стратегии в различных рыночных условиях.
Динамический стоп ATR является предпочтительным вариантом, по умолчанию, 2,5 раза ATR может терпеть нормальные колебания и своевременно остановить. Процентный стоп подходит для относительно стабильного количества колебаний, а режим SuperTrend сразу же выровняет позиции при обратном тренде.
Стоп-пост поддерживает риско-прибыльный коэффициент, при этом по умолчанию риско-прибыльный коэффициент 2.5:1 имеет статистическое преимущество. После включения отслеживания стоп-постов, стоп-пост прибыльной позиции будет динамически корректироваться в соответствии с расстоянием ATR в 2,5 раза, чтобы максимизировать прибыль в трендовых условиях.
Тренд-фильтр EMA обеспечивает запуск только при совпадении направления 50-циклической EMA, предотвращая обратную торговлю. Фильтрация в период колебаний напрямую пропускает сигнал режима = 0, хотя может пропустить некоторые возможности, но значительно снижает уровень ложных сигналов.
Фильтрация объема сделок требует, чтобы объем сделок был выше среднего значения 20 циклов при входе, чтобы обеспечить достаточную долю участия в рынке, чтобы поддержать ценовую прорыв. 10-циклический период охлаждения предотвращает частые сделки и снижает затраты на сделки.
Для криптовалют рекомендуется повысить минимальный рейтинг AI до 70 баллов, для традиционных акций - до 60 баллов. Для высокочастотных трейдеров рекомендуется сократить период охлаждения до 5 циклов, а для долгосрочных инвесторов - до 15 циклов.
ATR длины параметра 10 является оптимизированной точки равновесия, слишком короткий будет чрезмерно чувствительным, слишком длинный будет задерживаться. Основной коэффициент 3.0 подходит для большинства сортов, высокая волатильность сортов может быть изменена до 3.5, низкая волатильность сортов снижена до 2.5.
Важные подсказкиИсторические результаты ретроспектив не являются индикатором будущей прибыльности. Стратегия может иметь последовательные потери в экстремальных рыночных условиях, рекомендуется строго контролировать одну позицию не более чем на 30% от общего капитала.
/*backtest
start: 2026-01-01 00:00:00
end: 2026-02-24 00:00:00
period: 1h
basePeriod: 1h
exchanges: [{"eid":"Futures_Binance","currency":"PAXG_USDT","balance":500000}]
*/
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © DefinedEdge
//@version=6
strategy("SuperTrend AI Strategy [Adaptive]", "ST AI Strategy ◈",
overlay = true,
initial_capital = 10000,
default_qty_type = strategy.percent_of_equity,
default_qty_value= 30,
commission_type = strategy.commission.percent,
commission_value = 0.06,
slippage = 2,
pyramiding = 0,
calc_on_every_tick = false,
max_labels_count = 500)
// ============================================================================
// INPUTS
// ============================================================================
// --- SuperTrend Core ---
GRP_ST = "◈ SuperTrend"
i_atLen = input.int(10, "ATR Length", minval=1, maxval=50, group=GRP_ST)
i_bMult = input.float(3.0, "Base Multiplier", minval=0.5, maxval=10.0, step=0.1, group=GRP_ST)
i_src = input.source(hl2, "Source", group=GRP_ST)
// --- Regime Detection ---
GRP_REG = "◈ Regime Detection"
i_regLen = input.int(40, "Regime Lookback", minval=10, maxval=100, group=GRP_REG)
i_adxLen = input.int(14, "ADX Length", minval=5, maxval=50, group=GRP_REG)
i_adxThr = input.float(20, "ADX Trend Threshold", minval=10, maxval=40, step=1, group=GRP_REG)
i_adapt = input.bool(true, "Adaptive Multiplier", group=GRP_REG)
// --- AI Scoring ---
GRP_AI = "◈ AI Engine"
i_trendLen = input.int(50, "Trend EMA Length", minval=10, maxval=200, group=GRP_AI)
i_volLen = input.int(20, "Volume MA Length", minval=5, maxval=50, group=GRP_AI)
i_minSc = input.int(65, "Min Signal Score", minval=0, maxval=90, group=GRP_AI, tooltip="Only enter trades when the AI score meets this threshold.")
// --- Risk Management ---
GRP_RISK = "◈ Risk Management"
i_slMode = input.string("ATR", "Stop Loss Mode", options=["ATR", "Percent", "SuperTrend"], group=GRP_RISK, tooltip="ATR: dynamic SL based on volatility. Percent: fixed %. SuperTrend: exit on trend flip.")
i_slAtr = input.float(2.5, "SL ATR Multiplier", minval=0.5, maxval=8.0, step=0.1, group=GRP_RISK)
i_slPct = input.float(3.0, "SL Percent", minval=0.5, maxval=10.0, step=0.1, group=GRP_RISK)
i_tpMode = input.string("RR", "Take Profit Mode", options=["RR", "Percent", "None"], group=GRP_RISK, tooltip="RR: risk/reward ratio based on SL distance. Percent: fixed %. None: hold until SL or flip.")
i_tpRR = input.float(2.5, "TP Risk:Reward", minval=0.5, maxval=10.0, step=0.1, group=GRP_RISK)
i_tpPct = input.float(6.0, "TP Percent", minval=0.5, maxval=20.0, step=0.1, group=GRP_RISK)
i_trail = input.bool(true, "Trailing Stop", group=GRP_RISK, tooltip="When enabled, SL trails in the direction of the trade after entry.")
i_trailAtr = input.float(2.5, "Trail ATR Mult", minval=0.5, maxval=8.0, step=0.1, group=GRP_RISK)
// --- Filters ---
GRP_FLT = "◈ Trade Filters"
i_trendF = input.bool(true, "EMA Trend Filter", group=GRP_FLT, tooltip="Only take longs above EMA, shorts below EMA.")
i_regF = input.bool(true, "Skip Ranging", group=GRP_FLT, tooltip="Skip entries during ranging regime. Reduces whipsaws.")
i_volF = input.bool(true, "Volume Filter", group=GRP_FLT, tooltip="Only enter if volume is above average.")
i_sigCD = input.int(10, "Cooldown (bars)", minval=0, maxval=50, group=GRP_FLT)
// --- Backtest Window ---
GRP_BT = "◈ Backtest"
bool inWindow = true
// --- Visuals ---
GRP_VIS = "◈ Visuals"
i_sGlow = input.bool(true, "Band Glow Effect", group=GRP_VIS)
i_sRegBg = input.bool(true, "Regime Background", group=GRP_VIS)
// --- Colors ---
GRP_COL = "◈ Colors"
i_cBull = input.color(color.new(#089981, 0), "Bull", inline="c1", group=GRP_COL)
i_cBear = input.color(color.new(#f23645, 0), "Bear", inline="c1", group=GRP_COL)
// ============================================================================
// CORE CALCULATIONS
// ============================================================================
int n = bar_index
float atr = ta.atr(i_atLen)
float safeAtr = nz(atr, 0.001)
// ── Regime Detection ──
float atrMa = ta.sma(atr, i_regLen)
float atrRatio = atrMa > 0 ? atr / atrMa : 1.0
// ADX
float upMove = high - high[1]
float dnMove = low[1] - low
float plusDM = upMove > dnMove and upMove > 0 ? upMove : 0
float minusDM = dnMove > upMove and dnMove > 0 ? dnMove : 0
float trueR = ta.tr
float smoothTR = ta.rma(trueR, i_adxLen)
float smoothPD = ta.rma(plusDM, i_adxLen)
float smoothND = ta.rma(minusDM, i_adxLen)
float plusDI = smoothTR > 0 ? 100 * smoothPD / smoothTR : 0
float minusDI = smoothTR > 0 ? 100 * smoothND / smoothTR : 0
float diSum = plusDI + minusDI
float dx = diSum > 0 ? 100 * math.abs(plusDI - minusDI) / diSum : 0
float adx = ta.rma(dx, i_adxLen)
var int regime = 1
if atrRatio > 1.4
regime := 2
else if adx < i_adxThr and atrRatio < 0.9
regime := 0
else
regime := 1
// ── Adaptive Multiplier ──
float adaptMult = i_bMult
if i_adapt
if regime == 2
adaptMult := i_bMult * (1.0 + (atrRatio - 1.0) * 0.4)
else if regime == 0
adaptMult := i_bMult * 0.85
adaptMult := math.max(math.min(adaptMult, i_bMult * 2.0), i_bMult * 0.5)
// ── SuperTrend ──
var float stBand = na
var int stDir = 1
float upperBase = i_src + adaptMult * atr
float lowerBase = i_src - adaptMult * atr
float prevBand = nz(stBand[1], stDir == 1 ? lowerBase : upperBase)
if stDir == 1
stBand := math.max(lowerBase, prevBand)
if close < stBand
stDir := -1
stBand := upperBase
else
stBand := math.min(upperBase, prevBand)
if close > stBand
stDir := 1
stBand := lowerBase
bool trendFlip = stDir != stDir[1]
// ── Trend EMA ──
float trendMa = ta.ema(close, i_trendLen)
bool trendUp = close > trendMa
bool trendDn = close < trendMa
// ── Volume ──
float volMa = ta.sma(volume, i_volLen)
// ============================================================================
// AI SIGNAL SCORING
// ============================================================================
scoreSignal(bool isBull) =>
float score = 0
// Factor 1: Volume surge (0-20)
float vRat = volMa > 0 ? volume / volMa : 1.0
score += vRat >= 2.5 ? 20 : vRat >= 1.5 ? 14 : vRat >= 1.0 ? 8 : 3
// Factor 2: Displacement beyond band (0-25)
float disp = isBull ? (close - stBand) : (stBand - close)
float dispAtr = safeAtr > 0 ? disp / safeAtr : 0
score += dispAtr >= 1.5 ? 25 : dispAtr >= 0.8 ? 18 : dispAtr >= 0.3 ? 12 : dispAtr > 0 ? 5 : 0
// Factor 3: EMA trend alignment (0-20)
bool aligned = (isBull and trendUp) or (not isBull and trendDn)
float emaDist = math.abs(close - trendMa) / safeAtr
score += aligned and emaDist > 0.5 ? 20 : aligned ? 14 : emaDist < 0.3 ? 8 : 2
// Factor 4: Regime quality (0-15)
score += regime == 1 ? 15 : regime == 2 ? 8 : 3
// Factor 5: Band distance before flip (0-20)
float prevDist = not na(stBand[1]) ? math.abs(close[1] - stBand[1]) / safeAtr : 0
score += prevDist >= 2.0 ? 20 : prevDist >= 1.0 ? 14 : prevDist >= 0.5 ? 8 : 3
int(math.min(math.round(score), 100))
// ============================================================================
// TRADE LOGIC
// ============================================================================
var int lastEntryBar = 0
var float entryPrice = 0.0
var float slPrice = 0.0
var float tpPrice = 0.0
var int lastSigScore = 0
var int lastSigDir = 0
var bool lastSigBright = false
bool longEntry = false
bool shortEntry = false
int sigScore = 0
// Cooldown check
bool cdOk = (n - lastEntryBar) > i_sigCD
if trendFlip and inWindow and cdOk and barstate.isconfirmed
if stDir == 1
sigScore := scoreSignal(true)
// Apply filters
bool passScore = sigScore >= i_minSc
bool passTrend = not i_trendF or trendUp
bool passReg = not i_regF or regime != 0
bool passVol = not i_volF or (volume > volMa)
if passScore and passTrend and passReg and passVol
longEntry := true
else
sigScore := scoreSignal(false)
bool passScore = sigScore >= i_minSc
bool passTrend = not i_trendF or trendDn
bool passReg = not i_regF or regime != 0
bool passVol = not i_volF or (volume > volMa)
if passScore and passTrend and passReg and passVol
shortEntry := true
// ── Calculate SL/TP Levels ──
float slDist = 0.0
if i_slMode == "ATR"
slDist := atr * i_slAtr
else if i_slMode == "Percent"
slDist := close * i_slPct / 100
else // SuperTrend mode
slDist := math.abs(close - stBand)
float tpDist = 0.0
if i_tpMode == "RR"
tpDist := slDist * i_tpRR
else if i_tpMode == "Percent"
tpDist := close * i_tpPct / 100
// ── Execute Entries ──
if longEntry
// Close any existing short
if strategy.position_size < 0
strategy.close("Short")
entryPrice := close
slPrice := close - slDist
tpPrice := i_tpMode != "None" ? close + tpDist : na
strategy.entry("Long", strategy.long)
if not na(slPrice) and i_tpMode != "None" and not na(tpPrice)
strategy.exit("Long Exit", "Long", stop=slPrice, limit=tpPrice,
trail_points = i_trail ? slDist / syminfo.mintick : na,
trail_offset = i_trail ? (atr * i_trailAtr) / syminfo.mintick : na)
else if not na(slPrice)
strategy.exit("Long SL", "Long", stop=slPrice,
trail_points = i_trail ? slDist / syminfo.mintick : na,
trail_offset = i_trail ? (atr * i_trailAtr) / syminfo.mintick : na)
lastEntryBar := n
lastSigScore := sigScore
lastSigDir := 1
lastSigBright := sigScore >= 70
if shortEntry
// Close any existing long
if strategy.position_size > 0
strategy.close("Long")
entryPrice := close
slPrice := close + slDist
tpPrice := i_tpMode != "None" ? close - tpDist : na
strategy.entry("Short", strategy.short)
if not na(slPrice) and i_tpMode != "None" and not na(tpPrice)
strategy.exit("Short Exit", "Short", stop=slPrice, limit=tpPrice,
trail_points = i_trail ? slDist / syminfo.mintick : na,
trail_offset = i_trail ? (atr * i_trailAtr) / syminfo.mintick : na)
else if not na(slPrice)
strategy.exit("Short SL", "Short", stop=slPrice,
trail_points = i_trail ? slDist / syminfo.mintick : na,
trail_offset = i_trail ? (atr * i_trailAtr) / syminfo.mintick : na)
lastEntryBar := n
lastSigScore := sigScore
lastSigDir := -1
lastSigBright := sigScore >= 70
// ── SuperTrend Flip Exit (if SL mode is SuperTrend) ──
if i_slMode == "SuperTrend" and trendFlip
if strategy.position_size > 0 and stDir == -1
strategy.close("Long", comment="ST Flip")
if strategy.position_size < 0 and stDir == 1
strategy.close("Short", comment="ST Flip")
// ============================================================================
// VISUALS
// ============================================================================
// ── Band Color ──
color bandCore = stDir == 1 ? i_cBull : i_cBear
color bandColor = regime == 2 ? color.new(#ffab00, 0) : regime == 0 ? color.new(#78909c, 20) : bandCore
// ── Glow ──
plot(i_sGlow ? stBand : na, "Glow Outer", color=color.new(bandColor, 85), linewidth=6, style=plot.style_linebr)
plot(i_sGlow ? stBand : na, "Glow Mid", color=color.new(bandColor, 70), linewidth=4, style=plot.style_linebr)
// ── Band ──
plot(regime != 0 ? stBand : na, "Band (Solid)", color=bandColor, linewidth=2, style=plot.style_linebr)
plot(regime == 0 ? stBand : na, "Band (Ranging)", color=bandColor, linewidth=2, style=plot.style_linebr)
// ── Flip Dot ──
plot(trendFlip ? stBand : na, "Flip Dot", color=bandCore, style=plot.style_circles, linewidth=5, join=false)
// ── Regime Background ──
bgcolor(i_sRegBg and regime == 2 ? color.new(#ffab00, 95) : na, title="Volatile BG")
bgcolor(i_sRegBg and regime == 0 ? color.new(#78909c, 96) : na, title="Ranging BG")
// ── Trend EMA ──
plot(trendMa, "Trend EMA", color=color.new(trendUp ? i_cBull : i_cBear, 65), linewidth=1)
// ============================================================================
// HIDDEN PLOTS
// ============================================================================
plot(sigScore > 0 ? sigScore : na, "Signal Score", display=display.none)
plot(adaptMult, "Adaptive Mult", display=display.none)
plot(adx, "ADX", display=display.none)
plot(float(regime), "Regime", display=display.none)
plot(float(stDir), "Trend Direction", display=display.none)