EES-Hedger (erweitert)
Überblick
Die Strategie spiegelt das Verhalten des klassischen MetaTrader „EES Hedger“-Expertenberaters wider. Immer wenn ein externer Händler, diskretionärer Betreiber oder ein anderes automatisiertes System eine Position auf demselben Konto eröffnet, erstellt die Strategie sofort eine gegenläufige Absicherung mit einem konfigurierbaren Volumen. Anschließend verwaltet es die Absicherung mit Stop-Loss-, Take-Profit-, Break-Even- und Trailing-Stop-Regeln, sodass das Risiko neutralisiert und gleichzeitig die Gewinne aus der Absicherung geschützt werden.
Im Gegensatz zu herkömmlichen signalgesteuerten Strategien geht dieses Modul davon aus, dass Einträge an anderer Stelle erstellt werden. Seine alleinige Verantwortung besteht darin, Kontogeschäfte zu beobachten, auf übereinstimmende Tickets zu reagieren und die Absicherungsposition zu schützen, bis sie entweder durch Schutzaufträge oder manuell geschlossen wird.
Handelslogik
- Erkennung externer Trades – der Connector-Strom der Konto-Trades wird überwacht. Geschäfte, deren Kommentar mit
OriginalOrderComment übereinstimmt (oder alle Geschäfte, wenn das Feld leer ist), werden als die Quelle behandelt, die abgesichert werden muss. Durch die Strategie selbst erzeugte Trades werden durch die Speicherung ihrer Transaktionskennungen gefiltert.
- Spiegelungsaufträge – Sobald ein qualifizierter Handel eingeht, übermittelt die Strategie sofort einen Marktauftrag in die entgegengesetzte Richtung mit einem Volumen von
HedgeVolume. Ein optionales HedgerOrderComment hilft Backoffice-Tools dabei, die Sicherungsaufträge von anderen Aktivitäten zu trennen.
- Risikomanagement – nachdem die Absicherung erfüllt ist, platziert die Strategie Stop-Loss- und Take-Profit-Orders in Abständen, die durch die Pip-Parameter definiert sind. Wenn die Break-Even-Bedingungen erfüllt sind, wird der Stop auf den Einstiegspreis plus einen Pip verschoben. Wenn das Trailing aktiviert ist, wird der Stop weiter vorgezogen, da sich der Markt weiterhin zugunsten der Absicherung bewegt.
- Statusbereinigung – wenn die Position Null erreicht (z. B. nach einem manuellen Abschluss), werden alle Schutzaufträge storniert und interne Flags zurückgesetzt, sodass der nächste externe Handel von Grund auf abgesichert werden kann.
Parameter
| Parameter |
Beschreibung |
HedgeVolume |
Volumen, das zur Eröffnung der entgegengesetzten Hedge-Position verwendet wird. |
StopLossPips |
Abstand vom Einstiegspreis zur schützenden Stop-Loss-Order. |
TakeProfitPips |
Abstand vom Einstiegspreis bis zur Take-Profit-Order. |
TrailingStopPips |
Abstand, der vom Trailing Stop eingehalten wird, sobald die Aktivierungsschwelle überschritten wird. Auf Null setzen, um das Nachziehen zu deaktivieren. |
TrailingActivationPips |
Mindestgewinn (in Pips), der erforderlich ist, bevor sich der Trailing Stop zu bewegen beginnt. |
BreakEvenPips |
Gewinnschwelle (in Pips), nach der der Stop-Loss auf den Einstiegspreis plus einen Pip verschoben wird. |
OriginalOrderComment |
Optionaler Kommentarfilter, der auswählt, welche externen Geschäfte abgesichert werden sollen. Lassen Sie dieses Feld leer, um alle Trades des Instruments abzusichern. |
HedgerOrderComment |
Kommentar zu Absicherungsaufträgen und Schutzstopps, die durch die Strategie generiert werden. |
Praktische Hinweise
- Weisen Sie der Strategie dasselbe Portfolio/Konto zu wie der externe Händler. Alle auf diesem Konto erstellten Positionen sind für den Connector sichtbar und können daher abgesichert werden.
- Bei Verwendung mit MetaTrader-Brücken konfigurieren Sie den Expertenberater oder die Brücke so, dass der ursprüngliche Bestellkommentar kopiert wird, damit die Filterung wie erwartet funktioniert.
- Die Pip-Größe wird aus der Preisstufe des Instruments abgeleitet. Bei fünfstelligen FX-Symbolen übersetzt der Abstand automatisch die angegebenen Pip-Werte in korrekte Preis-Offsets.
- Break-Even- und Trailing-Logik bewegen den Stop niemals weiter vom Einstiegspreis weg. Es werden nur Verbesserungen vorgenommen, um sicherzustellen, dass der Stopp nach Erreichen der Gewinnschwelle nie wieder auf ein Verlustniveau zurückfällt.
- Die Strategie verwaltet nicht die ursprüngliche Position. Die Schließung oder Änderung liegt weiterhin in der Verantwortung des primären Handelssystems.
Nutzungsworkflow
- Konfigurieren Sie die Strategieparameter und achten Sie dabei besonders auf die Kommentarfilter und das Volumen der Absicherung.
- Starten Sie die Strategie und bestätigen Sie, dass sie mit dem Broker-Feed verbunden ist. Es bleibt inaktiv, bis ein externer Handel eintrifft.
- Sobald ein qualifizierter Trade erscheint, beobachten Sie, wie die Absicherungsorder erstellt und wie Schutzaufträge im DOM platziert werden.
- Überwachen Sie das Break-Even- und Trailing-Verhalten, um sicherzustellen, dass die konfigurierten Pip-Abstände mit den Vertragsspezifikationen des Brokers übereinstimmen.
- Stoppen Sie die Strategie, wenn keine Absicherung mehr erforderlich ist. Während des Shutdowns werden alle aktiven Schutzanordnungen aufgehoben.
Einschränkungen
- Das Modul übernimmt den Zugriff auf den Handelsstrom des Kontos. Es kann keine Geschäfte absichern, die für den Connector völlig unsichtbar sind.
- Die Regeln zur Volumenrundung sind Broker-spezifisch. Stellen Sie sicher, dass der konfigurierte
HedgeVolume mit der Chargenstufe des Geräts kompatibel ist.
- Da die Strategie Marktaufträge sofort platziert, kann ein Ausrutschen in schnellen Märkten zu unvollständigen Absicherungen führen. Erhöhen Sie die Stop-Loss-Abstände, um dies bei Bedarf zu berücksichtigen.
using System;
using System.Linq;
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;
/// <summary>
/// Adapted from the MetaTrader "EES Hedger" expert advisor.
/// Uses EMA crossover signals with break-even and trailing stop risk management.
/// </summary>
public class EesHedgerAdvancedStrategy : Strategy
{
private readonly StrategyParam<int> _fastPeriod;
private readonly StrategyParam<int> _slowPeriod;
private readonly StrategyParam<int> _stopLossPips;
private readonly StrategyParam<int> _takeProfitPips;
private readonly StrategyParam<DataType> _candleType;
/// <summary>
/// Fast EMA period.
/// </summary>
public int FastPeriod
{
get => _fastPeriod.Value;
set => _fastPeriod.Value = value;
}
/// <summary>
/// Slow EMA period.
/// </summary>
public int SlowPeriod
{
get => _slowPeriod.Value;
set => _slowPeriod.Value = value;
}
/// <summary>
/// Stop-loss distance in price steps.
/// </summary>
public int StopLossPips
{
get => _stopLossPips.Value;
set => _stopLossPips.Value = value;
}
/// <summary>
/// Take-profit distance in price steps.
/// </summary>
public int TakeProfitPips
{
get => _takeProfitPips.Value;
set => _takeProfitPips.Value = value;
}
/// <summary>
/// Candle type used by the strategy.
/// </summary>
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
/// <summary>
/// Initializes default parameters.
/// </summary>
public EesHedgerAdvancedStrategy()
{
_fastPeriod = Param(nameof(FastPeriod), 10)
.SetGreaterThanZero()
.SetDisplay("Fast EMA", "Fast EMA period", "Indicators");
_slowPeriod = Param(nameof(SlowPeriod), 30)
.SetGreaterThanZero()
.SetDisplay("Slow EMA", "Slow EMA period", "Indicators");
_stopLossPips = Param(nameof(StopLossPips), 500)
.SetDisplay("Stop Loss", "Stop-loss distance", "Risk Management");
_takeProfitPips = Param(nameof(TakeProfitPips), 500)
.SetDisplay("Take Profit", "Take-profit distance", "Risk Management");
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(1).TimeFrame())
.SetDisplay("Candle Type", "Candles used for calculations", "Market Data");
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return new[] { (Security, CandleType) };
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
var fastEma = new EMA { Length = FastPeriod };
var slowEma = new EMA { Length = SlowPeriod };
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(fastEma, slowEma, ProcessCandle)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, fastEma);
DrawIndicator(area, slowEma);
DrawOwnTrades(area);
}
// Use StartProtection for SL/TP
var tp = TakeProfitPips > 0 ? new Unit(TakeProfitPips, UnitTypes.Absolute) : null;
var sl = StopLossPips > 0 ? new Unit(StopLossPips, UnitTypes.Absolute) : null;
StartProtection(tp, sl);
base.OnStarted2(time);
}
private decimal _prevFast;
private decimal _prevSlow;
private bool _hasPrev;
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevFast = 0;
_prevSlow = 0;
_hasPrev = false;
}
private void ProcessCandle(ICandleMessage candle, decimal fastValue, decimal slowValue)
{
if (candle.State != CandleStates.Finished)
return;
if (!IsFormedAndOnlineAndAllowTrading())
{
_prevFast = fastValue;
_prevSlow = slowValue;
_hasPrev = true;
return;
}
if (!_hasPrev)
{
_prevFast = fastValue;
_prevSlow = slowValue;
_hasPrev = true;
return;
}
// EMA crossover detection
var crossedUp = _prevFast <= _prevSlow && fastValue > slowValue;
var crossedDown = _prevFast >= _prevSlow && fastValue < slowValue;
if (crossedUp)
{
// Close short if any, then go long
if (Position < 0)
BuyMarket(Math.Abs(Position));
if (Position <= 0)
BuyMarket(Volume);
}
else if (crossedDown)
{
// Close long if any, then go short
if (Position > 0)
SellMarket(Position);
if (Position >= 0)
SellMarket(Volume);
}
_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, Math
from StockSharp.Messages import DataType, CandleStates, UnitTypes, Unit
from StockSharp.Algo.Strategies import Strategy
from StockSharp.Algo.Indicators import ExponentialMovingAverage
class ees_hedger_advanced_strategy(Strategy):
def __init__(self):
super(ees_hedger_advanced_strategy, self).__init__()
self._fast_period = self.Param("FastPeriod", 10) \
.SetDisplay("Fast EMA", "Fast EMA period", "Indicators")
self._slow_period = self.Param("SlowPeriod", 30) \
.SetDisplay("Slow EMA", "Slow EMA period", "Indicators")
self._stop_loss_pips = self.Param("StopLossPips", 500) \
.SetDisplay("Stop Loss", "Stop-loss distance", "Risk Management")
self._take_profit_pips = self.Param("TakeProfitPips", 500) \
.SetDisplay("Take Profit", "Take-profit distance", "Risk Management")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(1))) \
.SetDisplay("Candle Type", "Candles used for calculations", "Market Data")
self._prev_fast = 0.0
self._prev_slow = 0.0
self._has_prev = False
@property
def FastPeriod(self):
return self._fast_period.Value
@property
def SlowPeriod(self):
return self._slow_period.Value
@property
def StopLossPips(self):
return self._stop_loss_pips.Value
@property
def TakeProfitPips(self):
return self._take_profit_pips.Value
@property
def CandleType(self):
return self._candle_type.Value
def OnStarted2(self, time):
super(ees_hedger_advanced_strategy, self).OnStarted2(time)
fast_ema = ExponentialMovingAverage()
fast_ema.Length = self.FastPeriod
slow_ema = ExponentialMovingAverage()
slow_ema.Length = self.SlowPeriod
subscription = self.SubscribeCandles(self.CandleType)
subscription.Bind(fast_ema, slow_ema, self.ProcessCandle).Start()
tp = Unit(self.TakeProfitPips, UnitTypes.Absolute) if self.TakeProfitPips > 0 else None
sl = Unit(self.StopLossPips, UnitTypes.Absolute) if self.StopLossPips > 0 else None
self.StartProtection(tp, sl)
def ProcessCandle(self, candle, fast_value, slow_value):
if candle.State != CandleStates.Finished:
return
fast_value = float(fast_value)
slow_value = float(slow_value)
if not self.IsFormedAndOnlineAndAllowTrading():
self._prev_fast = fast_value
self._prev_slow = slow_value
self._has_prev = True
return
if not self._has_prev:
self._prev_fast = fast_value
self._prev_slow = slow_value
self._has_prev = True
return
crossed_up = self._prev_fast <= self._prev_slow and fast_value > slow_value
crossed_down = self._prev_fast >= self._prev_slow and fast_value < slow_value
if crossed_up:
if self.Position < 0:
self.BuyMarket(abs(self.Position))
if self.Position <= 0:
self.BuyMarket(self.Volume)
elif crossed_down:
if self.Position > 0:
self.SellMarket(self.Position)
if self.Position >= 0:
self.SellMarket(self.Volume)
self._prev_fast = fast_value
self._prev_slow = slow_value
def OnReseted(self):
super(ees_hedger_advanced_strategy, self).OnReseted()
self._prev_fast = 0.0
self._prev_slow = 0.0
self._has_prev = False
def CreateClone(self):
return ees_hedger_advanced_strategy()