Die ZeeZee-Level-Strategie repliziert das Verhalten des ursprünglichen MetaTrader Expert Advisors "ZeeZee Level" mit der High-Level-API von StockSharp. Die Strategie analysiert ZigZag-Schwünge auf dem ausgewählten Zeitrahmen und handelt in Richtung des jüngsten Extrems. Schutz-Stop-Loss-, Take-Profit- und Trailing-Stop-Distanzen werden in Pips ausgedrückt, und die Positionsgröße folgt nach Verlusttrades einer martingaleartigen Progression.
Handelslogik
Kerzen werden mit dem durch CandleType definierten Zeitrahmen abonniert.
Ein ZigZagIndicator mit konfigurierbaren Parametern für Tiefe, Abweichung und Backstep verfolgt Swing-Hochs und Swing-Tiefs.
Wenn keine Position offen ist, vergleicht die Strategie die Aktualität des letzten bestätigten ZigZag-Hochs und -Tiefs innerhalb des Fensters ZigZagIdInterval:
Wenn das letzte Swing-Hoch aktueller ist als das letzte Swing-Tief, wird eine Short-Position eröffnet.
Wenn das letzte Swing-Tief aktueller ist als das letzte Swing-Hoch, wird eine Long-Position eröffnet.
Es wird jeweils nur eine Position gehalten. Das Einstiegsvolumen wird auf den Volumenschritt des Instruments gerundet.
Nach dem Eröffnen der Position werden Stop-Loss-, Take-Profit- und optionale Trailing-Stop-Niveaus mit den konfigurierten Pip-Distanzen angehängt. Der Trailing Stop folgt dem Extrempreis, während sich der Trade zu seinen Gunsten bewegt.
Positionen werden geschlossen, sobald entweder das Stop-Loss- oder das Take-Profit-Niveau berührt wird. Werden beide Niveaus in derselben Kerze erreicht, entscheidet das zum Einstiegspreis nähere Niveau.
Nach jedem Ausstieg wird das Volumen bei Gewinntrades auf den Anfangswert zurückgesetzt oder bei Verlusttrades mit dem Martingale-Faktor multipliziert.
Parameter
Parameter
Beschreibung
ZigZagDepth
Anzahl der Kerzen, die bei der Suche nach neuen ZigZag-Pivots berücksichtigt werden.
ZigZagDeviation
Minimale Preisbewegung (in Preisschritten), die zur Bestätigung eines neuen Pivots erforderlich ist.
ZigZagBackstep
Mindestanzahl von Bars, bevor der Indikator die Richtung wechseln kann.
ZigZagIdInterval
Maximale Anzahl von Bars, die für die Suche nach den letzten ZigZag-Hochs und -Tiefs zurückgeblickt wird.
StopLossPips
Stop-Loss-Distanz in Pips. Auf null setzen, um zu deaktivieren.
TakeProfitPips
Take-Profit-Distanz in Pips. Auf null setzen, um zu deaktivieren.
TrailingStopPips
Trailing-Stop-Distanz in Pips. Auf null setzen, um zu deaktivieren.
InitialVolume
Basis-Handelsvolumen zu Beginn eines Martingale-Zyklus.
MartingaleMultiplier
Faktor, der nach einer Verlustposition auf das nächste Handelsvolumen angewendet wird.
CandleType
Kerzentyp und Zeitrahmen für die Analyse.
Geldmanagement
Volumina werden an den Volumenschritt des Instruments angepasst und zwischen den Mindest- und Höchstgrenzen der Börse begrenzt.
Gewinntrades setzen das Volumen auf InitialVolume zurück, während Verlusttrades es mit MartingaleMultiplier multiplizieren.
Risikomanagement
Stop-Loss-, Take-Profit- und Trailing-Stop-Distanzen werden auf jeder abgeschlossenen Kerze bewertet.
Der Trailing Stop bewegt sich nur in Trade-Richtung und zieht nie zurück.
Der Handel wird übersprungen, solange die Strategie bereits eine Position hält oder die ZigZag-Schwünge innerhalb des konfigurierten Intervalls nicht verfügbar sind.
Hinweise
Die Strategie verwendet nur geschlossene Kerzen, um dem Verhalten des ursprünglichen Expert Advisors zu entsprechen.
Pip-Umrechnungen stützen sich auf den PriceStep des Instruments. Stellen Sie sicher, dass die Instrumentenmetadaten geladen sind, bevor die Strategie gestartet wird.
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 ZeeZeeLevelStrategy : 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 ZeeZeeLevelStrategy()
{
_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 zee_zee_level_strategy(Strategy):
def __init__(self):
super(zee_zee_level_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(zee_zee_level_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(zee_zee_level_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 zee_zee_level_strategy()