Start
/
Strategie-Beispiele
Auf GitHub ansehen
Strategie Cronex DeMarker
Die Cronex-DeMarker-Strategie reproduziert den klassischen Cronex-Experten-Advisor, der den DeMarker-Oszillator mit einem doppelten Glättungs-Stack kombiniert. Zunächst werden die DeMarker-Werte durch einen schnellen einfachen gleitenden Durchschnitt geglättet, dann wird das Ergebnis durch einen langsameren Durchschnitt noch einmal geglättet. Die Distanz und relative Anordnung dieser zwei Linien liefern reversal-artige Einstiegssignale.
Die ursprüngliche MQL5-Implementierung erlaubt Handelsrichtungs-Umschaltungen und funktioniert auf höheren Zeitrahmen. Dieser StockSharp-Port behält dieselbe Philosophie: Er reagiert, wenn die schnelle Linie durch die langsame kreuzt, und schließt sofort jede entgegengesetzte Position. Da das System konträr ist, öffnet ein Kreuzen unter der langsamen Linie eine Long-Position, während ein Kreuzen darüber eine Short öffnet. Beide Richtungen können über Parameter unabhängig deaktiviert werden, was die Strategie für verschiedene Portfolio-Allokationen flexibel macht.
Funktionsweise
Kerzen für den ausgewählten Zeitrahmen anfordern (standardmäßig 4H).
Den DeMarker-Oszillator berechnen und mit einem schnellen SMA glätten (Standard 14 Balken).
Einen zweiten SMA (Standard 25 Balken) auf die schnelle Linie anwenden, um die Signallinie zu erhalten.
Wenn die schnelle Linie bei der vorherigen Kerze über der langsamen lag und jetzt darunter fällt, kauft die Strategie (konträre Umkehr). Jede bestehende Short-Position wird geglättet.
Wenn die schnelle Linie bei der vorherigen Kerze unter der langsamen lag und jetzt darüber steigt, verkauft die Strategie und schließt jede offene Long-Position.
Die Positionsgröße wird durch die Volume-Eigenschaft definiert; Umkehrungen verwenden die absolute Position, um sofort umzukehren.
Diese Logik ermöglicht dem Experten, kurzfristige Erschöpfungsbewegungen nach starken Momentum-Schüben zu erfassen, was ihn zu einem Mean-Reversion-Werkzeug macht, das Range- oder Chop-Märkte bevorzugt.
Standardparameter
Parameter
Standard
Beschreibung
DeMarkerPeriod
25
Anzahl der Balken, die vom DeMarker-Oszillator verwendet werden.
FastPeriod
14
Länge des ersten Glättungs-SMA, der auf DeMarker-Werte angewendet wird.
SlowPeriod
25
Länge des Signal-SMA, der auf die schnelle Linie angewendet wird.
CandleType
4 Stunden
Kerzenserie für Indikatorberechnungen.
EnableLongEntry
true
Konträre Long-Einstiege erlauben, wenn die schnelle Linie unter die langsame kreuzt.
EnableShortEntry
true
Short-Einstiege erlauben, wenn die schnelle Linie über die langsame kreuzt.
EnableLongExit
true
Bestehende Long-Positionen schließen, wenn bärische Bedingungen auftreten.
EnableShortExit
true
Bestehende Short-Positionen schließen, wenn bullische Bedingungen auftreten.
Kategorie : Mean Reversion, Oszillator-basiert
Richtung : Long & Short (konfigurierbar)
Indikatoren : DeMarker, Einfacher gleitender Durchschnitt (doppelte Glättung)
Stops : Keine (vollständig signalgesteuert)
Zeitrahmen : Swing Trading (H4 standardmäßig, anpassbar)
Komplexität : Mittel aufgrund der sequentiellen Indikatorkette
Risikoprofil : Mittel — konträre Einstiege können auf anhaltende Trends treffen
Automatisierung : Vollständig automatisiert über die StockSharp High-Level-API
Verwendungshinweise
Die Strategie verarbeitet nur abgeschlossene Kerzen, um Neuzeichnungsprobleme zu vermeiden.
Umkehrorders verwenden die absolute Positionsgröße wieder und garantieren sofortiges Glätten vor dem Einsteigen in die neue Richtung.
Chartausgabe zeichnet die zwei geglätteten Linien und Trade-Marker, was bei der diskretionären Validierung hilft.
Für Portfolios, die nur eine Richtung erlauben, unerwünschte Einstiege und Ausstiege über die bereitgestellten Parameter deaktivieren.
Externe Risikokontrollen (Stop-Loss, Trailing-Ausstieg) in Betracht ziehen, wenn auf volatilen Assets eingesetzt.
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 CronexDeMarkerStrategy : 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 CronexDeMarkerStrategy()
{
_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 cronex_de_marker_strategy(Strategy):
def __init__(self):
super(cronex_de_marker_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(cronex_de_marker_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(cronex_de_marker_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 cronex_de_marker_strategy()