Die Simple MACD EA-Strategie ist eine direkte Portierung des klassischen MetaTrader Expert Advisors „Simple MACD EA“. Der Ansatz verwendet zwei exponentielle gleitende Durchschnitte (EMAs), um das MACD-Histogramm zu emulieren und den vorherrschenden Trend bei Ein-Minuten-Kerzen zu bestimmen. Long-Positionen werden eröffnet, wenn der schnelle EMA (Periode 100) den langsamen EMA (benutzerdefiniertes MACD-Niveau) überschreitet. Short-Positionen werden eröffnet, wenn der schnelle EMA unter den langsamen EMA fällt. Es wird immer nur eine Position beibehalten.
Handelsmanagementlogik
Trenderkennung: Die Differenz zwischen dem 100-Perioden-EMA und dem konfigurierbaren MACD EMA definiert die aktuelle Trendrichtung (+1, 0, -1). Eine Umkehr von negativ zu positiv eröffnet eine Long-Position. Eine Umkehr von positiv zu negativ eröffnet eine Short-Position.
Momentum-Bestätigung: Die Strategie verfolgt den Unterschied zwischen dem MACD EMA und einem etwas langsameren EMA (MACD level + 1). Wenn die Differenz gegenüber dem aktuellen Handel kleiner wird, nachdem sich der Preis um mindestens fünf Punkte im Gewinn bewegt hat, wird die Position vorzeitig geschlossen.
Zeitbasierter Schutz: Nachdem ein Trade für eine benutzerdefinierte Anzahl von Bewertungszyklen offen bleibt, aktiviert das System einen Soft-Stop, der die Toleranz für ungünstige Preisbewegungen im Verhältnis zum Einstiegspreis verringert.
Trailing-Exit: Sobald der Trade in die Gewinnzone geht und für genügend Zyklen aktiv bleibt, wird ein interner Trailing-Stop aktiviert. Das Stop-Level folgt dem Preis um die konfigurierte Anzahl von Punkten und kann eine begrenzte Anzahl von Malen aktualisiert werden. Bei Erreichen des Limits wird die Position geschlossen.
Ausstieg bei Trendumkehr: Wenn das Trendsignal in die entgegengesetzte Richtung wechselt, während der Preis bereits fünf Punkte im Gewinn liegt, wird die Position sofort geschlossen.
Parameter
Kerzentyp – Zeitrahmen, der für die EMA-Berechnungen verwendet wird (Standard: 1-Minuten-Kerzen).
Volumen – Bestellvolumen für Neuzugänge.
MACD Level – EMA Länge, die die langsame MACD-Komponente definiert. Ein sekundäres EMA mit der Länge MACD Level + 1 wird automatisch abgeleitet.
Trailing Stop – Entfernung in Punkten für den Trailing Exit. Zum Deaktivieren auf Null setzen.
Trailing-Updates – Maximale Anzahl von Trailing-Stop-Anpassungen pro Trade.
Wartezyklen – Anzahl der Kerzenauswertungen, die gewartet werden müssen, bevor der adaptive Softstopp aktiv wird.
Zusätzliche Hinweise
Die Strategie flacht immer die aktuelle Position ab, bevor die Richtung umgekehrt wird.
Preisschrittinformationen des ausgewählten Wertpapiers werden verwendet, um punktbasierte Entfernungen in tatsächliche Preise umzuwandeln.
Die Implementierung basiert auf dem High-Level-Kerzenabonnement API von StockSharp und stellt keine benutzerdefinierten Indikatorpuffer in die Warteschlange.
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>
/// Simple MACD EA strategy using fast/slow EMA difference for trend detection.
/// Buy when EMA difference crosses above zero, sell when it crosses below zero.
/// </summary>
public class SimpleMacdEaStrategy : Strategy
{
private readonly StrategyParam<int> _fastEmaPeriod;
private readonly StrategyParam<int> _slowEmaPeriod;
private readonly StrategyParam<DataType> _candleType;
private decimal _prevDiff;
private bool _hasPrev;
public int FastEmaPeriod
{
get => _fastEmaPeriod.Value;
set => _fastEmaPeriod.Value = value;
}
public int SlowEmaPeriod
{
get => _slowEmaPeriod.Value;
set => _slowEmaPeriod.Value = value;
}
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
public SimpleMacdEaStrategy()
{
_fastEmaPeriod = Param(nameof(FastEmaPeriod), 12)
.SetDisplay("Fast EMA", "Fast EMA period", "Indicators");
_slowEmaPeriod = Param(nameof(SlowEmaPeriod), 26)
.SetDisplay("Slow EMA", "Slow EMA period", "Indicators");
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(1).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();
_prevDiff = 0m;
_hasPrev = false;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_hasPrev = false;
var fastEma = new ExponentialMovingAverage { Length = FastEmaPeriod };
var slowEma = new ExponentialMovingAverage { Length = SlowEmaPeriod };
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(fastEma, slowEma, ProcessCandle)
.Start();
}
private void ProcessCandle(ICandleMessage candle, decimal fast, decimal slow)
{
if (candle.State != CandleStates.Finished)
return;
var diff = fast - slow;
if (!_hasPrev)
{
_prevDiff = diff;
_hasPrev = true;
return;
}
// Buy: MACD crosses above zero
var longSignal = _prevDiff <= 0 && diff > 0;
// Sell: MACD crosses below zero
var shortSignal = _prevDiff >= 0 && diff < 0;
if (Position <= 0 && longSignal)
{
if (Position < 0)
BuyMarket();
BuyMarket();
}
else if (Position >= 0 && shortSignal)
{
if (Position > 0)
SellMarket();
SellMarket();
}
_prevDiff = diff;
}
}
import clr
clr.AddReference("StockSharp.Messages")
clr.AddReference("StockSharp.Algo")
clr.AddReference("StockSharp.Algo.Indicators")
clr.AddReference("StockSharp.Algo.Strategies")
from System import TimeSpan, Math
from StockSharp.Messages import DataType, CandleStates
from StockSharp.Algo.Indicators import ExponentialMovingAverage
from StockSharp.Algo.Strategies import Strategy
class simple_macd_ea_strategy(Strategy):
"""Simple MACD EA using fast/slow EMA difference for trend detection.
Buy when EMA difference crosses above zero, sell when it crosses below zero."""
def __init__(self):
super(simple_macd_ea_strategy, self).__init__()
self._fast_ema_period = self.Param("FastEmaPeriod", 12) \
.SetDisplay("Fast EMA", "Fast EMA period", "Indicators")
self._slow_ema_period = self.Param("SlowEmaPeriod", 26) \
.SetDisplay("Slow EMA", "Slow EMA period", "Indicators")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(1))) \
.SetDisplay("Candle Type", "Candle timeframe", "General")
self._prev_diff = 0.0
self._has_prev = False
@property
def CandleType(self):
return self._candle_type.Value
@CandleType.setter
def CandleType(self, value):
self._candle_type.Value = value
@property
def FastEmaPeriod(self):
return self._fast_ema_period.Value
@property
def SlowEmaPeriod(self):
return self._slow_ema_period.Value
def OnReseted(self):
super(simple_macd_ea_strategy, self).OnReseted()
self._prev_diff = 0.0
self._has_prev = False
def OnStarted2(self, time):
super(simple_macd_ea_strategy, self).OnStarted2(time)
self._has_prev = False
fast_ema = ExponentialMovingAverage()
fast_ema.Length = self.FastEmaPeriod
slow_ema = ExponentialMovingAverage()
slow_ema.Length = self.SlowEmaPeriod
subscription = self.SubscribeCandles(self.CandleType)
subscription.Bind(fast_ema, slow_ema, self._process_candle).Start()
def _process_candle(self, candle, fast, slow):
if candle.State != CandleStates.Finished:
return
diff = float(fast) - float(slow)
if not self._has_prev:
self._prev_diff = diff
self._has_prev = True
return
# Buy: MACD crosses above zero
long_signal = self._prev_diff <= 0 and diff > 0
# Sell: MACD crosses below zero
short_signal = self._prev_diff >= 0 and diff < 0
if self.Position <= 0 and long_signal:
if self.Position < 0:
self.BuyMarket()
self.BuyMarket()
elif self.Position >= 0 and short_signal:
if self.Position > 0:
self.SellMarket()
self.SellMarket()
self._prev_diff = diff
def CreateClone(self):
return simple_macd_ea_strategy()