Diese Strategie ist ein StockSharp High-Level-Port des MetaTrader 5-Expertenberaters Exp_Slow-Stoch_Duplex. Sie kombiniert zwei langsame stochastische Oszillatoren, die auf unabhängigen Zeitrahmen arbeiten, um koordinierte Long- und Short-Signale zu erzeugen. Jeder Oszillator liefert seine eigenen Kreuzungssignale, sodass die Strategie gerichtete Positionen öffnen oder schließen kann, während die Schutzorders das ursprüngliche Stop-Loss- und Take-Profit-Management emulieren.
Handelsregeln
Long-Modul
Bewertet den Long-Stochastik auf dem LongCandleType-Zeitrahmen.
Wendet die konfigurierte Glättungsmethode auf die %K- und %D-Werte an und verschiebt sie um LongSignalBar Balken.
Öffnet eine Long-Position, wenn %K über %D kreuzt (previousK <= previousD und currentK > currentD).
Schließt eine bestehende Long-Position, wenn %K wieder unter %D fällt (currentK < currentD).
Short-Modul
Bewertet den Short-Stochastik auf dem ShortCandleType-Zeitrahmen.
Öffnet eine Short-Position, wenn %K unter %D kreuzt (previousK >= previousD und currentK < currentD).
Schließt eine bestehende Short-Position, wenn %K wieder über %D steigt (currentK > currentD).
Orders werden als Marktorders ausgeführt. Das gesendete Volumen entspricht TradeVolume plus dem Absolutwert der aktuellen Position, damit Umkehrungen die vorherige Exposition zuerst flatten.
Ein schützender Take-Profit und Stop-Loss in Preispunkten werden über StartProtection angehängt, um die MT5-Orderparameter nachzuahmen.
Parameter
Parameter
Typ
Standard
Beschreibung
LongCandleType
DataType
8-Stunden-Kerzen
Zeitrahmen für den Long-Stochastik-Oszillator.
LongKPeriod
int
5
%K-Berechnungsperiode für den Long-Stochastik.
LongDPeriod
int
3
%D-Glättungsperiode für den Long-Stochastik.
LongSlowing
int
3
Zusätzliche Verlangsamung innerhalb der stochastischen Berechnung.
LongSignalBar
int
1
Anzahl geschlossener Balken für die Kreuzungsbewertung.
LongSmoothingMethod
SmoothingMethod
Smoothed
Sekundäre Glättung für %K und %D (None, Simple, Exponential, Smoothed, Weighted).
LongSmoothingLength
int
5
Länge des sekundären Glättungsfilters für den Long-Oszillator.
LongEnableOpen
bool
true
Erlaubt Long-Positionen zu öffnen.
LongEnableClose
bool
true
Erlaubt Long-Positionen zu schließen.
ShortCandleType
DataType
8-Stunden-Kerzen
Zeitrahmen für den Short-Stochastik-Oszillator.
ShortKPeriod
int
5
%K-Berechnungsperiode für den Short-Stochastik.
ShortDPeriod
int
3
%D-Glättungsperiode für den Short-Stochastik.
ShortSlowing
int
3
Zusätzliche Verlangsamung innerhalb der stochastischen Berechnung.
ShortSignalBar
int
1
Anzahl geschlossener Balken für die Short-Kreuzungsbewertung.
ShortSmoothingMethod
SmoothingMethod
Smoothed
Sekundäre Glättung für die Short-%K- und %D-Werte.
ShortSmoothingLength
int
5
Länge des sekundären Glättungsfilters für den Short-Oszillator.
ShortEnableOpen
bool
true
Erlaubt Short-Positionen zu öffnen.
ShortEnableClose
bool
true
Erlaubt Short-Positionen zu schließen.
TradeVolume
decimal
0.1
Basisvolumen für Positionseintritte.
TakeProfitPoints
decimal
2000
Take-Profit-Abstand in Preispunkten.
StopLossPoints
decimal
1000
Stop-Loss-Abstand in Preispunkten.
Hinweise
Die zusätzliche SmoothingMethod ahmt die optionale JJMA-basierte Glättung des ursprünglichen Indikators mithilfe der in StockSharp verfügbaren Standard-Moving-Averages nach. Wählen Sie None, um diese Stufe zu deaktivieren, wenn keine exakte Replikation erforderlich ist.
Long- und Short-Module sind unabhängig; Sie können jede Seite über die entsprechenden boolean Flags aktivieren oder deaktivieren.
Da StockSharp mit Nettopositionen arbeitet, schließt die Strategie immer die entgegengesetzte Exposition, wenn ein neues Signal die Richtung umkehrt.
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;
/// <summary>
/// Slow Stochastic Duplex strategy using EMA crossover.
/// Buys when fast EMA crosses above slow EMA, sells on reverse.
/// </summary>
public class ExpSlowStochDuplexStrategy : 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 ExpSlowStochDuplexStrategy()
{
_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 exp_slow_stoch_duplex_strategy(Strategy):
def __init__(self):
super(exp_slow_stoch_duplex_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(exp_slow_stoch_duplex_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(exp_slow_stoch_duplex_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 exp_slow_stoch_duplex_strategy()