Die Avalanche-Strategie ist ein gitterartiges Mean-Reversion-System, das vom ursprünglichen Expertenberater MetaTrader Avalanche v1.2 inspiriert wurde. Die Idee besteht darin, die Beziehung zwischen dem Preis und einem Gleichgewichtsreferenzpreis (ERP) in einem höheren Zeitrahmen zu überwachen, der als einfacher gleitender Durchschnitt berechnet wird. Wenn der Preis unter dem ERP liegt, erwartet die Strategie eine Erholung in Richtung des Durchschnitts und baut Long-Positionen auf. Wenn der Preis über dem ERP liegt, sucht die Strategie nach einem Rückgang und baut Short-Positionen auf. Jede zusätzliche Position ist durch konfigurierbare Abstandsschwellen voneinander getrennt, während jeder Eintrag individuelle Stop-Loss- und Take-Profit-Level erhält.
Dieser StockSharp-Port konzentriert sich auf den „in Richtung“-Zweig des ursprünglichen Algorithmus. Absicherungsaufträge außerhalb des ERP-Systems aus der MQL-Version werden nicht repliziert, da die StockSharp-Strategien auf einer einzigen Nettoposition basieren, aber die Grid-Stacking-, Puffer- und Gewinnmitnahmelogik bleibt dem ursprünglichen Ansatz treu.
Wie es funktioniert
Abonnieren Sie zwei Kerzenserien: den Handelszeitrahmen und einen ERP-Zeitrahmen, der den gleitenden Durchschnitt speist.
Berechnen Sie einen einfachen gleitenden ERP-Durchschnitt und bestimmen Sie, ob der Preis darüber oder darunter liegt. Ein konfigurierbarer Puffer verhindert häufiges Umdrehen.
Wenn eine neue ERP-Verzerrung auftritt, schließen Sie alle offenen Gitter und warten Sie auf neue Signale.
Eröffnen Sie eine Anfangsposition in der Richtung, die den Preis wieder in Richtung ERP bringen soll (Long unten, Short oben), wenn das Flag OpenStartingOrders aktiviert ist.
Fügen Sie weiterhin Positionen in die gleiche Richtung hinzu, wenn der Preis um die Distanz IntervalToward steigt (Momentum-Stacking).
Fügen Sie zusätzliche Schutzeinträge hinzu, wenn sich der Preis um IntervalToward + StackBufferToward gegen das Raster bewegt (Martingal-Stacking).
Jeder Eintrag verfügt über ein eigenes Stop-Loss- und Take-Profit-Ziel, das in Punkten gemessen wird. Dadurch wird sichergestellt, dass profitable Abschnitte einzeln geschlossen werden können, während das Raster weiterhin das verbleibende Risiko verwaltet.
Parameter
Name
Beschreibung
BaseVolume
Basisauftragsvolumen vor Anwendung von Multiplikatoren.
TowardMultiplier
Lot-Multiplikator für Standard-ERP-Einträge.
TowardInterestMultiplier
Multiplikator, der verwendet wird, wenn das Instrument einen positiven Swap in Handelsrichtung zahlt.
IntervalToward
Distanz in Punkten, die erforderlich ist, um einen trendfolgenden Stapel hinzuzufügen.
StackBufferToward
Beim Stapeln gegen ungünstige Preisbewegungen wird dem Intervall zusätzlicher Puffer hinzugefügt.
TakeProfitToward
Take-Profit-Distanz in Punkten für jeden Eintrag. Zum Deaktivieren auf 0 setzen.
StopLossToward
Stop-Loss-Distanz in Punkten für jeden Eintrag. Zum Deaktivieren auf 0 setzen.
ErpPeriod
Anzahl der Perioden für den einfachen gleitenden ERP-Durchschnitt.
ErpChangeBuffer
Puffer (in Punkten), der um das ERP herum angewendet wird, bevor der Bias umgeschaltet wird.
CandleType
Handelszeitrahmen, der zum Auslösen von Ein- und Ausstiegen verwendet wird.
ErpCandleType
Zeitrahmen, der zur Berechnung des gleitenden ERP-Durchschnitts verwendet wird.
OpenStartingOrders
Wenn diese Option aktiviert ist, wird sofort die erste Rasterbestellung geöffnet, wenn die Bedingungen erfüllt sind.
Unterschiede zum Original EA
Da die StockSharp-Strategie eine einzige Nettoposition beibehält, wird nur der Richtung-ERP-Zweig implementiert. Absicherungsaufträge entfallen.
Die Auftragsausführung basiert auf Marktaufträgen und nicht auf den ausstehenden Stop-Aufträgen, die in der MQL-Version verwendet werden.
Die Erkennung der Swap-Richtung bleibt erhalten, um zwischen dem Standard- und dem Zinsmultiplikator zu wählen.
Anwendungstipps
Passen Sie IntervalToward und StackBufferToward an, um zu steuern, wie aggressiv das Raster neue Trades hinzufügt.
Stellen Sie sicher, dass das ausgewählte Instrument und die Zeitrahmen ausreichend Liquidität bieten; Gittersysteme können eine beträchtliche Belastung ansammeln.
Kombinieren Sie die Strategie mit externen Risikokontrollen (Aktienstopps, Sitzungsfilter), wenn Sie sie in der Produktion ausführen.
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()