Die Pending Limit Grid Strategy reproduziert das Verhalten des MetaTrader-Experten
gespeichert in MQL/8147. Die Strategie baut ein symmetrisches Raster aus ausstehenden Limit-Orders auf
um die aktuellen Geld-/Briefkurse herum. Es hält das Netz aktiv, während der Gewinn schwankt
bleibt innerhalb eines konfigurierten Gewinnziels und einer Drawdown-Schwelle. Wenn einer der
Schwellenwerte werden überschritten, alle Aufträge werden storniert, offene Positionen werden abgeflacht und
Das Raster wird unter Verwendung des neuen Kontokapitals als Basis neu aufgebaut.
Handelslogik
Abonnieren Sie Level-One-Daten, um die besten Geld- und Briefkurse zu verfolgen.
Erfassen Sie das Kontoguthaben beim ersten Empfang von Live-Daten und speichern Sie es als
die Sitzungsbasislinie.
Platzieren Sie LevelsPerSide Verkaufslimits über dem Markt und die gleiche Anzahl an Käufen
Grenzen unterhalb des Marktes. Der Abstand zwischen den Gitterebenen wird durch gesteuert
GridStepPoints in den Instrumentenpreisschritt umgerechnet.
Halten Sie die ausstehenden Aufträge zurück, ohne neue Aufträge erneut auszugeben, wenn sie ausgeführt werden. Die
Das Raster wird erst nach einem vollständigen Reset neu erstellt.
Floating PnL kontinuierlich überwachen:
Wenn der Gewinn ProfitTargetCurrency erreicht, alle Engagements schließen und zurücksetzen.
Wenn der Drawdown MaxDrawdownCurrency überschreitet, glätten Sie das Buch und setzen Sie es zurück.
Nach jedem Zurücksetzen wird das Grundkapital erneut erfasst und das Raster neu aufgebaut
unter Verwendung des aktuellsten Bid/Ask-Snapshots.
Parameter
Parameter
Beschreibung
ProfitTargetCurrency
Nettogewinn (in Kontowährung), der einen vollständigen Reset des Rasters auslöst.
MaxDrawdownCurrency
Maximal tolerierter Floating-Verlust, bevor die gesamte Exposition geschlossen wird.
GridStepPoints
Abstand zwischen aufeinanderfolgenden Rasterebenen, ausgedrückt in Brokerpunkten.
LevelsPerSide
Anzahl der ausstehenden Aufträge, die über und unter dem Marktwert erstellt wurden.
OrderVolume
Das jeder ausstehenden Limit-Order zugewiesene Volumen.
Risikomanagement
Die Strategie sieht keine Stopps oder Ziele pro Order vor. Stattdessen überwacht es die
aggregierter Gewinn und Verlust. Der RequestFlatten-Helfer storniert ausstehende Orders und
verwendet Marktaufträge (über ClosePosition), um alle offenen Positionen zu entfernen. Nach dem
Wenn die Abflachung abgeschlossen ist, werden der Gitterstatus und die Grundliniengerechtigkeit vor dem Platzieren zurückgesetzt
neue Aufträge.
Notizen
Die Preise werden bis Security.ShrinkPrice normalisiert, um den Umtausch zu berücksichtigen
Preisschritt.
Der „Punkt“-Wert MetaTrader wird durch Analyse des Instruments PriceStep emuliert.
um vier- und fünfstellige Anführungszeichen abzugleichen.
Die Strategie vermeidet das erneute Senden von Grid-Bestellungen, sobald sie platziert wurden, und ahmt dies nach
ursprünglicher Experte, der sich auf Flag-Variablen stützte, um jedes Level bis dahin einzigartig zu halten
Es erfolgt ein manueller oder automatischer Reset.
using System;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
public class PendingLimitGridStrategy : Strategy
{
private readonly StrategyParam<int> _channelPeriod;
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _cooldownBars;
private decimal _prevClose;
private decimal _prevMid;
private bool _hasPrev;
private int _barsSinceLastTrade;
public int ChannelPeriod { get => _channelPeriod.Value; set => _channelPeriod.Value = value; }
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public int CooldownBars { get => _cooldownBars.Value; set => _cooldownBars.Value = value; }
public PendingLimitGridStrategy()
{
_channelPeriod = Param(nameof(ChannelPeriod), 24).SetDisplay("Channel Period", "Grid channel lookback", "Indicators");
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame()).SetDisplay("Candle Type", "Candle timeframe", "General");
_cooldownBars = Param(nameof(CooldownBars), 200).SetDisplay("Cooldown Bars", "Minimum bars between trades", "Risk");
}
protected override void OnReseted()
{
base.OnReseted();
_prevClose = 0;
_prevMid = 0;
_hasPrev = false;
_barsSinceLastTrade = 0;
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_hasPrev = false;
_barsSinceLastTrade = 0;
var highest = new Highest { Length = ChannelPeriod };
var lowest = new Lowest { Length = ChannelPeriod };
var subscription = SubscribeCandles(CandleType);
subscription.Bind(highest, lowest, ProcessCandle).Start();
}
private void ProcessCandle(ICandleMessage candle, decimal highest, decimal lowest)
{
if (candle.State != CandleStates.Finished) return;
var close = candle.ClosePrice;
var mid = (highest + lowest) / 2;
if (!_hasPrev) { _prevClose = close; _prevMid = mid; _hasPrev = true; return; }
_barsSinceLastTrade++;
if (_barsSinceLastTrade >= CooldownBars)
{
if (_prevClose <= _prevMid && close > mid && Position <= 0)
{
if (Position < 0) BuyMarket();
BuyMarket();
_barsSinceLastTrade = 0;
}
else if (_prevClose >= _prevMid && close < mid && Position >= 0)
{
if (Position > 0) SellMarket();
SellMarket();
_barsSinceLastTrade = 0;
}
}
_prevClose = close;
_prevMid = mid;
}
}
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 Highest, Lowest
from StockSharp.Algo.Strategies import Strategy
from datatype_extensions import *
from indicator_extensions import *
class pending_limit_grid_strategy(Strategy):
def __init__(self):
super(pending_limit_grid_strategy, self).__init__()
self._channel_period = self.Param("ChannelPeriod", 24).SetDisplay("Channel Period", "Grid channel lookback", "Indicators")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(5))).SetDisplay("Candle Type", "Candle timeframe", "General")
@property
def CandleType(self): return self._candle_type.Value
@CandleType.setter
def CandleType(self, value): self._candle_type.Value = value
def OnReseted(self):
super(pending_limit_grid_strategy, self).OnReseted()
self._has_prev = False
self._prev_close = 0
self._prev_mid = 0
def OnStarted2(self, time):
super(pending_limit_grid_strategy, self).OnStarted2(time)
self._has_prev = False
self._prev_close = 0
self._prev_mid = 0
highest = Highest()
highest.Length = self._channel_period.Value
lowest = Lowest()
lowest.Length = self._channel_period.Value
sub = self.SubscribeCandles(self.CandleType)
sub.Bind(highest, lowest, self.OnProcess).Start()
def OnProcess(self, candle, highest, lowest):
if candle.State != CandleStates.Finished:
return
close = candle.ClosePrice
mid = (highest + lowest) / 2.0
if not self._has_prev:
self._prev_close = close
self._prev_mid = mid
self._has_prev = True
return
if self._prev_close <= self._prev_mid and close > mid and self.Position <= 0:
if self.Position < 0:
self.BuyMarket()
self.BuyMarket()
elif self._prev_close >= self._prev_mid and close < mid and self.Position >= 0:
if self.Position > 0:
self.SellMarket()
self.SellMarket()
self._prev_close = close
self._prev_mid = mid
def CreateClone(self):
return pending_limit_grid_strategy()