Diese Strategie portiert den MetaTrader Expertenberater „_HPCS_IntFourth_MT4_EA_V01_WE“ auf den StockSharp High-Level API. Das ursprüngliche Skript eröffnet sofort eine Long-Position, wendet schützende Stop-Loss- und Take-Profit-Werte in MetaTrader Pips an und schließt den Handel nach einer kurzen Haltedauer zwangsweise. Die C#-Version reproduziert das gleiche Verhalten, indem sie den integrierten Schutzmanager mit einem Ein-Sekunden-Timer kombiniert, der die seit der Eingabe verstrichene Zeit überwacht.
Handelslogik
Initialisierung
Wenn die Strategie startet, berechnet sie die Pip-Größe von MetaTrader aus der Sicherheit PriceStep und der Dezimalgenauigkeit (5- und 3-stellige Symbole verwenden einen 10-fachen Multiplikator).
Der High-Level-Helfer StartProtection ist mit den angeforderten Take-Profit- und Stop-Loss-Abständen konfiguriert. Die Stop-Loss-Distanz beinhaltet den zusätzlichen Puffer, den das ursprüngliche EA mit OrderModify anwendet.
Die Lautstärke ist fest und ergibt sich aus dem Parameter OrderVolume.
Eintrag
Unmittelbar nach dem Start der Strategie wird eine Single-Market-Kauforder übermittelt. Es werden keine weiteren Einträge vorgenommen.
Sobald die erste Füllung gemeldet wird, speichert die Strategie die Ausführungszeit.
Ausstieg
Ein Timer prüft jede Sekunde die Offenstellung.
Wenn die Haltedauer CloseDelaySeconds erreicht, schließt die Strategie die Long-Position mit einer Market-Sell-Order, wenn das Exposure immer noch positiv ist.
Schützende Stop-Loss- und Take-Profit-Orders werden vom Schutzmanager automatisch über Marktausgänge aufrechterhalten.
Die Logik handelt nur in der langen Richtung und spiegelt das Verhalten des MetaTrader-Skripts wider.
Parameter
Name
Beschreibung
Standard
Optimierbar
OrderVolume
Festes Volumen, das beim Senden der ersten Marktkauforder verwendet wird.
1
Nein
StopLossPips
Basis-Pip-Distanz von MetaTrader, angewendet auf den anfänglichen Stop-Loss.
10
Nein
ExtraStopPips
Zusätzlicher MetaTrader Pip-Puffer, der nach dem Eintritt vom Stopp abgezogen wird.
10
Nein
TakeProfitPips
MetaTrader Pip Abstand vom Gewinnziel.
10
Nein
CloseDelaySeconds
Zeit in Sekunden, bevor die Position zwangsweise geschlossen wird. 0 deaktiviert den Timer-Exit.
30
Nein
Implementierungshinweise
Der Pip-Size-Helfer multipliziert den gemeldeten PriceStep mit 10 für 3- und 5-Dezimal-Instrumente, sodass die Parameterwerte die gleiche Skalierung wie in MetaTrader behalten.
StartProtection verwendet UnitTypes.Price Abstände, sodass Schutzanordnungen bei Marktaustritten funktionieren, genau wie es EA mit OrderClose tat.
OnNewMyTrade zeichnet den ersten ausgeführten Kaufhandel auf, um den Countdown für die Haltedauer zu starten, und setzt den Status zurück, wenn die Position vollständig geschlossen ist.
Der Timer läuft in Ein-Sekunden-Intervallen, um die ursprüngliche OnTick-Zeitprüfung zu reproduzieren und bleibt dabei unempfindlich gegenüber Marktinaktivität.
Alle Codekommentare sind in englischer Sprache verfasst, um den Repository-Richtlinien zu entsprechen.
using System;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// Port of the "_HPCS_IntFourth_MT4_EA_V01_WE" MetaTrader expert advisor.
/// Uses SMA crossover to enter positions with time-based exit.
/// </summary>
public class HpcsInter4Strategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _fastPeriod;
private readonly StrategyParam<int> _slowPeriod;
private decimal _prevFast;
private decimal _prevSlow;
private bool _isFirstValue = true;
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 HpcsInter4Strategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(60).TimeFrame())
.SetDisplay("Candle Type", "Time frame for calculation", "General");
_fastPeriod = Param(nameof(FastPeriod), 20)
.SetGreaterThanZero()
.SetDisplay("Fast SMA", "Fast SMA period", "Indicators");
_slowPeriod = Param(nameof(SlowPeriod), 50)
.SetGreaterThanZero()
.SetDisplay("Slow SMA", "Slow SMA period", "Indicators");
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevFast = 0;
_prevSlow = 0;
_isFirstValue = true;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_prevFast = 0;
_prevSlow = 0;
_isFirstValue = true;
var fastSma = new ExponentialMovingAverage { Length = FastPeriod };
var slowSma = new ExponentialMovingAverage { Length = SlowPeriod };
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(fastSma, slowSma, ProcessCandle)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, fastSma);
DrawIndicator(area, slowSma);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle, decimal fastValue, decimal slowValue)
{
if (candle.State != CandleStates.Finished)
return;
if (!IsFormedAndOnlineAndAllowTrading())
return;
if (_isFirstValue)
{
_prevFast = fastValue;
_prevSlow = slowValue;
_isFirstValue = false;
return;
}
// Fast crosses above slow - buy
if (_prevFast <= _prevSlow && fastValue > slowValue && Position <= 0)
{
BuyMarket();
}
// Fast crosses below slow - sell
else if (_prevFast >= _prevSlow && fastValue < slowValue && Position >= 0)
{
SellMarket();
}
_prevFast = fastValue;
_prevSlow = slowValue;
}
}