Diese Strategie ist ein StockSharp-Port des MetaTrader-Expertenberaters "Hedging Martingale" (Ordner MQL/23693). Sie hält eine ausgeglichene Hedge aufrecht, indem sie bei jeder neuen Bar sowohl eine Long- als auch eine Short-Position eröffnet, und wendet dann ein Martingal-Averaging-Schema an. Wenn sich der Preis um eine konfigurierbare Pip-Distanz ungünstig bewegt, fügt die Strategie eine neue Position auf der Verlustseite mit erhöhtem Volumen hinzu, während die entgegengesetzte Hedge bestehen bleibt. Der schwebende Gewinn wird mit geld- und prozentbasierten Zielen zusammen mit einer optionalen Trailing-Sperre verwaltet.
Trading-Logik
Anfängliche Hedge: Wann immer die Strategie flat ist und eine neue Kerze schließt, kauft und verkauft sie gleichzeitig mit demselben Basisvolumen.
Martingal-Schritte: Wenn sich der Preis um Pip Step Pips gegen eine Seite bewegt, wird auf dieser Seite eine zusätzliche Order eröffnet. Das Volumen wird mit dem Volume Multiplier multipliziert, was die progressive Lot-Größenbestimmung aus der MQL-Version emuliert. Die entgegengesetzte Seite bleibt offen, um die Hedge aufrechtzuerhalten.
Take-Profit pro Trade: Jeder offene Eintrag hat eine individuelle Take-Profit-Distanz, die durch Take Profit (pips) definiert ist. Wenn sich der Markt um diese Distanz zugunsten eines Beins bewegt, wird das Bein durch eine Gegenbuchung reduziert.
Korb-Ausstiege: Das gesamte Positionsset kann geschlossen werden, wenn der schwebende Gewinn ein Geldziel, einen Prozentsatz des Anfangskapitals erreicht oder nachdem eine Trailing-Sperre mehr als den erlaubten Rückzug zurückgibt. Diese Verhaltensweisen replizieren Take_Profit_In_Money, Take_Profit_In_percent und TRAIL_PROFIT_IN_MONEY2 aus dem ursprünglichen Experten.
Trade-Limits: Der Parameter Max Trades beschränkt die Anzahl der aktiven Martingal-Schritte. Wenn Close On Max aktiviert ist, wird der Korb liquidiert, sobald das Limit überschritten wird.
Parameter
Name
Beschreibung
Candle Type
Zeitrahmen, der die Logik antreibt. Jede abgeschlossene Kerze kann neue Hedging-Aktionen auslösen.
Use Money TP / Money Take Profit
Aktivieren und den schwebenden Gewinn (in Währungseinheiten) definieren, der alle Positionen schließt.
Use Percent TP / Percent Take Profit
Korb schließen, wenn der schwebende Gewinn einen Prozentsatz des anfänglichen Portfoliowerts erreicht.
Enable Trailing / Trailing Start / Trailing Step
Geldbasierte Trailing-Sperre für den Korb aktivieren und Triggerniveau zusammen mit dem erlaubten Gewinnrückzug konfigurieren.
Take Profit (pips)
Distanz in Pips für Take-Profit-Ausstiege pro Bein.
Pip Step
Ungünstige Preisbewegung (in Pips) erforderlich, bevor eine weitere Martingal-Order hinzugefügt wird.
Base Volume
Anfangsvolumen für beide Buy- und Sell-Beine.
Volume Multiplier
Multiplikator beim größten Positionsvolumen, wenn Martingal-Einstiege hinzugefügt werden.
Max Trades
Maximale Anzahl gleichzeitig offener Einstiege (in beiden Richtungen).
Close On Max
Ob alle Positionen liquidiert werden sollen, sobald die maximale Trade-Anzahl überschritten wird.
Hinweise
Die Strategie verwendet BuyMarket und SellMarket für alle Orderplatzierungen und spiegelt das Market-Execution-Modell des Quell-Experten wider.
Volumenwerte werden auf den Lot-Schritt des Instruments normalisiert, um abgelehnte Orders zu vermeiden.
Wenn die Strategie flat wird, wird die Trailing-Sperre zurückgesetzt, damit neue Körbe mit einer sauberen Gewinnreferenz beginnen.
Dateien
CS/HedgingMartingaleStrategy.cs – Implementierung der konvertierten Strategie (C#).
README.md – diese Dokumentation (Englisch).
README_zh.md – Chinesische Übersetzung.
README_ru.md – Russische Übersetzung.
using System;
using System.Collections.Generic;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
public class HedgingMartingaleStrategy : Strategy
{
private readonly StrategyParam<int> _fastPeriod;
private readonly StrategyParam<int> _slowPeriod;
private readonly StrategyParam<int> _stopLossPoints;
private readonly StrategyParam<int> _takeProfitPoints;
private ExponentialMovingAverage _fast;
private ExponentialMovingAverage _slow;
private decimal _prevFast;
private decimal _prevSlow;
private decimal _entryPrice;
private int _cooldown;
public int FastPeriod { get => _fastPeriod.Value; set => _fastPeriod.Value = value; }
public int SlowPeriod { get => _slowPeriod.Value; set => _slowPeriod.Value = value; }
public int StopLossPoints { get => _stopLossPoints.Value; set => _stopLossPoints.Value = value; }
public int TakeProfitPoints { get => _takeProfitPoints.Value; set => _takeProfitPoints.Value = value; }
public HedgingMartingaleStrategy()
{
_fastPeriod = Param(nameof(FastPeriod), 14).SetGreaterThanZero().SetDisplay("Fast Period", "Fast EMA period", "Indicator");
_slowPeriod = Param(nameof(SlowPeriod), 50).SetGreaterThanZero().SetDisplay("Slow Period", "Slow EMA period", "Indicator");
_stopLossPoints = Param(nameof(StopLossPoints), 200).SetNotNegative().SetDisplay("Stop Loss", "Stop-loss in price steps", "Risk");
_takeProfitPoints = Param(nameof(TakeProfitPoints), 400).SetNotNegative().SetDisplay("Take Profit", "Take-profit in price steps", "Risk");
}
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
yield return (Security, TimeSpan.FromMinutes(5).TimeFrame());
}
protected override void OnReseted()
{
base.OnReseted();
_fast = null; _slow = null;
_prevFast = 0; _prevSlow = 0; _entryPrice = 0; _cooldown = 0;
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_fast = new ExponentialMovingAverage { Length = FastPeriod };
_slow = new ExponentialMovingAverage { Length = SlowPeriod };
var subscription = SubscribeCandles(TimeSpan.FromMinutes(5).TimeFrame());
subscription.Bind(_fast, _slow, ProcessCandle);
subscription.Start();
}
private void ProcessCandle(ICandleMessage candle, decimal fastValue, decimal slowValue)
{
if (candle.State != CandleStates.Finished) return;
if (!_fast.IsFormed || !_slow.IsFormed) { _prevFast = fastValue; _prevSlow = slowValue; return; }
if (_cooldown > 0) { _cooldown--; _prevFast = fastValue; _prevSlow = slowValue; return; }
var close = candle.ClosePrice;
var step = Security?.PriceStep ?? 1m;
if (Position > 0 && _entryPrice > 0)
{
if (StopLossPoints > 0 && close <= _entryPrice - StopLossPoints * step) { SellMarket(); _entryPrice = 0; _cooldown = 100; _prevFast = fastValue; _prevSlow = slowValue; return; }
if (TakeProfitPoints > 0 && close >= _entryPrice + TakeProfitPoints * step) { SellMarket(); _entryPrice = 0; _cooldown = 100; _prevFast = fastValue; _prevSlow = slowValue; return; }
}
else if (Position < 0 && _entryPrice > 0)
{
if (StopLossPoints > 0 && close >= _entryPrice + StopLossPoints * step) { BuyMarket(); _entryPrice = 0; _cooldown = 100; _prevFast = fastValue; _prevSlow = slowValue; return; }
if (TakeProfitPoints > 0 && close <= _entryPrice - TakeProfitPoints * step) { BuyMarket(); _entryPrice = 0; _cooldown = 100; _prevFast = fastValue; _prevSlow = slowValue; return; }
}
if (_prevFast <= _prevSlow && fastValue > slowValue && Position <= 0)
{ if (Position < 0) BuyMarket(); BuyMarket(); _entryPrice = close; _cooldown = 100; }
else if (_prevFast >= _prevSlow && fastValue < slowValue && Position >= 0)
{ if (Position > 0) SellMarket(); SellMarket(); _entryPrice = close; _cooldown = 100; }
_prevFast = fastValue; _prevSlow = slowValue;
}
}
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 hedging_martingale_strategy(Strategy):
def __init__(self):
super(hedging_martingale_strategy, self).__init__()
self._fast_period = self.Param("FastPeriod", 14) \
.SetDisplay("Fast Period", "Fast MA period", "Indicator")
self._slow_period = self.Param("SlowPeriod", 50) \
.SetDisplay("Slow Period", "Slow MA period", "Indicator")
self._stop_loss_points = self.Param("StopLossPoints", 200) \
.SetDisplay("Stop Loss", "Stop-loss in price steps", "Risk")
self._take_profit_points = self.Param("TakeProfitPoints", 400) \
.SetDisplay("Take Profit", "Take-profit in price steps", "Risk")
self._fast = None
self._slow = None
self._prev_fast = 0.0
self._prev_slow = 0.0
self._entry_price = 0.0
self._cooldown = 0
@property
def fast_period(self):
return self._fast_period.Value
@property
def slow_period(self):
return self._slow_period.Value
@property
def stop_loss_points(self):
return self._stop_loss_points.Value
@property
def take_profit_points(self):
return self._take_profit_points.Value
def OnReseted(self):
super(hedging_martingale_strategy, self).OnReseted()
self._fast = None
self._slow = None
self._prev_fast = 0.0
self._prev_slow = 0.0
self._entry_price = 0.0
self._cooldown = 0
def OnStarted2(self, time):
super(hedging_martingale_strategy, self).OnStarted2(time)
self._fast = ExponentialMovingAverage()
self._fast.Length = self.fast_period
self._slow = ExponentialMovingAverage()
self._slow.Length = self.slow_period
subscription = self.SubscribeCandles(DataType.TimeFrame(TimeSpan.FromMinutes(5)))
subscription.Bind(self._fast, self._slow, self._process_candle)
subscription.Start()
def _process_candle(self, candle, fast_value, slow_value):
if candle.State != CandleStates.Finished:
return
fast_val = float(fast_value)
slow_val = float(slow_value)
if not self._fast.IsFormed or not self._slow.IsFormed:
self._prev_fast = fast_val
self._prev_slow = slow_val
return
if self._cooldown > 0:
self._cooldown -= 1
self._prev_fast = fast_val
self._prev_slow = slow_val
return
close = float(candle.ClosePrice)
step = float(self.Security.PriceStep) if self.Security is not None and self.Security.PriceStep is not None else 1.0
if self.Position > 0 and self._entry_price > 0:
if self.stop_loss_points > 0 and close <= self._entry_price - self.stop_loss_points * step:
self.SellMarket()
self._entry_price = 0.0
self._cooldown = 100
self._prev_fast = fast_val
self._prev_slow = slow_val
return
if self.take_profit_points > 0 and close >= self._entry_price + self.take_profit_points * step:
self.SellMarket()
self._entry_price = 0.0
self._cooldown = 100
self._prev_fast = fast_val
self._prev_slow = slow_val
return
elif self.Position < 0 and self._entry_price > 0:
if self.stop_loss_points > 0 and close >= self._entry_price + self.stop_loss_points * step:
self.BuyMarket()
self._entry_price = 0.0
self._cooldown = 100
self._prev_fast = fast_val
self._prev_slow = slow_val
return
if self.take_profit_points > 0 and close <= self._entry_price - self.take_profit_points * step:
self.BuyMarket()
self._entry_price = 0.0
self._cooldown = 100
self._prev_fast = fast_val
self._prev_slow = slow_val
return
if self._prev_fast <= self._prev_slow and fast_val > slow_val and self.Position <= 0:
if self.Position < 0:
self.BuyMarket()
self.BuyMarket()
self._entry_price = close
self._cooldown = 100
elif self._prev_fast >= self._prev_slow and fast_val < slow_val and self.Position >= 0:
if self.Position > 0:
self.SellMarket()
self.SellMarket()
self._entry_price = close
self._cooldown = 100
self._prev_fast = fast_val
self._prev_slow = slow_val
def CreateClone(self):
return hedging_martingale_strategy()