Estrategia de scalping con triple retroceso de EMA

EMA ATR PULLBACK SCALPING
Fecha de creación: 2025-09-30 13:04:41 Última modificación: 2025-09-30 13:04:41
Copiar: 0 Número de Visitas: 443
2
Seguir
319
Seguidores

Estrategia de scalping con triple retroceso de EMA Estrategia de scalping con triple retroceso de EMA

25/50/100 EMA triple filtrado, esto es el verdadero retiro de la tendencia

Dejar de operar con una sola línea de equilibrio. Esta estrategia construye un sistema de identificación de tendencias completo con tres EMA de 25/50/100, que requiere que los EMA se alineen en orden y se inclinen en la misma dirección, además de un requisito de intervalo mínimo de 0.10 veces el ATR. Los datos muestran que este mecanismo de triple filtración es eficaz para evitar falsos rebotes en mercados convulsos y solo funciona en condiciones de tendencia real.

La clave está en una “arregla EMA limpia”: 25>50>100 en caso de que haya varios ejes y todos se inclinen hacia arriba, y 25<50<100 en caso de que haya un ejes vacío y todos se inclinen hacia abajo. El filtro de intervalo asegura que la tendencia sea lo suficientemente fuerte como para evitar señales no válidas en el estado de adhesión uniforme.

El diseño de la lógica de reversión es preciso y la reversión debe ser confirmada en 15 ciclos.

El núcleo de la estrategia es el mecanismo de detección de reversión. Un reversión múltiple requiere que el precio toque 25 o 50 EMA pero se mantenga por encima de 100 EMA, y un reversión en blanco requiere que el precio toque 25 o 50 EMA pero se mantenga por debajo de 100 EMA. Este diseño es más preciso que el tradicional “romper el soporte y volver a comprar”.

La configuración de la ventana de retroceso de 15 ciclos es razonable. Los datos de retroceso indican que la verdadera retroceso de tendencia generalmente se completa en una reversión de 10 a 15 ciclos, y la retroceso más allá de esta ventana de tiempo a menudo significa que la tendencia puede cambiar.

El mecanismo de confirmación de entrada es estricto, toda la línea K debe estar completamente separada de 25EMA

Las condiciones de entrada son muy estrictas: después de confirmar el cierre de la línea K, toda la línea K (abierta, alta, baja, cerrada) debe estar completamente en el lado correcto de 25EMA. Este diseño evita falsas rupturas y ruido en el disco, asegurando la entrada solo después de la confirmación de la inversión real.

Requisitos de entrada de múltiples cabezas: apertura> 25EMA, mínimo> 25EMA, cierre> 25EMA. Requisitos de entrada de cabezas vacías: apertura <25EMA, máximo <25EMA, cierre <25EMA. Este método de “confirmación de la línea K completa” mejora significativamente la calidad de la entrada y reduce las transacciones no válidas.

10% de la posición + 0.05% de los honorarios, adecuado para operaciones de extirpación de alta frecuencia

La estrategia de configuración de posición predeterminada del 10% es moderada, tanto para obtener suficientes ganancias como para controlar el riesgo individual. La configuración de comisión del 0.05% es cercana al costo real de la transacción, y los resultados de la retrospectiva tienen más valor de referencia.

Nota importante: La estrategia solo incluye la lógica de entrada, no se ha configurado el stop loss. El uso en el entorno físico debe estar acompañado de una estricta gestión de riesgos, se recomienda configurar un stop loss de 2-3 veces el ATR y un stop loss de 1.5-2 veces el RRR.

El escenario de aplicación es claro, el mercado de tendencias está funcionando bien, pero los mercados convulsivos deben tener cuidado

La estrategia funciona muy bien en mercados de tendencia clara, especialmente en el caso de retracciones y compras unilaterales. Sin embargo, en mercados de volatilidad horizontal, los requisitos de clasificación de EMA son difíciles de cumplir y las oportunidades de negociación son relativamente escasas. Esto es en realidad la ventaja de la estrategia, que evita el exceso de operaciones en un entorno desfavorable.

Nota de riesgo: La retroalimentación histórica no representa ganancias futuras, la estrategia tiene un riesgo de pérdidas continuas. El mercado de la oscilación puede presentar un estado de ausencia de señal prolongado, y se debe esperar pacientemente el entorno de mercado adecuado. Se recomienda una verificación de transacciones simuladas adecuadas antes de su uso.

Código Fuente de la Estrategia
/*backtest
start: 2025-01-01 00:00:00
end: 2025-09-27 08:00:00
period: 1d
basePeriod: 1d
exchanges: [{"eid":"Futures_Bybit","currency":"ETH_USDT","balance":500000}]
*/

//@version=6
strategy("Clean 25/50/100 EMA Pullback Scalper — Entries Only (Side Select)",
     overlay=true, calc_on_every_tick=true, calc_on_order_fills=true,
     initial_capital=10000, commission_type=strategy.commission.percent, commission_value=0.05,
     pyramiding=0, default_qty_type=strategy.percent_of_equity, default_qty_value=10)

// === Side selector ===
side = input.string("Both", "Trade Side", options=["Both", "Long Only", "Short Only"])
longsEnabled  = side == "Both" or side == "Long Only"
shortsEnabled = side == "Both" or side == "Short Only"

