Auf GitHub ansehen

ZigZag-Climber-Strategie

Überblick

Der von fxDreema erzeugte ZigZag-Climber-Expert-Advisor enthält nur drei Blöcke: einen No trade-Filter, gefolgt von Buy now- und Sell now-Aktionen. Sobald das Terminal erkennt, dass keine Positionen offen sind, sendet es sofort eine Markt-Kauforder mit vordefinierten Stop-Loss- und Take-Profit-Niveaus und platziert ohne weitere Prüfungen eine symmetrische Markt-Verkaufsorder. Beide Trades übernehmen dieselben Risikoparameter und sollen als gehedgtes Paar koexistieren.

Dieser C#-Port reproduziert dieses Verhalten in StockSharp, indem er auf die erste abgeschlossene Kerze des gewählten Zeitrahmens wartet und dann Kauf- und Verkaufsschenkel direkt nacheinander mit identischen Schutzdistanzen sendet. Zusätzliche Signalgenerierung, Trailing-Logik oder Positionsverwaltung gibt es nicht, exakt wie im MQL-Quellprojekt.

Handelslogik

  1. Warten, bis die erste Kerze des konfigurierten Zeitrahmens vollständig gebildet ist.
  2. Wenn die Strategie handeln darf und noch keine Orders platziert wurden, eine Markt-Kauforder mit festem Volumen senden.
  3. Stop-Loss- und Take-Profit-Orders an den Long-Trade mit MetaTrader-artigen Pip-Distanzen anhängen (über PriceStep des Instruments konvertiert).
  4. Sofort eine Markt-Verkaufsorder mit demselben Volumen senden und gespiegelte Schutzniveaus anhängen.
  5. Für den Rest des Laufs keine weiteren Orders eröffnen.

Wichtig: MetaTrader 4 arbeitet im Hedging-Modus, daher können beide Seiten gleichzeitig offen bleiben. StockSharp verwendet das Ausführungsmodell des Brokers; auf Netting-Konten wird die zweite Order die erste ausgleichen und die Strategie endet flach. Verwenden Sie einen hedgingfähigen Connector (z. B. MetaTrader-Gateway für Hedge-Konten), wenn beide Schenkel offen bleiben sollen.

Parameter

Name Standard Beschreibung
Candle Type 1 Minute Zeitrahmen, der die einmalige Einstiegssequenz auslöst.
Trade Volume 0.01 Festes Volumen für beide Marktorders.
Stop-Loss (pips) 99.9 Distanz des Schutzstops in MetaTrader-Pips (behandelt 4-/5-stellige Symbole automatisch).
Take-Profit (pips) 100 Zieldistanz in MetaTrader-Pips.

Alle Distanzen werden über PriceStep und Dezimalpräzision des Instruments in Preispunkte umgerechnet, bevor sie an SetStopLoss/SetTakeProfit übergeben werden.

Risikomanagement

Die Strategie verlässt sich auf den integrierten Dienst StartProtection() und die Hilfsmethoden SetStopLoss/SetTakeProfit, um Schutzorders direkt nach jeder Marktorder zu platzieren. Es gibt keine Trailing- oder Break-even-Logik.

Nutzungshinweise

  • Weisen Sie vor dem Start die gewünschte Security und das Portfolio zu. Stellen Sie sicher, dass das Symbol PriceStep und Decimals bereitstellt, damit die Pip-Konvertierung korrekt funktioniert.
  • Da die Einstiegslogik nur einmal läuft, ist ein Neustart der Strategie der einzige Weg, einen neuen Hedge-Zyklus zu erzeugen.
  • Beim Test auf einem Netting-Simulator weicht das reale Verhalten von MetaTrader ab: Die Verkaufsorder neutralisiert die Kauforder nahezu sofort.
using System;

using Ecng.Common;

using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;

namespace StockSharp.Samples.Strategies;

/// <summary>
/// ZigZag Climber strategy: Highest/Lowest channel breakout.
/// Buys when close >= highest, sells when close <= lowest.
/// </summary>
public class ZigZagClimberStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _channelPeriod;

	public DataType CandleType
	{
		get => _candleType.Value;
		set => _candleType.Value = value;
	}

	public int ChannelPeriod
	{
		get => _channelPeriod.Value;
		set => _channelPeriod.Value = value;
	}

	public ZigZagClimberStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame())
			.SetDisplay("Candle Type", "Candle timeframe", "General");

		_channelPeriod = Param(nameof(ChannelPeriod), 12)
			.SetGreaterThanZero()
			.SetDisplay("Channel Period", "Highest/Lowest lookback", "Indicators");
	}

	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);

		var high = new Highest { Length = ChannelPeriod };
		var low = new Lowest { Length = ChannelPeriod };

		var subscription = SubscribeCandles(CandleType);
		subscription
			.Bind(high, low, ProcessCandle)
			.Start();

		var area = CreateChartArea();
		if (area != null)
		{
			DrawCandles(area, subscription);
			DrawOwnTrades(area);
		}
	}

	private void ProcessCandle(ICandleMessage candle, decimal high, decimal low)
	{
		if (candle.State != CandleStates.Finished)
			return;

		if (!IsFormedAndOnlineAndAllowTrading())
			return;

		if (candle.ClosePrice >= high && Position <= 0)
		{
			BuyMarket();
		}
		else if (candle.ClosePrice <= low && Position >= 0)
		{
			SellMarket();
		}
	}
}