Diese Strategie ist eine StockSharp-Portierung des MetaTrader 4-Experten AG.mq4. Der Roboter arbeitet mit zwei Berechnungen der Moving Average Convergence Divergence (MACD), die unterschiedliche Parametersätze verwenden. Der primäre MACD erzeugt Einstiegsauslöser, während der sekundäre (skalierte) MACD als Richtungsfilter fungiert, um Gegentrend-Trades zu vermeiden und Ausstiege zu kontrollieren. Die Logik spiegelt den ursprünglichen MQL4-Experten wider, indem sie nur geschlossene Kerzen auswertet und die Signalleitungsvorzeichenprüfungen wiederverwendet, die die ursprünglichen Aufträge gesperrt haben.
Handelslogik
Indikatoren
Primär MACD: schneller EMA = FastEmaLength, langsamer EMA = SlowEmaLength, Signal SMA = SignalSmaLength.
Sekundär MACD: schneller EMA = SlowEmaLength * 2, langsamer EMA = FastEmaLength * 2, Signal SMA = SignalSmaLength * 2.
Langer Eintrag
Die primäre MACD-Hauptleitung liegt über ihrer Signalleitung.
Die primäre MACD-Signalleitung ist negativ (unterhalb der Wasserlinie).
Die sekundäre MACD-Hauptleitung liegt über ihrer Signalleitung.
Die sekundäre MACD-Signalleitung ist negativ.
Kurzer Eintrag
Die primäre MACD-Hauptleitung liegt unterhalb ihrer Signalleitung.
Die primäre Signalleitung MACD ist positiv.
Die sekundäre MACD-Hauptleitung liegt unterhalb ihrer Signalleitung.
Die sekundäre Signalleitung MACD ist positiv.
Ausgangsregeln
Schließen Sie Long-Positionen, wenn der sekundäre MACD rückläufig wird, während die primäre Signallinie über Null bleibt.
Schließen Sie Short-Positionen, wenn der sekundäre MACD bullisch wird, während die primäre Signallinie unter Null bleibt.
Die Strategie reagiert nur auf fertige Kerzen und ignoriert unfertige Balken, um ein Neulackieren zu vermeiden.
Positionsmanagement
Alle Aufträge sind Marktaufträge mit dem durch OrderVolume definierten festen Volumen.
MaxOpenOrders spiegelt die ursprüngliche ORDER-Eingabe wider und begrenzt die Gesamtzahl der aktiven Orders plus offene Positionen. Stellen Sie es auf 0, um die Kappe zu entfernen.
StartProtection() wird aktiviert, sobald die Strategie startet, sodass der Risikomanager StockSharp das offene Risiko überwachen kann.
Parameter
Name
Beschreibung
OrderVolume
Basislosgröße für neue Trades.
FastEmaLength
Schneller EMA Zeitraum des primären MACD.
SlowEmaLength
Langsamer EMA Zeitraum des primären MACD.
SignalSmaLength
Signalglättungszeitraum für beide MACDs.
MaxOpenOrders
Maximale Anzahl kombinierter aktiver Orders und offener Positionen. Stellen Sie 0 auf unbegrenzt ein.
CandleType
Zeitrahmen, der zum Aufbau von Kerzen für beide Indikatoren verwendet wird.
Notizen
Das sekundäre MACD behält die gleiche Schnell-/Langsam-Reihenfolge wie im ursprünglichen EA bei, auch wenn die schnelle Periode größer als die langsame wird, um die Berechnungen des Autors beizubehalten.
Die Strategie platziert keine ausstehenden Aufträge; Es öffnet oder schließt zum Marktpreis, sobald die Bedingungen vorliegen.
Es werden keine zusätzlichen Stop-Loss- oder Take-Profit-Level hinzugefügt, da sich der ursprüngliche Experte ausschließlich auf Signalumkehrungen verlassen hat.
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>
/// AG MACD Dual strategy - MACD histogram crossover with EMA trend filter.
/// Buys when MACD histogram crosses above zero while price is above EMA.
/// Sells when MACD histogram crosses below zero while price is below EMA.
/// </summary>
public class AgMacdDualStrategy : Strategy
{
private readonly StrategyParam<int> _emaPeriod;
private readonly StrategyParam<DataType> _candleType;
private decimal _prevMacd;
private decimal _prevSignal;
private bool _hasPrev;
private decimal _currentEma;
public int EmaPeriod { get => _emaPeriod.Value; set => _emaPeriod.Value = value; }
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public AgMacdDualStrategy()
{
_emaPeriod = Param(nameof(EmaPeriod), 50)
.SetDisplay("EMA Period", "EMA trend filter", "Indicators");
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
.SetDisplay("Candle Type", "Candle timeframe", "General");
}
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities() => [(Security, CandleType)];
protected override void OnReseted() { base.OnReseted(); _prevMacd = 0m; _prevSignal = 0m; _hasPrev = false; _currentEma = 0m; }
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_hasPrev = false;
var macd = new MovingAverageConvergenceDivergenceSignal();
var ema = new ExponentialMovingAverage { Length = EmaPeriod };
var subscription = SubscribeCandles(CandleType);
subscription
.BindEx(macd, ProcessMacd)
.Bind(ema, ProcessEma)
.Start();
}
private void ProcessEma(ICandleMessage candle, decimal ema)
{
if (candle.State != CandleStates.Finished)
return;
_currentEma = ema;
}
private void ProcessMacd(ICandleMessage candle, IIndicatorValue value)
{
if (candle.State != CandleStates.Finished)
return;
if (!value.IsFinal || value.IsEmpty)
return;
var macdVal = value as MovingAverageConvergenceDivergenceSignalValue;
if (macdVal == null)
return;
var macdLine = macdVal.Macd;
var signalLine = macdVal.Signal;
if (macdLine == null || signalLine == null)
return;
var histogram = macdLine.Value - signalLine.Value;
if (!_hasPrev)
{
_prevMacd = macdLine.Value;
_prevSignal = signalLine.Value;
_hasPrev = true;
return;
}
var prevHist = _prevMacd - _prevSignal;
var close = candle.ClosePrice;
if (prevHist <= 0 && histogram > 0 && close > _currentEma && Position <= 0)
{
if (Position < 0)
BuyMarket();
BuyMarket();
}
else if (prevHist >= 0 && histogram < 0 && close < _currentEma && Position >= 0)
{
if (Position > 0)
SellMarket();
SellMarket();
}
_prevMacd = macdLine.Value;
_prevSignal = signalLine.Value;
}
}
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 MovingAverageConvergenceDivergenceSignal, ExponentialMovingAverage
from StockSharp.Algo.Strategies import Strategy
class ag_macd_dual_strategy(Strategy):
def __init__(self):
super(ag_macd_dual_strategy, self).__init__()
self._ema_period = self.Param("EmaPeriod", 50).SetDisplay("EMA Period", "EMA trend filter", "Indicators")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(4))).SetDisplay("Candle Type", "Candle timeframe", "General")
self._prev_macd = 0.0; self._prev_signal = 0.0; self._has_prev = False; self._current_ema = 0.0
@property
def ema_period(self): return self._ema_period.Value
@property
def candle_type(self): return self._candle_type.Value
def OnReseted(self):
super(ag_macd_dual_strategy, self).OnReseted()
self._prev_macd = 0.0; self._prev_signal = 0.0; self._has_prev = False; self._current_ema = 0.0
def OnStarted2(self, time):
super(ag_macd_dual_strategy, self).OnStarted2(time)
self._has_prev = False
macd = MovingAverageConvergenceDivergenceSignal()
ema = ExponentialMovingAverage(); ema.Length = self.ema_period
sub = self.SubscribeCandles(self.candle_type)
sub.BindEx(macd, self.process_macd).Bind(ema, self.process_ema).Start()
def process_ema(self, candle, ema):
if candle.State != CandleStates.Finished: return
self._current_ema = float(ema)
def process_macd(self, candle, value):
if candle.State != CandleStates.Finished: return
if not value.IsFinal or value.IsEmpty: return
if value.Macd is None or value.Signal is None: return
ml = float(value.Macd); sl = float(value.Signal); hist = ml - sl
if not self._has_prev: self._prev_macd = ml; self._prev_signal = sl; self._has_prev = True; return
prev_hist = self._prev_macd - self._prev_signal; close = float(candle.ClosePrice)
if prev_hist <= 0 and hist > 0 and close > self._current_ema and self.Position <= 0:
if self.Position < 0: self.BuyMarket()
self.BuyMarket()
elif prev_hist >= 0 and hist < 0 and close < self._current_ema and self.Position >= 0:
if self.Position > 0: self.SellMarket()
self.SellMarket()
self._prev_macd = ml; self._prev_signal = sl
def CreateClone(self): return ag_macd_dual_strategy()