La estrategia Avalanche es un sistema de reversión a la media estilo cuadrícula inspirado en el asesor experto original MetaTrader Avalanche v1.2. La idea es monitorear la relación entre el precio y un precio de referencia de equilibrio (ERP) de marco temporal más alto calculado como un promedio móvil simple. Cuando el precio cotiza por debajo del ERP, la estrategia espera un rebote hacia el promedio y acumula posiciones largas. Cuando el precio cotiza por encima del ERP, la estrategia busca una caída y acumula posiciones cortas. Cada posición adicional está espaciada por umbrales de distancia configurables, mientras que cada entrada recibe niveles individuales de stop-loss y take-profit.
Este puerto StockSharp se centra en el tramo "hacia" del algoritmo original. Las órdenes de cobertura fuera del ERP de la versión MQL no se replican porque las estrategias StockSharp operan en una sola posición neta, pero la lógica de acumulación, almacenamiento en búfer y toma de ganancias de la red se mantiene fiel al enfoque original.
como funciona
Suscríbase a dos series de velas: el marco temporal de operaciones y un marco temporal de ERP que alimenta la media móvil.
Calcule una media móvil simple de ERP y determine si el precio está posicionado por encima o por debajo de ella. Un búfer configurable evita cambios frecuentes.
Cuando aparezca un nuevo sesgo de ERP, cierre cualquier cuadrícula abierta y espere nuevas señales.
Abra una posición inicial en la dirección que debería hacer que el precio regrese hacia el ERP (largo por debajo, corto por arriba) si la bandera OpenStartingOrders está habilitada.
Continúe agregando posiciones en la misma dirección cuando el precio avance una distancia IntervalToward (apilamiento de impulso).
Agregue entradas de protección adicionales cuando el precio se mueva contra la cuadrícula en IntervalToward + StackBufferToward (apilamiento de martingala).
Cada entrada tiene su propio objetivo de stop-loss y take-profit medido en puntos, lo que garantiza que las partes rentables se puedan cerrar individualmente mientras la red continúa gestionando la exposición restante.
Parámetros
Nombre
Descripción
BaseVolume
Volumen de orden base utilizado antes de aplicar multiplicadores.
TowardMultiplier
Multiplicador de lote para entradas estándar hacia ERP.
TowardInterestMultiplier
Multiplicador utilizado cuando el instrumento paga un swap positivo en la dirección de negociación.
IntervalToward
Distancia en puntos requerida para agregar una pila de seguimiento de tendencias.
StackBufferToward
Se agrega un colchón adicional al intervalo cuando se acumula contra movimientos adversos de precios.
TakeProfitToward
Distancia de toma de ganancias en puntos para cada entrada. Establezca en 0 para desactivar.
StopLossToward
Distancia de stop-loss en puntos para cada entrada. Establezca en 0 para desactivar.
ErpPeriod
Número de periodos para la media móvil simple del ERP.
ErpChangeBuffer
Búfer (en puntos) aplicado alrededor del ERP antes de cambiar el sesgo.
CandleType
Plazo de negociación utilizado para activar entradas y salidas.
ErpCandleType
Plazo utilizado para calcular la media móvil del ERP.
OpenStartingOrders
Si está habilitado, abre inmediatamente la primera orden de la cuadrícula cuando se cumplen las condiciones.
Diferencias vs. el EA original
Solo se implementa el tramo hacia ERP porque la estrategia StockSharp mantiene una única posición neta. Se omiten las órdenes de cobertura.
La ejecución de órdenes se basa en órdenes de mercado en lugar de las órdenes stop pendientes utilizadas por la versión MQL.
La detección de la dirección del swap se conserva para elegir entre los multiplicadores estándar y de interés.
Consejos de uso
Ajuste IntervalToward y StackBufferToward para controlar la agresividad con la que la cuadrícula agrega nuevas operaciones.
Garantizar que el instrumento y los plazos seleccionados proporcionen suficiente liquidez; Los sistemas de red pueden acumular una exposición considerable.
Combine la estrategia con controles de riesgo externos (paradas de acciones, filtros de sesión) cuando se ejecute en producción.
using System;
using System.Collections.Generic;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// Avalanche grid strategy - mean reversion around EMA.
/// Buys when price drops below EMA, sells when above.
/// Uses RSI to confirm oversold/overbought conditions.
/// </summary>
public class AvalancheStrategy : Strategy
{
private readonly StrategyParam<int> _emaPeriod;
private readonly StrategyParam<int> _rsiPeriod;
private readonly StrategyParam<decimal> _rsiOversold;
private readonly StrategyParam<decimal> _rsiOverbought;
private readonly StrategyParam<DataType> _candleType;
public int EmaPeriod { get => _emaPeriod.Value; set => _emaPeriod.Value = value; }
public int RsiPeriod { get => _rsiPeriod.Value; set => _rsiPeriod.Value = value; }
public decimal RsiOversold { get => _rsiOversold.Value; set => _rsiOversold.Value = value; }
public decimal RsiOverbought { get => _rsiOverbought.Value; set => _rsiOverbought.Value = value; }
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public AvalancheStrategy()
{
_emaPeriod = Param(nameof(EmaPeriod), 20)
.SetDisplay("EMA Period", "EMA period for equilibrium", "Indicators");
_rsiPeriod = Param(nameof(RsiPeriod), 14)
.SetDisplay("RSI Period", "RSI period", "Indicators");
_rsiOversold = Param(nameof(RsiOversold), 35m)
.SetDisplay("RSI Oversold", "RSI oversold level", "Indicators");
_rsiOverbought = Param(nameof(RsiOverbought), 65m)
.SetDisplay("RSI Overbought", "RSI overbought level", "Indicators");
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
.SetDisplay("Candle Type", "Candle timeframe", "General");
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType)];
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var ema = new ExponentialMovingAverage { Length = EmaPeriod };
var rsi = new RelativeStrengthIndex { Length = RsiPeriod };
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(ema, rsi, ProcessCandle)
.Start();
}
private void ProcessCandle(ICandleMessage candle, decimal emaValue, decimal rsiValue)
{
if (candle.State != CandleStates.Finished)
return;
var close = candle.ClosePrice;
// Below EMA and oversold - buy
if (close < emaValue && rsiValue <= RsiOversold && Position <= 0)
{
if (Position < 0)
BuyMarket();
BuyMarket();
}
// Above EMA and overbought - sell
else if (close > emaValue && rsiValue >= RsiOverbought && Position >= 0)
{
if (Position > 0)
SellMarket();
SellMarket();
}
}
}
import clr
clr.AddReference("StockSharp.Messages")
clr.AddReference("StockSharp.Algo")
clr.AddReference("StockSharp.Algo.Indicators")
clr.AddReference("StockSharp.Algo.Strategies")
from System import TimeSpan
from StockSharp.Messages import DataType, CandleStates
from StockSharp.Algo.Indicators import ExponentialMovingAverage, RelativeStrengthIndex
from StockSharp.Algo.Strategies import Strategy
class avalanche_strategy(Strategy):
def __init__(self):
super(avalanche_strategy, self).__init__()
self._ema_period = self.Param("EmaPeriod", 20) \
.SetDisplay("EMA Period", "EMA period for equilibrium", "Indicators")
self._rsi_period = self.Param("RsiPeriod", 14) \
.SetDisplay("RSI Period", "RSI period", "Indicators")
self._rsi_oversold = self.Param("RsiOversold", 35.0) \
.SetDisplay("RSI Oversold", "RSI oversold level", "Indicators")
self._rsi_overbought = self.Param("RsiOverbought", 65.0) \
.SetDisplay("RSI Overbought", "RSI overbought level", "Indicators")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(4))) \
.SetDisplay("Candle Type", "Candle timeframe", "General")
@property
def ema_period(self):
return self._ema_period.Value
@property
def rsi_period(self):
return self._rsi_period.Value
@property
def rsi_oversold(self):
return self._rsi_oversold.Value
@property
def rsi_overbought(self):
return self._rsi_overbought.Value
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(avalanche_strategy, self).OnReseted()
def OnStarted2(self, time):
super(avalanche_strategy, self).OnStarted2(time)
ema = ExponentialMovingAverage()
ema.Length = self.ema_period
rsi = RelativeStrengthIndex()
rsi.Length = self.rsi_period
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(ema, rsi, self.process_candle).Start()
def process_candle(self, candle, ema_value, rsi_value):
if candle.State != CandleStates.Finished:
return
close = float(candle.ClosePrice)
ema_val = float(ema_value)
rsi_val = float(rsi_value)
if close < ema_val and rsi_val <= self.rsi_oversold and self.Position <= 0:
if self.Position < 0:
self.BuyMarket()
self.BuyMarket()
elif close > ema_val and rsi_val >= self.rsi_overbought and self.Position >= 0:
if self.Position > 0:
self.SellMarket()
self.SellMarket()
def CreateClone(self):
return avalanche_strategy()