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
Beim Start abonniert die Strategie Kerzen und wartet auf die erste abgeschlossene Kerze.
Anhand des Schlusskurses dieser Kerze wird das Grid mit der konfigurierten Anzahl von Levels aufgebaut.
Für jedes Level werden Kauf- und/oder Verkaufs-Limit-Orders je nach erlaubten Seiten platziert.
Wenn eine Einstiegsorder ausgeführt wird, wird eine entgegengesetzte Limit-Order zum berechneten
Take-Profit-Preis des gewählten Rangs registriert.
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();
}
}
}
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, StandardDeviation
from StockSharp.Algo.Strategies import Strategy
class three_level_grid_strategy(Strategy):
def __init__(self):
super(three_level_grid_strategy, self).__init__()
self._ema_length = self.Param("EmaLength", 30) \
.SetDisplay("EMA Length", "EMA period for center line", "Indicators")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(4))) \
.SetDisplay("Candle Type", "Type of candles", "General")
@property
def ema_length(self):
return self._ema_length.Value
@property
def candle_type(self):
return self._candle_type.Value
def OnStarted2(self, time):
super(three_level_grid_strategy, self).OnStarted2(time)
ema = ExponentialMovingAverage()
ema.Length = self.ema_length
atr = StandardDeviation()
atr.Length = 14
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(ema, atr, self.on_process).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawOwnTrades(area)
def on_process(self, candle, ema_val, atr_val):
if candle.State != CandleStates.Finished:
return
if atr_val <= 0:
return
close = candle.ClosePrice
diff = close - ema_val
# Buy at different grid levels below EMA
if diff < -1.5 * atr_val and self.Position <= 0:
if self.Position < 0:
self.BuyMarket()
self.BuyMarket()
# Sell at different grid levels above EMA
elif diff > 1.5 * atr_val and self.Position >= 0:
if self.Position > 0:
self.SellMarket()
self.SellMarket()
# Mean reversion exit
elif self.Position > 0 and close > ema_val + 0.5 * atr_val:
self.SellMarket()
elif self.Position < 0 and close < ema_val - 0.5 * atr_val:
self.BuyMarket()
def CreateClone(self):
return three_level_grid_strategy()