Diese Strategie portiert den MetaTrader-Experten Starter.mq5 auf die High-Level-API von StockSharp. Sie synchronisiert drei stochastische Oszillatoren (schnell, normal, langsam) mit passenden gleitenden Durchschnitten, die auf verschiedenen Zeitrahmen berechnet werden. Ein Trade wird nur zugelassen, wenn alle Filter dieselbe Richtung bestätigen und der Preis auf der richtigen Seite jedes verschobenen gleitenden Durchschnitts handelt.
Handelslogik
Die Strategie abonniert drei Kerzenstreams:
Schneller Zeitrahmen (Standard M5).
Normaler Zeitrahmen (Standard M30).
Langsamer Zeitrahmen (Standard H2).
Für jeden Stream erstellt sie einen gleitenden Durchschnitt (konfigurierbarer Methode, Länge und angewendeter Preis) und einen stochastischen Oszillator mit denselben %K-, %D- und Verlangsamungsparametern.
Der langsame Zeitrahmen steuert die Ausführung. Wenn eine langsame Kerze schließt, werden die neuesten Werte aller Zeitrahmen verglichen:
Long-Setup: jede stochastische Linie hat %K > %D, alle %K-Werte liegen unter 50, und der Preis liegt unter jedem verschobenen gleitenden Durchschnitt.
Short-Setup: jede stochastische Linie hat %K < %D, alle %K-Werte liegen über 50, und der Preis liegt über jedem verschobenen gleitenden Durchschnitt.
Signale können optional durch ReverseSignals invertiert werden. Wenn ein Einstieg getätigt wird, kehrt die Strategie entweder die bestehende Exposition (wenn CloseOppositePositions = true) oder ignoriert das Signal, bis die entgegengesetzte Position geschlossen ist.
Nach einem Fill werden Stop-Loss- und Take-Profit-Niveaus im Preisraum simuliert. Ein Trailing Stop repliziert die originale MQL-Logik, indem TrailingStopPips + TrailingStepPips Gewinn erforderlich ist, bevor der Stop um TrailingStopPips verschoben wird.
Risikobasiertes Positions-Sizing spiegelt den MetaTrader lot/risk-Schalter wider. Wenn der Modus RiskPercent ist, wird das Trade-Volumen aus dem Kontowert, dem Risikoprozentsatz und dem Stop-Loss-Abstand in Pips berechnet.
Parameter
Name
Standard
Beschreibung
StopLossPips
45
Schutz-Stop-Abstand in Pips. Auf 0 setzen, um den festen Stop zu deaktivieren.
TakeProfitPips
105
Take-Profit-Abstand in Pips. Auf 0 setzen, um das Ziel zu deaktivieren.
TrailingStopPips
5
Trailing-Stop-Offset nach dem Mindestfortschritt.
TrailingStepPips
5
Mindestgewinnfortschritt (in Pips), bevor der Trailing Stop sich bewegt.
MoneyMode
RiskPercent
Wählt zwischen festem Lot-Sizing und prozentualem Risiko pro Trade.
MoneyValue
3
Lot-Größe bei FixedLot oder Risikoprozentsatz bei RiskPercent.
FastCandleType
M5
Kerzentyp für den schnellen Indikatorensatz.
NormalCandleType
M30
Kerzentyp für den mittleren Indikatorensatz.
SlowCandleType
H2
Kerzentyp, der die Signalauswertung und Orders auslöst.
MaPeriod
20
Länge aller gleitenden Durchschnitte.
MaShift
1
Horizontale Verschiebung für jeden gleitenden Durchschnitt (Balken zurück).
MaMethod
Simple
Gleitender-Durchschnitt-Glättung: Simple, Exponential, Smoothed oder Weighted.
MaPriceType
Close
Angewendeter Preis für die gleitenden Durchschnitte.
StochasticKPeriod
5
%K-Länge für alle stochastischen Oszillatoren.
StochasticDPeriod
3
%D-Glättungslänge.
StochasticSlowing
3
Endgültiger Verlangsamungsfaktor für %K.
ReverseSignals
false
Tauscht die Long- und Short-Bedingungen aus.
CloseOppositePositions
false
Wenn true, kehrt die Position in einer einzigen Order um, wenn ein Signal in der entgegengesetzten Richtung erscheint.
Geldverwaltung
MoneyMode = FixedLot sendet jede Order mit dem genauen MoneyValue-Volumen.
MoneyMode = RiskPercent reproduziert das Originalverhalten: der riskierte Betrag entspricht AccountValue * MoneyValue / 100. Die Trade-Größe wird als riskierter Betrag / (StopLossPips * Pip-Größe) berechnet. Wenn StopLossPips null ist oder der Portfoliowert nicht verfügbar ist, verweigert die Strategie den Handel.
Schutz und Trailing
Stop-Loss- und Take-Profit-Niveaus werden intern verfolgt und mit Kerzenhochs/-tiefs verglichen, um MetaTrader's Schutzorders zu emulieren.
Der Trailing Stop aktiviert sich erst, wenn der unrealisierte Gewinn TrailingStopPips + TrailingStepPips Pips überschreitet, was der originalen Anforderung entspricht, dass sowohl ein anfänglicher Offset als auch ein Mindestschritt erfüllt sein müssen, bevor der Stop verschoben wird.
Multi-Zeitrahmen-Ausrichtung
Alle Indikatoren werden bei jeder geschlossenen Kerze ihres jeweiligen Zeitrahmens neu berechnet. Der langsame Zeitrahmen wartet, bis alle drei gleitenden Durchschnitte und Stochastiken geformt sind, und verwendet die neuesten verschobenen gleitenden Durchschnittswerte, was den MetaTrader-iMA-Shift-Parameter nachahmt. Dies stellt sicher, dass der StockSharp-Port Trades auf demselben Balken wie der originale MQL-Experte auslöst.
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 StarterTripleStochasticStrategy : 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 StarterTripleStochasticStrategy()
{
_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 starter_triple_stochastic_strategy(Strategy):
def __init__(self):
super(starter_triple_stochastic_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(starter_triple_stochastic_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(starter_triple_stochastic_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 starter_triple_stochastic_strategy()