Diese Strategie repliziert den klassischen Moving-Average-Crossover-Expert-Advisor aus MQL. Sie nutzt StockSharp-High-Level-APIs, um zwei einfache gleitende Durchschnitte aus der gewählten Kerzenserie zu überwachen. Signale entstehen, wenn der schnelle Durchschnitt den langsamen kreuzt, und die Strategie kann optional eine aktive Position schließen, wenn das entgegengesetzte Crossover auftritt.
Handelslogik
Den konfigurierten Kerzentyp abonnieren und schnelle sowie langsame SMA auf jeder abgeschlossenen Kerze berechnen.
Ein bullisches Crossover erkennen, wenn die schnelle SMA von unterhalb auf oberhalb der langsamen SMA wechselt. Ist keine Position aktiv, eine Long-Position mit dem angegebenen Volumen öffnen.
Ein bärisches Crossover erkennen, wenn die schnelle SMA von oberhalb auf unterhalb der langsamen SMA wechselt. Ist keine Position aktiv, eine Short-Position mit dem angegebenen Volumen öffnen.
Optional eine bestehende Position sofort schließen, wenn das entgegengesetzte Crossover erkannt wird, entsprechend dem "Close on Opposite Signal"-Schalter des ursprünglichen Skripts.
Risikomanagement
Feste Stop-Loss- und Take-Profit-Werte in Preispunkten anwenden. Beide Niveaus werden für jeden neuen Einstieg neu berechnet.
Den Schutzstop auf Break-even verschieben, nachdem der Preis die konfigurierte Triggerdistanz zurückgelegt hat, und einen zusätzlichen Offset als gesicherten Gewinn behalten.
Einen Trailing Stop aktivieren, sobald die Position die definierte Startdistanz gewinnt. Der Stop wird anhand des günstigsten Kerzenpreises verschoben und nie gegen den Trade bewegt.
Parameter
Fast MA Period: Länge der schnellen SMA zur Crossover-Erkennung.
Slow MA Period: Länge der langsamen SMA zur Crossover-Erkennung.
Trade Volume: Ordergröße in Lots.
Stop Loss (points): Distanz in Instrumentpunkten für den anfänglichen Stop Loss.
Take Profit (points): Distanz in Instrumentpunkten für den anfänglichen Take Profit.
Break-even Trigger: Gewinndistanz, die die Verschiebung des Stops auf Break-even aktiviert.
Break-even Offset: Zusätzliche Punkte, die nach Break-even als Gewinn behalten werden.
Trailing Start: Gewinndistanz, die vor Aktivierung des Trailing Stops erforderlich ist.
Trailing Distance: Abstand zwischen Preis und Trailing Stop.
Close On Opposite: Ob ein aktiver Trade geschlossen wird, wenn ein entgegengesetztes Crossover erscheint.
Candle Type: Kerzenserie für Indikatorberechnungen.
Nutzungshinweise
Stellen Sie sicher, dass die Strategie an eine Security mit gültigem PriceStep gebunden ist. Wenn der Schritt nicht verfügbar ist, wird der Wert 1 verwendet.
Trailing- und Break-even-Verwaltung arbeiten auf abgeschlossenen Kerzen und entsprechen dem Verhalten des ursprünglichen EA, der auf Barschluss reagiert.
Optimieren Sie Moving-Average-Längen und Risikoeinstellungen, um das System an verschiedene Märkte oder Zeitrahmen anzupassen.
using System;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// Moving Averages Crossover strategy: EMA crossover.
/// Buys when fast EMA crosses above slow EMA. Sells on cross below.
/// </summary>
public class MovingAveragesCrossoverStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _fastPeriod;
private readonly StrategyParam<int> _slowPeriod;
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
public int FastPeriod
{
get => _fastPeriod.Value;
set => _fastPeriod.Value = value;
}
public int SlowPeriod
{
get => _slowPeriod.Value;
set => _slowPeriod.Value = value;
}
public MovingAveragesCrossoverStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(15).TimeFrame())
.SetDisplay("Candle Type", "Candle timeframe", "General");
_fastPeriod = Param(nameof(FastPeriod), 10)
.SetGreaterThanZero()
.SetDisplay("Fast EMA", "Fast EMA period", "Indicators");
_slowPeriod = Param(nameof(SlowPeriod), 30)
.SetGreaterThanZero()
.SetDisplay("Slow EMA", "Slow EMA period", "Indicators");
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var fast = new ExponentialMovingAverage { Length = FastPeriod };
var slow = new ExponentialMovingAverage { Length = SlowPeriod };
decimal? prevFast = null;
decimal? prevSlow = null;
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(fast, slow, (candle, fastVal, slowVal) =>
{
if (candle.State != CandleStates.Finished)
return;
if (!IsFormedAndOnlineAndAllowTrading())
return;
if (prevFast.HasValue && prevSlow.HasValue)
{
var crossUp = prevFast.Value <= prevSlow.Value && fastVal > slowVal;
var crossDown = prevFast.Value >= prevSlow.Value && fastVal < slowVal;
if (crossUp && Position <= 0)
BuyMarket();
else if (crossDown && Position >= 0)
SellMarket();
}
prevFast = fastVal;
prevSlow = slowVal;
})
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, fast);
DrawIndicator(area, slow);
DrawOwnTrades(area);
}
}
}
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
from StockSharp.Algo.Strategies import Strategy
class moving_averages_crossover_strategy(Strategy):
def __init__(self):
super(moving_averages_crossover_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(15))) \
.SetDisplay("Candle Type", "Candle timeframe", "General")
self._fast_period = self.Param("FastPeriod", 10) \
.SetGreaterThanZero() \
.SetDisplay("Fast EMA", "Fast EMA period", "Indicators")
self._slow_period = self.Param("SlowPeriod", 30) \
.SetGreaterThanZero() \
.SetDisplay("Slow EMA", "Slow EMA period", "Indicators")
self._prev_fast = None
self._prev_slow = None
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(moving_averages_crossover_strategy, self).OnReseted()
self._prev_fast = None
self._prev_slow = None
def OnStarted2(self, time):
super(moving_averages_crossover_strategy, self).OnStarted2(time)
self._fast_ind = ExponentialMovingAverage()
self._fast_ind.Length = self._fast_period.Value
self._slow_ind = ExponentialMovingAverage()
self._slow_ind.Length = self._slow_period.Value
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(self._fast_ind, self._slow_ind, self._process_candle).Start()
def _process_candle(self, candle, fast_value, slow_value):
if candle.State != CandleStates.Finished:
return
if not self.IsFormedAndOnlineAndAllowTrading():
return
fast_val = float(fast_value)
slow_val = float(slow_value)
if self._prev_fast is not None and self._prev_slow is not None:
if self._prev_fast <= self._prev_slow and fast_val > slow_val and self.Position <= 0:
self.BuyMarket()
elif self._prev_fast >= self._prev_slow and fast_val < slow_val and self.Position >= 0:
self.SellMarket()
self._prev_fast = fast_val
self._prev_slow = slow_val
def CreateClone(self):
return moving_averages_crossover_strategy()