Auf GitHub ansehen

ZeeZee-Level-Strategie

Überblick

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

  1. Kerzen werden mit dem durch CandleType definierten Zeitrahmen abonniert.
  2. Ein ZigZagIndicator mit konfigurierbaren Parametern für Tiefe, Abweichung und Backstep verfolgt Swing-Hochs und Swing-Tiefs.
  3. 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.
  4. Es wird jeweils nur eine Position gehalten. Das Einstiegsvolumen wird auf den Volumenschritt des Instruments gerundet.
  5. 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.
  6. 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.
  7. 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;
	}
}