
SUPERTREND, ATR, ADX, EMA, AI
O maior problema das estratégias tradicionais de SuperTrend? Os parâmetros fixos apresentam uma grande variação de desempenho em diferentes cenários de mercado. Esta versão aumentada por AI ajusta dinamicamente o múltiplo ATR, aumentando o múltiplo para o dobro do valor base durante a alta flutuação e diminuindo para 0,85 vezes durante a baixa flutuação. Os dados de retrospectiva mostram que esse mecanismo de adaptação pode reduzir significativamente os falsos sinais em mercados de turbulência.
A inovação central reside no sistema de filtragem em três níveis: identificação do estado do mercado, classificação do sinal de AI e mecanismo de confirmação múltipla. Não é mais simples que o preço quebre a linha SuperTrend para entrar em jogo, mas exige que a classificação de AI atinja mais de 65 pontos para desencadear um sinal de negociação.
O mecanismo de pontuação foi elaborado com precisão: o surto de volume de transação foi ponderado em 20 pontos, o desvio de preço da linha SuperTrend em 25 pontos, a consistência da tendência EMA em 20 pontos, a qualidade do estado de mercado em 15 pontos e a distância entre o preço e a linha de tendência em 20 pontos. Com um total de 100 pontos, o limiar de 65 pontos por defeito significa que apenas sinais de alta qualidade podem ser filtrados.
Especificamente, quando o volume de transação é superior a 2,5 vezes a média de 20 ciclos, recebe uma pontuação de 20 pontos, e o desvio de preço da linha SuperTrend é superior a 1,5 vezes o ATR, recebe uma pontuação de 25 pontos. Esta pontuação quantitativa evita julgamentos subjetivos, e cada sinal tem um apoio de dados claro. Em uso prático, recomenda-se ajustar os requisitos mínimos de pontuação de acordo com as características de diferentes variedades.
A estratégia identifica três tipos de estados de mercado através do índice ATR e do indicador ADX: período de tendência (regime = 1), período de alta volatilidade (regime = 2) e período de turbulência (regime = 0). Quando o índice ATR é superior a 1,4, é considerado um período de alta volatilidade, quando o ADX é inferior a 20 e o índice ATR é inferior a 0,9, é considerado um período de turbulência.
A lógica de ajuste do multiplicador de auto-adaptação: o multiplicador de período de alta volatilidade aumenta em 40% × (ATR -1,0), o multiplicador de período de turbulência diminui em 85% do valor de base. Isso significa que o multiplicador de base de 3,0 pode ser ajustado para 4,2 em caso de extrema volatilidade e diminui para 2,55 em caso de turbulência. Este mecanismo de ajuste dinâmico aumenta significativamente a adaptabilidade da estratégia em diferentes ambientes de mercado.
O ATR é a opção preferida, com o padrão de 2,5 vezes o ATR para tolerar flutuações normais e parar em tempo hábil. A paralisação percentual é adequada para variedades com uma taxa de flutuação relativamente estável, enquanto o SuperTrend é o padrão de parada imediata quando a tendência é invertida.
A configuração de stop-loss suporta o modelo de risco-receita, com um risco-receita padrão de 2.5:1 que tem uma vantagem estatística. Após a ativação do stop-loss tracking, a linha de stop-loss de uma posição lucrativa é ajustada dinamicamente de acordo com a distância ATR de 2,5 vezes, maximizando o lucro em condições de tendência.
O filtro de tendência da EMA assegura a entrada apenas quando a direção da EMA de 50 ciclos é consistente, evitando a negociação de contracorrente. O filtro de período de turbulência salta diretamente o sinal de regime = 0, embora possa perder algumas oportunidades, mas reduz significativamente a taxa de falso sinal.
O filtro de volume de transação exige que o volume de transação seja superior à média de 20 ciclos de entrada, garantindo que haja participação de mercado suficiente para suportar a quebra do preço. O período de resfriamento de 10 ciclos evita transações frequentes e reduz os custos de transação.
Para as criptomoedas, recomenda-se que a pontuação mínima de AI seja aumentada para 70 pontos, enquanto que as ações tradicionais podem ser reduzidas para 60 pontos. Os comerciantes de alta frequência podem reduzir o período de arrefecimento para 5 ciclos, enquanto os investidores de longa linha recomendam um período de 15 ciclos.
O parâmetro de comprimento do ATR 10 é um ponto de equilíbrio otimizado, excesso de curto será excessivamente sensível, excesso de comprimento será retardado. O múltiplo básico de 3.0 é adequado para a maioria das variedades, variedades de alta flutuação podem ser ajustadas para 3.5, variedades de baixa flutuação para 2.5.
Informações importantes sobre os riscosOs resultados de retrospectiva histórica não são indicadores de resultados futuros. A estratégia pode sofrer perdas contínuas em condições de mercado extremas e é recomendado um controle rigoroso de posições individuais não superiores a 30% do capital total. Há diferenças significativas no desempenho da estratégia em diferentes ambientes de mercado e é necessário monitorar e ajustar os parâmetros.
/*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)