Die VR Smart Grid Lite-Strategie repliziert die Logik des gleichnamigen Expertenberaters MetaTrader. Die Strategie erstellt mithilfe von Marktaufträgen ein Mittelungsgitter im Martingal-Stil. Die Positionsgröße beginnt bei einem Basisvolumen und verdoppelt sich jedes Mal, wenn sich der Preis um eine benutzerdefinierte Distanz gegenüber der bestehenden Position bewegt. Die Strategie unterstützt zwei Ausstiegsmodi: die Schließung der Extremgeschäfte zu einem gewichteten Take-Profit-Preis oder die teilweise Reduzierung des Engagements bei gleichzeitig aktivem Netz.
Parameter
Take Profit (Pips) – Abstand in Pips, der zum Ausstieg benötigt wird, wenn nur eine Position aktiv ist.
Startvolumen – anfängliches Ordervolumen für den ersten Trade in jede Richtung.
Maximales Volumen – feste Obergrenze für jede einzelne vom Raster geöffnete Bestellung.
Schließmodus – Average schließt die ältesten und neuesten Bestellungen zu einem gewichteten Ziel; PartClose schließt einen Teil der neuesten Bestellung und die gesamte älteste Bestellung.
Order Step (Pips) – Mindestpreisentfernung, die gegenüber der Position zurückgelegt werden muss, bevor ein neuer Trade eröffnet wird.
Minimaler Gewinn (Pips) – zusätzliche Gewinnspanne, die zum gewichteten durchschnittlichen Ausstiegspreis hinzugefügt wird.
Slippage (Pips) – Platzhalterparameter, der der Vollständigkeit halber vom ursprünglichen EA übernommen wurde.
Kerzentyp – Zeitrahmen, der zur Entscheidungsfindung verwendet wird (die zuvor abgeschlossene Kerze bestimmt die Handelsausrichtung).
Algorithmus
Bei jeder fertigen Kerze bewertet die Strategie die Richtung der vorherigen Kerze.
Wenn die vorherige Kerze bullisch schloss und entweder keine Long-Trades vorhanden sind oder der Preis um den konfigurierten Schritt nach unten gesunken ist, wird eine neue Kaufmarkt-Order platziert.
Wenn die vorherige Kerze bärisch geschlossen hat und entweder keine Short-Trades vorhanden sind oder der Preis um die konfigurierte Stufe gestiegen ist, wird eine neue Verkaufsmarkt-Order platziert.
Die Volumina werden ausgehend von der Position mit dem niedrigsten Preis in der Richtung berechnet und auf jeder neuen Ebene verdoppelt, wobei das maximale Volumen und die Broker-Volumenschritte berücksichtigt werden.
Wenn nur noch eine Position übrig ist, wendet die Strategie die einfache Take-Profit-Distanz an und steigt bei Berührung aus.
Bei mehreren Positionen berechnet die Strategie gewichtete Durchschnitte anhand der extremen Einträge:
Der Durchschnittsmodus schließt beide Extreme, wenn der Preis das gewichtete Ziel plus den minimalen Gewinnpuffer erreicht.
PartClose-Modus schließt einen Teil der neuesten Bestellung, der dem Startvolumen entspricht, und schließt die älteste Bestellung vollständig, sodass das Raster mit reduzierter Belichtung weiterlaufen kann.
Alle gefüllten und geschlossenen Positionen werden verfolgt, um den internen Rasterstatus mit dem Live-Portfolio synchronisiert zu halten.
Notizen
Die Strategie basiert auf Marktaufträgen, sodass die tatsächliche Ausführungsqualität und der Slippage von den Bedingungen des Brokers abhängen.
Stellen Sie sicher, dass die Volumenbeschränkungen des Instruments (Mindestvolumen und Volumenschritt) mit dem ausgewählten Startvolumen kompatibel sind.
Wie bei jedem Grid- oder Martingal-Ansatz kann das Risiko schnell wachsen, wenn die Märkte stark gegen die Position tendieren; Verwenden Sie ein umsichtiges Geldmanagement.
namespace StockSharp.Samples.Strategies;
using System;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.Messages;
/// <summary>
/// VR Smart Grid Lite: grid trading based on price levels with SMA filter.
/// </summary>
public class VrSmartGridLiteStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<decimal> _gridPercent;
private readonly StrategyParam<int> _smaPeriod;
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
public decimal GridPercent
{
get => _gridPercent.Value;
set => _gridPercent.Value = value;
}
public int SmaPeriod
{
get => _smaPeriod.Value;
set => _smaPeriod.Value = value;
}
public VrSmartGridLiteStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(30).TimeFrame())
.SetDisplay("Candle Type", "Candle timeframe", "General");
_gridPercent = Param(nameof(GridPercent), 3.0m)
.SetGreaterThanZero()
.SetDisplay("Grid %", "Grid step percentage", "Grid");
_smaPeriod = Param(nameof(SmaPeriod), 20)
.SetGreaterThanZero()
.SetDisplay("SMA Period", "SMA period for trend", "Indicators");
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var sma = new SimpleMovingAverage { Length = SmaPeriod };
decimal? lastTradePrice = null;
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(sma, (candle, smaVal) =>
{
if (candle.State != CandleStates.Finished)
return;
if (!IsFormedAndOnlineAndAllowTrading())
return;
var close = candle.ClosePrice;
if (!lastTradePrice.HasValue)
{
lastTradePrice = close;
return;
}
var step = lastTradePrice.Value * GridPercent / 100m;
if (close <= lastTradePrice.Value - step)
{
BuyMarket();
lastTradePrice = close;
}
else if (close >= lastTradePrice.Value + step)
{
SellMarket();
lastTradePrice = close;
}
})
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, sma);
DrawOwnTrades(area);
}
}
}
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 SimpleMovingAverage
from StockSharp.Algo.Strategies import Strategy
class vr_smart_grid_lite_strategy(Strategy):
def __init__(self):
super(vr_smart_grid_lite_strategy, self).__init__()
self._grid_percent = self.Param("GridPercent", 3.0) \
.SetDisplay("Grid %", "Grid step percentage", "Grid")
self._sma_period = self.Param("SmaPeriod", 20) \
.SetDisplay("SMA Period", "SMA period for trend", "Indicators")
self._sma = None
self._last_trade_price = None
@property
def grid_percent(self):
return self._grid_percent.Value
@property
def sma_period(self):
return self._sma_period.Value
def OnReseted(self):
super(vr_smart_grid_lite_strategy, self).OnReseted()
self._sma = None
self._last_trade_price = None
def OnStarted2(self, time):
super(vr_smart_grid_lite_strategy, self).OnStarted2(time)
self._sma = SimpleMovingAverage()
self._sma.Length = self.sma_period
subscription = self.SubscribeCandles(DataType.TimeFrame(TimeSpan.FromMinutes(30)))
subscription.Bind(self._sma, self._process_candle)
subscription.Start()
def _process_candle(self, candle, sma_value):
if candle.State != CandleStates.Finished:
return
if not self._sma.IsFormed:
return
close = float(candle.ClosePrice)
if self._last_trade_price is None:
self._last_trade_price = close
return
step = self._last_trade_price * self.grid_percent / 100.0
if close <= self._last_trade_price - step:
self.BuyMarket()
self._last_trade_price = close
elif close >= self._last_trade_price + step:
self.SellMarket()
self._last_trade_price = close
def CreateClone(self):
return vr_smart_grid_lite_strategy()