Grundlegend Martingale EA 3
Überblick
Die Basic Martingale EA 3-Strategie repliziert den MetaTrader 5 Expert Advisor, der einen Trendfilter basierend auf dem Triple Exponential Moving Average (TEMA) mit ATR-gesteuerter Martingal-Mittelwertbildung kombiniert. Die konvertierte StockSharp-Version behält die gleichen Risikoparameter, das gleiche Handelsfenster und die gleiche Geldverwaltungslogik bei, während alles durch Strategieparameter zur Optimierung offengelegt wird.
Handelslogik
- Signalgenerierung – bei jeder abgeschlossenen Kerze des ausgewählten Zeitrahmens wird der Schlusskurs mit dem TEMA-Wert verglichen. Ein Schlusskurs über dem Indikator öffnet einen Long-Korb, während ein Schlusskurs darunter einen Short-Korb öffnet. Es kann immer nur eine Richtung gleichzeitig aktiv sein.
- Handelsfenster – neue Körbe sind nur zwischen
StartHour und EndHour (Umtauschzeit) zulässig. Wenn beide Stunden gleich sind, gilt das Fenster als immer geöffnet. Setzen Sie TradeAtNewBar auf true, um neue Körbe auf einen pro Kerze zu beschränken, ähnlich dem ursprünglichen TradeAtNewBar-Schalter in MT5.
- Durchschnittsraster – Sobald eine Position existiert, misst die Strategie den Abstand vom schlechtesten/besten Einstiegspreis. Immer wenn sich der Markt um mindestens
GridMultiplier × ATR bewegt, wird eine zusätzliche Order in der durch Averaging definierten Richtung (Durchschnitt nach unten oder Durchschnitt nach oben) hinzugefügt, bis MaxAverageOrders erreicht ist. Die neue Ordergröße folgt dem gewählten Martingalmodus (Multiply oder Increment).
- Schutzausstiege – optionale Stop-Loss- und Take-Profit-Level werden von der ersten Order im Warenkorb übernommen. Darüber hinaus ahmt der Trailing Block die MT5-Implementierung nach: Nach
TrailingStart Gewinnpunkten wird der Stop auf price - TrailingStop (oder price + TrailingStop für Shorts) verschoben und um TrailingStep verschärft.
- Abflachung – wenn ein Stop-, Take-Profit- oder Trailing-Level erreicht wird, wird der gesamte Korb zum Marktwert geschlossen und alle Durchschnittszähler werden zurückgesetzt.
Parameter
| Parameter |
Typ |
Standard |
Beschreibung |
CandleType |
DataType |
H1-Zeitrahmen |
Kerzenserie, die die Strategie vorantreibt. |
StartVolume |
decimal |
0.01 |
Anfangsvolumen für die erste Bestellung in einem Warenkorb. |
StopLossPoints |
decimal |
20 |
Stop-Loss-Distanz in Preisschritten. Zum Deaktivieren auf 0 setzen. |
TakeProfitPoints |
decimal |
20 |
Take-Profit-Distanz in Preisschritten. Zum Deaktivieren auf 0 setzen. |
StartHour |
int |
3 |
Stunde (einschließlich), in der neue Körbe beginnen können. |
EndHour |
int |
18 |
Stunde (exklusiv), in der die Warenkorberstellung stoppt. |
TemaPeriod |
int |
50 |
Länge des TEMA-Indikators. |
BarsCalculated |
int |
3 |
Anzahl der benötigten fertigen Kerzen, bevor der Handel beginnt. |
AtrPeriod |
int |
14 |
Zeitraum des Average True Range-Indikators. |
GridMultiplier |
decimal |
0.75 |
ATR-Multiplikator, der den Rasterabstand definiert. |
MaxAverageOrders |
int |
3 |
Maximale Anzahl von Durchschnittsaufträgen pro Richtung (einschließlich der anfänglichen). |
Averaging |
Aufzählung |
AverageDown |
Wählen Sie zwischen der Mittelwertbildung beim Drawdown, der Mittelwertbildung beim Gewinn oder der Deaktivierung zusätzlicher Einträge. |
Martin |
Aufzählung |
Multiply |
Wählen Sie zwischen multiplikativer oder inkrementeller Martingal-Größenbestimmung. |
LotMultiplier |
decimal |
1.5 |
Vom Martingalmodus Multiply verwendeter Faktor. |
LotIncrement |
decimal |
0.1 |
Zusätzliches Volumen, das vom Martingalmodus Increment verwendet wird. |
TradeAtNewBar |
bool |
false |
Beschränken Sie die Anzahl neuer Körbe auf einen pro fertiger Kerze. |
TrailingStart |
int |
100 |
Profitieren Sie von den zur Aktivierung des Trailings erforderlichen Punkten. |
TrailingStop |
int |
50 |
Trailing-Stop-Distanz in Punkten. |
TrailingStep |
int |
30 |
Minimale Verbesserung (Punkte), bevor der Trailing Stop erneut verschoben wird. |
Konvertierungshinweise
- Die StockSharp-Version behält die MT5-Indikatorkonfiguration (TEMA(50) + ATR(14)) bei und stellt den Parameter
bar als BarsCalculated bereit, wodurch sichergestellt wird, dass vor dem Handel mindestens die angegebene Anzahl von Kerzen vorhanden ist.
- Bei der Volumenverarbeitung werden die Werte
MinVolume, MaxVolume und VolumeStep des Instruments berücksichtigt, sodass beim Live-Handel die Börsenlimits auch bei gebrochenen Martingalschritten eingehalten werden.
- Die Trailing-Logik folgt dem ursprünglichen Break-Even-Plus-Trailing-Step-Verhalten, wird jedoch mit aggregierten Positionsdaten implementiert, da StockSharp Positionen nach Instrument saldiert werden.
- Diagrammanmerkungen des MT5-Experten wurden nicht portiert, da StockSharp bereits eine Auftrags- und Positionsvisualisierung in den Diagrammfeldern bereitstellt.
namespace StockSharp.Samples.Strategies;
using System;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.Messages;
/// <summary>
/// Basic Martingale EA 3 strategy: WMA crossover with RSI filter.
/// Buys when WMA fast crosses above slow and RSI below midline, sells on opposite conditions.
/// </summary>
public class BasicMartingaleEa3Strategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _fastPeriod;
private readonly StrategyParam<int> _slowPeriod;
private readonly StrategyParam<int> _rsiPeriod;
private decimal _prevFast;
private decimal _prevSlow;
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 RsiPeriod { get => _rsiPeriod.Value; set => _rsiPeriod.Value = value; }
public BasicMartingaleEa3Strategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame())
.SetDisplay("Candle Type", "Candle timeframe", "General");
_fastPeriod = Param(nameof(FastPeriod), 5)
.SetGreaterThanZero()
.SetDisplay("Fast WMA", "Fast WMA period", "Indicators");
_slowPeriod = Param(nameof(SlowPeriod), 15)
.SetGreaterThanZero()
.SetDisplay("Slow WMA", "Slow WMA period", "Indicators");
_rsiPeriod = Param(nameof(RsiPeriod), 14)
.SetGreaterThanZero()
.SetDisplay("RSI Period", "RSI period", "Indicators");
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevFast = 0;
_prevSlow = 0;
_hasPrev = false;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_hasPrev = false;
var fast = new ExponentialMovingAverage { Length = FastPeriod };
var slow = new ExponentialMovingAverage { Length = SlowPeriod };
var rsi = new RelativeStrengthIndex { Length = RsiPeriod };
var subscription = SubscribeCandles(CandleType);
subscription.Bind(fast, slow, rsi, ProcessCandle).Start();
}
private void ProcessCandle(ICandleMessage candle, decimal fastValue, decimal slowValue, decimal rsiValue)
{
if (candle.State != CandleStates.Finished) return;
if (_hasPrev)
{
if (_prevFast <= _prevSlow && fastValue > slowValue && rsiValue < 45 && Position <= 0)
BuyMarket();
else if (_prevFast >= _prevSlow && fastValue < slowValue && rsiValue > 55 && Position >= 0)
SellMarket();
}
else
{
if (fastValue > slowValue && rsiValue < 45 && Position <= 0)
BuyMarket();
else if (fastValue < slowValue && rsiValue > 55 && Position >= 0)
SellMarket();
}
_prevFast = fastValue;
_prevSlow = slowValue;
_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 ExponentialMovingAverage, RelativeStrengthIndex
from StockSharp.Algo.Strategies import Strategy
class basic_martingale_ea3_strategy(Strategy):
def __init__(self):
super(basic_martingale_ea3_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(5))) \
.SetDisplay("Candle Type", "Candle timeframe", "General")
self._fast_period = self.Param("FastPeriod", 5) \
.SetGreaterThanZero() \
.SetDisplay("Fast WMA", "Fast WMA period", "Indicators")
self._slow_period = self.Param("SlowPeriod", 15) \
.SetGreaterThanZero() \
.SetDisplay("Slow WMA", "Slow WMA period", "Indicators")
self._rsi_period = self.Param("RsiPeriod", 14) \
.SetGreaterThanZero() \
.SetDisplay("RSI Period", "RSI period", "Indicators")
self._prev_fast = 0.0
self._prev_slow = 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 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 RsiPeriod(self):
return self._rsi_period.Value
@RsiPeriod.setter
def RsiPeriod(self, value):
self._rsi_period.Value = value
def OnReseted(self):
super(basic_martingale_ea3_strategy, self).OnReseted()
self._prev_fast = 0.0
self._prev_slow = 0.0
self._has_prev = False
def OnStarted2(self, time):
super(basic_martingale_ea3_strategy, self).OnStarted2(time)
self._has_prev = False
fast = ExponentialMovingAverage()
fast.Length = self.FastPeriod
slow = ExponentialMovingAverage()
slow.Length = self.SlowPeriod
rsi = RelativeStrengthIndex()
rsi.Length = self.RsiPeriod
subscription = self.SubscribeCandles(self.CandleType)
subscription.Bind(fast, slow, rsi, self._process_candle).Start()
def _process_candle(self, candle, fast_value, slow_value, rsi_value):
if candle.State != CandleStates.Finished:
return
fv = float(fast_value)
sv = float(slow_value)
rv = float(rsi_value)
if self._has_prev:
if self._prev_fast <= self._prev_slow and fv > sv and rv < 45 and self.Position <= 0:
self.BuyMarket()
elif self._prev_fast >= self._prev_slow and fv < sv and rv > 55 and self.Position >= 0:
self.SellMarket()
else:
if fv > sv and rv < 45 and self.Position <= 0:
self.BuyMarket()
elif fv < sv and rv > 55 and self.Position >= 0:
self.SellMarket()
self._prev_fast = fv
self._prev_slow = sv
self._has_prev = True
def CreateClone(self):
return basic_martingale_ea3_strategy()