Die Strategie ist ein High-Level-StockSharp-Port des Tipu MACD EA von MQL4. Es handelt ein einzelnes Symbol mithilfe von MACD-basierten Signalen und spiegelt die ursprünglichen Funktionen des Expert Advisors wider:
Optionaler Handelsstundenfilter mit zwei konfigurierbaren Zeitfenstern.
MACD-Nulllinien- und Signalleitungs-Crossover-Einträge mit einstellbaren EMA-Längen und -Verschiebung.
Automatisches Positionsmanagement einschließlich Take-Profit, Stop-Loss, Trailing Stop und Breakeven.
Volumenbegrenzung, die die Einstellung „Maximale Anzahl“ aus dem Quellcode emuliert.
Alle Operationen verwenden Marktaufträge. Schutzniveaus werden intern verfolgt und Aufträge werden geschlossen, sobald eine Kerze das Stop-Loss- oder Take-Profit-Niveau durchbricht.
Handelslogik
Abonnieren Sie den konfigurierten Kerzentyp und berechnen Sie einen MovingAverageConvergenceDivergenceSignal-Indikator (MACD-Linie + Signallinie).
Bewerten Sie MACD-Werte anhand der ausgewählten Verschiebung (MacdShift 0 = aktuelle Kerze, 1 = vorherige Kerze) und erstellen Sie Crossover-Signale:
Nulllinienübergang (optional) – kaufen, wenn MACD über Null kreuzt, verkaufen, wenn es darunter kreuzt.
Signallinienkreuzung (optional) – kaufen, wenn MACD die Signallinie überschreitet, verkaufen, wenn sie darunter liegt.
Bevor Sie eine Position eröffnen, stellen Sie sicher, dass die aktuelle Stunde zu mindestens einem der beiden Zeitfenster gehört, wenn der Filter aktiviert ist.
Wenn ein langes Signal erscheint:
Wenn die Absicherung deaktiviert ist und ein Short offen ist, schließen Sie ihn optional (CloseOnReverseSignal) oder überspringen Sie den neuen Trade.
Geben Sie eine Kauf-Market-Order für den kleineren Betrag von TradeVolume und dem verbleibenden Volumen auf, bis MaxPositionVolume erreicht ist.
Aktualisieren Sie den Long-Entry-Snapshot und berechnen Sie schützende Stopp-/Take-Level, falls aktiviert.
Wenn ein Short-Signal erscheint, befolgen Sie die symmetrische Logik für Verkaufsaufträge.
Während eine Position aktiv ist:
Überwachen Sie Stopps und Ziele für jede fertige Kerze und schließen Sie den Handel, wenn eines der beiden Niveaus durchbrochen wird.
Wenn das Trailing aktiviert ist und der Preis um TrailingPips + TrailingCushionPips steigt, verschieben Sie den Stopp, um einen Abstand von TrailingPips zum Preis beizubehalten.
Wenn das Breakeven-Modul aktiv ist und der Gewinn RiskFreePips übersteigt, verschieben Sie den Stop auf den Einstiegspreis.
Parameter
Name
Beschreibung
CandleType
Kerzenreihe, die für MACD-Berechnungen verwendet wird.
TradeVolume
Volumen jedes Markteintritts (Lots).
MaxPositionVolume
Maximal zulässige kumulative lange oder kurze Exposition.
UseTimeFilter
Aktiviert den Dual-Window-Handelsstundenfilter.
Zone1StartHour, Zone1EndHour
Start-/Endzeiten für das erste Handelsfenster (einschließlich Börsenzeit).
Zone2StartHour, Zone2EndHour
Start-/Endzeiten für das zweite Handelsfenster.
FastPeriod, SlowPeriod, SignalPeriod
MACD schnelle EMA, langsame EMA und Signallängen von SMA.
MacdShift
0 = den aktuellen Balken auswerten, 1 = den vorherigen Balken auswerten (entsprechend dem MQL iShift).
UseZeroCross
Ermöglicht MACD Nulllinien-Kreuzeingaben.
UseSignalCross
Ermöglicht MACD vs. Signalleitungskreuzeinträge.
AllowHedging
Ermöglicht den Aufbau sowohl langer als auch kurzer Belichtungen, ohne zuerst die gegenüberliegende Seite zu schließen.
CloseOnReverseSignal
Schließt die Gegenposition, wenn ein neues Signal erscheint (wird verwendet, wenn die Absicherung deaktiviert ist).
UseTakeProfit, TakeProfitPips
Aktiviert und konfiguriert die Take-Profit-Distanz (Pips).
UseStopLoss, StopLossPips
Aktiviert und konfiguriert den Stop-Loss-Abstand (Pips).
Ermöglicht die Nachlaufverwaltung, legt den Nachlaufabstand und das Polster (Pips) fest.
UseRiskFree, RiskFreePips
Verschiebt den Stop auf die Gewinnschwelle, sobald der Gewinn die angegebenen Pips überschreitet.
Nutzungshinweise
Konfigurieren Sie den Kerzentyp so, dass er dem in MetaTrader verwendeten Zeitrahmen entspricht (standardmäßige 15-Minuten-Balken).
Die Pip-Größe wird von Security.PriceStep abgeleitet. Fehlen dem Instrument diese Metadaten, wird der Standardwert 0,0001 verwendet.
Die Strategie geht von der sofortigen Ausführung von Marktaufträgen aus. Stellen Sie beim Betrieb unter Spannung ggf. eine ordnungsgemäße Handhabung des Schlupfs sicher.
Wenn sowohl Nulllinien- als auch Signallinieneinträge deaktiviert sind, bleibt die Strategie im Leerlauf.
namespace StockSharp.Samples.Strategies;
using System;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.Messages;
/// <summary>
/// Tipu MACD EA strategy: MACD signal line crossover.
/// Buys when MACD crosses above signal, sells when crosses below.
/// </summary>
public class TipuMacdEaStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _fastPeriod;
private readonly StrategyParam<int> _slowPeriod;
private readonly StrategyParam<int> _signalPeriod;
private readonly StrategyParam<int> _signalCooldownCandles;
private decimal _prevMacd;
private decimal _prevSignal;
private int _candlesSinceTrade;
private bool _hasPrev;
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 int SignalPeriod { get => _signalPeriod.Value; set => _signalPeriod.Value = value; }
public int SignalCooldownCandles { get => _signalCooldownCandles.Value; set => _signalCooldownCandles.Value = value; }
public TipuMacdEaStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(60).TimeFrame())
.SetDisplay("Candle Type", "Candle timeframe", "General");
_fastPeriod = Param(nameof(FastPeriod), 12)
.SetGreaterThanZero()
.SetDisplay("MACD Fast", "MACD fast EMA period", "Indicators");
_slowPeriod = Param(nameof(SlowPeriod), 26)
.SetGreaterThanZero()
.SetDisplay("MACD Slow", "MACD slow EMA period", "Indicators");
_signalPeriod = Param(nameof(SignalPeriod), 9)
.SetGreaterThanZero()
.SetDisplay("Signal Period", "MACD signal period", "Indicators");
_signalCooldownCandles = Param(nameof(SignalCooldownCandles), 4)
.SetGreaterThanZero()
.SetDisplay("Signal Cooldown", "Bars to wait between trades", "Trading");
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevMacd = 0;
_prevSignal = 0;
_candlesSinceTrade = SignalCooldownCandles;
_hasPrev = false;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_prevMacd = 0;
_prevSignal = 0;
_candlesSinceTrade = SignalCooldownCandles;
_hasPrev = false;
var macd = new MovingAverageConvergenceDivergenceSignal
{
Macd = { ShortMa = { Length = FastPeriod }, LongMa = { Length = SlowPeriod } },
SignalMa = { Length = SignalPeriod }
};
var subscription = SubscribeCandles(CandleType);
subscription.BindEx(macd, ProcessCandle).Start();
}
private void ProcessCandle(ICandleMessage candle, IIndicatorValue macdValue)
{
if (candle.State != CandleStates.Finished) return;
if (!macdValue.IsFinal) return;
if (_candlesSinceTrade < SignalCooldownCandles)
_candlesSinceTrade++;
if (macdValue is not MovingAverageConvergenceDivergenceSignalValue typed) return;
if (typed.Macd is not decimal macdMain || typed.Signal is not decimal signal) return;
if (_hasPrev)
{
if (_prevMacd <= _prevSignal && macdMain > signal && Position <= 0 && _candlesSinceTrade >= SignalCooldownCandles)
{
BuyMarket();
_candlesSinceTrade = 0;
}
else if (_prevMacd >= _prevSignal && macdMain < signal && Position >= 0 && _candlesSinceTrade >= SignalCooldownCandles)
{
SellMarket();
_candlesSinceTrade = 0;
}
}
_prevMacd = macdMain;
_prevSignal = signal;
_hasPrev = true;
}
}
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
from StockSharp.Algo.Strategies import Strategy
class tipu_macd_ea_strategy(Strategy):
def __init__(self):
super(tipu_macd_ea_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(60)))
self._fast_period = self.Param("FastPeriod", 12)
self._slow_period = self.Param("SlowPeriod", 26)
self._signal_period = self.Param("SignalPeriod", 9)
self._signal_cooldown_candles = self.Param("SignalCooldownCandles", 4)
self._prev_macd = 0.0
self._prev_signal = 0.0
self._candles_since_trade = 4
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 FastPeriod(self):
return self._fast_period.Value
@FastPeriod.setter
def FastPeriod(self, value):
self._fast_period.Value = value
@property
def SlowPeriod(self):
return self._slow_period.Value
@SlowPeriod.setter
def SlowPeriod(self, value):
self._slow_period.Value = value
@property
def SignalPeriod(self):
return self._signal_period.Value
@SignalPeriod.setter
def SignalPeriod(self, value):
self._signal_period.Value = value
@property
def SignalCooldownCandles(self):
return self._signal_cooldown_candles.Value
@SignalCooldownCandles.setter
def SignalCooldownCandles(self, value):
self._signal_cooldown_candles.Value = value
def OnReseted(self):
super(tipu_macd_ea_strategy, self).OnReseted()
self._prev_macd = 0.0
self._prev_signal = 0.0
self._candles_since_trade = self.SignalCooldownCandles
self._has_prev = False
def OnStarted2(self, time):
super(tipu_macd_ea_strategy, self).OnStarted2(time)
self._prev_macd = 0.0
self._prev_signal = 0.0
self._candles_since_trade = self.SignalCooldownCandles
self._has_prev = False
macd = MovingAverageConvergenceDivergenceSignal()
macd.Macd.ShortMa.Length = self.FastPeriod
macd.Macd.LongMa.Length = self.SlowPeriod
macd.SignalMa.Length = self.SignalPeriod
subscription = self.SubscribeCandles(self.CandleType)
subscription.BindEx(macd, self._process_candle).Start()
def _process_candle(self, candle, macd_value):
if candle.State != CandleStates.Finished:
return
if not macd_value.IsFinal:
return
if self._candles_since_trade < self.SignalCooldownCandles:
self._candles_since_trade += 1
if macd_value.Macd is None or macd_value.Signal is None:
return
macd_main = float(macd_value.Macd)
signal = float(macd_value.Signal)
if self._has_prev:
if self._prev_macd <= self._prev_signal and macd_main > signal and self.Position <= 0 and self._candles_since_trade >= self.SignalCooldownCandles:
self.BuyMarket()
self._candles_since_trade = 0
elif self._prev_macd >= self._prev_signal and macd_main < signal and self.Position >= 0 and self._candles_since_trade >= self.SignalCooldownCandles:
self.SellMarket()
self._candles_since_trade = 0
self._prev_macd = macd_main
self._prev_signal = signal
self._has_prev = True
def CreateClone(self):
return tipu_macd_ea_strategy()