A estratégia Avalanche é um sistema de reversão à média em estilo de grade inspirado no consultor especialista original MetaTrader Avalanche v1.2. A ideia é monitorar a relação entre o preço e um preço de referência de equilíbrio (ERP) de prazo superior calculado como uma média móvel simples. Quando o preço é negociado abaixo do ERP, a estratégia espera uma recuperação em direção à média e acumula posições longas. Quando o preço é negociado acima do ERP, a estratégia busca uma queda e acumula posições vendidas. Cada posição adicional é espaçada por limites de distância configuráveis, enquanto cada entrada recebe níveis individuais de stop-loss e take-profit.
Esta porta StockSharp concentra-se na perna "em direção" do algoritmo original. As ordens de hedge fora do ERP da versão MQL não são replicadas porque as estratégias StockSharp operam em uma única posição líquida, mas a lógica de empilhamento, buffer e realização de lucros da grade permanece fiel à abordagem original.
Como funciona
Assine duas séries de velas: o período de negociação e um período de ERP que alimenta a média móvel.
Calcule uma média móvel simples do ERP e determine se o preço está posicionado acima ou abaixo dela. Um buffer configurável evita inversões frequentes.
Quando uma nova tendência de ERP aparecer, feche qualquer grade aberta e aguarde novos sinais.
Abra uma posição inicial na direção que deve trazer o preço de volta ao ERP (comprado abaixo, vendido acima) se a sinalização OpenStartingOrders estiver habilitada.
Continue adicionando posições na mesma direção quando o preço avançar na distância IntervalToward (empilhamento de impulso).
Adicione entradas de proteção adicionais quando o preço se mover contra a grade em IntervalToward + StackBufferToward (empilhamento martingale).
Cada entrada tem sua própria meta de stop-loss e take-profit medida em pontos, garantindo que as pernas lucrativas possam ser fechadas individualmente enquanto a grade continua a gerenciar a exposição restante.
Parâmetros
Nome
Descrição
BaseVolume
Volume base do pedido usado antes de aplicar multiplicadores.
TowardMultiplier
Multiplicador de lote para entradas padrão para ERP.
TowardInterestMultiplier
Multiplicador usado quando o instrumento paga swap positivo na direção de negociação.
IntervalToward
Distância em pontos necessária para adicionar uma pilha de acompanhamento de tendências.
StackBufferToward
Buffer adicional adicionado ao intervalo ao acumular contra movimentos adversos de preços.
TakeProfitToward
Distância de lucro em pontos para cada entrada. Defina como 0 para desativar.
StopLossToward
Distância de stop-loss em pontos para cada entrada. Defina como 0 para desativar.
ErpPeriod
Número de períodos da média móvel simples do ERP.
ErpChangeBuffer
Buffer (em pontos) aplicado ao redor do ERP antes de mudar o viés.
CandleType
Prazo de negociação usado para acionar entradas e saídas.
ErpCandleType
Prazo usado para calcular a média móvel do ERP.
OpenStartingOrders
Se ativado, abre imediatamente a primeira ordem de grade quando as condições são satisfeitas.
Diferenças em relação ao original EA
Somente a perna voltada para ERP é implementada porque a estratégia StockSharp mantém uma única posição líquida. As ordens de proteção são omitidas.
A execução de ordens depende de ordens de mercado em vez de ordens de stop pendentes usadas pela versão MQL.
A detecção da direção de troca é preservada para escolher entre os multiplicadores padrão e de juros.
Dicas de uso
Ajuste IntervalToward e StackBufferToward para controlar a agressividade com que a grade adiciona novas negociações.
Garantir que o instrumento e os prazos selecionados forneçam liquidez suficiente; os sistemas de rede podem acumular uma exposição considerável.
Combine a estratégia com controles de risco externos (paradas de ações, filtros de sessão) ao executar em produção.
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()