Die Target-EA-Manager-Strategie ist eine getreue StockSharp-Portierung des MetaTrader-Experts TargetEA_v1.5. Die Strategie eröffnet selbst keine neuen Trades. Stattdessen überwacht sie ständig den schwebenden Gewinn und Verlust der Orders, die bereits zur Strategie gehören, und liquidiert bei Bedarf Positionen und storniert Pending Orders, wenn benutzerdefinierte Schwellen erreicht werden. Das Verhalten reproduziert die "Basket"-Management-Logik des ursprünglichen Experts: Kauf- und Verkaufsorders können unabhängig oder als ein kombinierter Basket bewertet werden.
Die Strategie abonniert Level1-Daten (bester Bid und Ask) und nutzt die High-Level-API für Positionsschließungen und Orderstornierungen. Echtzeit-Bid- und Ask-Kurse werden in unrealisierte Gewinnmetriken für die offene Exposure übersetzt.
Hauptfunktionen
Unabhängige oder kombinierte Baskets - wählen Sie über ManageBuySellOrders, ob Long- und Short-Orders getrennt oder zusammen behandelt werden.
Mehrere Zieltypen - Schwellenwerte können in Pips, in Kontowährung pro Lot oder als Prozentsatz des Portfoliosaldos ausgedrückt werden, passend zum TypeTargetUse-Flag der MQL-Version.
Trigger für beide Seiten - getrennte Schalter für Reaktionen auf schwebende Gewinne (CloseInProfit) und schwebende Verluste (CloseInLoss).
Bereinigung von Pending Orders - optionales Stornieren von Kauf- und/oder Verkauf-Pending-Orders jedes Mal, wenn ein Basket geschlossen wird.
High-Level-Operationen - Marktausstiege werden mit BuyMarket / SellMarket ausgeführt, Pending Orders werden über die Strategie-Orderkollektion storniert.
Parameter
Parameter
Beschreibung
ManageBuySellOrders
Separate emuliert zwei Baskets (Long und Short), Combined führt beide Seiten zusammen.
Storniert aktive Pending Orders, nachdem ein Basket geschlossen wurde.
TypeTargetUse
Pips, CurrencyPerLot oder PercentageOfBalance wählen die Messung für offenen PnL.
CloseInProfit / CloseInLoss
Aktiviert Gewinn- oder Verlusttrigger.
TargetProfitInPips, TargetLossInPips
Schwellenwerte in Pips. Wenn das Instrument PriceStep bereitstellt, wird der Pip-Wert als priceDifference / PriceStep * (volume / VolumeStep) berechnet.
TargetProfitInCurrency, TargetLossInCurrency
Schwebender Gewinn oder Verlust pro Lot, vor dem Vergleich mit dem aktuellen Volumen multipliziert.
TargetProfitInPercentage, TargetLossInPercentage
Prozentsatz des Portfoliosaldos, der vor dem Schließen erreicht werden muss. Der ursprüngliche Expert vergleicht rohen schwebenden Gewinn mit Balance ± Balance * Percentage / 100, und diese Portierung behält diese Konvention unverändert bei.
Verhalten
Zustandsverfolgung - ausgeführte Trades aktualisieren interne Long- und Short-Volumentotale sowie deren gewichtete Durchschnittspreise. Gehedgte Positionen (Long und Short) werden daher korrekt behandelt.
PnL-Berechnung - jede Level1-Aktualisierung erneuert Bid-/Ask-Werte, aus denen Pip- und Währungsgewinne für beide Seiten berechnet werden.
Zielbewertung - abhängig vom Zielmodus und Basket-Modus werden die entsprechenden Schwellen geprüft. Gewinnprüfungen verlangen Werte größer oder gleich den konfigurierten Zielen, während Verlustprüfungen kleiner oder gleich verwenden, passend zur MQL-Logik.
Basket-Liquidierung - wenn eine Bedingung erfüllt ist, storniert die Strategie optional Pending Orders auf dieser Seite und sendet die erforderliche Marktorder, um die offene Exposure glattzustellen.
Die Implementierung vermeidet bewusst zusätzliche Collections oder Indikatorspeicher und verlässt sich wie der ursprüngliche EA auf die High-Level-API von StockSharp.
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 TargetEaManagerStrategy : 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 TargetEaManagerStrategy()
{
_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 target_ea_manager_strategy(Strategy):
def __init__(self):
super(target_ea_manager_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(target_ea_manager_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(target_ea_manager_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 target_ea_manager_strategy()