// === Inputs ===
lenFast   = input.int(25,  "Fast EMA (pullback)", minval=1)
lenMid    = input.int(50,  "Mid EMA (filter)",    minval=1)
lenSlow   = input.int(100, "Slow EMA (safety)",   minval=1)

useSlope  = input.bool(true,  "Require EMAs sloping same way?")
useSpread = input.bool(true,  "Require clean spacing (min spread)?")
spreadPct = input.float(0.10, "Min spread vs ATR (0.10 = 0.10×ATR)", step=0.01, minval=0.0)

pullLookback = input.int(15, "Max bars after pullback", minval=1, maxval=100)
showSignals  = input.bool(true, "Show entry markers?")

// === Series ===
ema25  = ta.ema(close, lenFast)
ema50  = ta.ema(close, lenMid)
ema100 = ta.ema(close, lenSlow)
atr    = ta.atr(14)

// === Trend & spacing ===
isUpStack   = ema25 > ema50 and ema50 > ema100
isDownStack = ema25 < ema50 and ema50 < ema100
slopeUp     = ema25 > ema25[1] and ema50 > ema50[1] and ema100 > ema100[1]
slopeDown   = ema25 < ema25[1] and ema50 < ema50[1] and ema100 < ema100[1]

minGap = atr * spreadPct
spreadUpOK   = (ema25 - ema50) > minGap and (ema50 - ema100) > minGap
spreadDownOK = (ema100 - ema50) > minGap and (ema50 - ema25) > minGap

trendLongOK  = isUpStack   and (useSlope ? slopeUp   : true) and (useSpread ? spreadUpOK   : true)
trendShortOK = isDownStack and (useSlope ? slopeDown : true) and (useSpread ? spreadDownOK : true)

// === Pullback detection state ===
var bool  pullArmedLong   = false
var bool  pullArmedShort  = false
var int   pullBarIdxLong  = na
var int   pullBarIdxShort = na
var float pullMinLong     = na
var float pullMaxShort    = na

// Long pullback state
if trendLongOK
    touched25 = low <= ema25
    touched50 = low <= ema50
    stayedAbove100 = low > ema100
    if (touched25 or touched50) and stayedAbove100
        pullArmedLong  := true
        pullBarIdxLong := bar_index
        pullMinLong    := na(pullMinLong) ? low : math.min(pullMinLong, low)
    else if pullArmedLong
        pullMinLong := na(pullMinLong) ? low : math.min(pullMinLong, low)
        if low <= ema100 or (bar_index - pullBarIdxLong > pullLookback)
            pullArmedLong := false
            pullMinLong   := na
else
    pullArmedLong := false
    pullMinLong   := na

// Short pullback state
if trendShortOK
    touched25s = high >= ema25
    touched50s = high >= ema50
    stayedBelow100 = high < ema100
    if (touched25s or touched50s) and stayedBelow100
        pullArmedShort  := true
        pullBarIdxShort := bar_index
        pullMaxShort    := na(pullMaxShort) ? high : math.max(pullMaxShort, high)
    else if pullArmedShort
        pullMaxShort := na(pullMaxShort) ? high : math.max(pullMaxShort, high)
        if high >= ema100 or (bar_index - pullBarIdxShort > pullLookback)
            pullArmedShort := false
            pullMaxShort   := na
else
    pullArmedShort := false
    pullMaxShort   := na

// === Entry triggers (confirmed bar & whole candle outside 25 EMA) ===
longEntryRaw  = pullArmedLong  and barstate.isconfirmed and (open > ema25 and low > ema25 and close > ema25) and (na(pullMinLong)  or pullMinLong  > ema100)
shortEntryRaw = pullArmedShort and barstate.isconfirmed and (open < ema25 and high < ema25 and close < ema25) and (na(pullMaxShort) or pullMaxShort < ema100)

longEntry  = longsEnabled  and longEntryRaw
shortEntry = shortsEnabled and shortEntryRaw

// Disarm after trigger
if longEntry
    pullArmedLong := false
    pullMinLong   := na
if shortEntry
    pullArmedShort := false
    pullMaxShort   := na

// === Orders (entries only; no TP/SL) ===
if longEntry and strategy.position_size <= 0
    strategy.entry("Long", strategy.long)

if shortEntry and strategy.position_size >= 0
    strategy.entry("Short", strategy.short)

// === Plots & visuals ===
plot(ema25,  "EMA 25",  color=color.new(color.teal, 0))
plot(ema50,  "EMA 50",  color=color.new(color.orange, 0))
plot(ema100, "EMA 100", color=color.new(color.purple, 0))

bgcolor(trendLongOK  ? color.new(color.green, 92) : na)
bgcolor(trendShortOK ? color.new(color.red, 92)   : na)

if showSignals and longEntry
    label.new(bar_index, low, "▲ BUY\nFull candle above 25 EMA", style=label.style_label_up, textcolor=color.white, color=color.new(color.green, 0))
if showSignals and shortEntry
    label.new(bar_index, high, "▼ SELL\nFull candle below 25 EMA", style=label.style_label_down, textcolor=color.white, color=color.new(color.red, 0))