Auf GitHub ansehen

Drei-Ebenen-Grid-Strategie

Diese Strategie implementiert ein symmetrisches Grid-Handelssystem mit bis zu drei Take-Profit-Rängen. Limit-Orders werden oberhalb und unterhalb des aktuellen Preises in festen Abständen platziert. Wenn eine Einstiegsorder ausgeführt wird, wird eine entgegengesetzte Limit-Order eingereicht, um Gewinn in einem konfigurierbaren Abstand zu sichern. Die Methode eignet sich für seitwärts tendierende Märkte, in denen der Preis innerhalb einer Bandbreite oszilliert.

Parameter

  • Grid Size – Abstand zwischen Grid-Levels.
  • Levels – Anzahl der Grid-Levels auf jeder Seite des aktuellen Preises.
  • Base Take Profit – Basisgewinnabstand für den ersten Rang.
  • Order Volume – Volumen für jede Grid-Order.
  • Enable Rank1 – Orders mit Basis-Take-Profit platzieren.
  • Enable Rank2 – Orders mit Basis plus einem Grid-Size-Take-Profit platzieren.
  • Enable Rank3 – Orders mit Basis plus zwei Grid-Sizes Take-Profit platzieren.
  • Allow Longs – die Long-Seite des Grids aktivieren.
  • Allow Shorts – die Short-Seite des Grids aktivieren.
  • Candle Type – Kerzentyp zum Ermitteln des anfänglichen Referenzpreises.

Handelslogik

  1. Beim Start abonniert die Strategie Kerzen und wartet auf die erste abgeschlossene Kerze.
  2. Anhand des Schlusskurses dieser Kerze wird das Grid mit der konfigurierten Anzahl von Levels aufgebaut.
  3. Für jedes Level werden Kauf- und/oder Verkaufs-Limit-Orders je nach erlaubten Seiten platziert.
  4. Wenn eine Einstiegsorder ausgeführt wird, wird eine entgegengesetzte Limit-Order zum berechneten Take-Profit-Preis des gewählten Rangs registriert.
  5. Orders verbleiben im Markt, bis sie ausgeführt oder manuell storniert werden.

Diese Implementierung ist eine vereinfachte Konvertierung des ursprünglichen MQL-Grid-Systems und soll die Kernmechanik in StockSharp's High-Level-API hervorheben.

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>
/// Three-level grid strategy using EMA as center line.
/// Buys on dips below EMA at different levels, sells on rises above EMA.
/// </summary>
public class ThreeLevelGridStrategy : Strategy
{
	private readonly StrategyParam<int> _emaLength;
	private readonly StrategyParam<DataType> _candleType;

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

	public ThreeLevelGridStrategy()
	{
		_emaLength = Param(nameof(EmaLength), 30)
			.SetGreaterThanZero()
			.SetDisplay("EMA Length", "EMA period for center line", "Indicators");

		_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
			.SetDisplay("Candle Type", "Type of candles", "General");
	}

	public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
		=> [(Security, CandleType)];

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

		var ema = new ExponentialMovingAverage { Length = EmaLength };
		var atr = new StandardDeviation { Length = 14 };

		var subscription = SubscribeCandles(CandleType);
		subscription
			.Bind(ema, atr, ProcessCandle)
			.Start();
	}

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

		if (atrVal <= 0)
			return;

		var close = candle.ClosePrice;
		var diff = close - emaVal;

		// Buy at different grid levels below EMA
		if (diff < -1.5m * atrVal && Position <= 0)
		{
			if (Position < 0)
				BuyMarket();
			BuyMarket();
		}
		// Sell at different grid levels above EMA
		else if (diff > 1.5m * atrVal && Position >= 0)
		{
			if (Position > 0)
				SellMarket();
			SellMarket();
		}
		// Mean reversion exit
		else if (Position > 0 && close > emaVal + 0.5m * atrVal)
		{
			SellMarket();
		}
		else if (Position < 0 && close < emaVal - 0.5m * atrVal)
		{
			BuyMarket();
		}
	}
}