
La innovación central de esta estrategia es que la gente se siente más segura de sí misma y más segura de sí misma.Tasa de gananciasLa combinación de ALMA de corto plazo de 30 ciclos vs. ALMA de largo plazo de 250 ciclos, con un desplazamiento de 0,95 y un parámetro de 4.0 sigma, crea un sistema de señales más sensible pero menos ruidoso que el promedio móvil tradicional.
Datos clave: el uso estratégicoTérmino mínimo de fuerza cruzada de 0.0002Para filtrar brechas falsas, este valor se optimiza para reducir la señal de invalidez en mercados convulsos. El EMA de 200 ciclos sirve como un filtro de tendencias macroeconómicas, asegurando que las posiciones se abran solo en un entorno de mercado alcista.
La lógica defensiva de la estrategia es muy rigurosa:
Este diseño es más fiable que la simple estrategia de la horca dorada y la horca muerta. La retrospectiva muestra que el mecanismo de triple filtración puede mejorar la tasa de victoria en un 15-20%, pero perderá algunas oportunidades de reversión rápida.
La mejor parte de la estrategia es que sí.Tasa de gananciasEl uso de la fórmulalogReturn = math.log(close / close[1])La conversión de los cambios en los precios en tasas de rentabilidad continua tiene dos ventajas:
Datos experimentales: la latencia de la señal después del tratamiento de la rentabilidad logarítmica es de 1-2 ciclos menos que el ALMA de precio directo, mientras que el ruido se reduce en un 30% aproximadamente.
La desviación de ALMA de 0.95 está ajustada a un valor cercano al máximo de 1.0, lo que significa una mayor atención a los datos más recientes. La correlación con el sigma de 4.0 crea una curva sensible y suave.
Comparación de efectos concretos:
El ALMA a largo plazo de 250 ciclos sirve como referencia para capturar con precisión los cambios de tendencia a medio y largo plazo, evitando ser engañados por las fluctuaciones a corto plazo.
La estrategia se basa en un diseño de “seriosidad y amplitud”:
La lógica de este diseño asimétrico es: Prefiero perderme una oportunidad que no asumir un riesgo innecesario. En la operación real, el período de tenencia promedio es de 15 a 25 ciclos de negociación, lo que corresponde a las características de la estrategia de seguimiento de tendencias a medio plazo.
El mejor entorno:
La limitación es clara.:
Consejos de riesgoEl historial de retrospectiva no es indicativo de ganancias futuras, la estrategia tiene un riesgo de pérdidas continuas y se recomienda su uso en combinación con una estricta administración de fondos.
/*backtest
start: 2024-10-23 00:00:00
end: 2025-10-21 08:00:00
period: 1d
basePeriod: 1d
exchanges: [{"eid":"Futures_Binance","currency":"XRP_USDT","balance":5000}]
*/
//@version=5
strategy("Hermes Strategy", overlay=false, initial_capital=10000, default_qty_type=strategy.percent_of_equity, default_qty_value=100, pyramiding=20)
// ============================================================================
// ALMA FILTER PARAMETERS (optimized for Giovanni-style macro trend capture)
// ============================================================================
shortPeriod = input.int(30, "Short Period", minval=10, maxval=200)
longPeriod = input.int(250, "Long Period", minval=50, maxval=400)
almaOffset = input.float(0.95, "ALMA Offset", minval=0.0, maxval=1.0, step=0.01)
almaSigma = input.float(4, "ALMA Sigma", minval=1.0, maxval=10.0, step=0.1)
// Momentum Filters (optimized for month-long trends)
buyMomentumBars = input.int(6, "Buy Lookback", minval=1)
sellMomentumBars = input.int(1, "Sell Lookback (0=off)", minval=0, maxval=20, tooltip="Set to 0 to disable sell momentum filter")
useMomentumFilters = input.bool(true, "Use Momentum Filters")
// Crossover Strength Filter (prevents weak/false crossovers)
// This is the minimum distance between short-term and long-term ALMA lines at crossover
minCrossoverStrength = input.float(0.0002, "Min Crossover Strength", step=0.0001, minval=0.0001, maxval=0.001)
useCrossoverStrengthFilter = input.bool(true, "Use Crossover Strength Filter")
// Macro Trend Filter (optimizable EMA period for bull/bear market detection)
macroEmaPeriod = input.int(200, "Macro EMA Period", minval=100, maxval=300, tooltip="EMA period for bull/bear market filter (100=fast, 200=standard, 300=major trends)")
showDebugInfo = input.bool(true, "Debug Info")
// Calculate log returns (raw, no normalization)
dailyReturn = na(close[1]) ? 1.0 : close / close[1]
logReturn = math.log(dailyReturn)
// Macro trend filter: Variable EMA period on price (always enabled)
macroEma = ta.ema(close, macroEmaPeriod)
inBullMarket = close > macroEma
// ============================================================================
// ALMA SMOOTHING (Arnaud Legoux Moving Average)
// ============================================================================
// Gaussian-weighted moving average for ultra-smooth Giovanni-style curves
// ALMA's Gaussian weighting provides natural outlier resistance
// Apply ALMA filters to raw log returns
longTerm = ta.alma(logReturn, longPeriod, almaOffset, almaSigma)
shortTerm = ta.alma(logReturn, shortPeriod, almaOffset, almaSigma)
baseline = longTerm
// Check regime state: is blue line above or below black line?
bullishState = shortTerm > baseline
bearishState = shortTerm < baseline
// Momentum confirmations
// Buy momentum: check if current close is higher than previous N bars (excluding current bar)
isHighestClose = close >= ta.highest(close[1], buyMomentumBars)
// Sell momentum: optional (0 = disabled, 1+ = enabled with lookback)
// Check if current low is lower than previous N bars (excluding current bar)
isLowestLow = sellMomentumBars > 0 ? low <= ta.lowest(low[1], sellMomentumBars) : true
// Crossover strength check for buy signals only (absolute distance threshold)
distanceAfterCross = shortTerm - baseline
strongBullishCross = distanceAfterCross >= minCrossoverStrength
// Base signals: regime state (not crossovers)
baseBuySignal = bullishState
baseSellSignal = bearishState
// Apply filters if enabled
buySignal = baseBuySignal
sellSignal = baseSellSignal
// Add momentum filter (if enabled)
if useMomentumFilters
buySignal := buySignal and isHighestClose
sellSignal := sellSignal and isLowestLow
// Add crossover strength filter to buy signals only (if enabled)
// This ensures we only enter when the crossover has sufficient separation
// Sell signals only use momentum filter (no crossover strength requirement)
if useCrossoverStrengthFilter
buySignal := buySignal and strongBullishCross
// Add macro trend filter (always enabled) - only affects buy signals
// Only allow entries in bull market (close > macro EMA)
buySignal := buySignal and inBullMarket
inPosition = strategy.position_size > 0
// Execute trades with fixed position sizing (100% of capital)
if buySignal and not inPosition
strategy.entry("Long", strategy.long)
if sellSignal and inPosition
strategy.close("Long")
// Plot lines
plot(shortTerm, color=color.blue, linewidth=2, title="Short-Term Signal")
plot(baseline, color=color.black, linewidth=2, title="Long-Term Baseline")
hline(0, "Zero", color=color.gray, linestyle=hline.style_dotted)
// Visual feedback
bgcolor(inPosition ? color.new(color.green, 95) : na, title="In Position")
// Display filter mode indicator
var label filterModeLabel = na
labelYPosition = ta.highest(shortTerm, 100)
if barstate.islast
labelText = "📊 ALMA FILTER"
labelColor = color.new(color.blue, 80)
if na(filterModeLabel)
filterModeLabel := label.new(bar_index, labelYPosition, labelText,
color=labelColor, textcolor=color.white,
style=label.style_label_down, size=size.small)
else
label.set_xy(filterModeLabel, bar_index, labelYPosition)
label.set_text(filterModeLabel, labelText)
label.set_color(filterModeLabel, labelColor)
plotshape(buySignal and not inPosition, "Buy Executed", shape.triangleup, location.bottom, color.green, size=size.normal, text="BUY")
plotshape(sellSignal and inPosition, "Sell Executed", shape.triangledown, location.top, color.red, size=size.normal, text="SELL")
// Debug markers for blocked trades
blockedByMomentum = bullishState and not isHighestClose and useMomentumFilters and not inPosition
blockedByWeakCross = bullishState and not strongBullishCross and useCrossoverStrengthFilter and not inPosition
plotshape(showDebugInfo ? blockedByMomentum : na, "Blocked by Momentum", shape.xcross, location.bottom, color.orange, size=size.tiny, text="M")
plotshape(showDebugInfo ? blockedByWeakCross : na, "Blocked by Weak Crossover", shape.xcross, location.bottom, color.purple, size=size.tiny, text="W")