Diese Strategie ist eine StockSharp-Portierung des MetaTrader 4-Expertenberaters RUBBERBANDS_3. Es hält zwei laufende Preisextreme aufrecht, eröffnet zusätzliche Positionen, wenn der Preis um eine konfigurierbare Distanz steigt, und liquidiert die gesamte Sequenz, sobald eine Gegenbewegung einer bestimmten Größe auftritt. Nach einem Retracement wechselt die Strategie optional in die entgegengesetzte Richtung und überwacht dabei ein Gewinn- und Verlustziel auf Sitzungsebene.
Hinweis: StockSharp arbeitet mit saldierten Positionen. Das ursprüngliche MT4-Skript kann Long- und Short-Orders gleichzeitig halten, aber der Port schließt die aktive Sequenz, bevor er die Richtung umkehrt. Das allgemeine Verhalten des Skalierens in Trends und des Abwickelns bei Pullbacks bleibt erhalten.
Handelslogik
Notieren Sie den aktuellen Schlusskurs sowohl als laufendes Maximum als auch als Minimum (oder verwenden Sie gespeicherte Werte beim Neustart erneut).
Wenn der Preis um PipStep Punkte über das aktuelle Maximum steigt, erteilen Sie eine Marktkauforder der Größe OrderVolume und aktualisieren Sie das Maximum auf den neuen Preis.
Wenn der Preis um PipStep Punkte unter den aktuellen Mindestpreis fällt, übermitteln Sie einen Marktverkaufsauftrag der Größe OrderVolume und aktualisieren Sie den Mindestpreis.
Wenn der Markt um BackStep Punkte gegen die aktive Richtung zurückgeht, schließen Sie alle Positionen in dieser Richtung und richten Sie eine Umkehr ein. Die Gegenseite wird geöffnet, sobald die vorherige Sequenz vollständig liquidiert ist.
Überwachen Sie das kumulative Sitzungsergebnis. Wenn der realisierte plus offene Gewinn SessionTakeProfit × OrderVolume erreicht, schließen Sie die Sitzung. Wenn der Absenkvorgang beim Rückwärtsfahren mehr als SessionStopLoss × OrderVolume beträgt, schließen Sie ebenfalls alles.
Der QuiesceNow-Schalter verhindert neue Trades, wenn die Strategie flach ist. Das Flag StopNow pausiert die gesamte Logik und CloseNow fordert eine sofortige Reduzierung des Portfolios an.
Aufträge werden aus fertigen Kerzen der konfigurierten CandleType generiert. Der Standardzeitraum beträgt eine Minute und entspricht dem Timing des ursprünglichen EA, der zu Beginn jeder Minute Prüfungen auslöste.
Parameter
Parameter
Beschreibung
Standard
OrderVolume
Basisgröße jeder Marktorder.
0.02
MaxOrders
Maximale Anzahl gleichzeitiger Positionen in einer Richtung. Bei Erreichen des Limits werden weitere Einträge gesperrt.
10
PipStep
Erweiterungsentfernung in Punkten, die einen neuen Handel hinzufügt.
100
BackStep
Gegenbewegung in Punkten, die einen Ausstieg erzwingt und eine Umkehr vorbereitet.
20
QuiesceNow
Bei true bleibt die Strategie inaktiv, solange keine Positionen offen sind.
false
DoNow
Öffnet die allererste lange Sequenz unmittelbar nach Beginn der Strategie.
false
StopNow
Hard-Stop-Flag, das jede weitere Verarbeitung verhindert. Bestehende Positionen bleiben unberührt.
false
CloseNow
Fordert eine sofortige flache Position an und löst sequenzielle Schließungen aus.
false
UseSessionTakeProfit
Aktiviert den kumulativen Sitzungs-Take-Profit.
true
SessionTakeProfit
Zielgewinn in Kontowährung pro Lot, das zum Schließen der Sitzung verwendet wird.
2000
UseSessionStopLoss
Aktiviert den kumulativen Sitzungs-Stop-Loss.
true
SessionStopLoss
Maximal tolerierter Verlust pro Los beim Rückwärtsfahren, bevor die Sitzung geschlossen wird.
4000
UseInitialValues
Verwenden Sie beim Neustart die manuell bereitgestellten InitialMax und InitialMin anstelle des letzten Schlusskurses erneut.
false
InitialMax
Gespeicherter oberer Extremwert wird wiederverwendet, wenn UseInitialValues aktiviert ist.
0
InitialMin
Gespeichertes unteres Extremwert wird wiederverwendet, wenn UseInitialValues aktiviert ist.
0
CandleType
Von der Strategie verarbeitete Kerzenserie. Standardmäßig werden Ein-Minuten-Kerzen verwendet.
TimeFrame(1m)
Sitzungsverwaltung
Gewinnaggregation: Realisierte Gewinne werden nach jedem vollständigen Abschluss akkumuliert, während nicht realisierte Gewinne aus den gewichteten durchschnittlichen Einstiegspreisen aller offenen Positionen neu berechnet werden.
Sitzungs-Take-Profit: Sobald SessionTakeProfit erreicht ist, schließt die Strategie alle Trades und setzt die gespeicherten Extreme zurück.
Session Stop-Loss: Während einer Umkehrsequenz (BackStep ausgelöst) verfolgt die Strategie den schwebenden Verlust. Wenn der Drawdown SessionStopLoss überschreitet, werden alle Positionen liquidiert und die Sitzung beginnt mit gelöschten Statistiken neu.
Nutzungshinweise
Der Preisschritt, der zum Umrechnen von Punkten in Preise verwendet wird, wird von Security.PriceStep übernommen. Konfigurieren Sie die Instrumentenmetadaten entsprechend; andernfalls wird ein Fallback von 0.0001 angewendet.
Da Aufträge saldiert werden, führt die Strategie Abschlussgeschäfte aus, bevor sie in die entgegengesetzte Richtung eröffnet. Beachten Sie bei der Migration von Altdaten, dass die Bestellhistorie bei abgesicherten Plattformen abweichen kann.
Die Flagge DoNow eröffnet nur die allererste Long-Position. Weitere Einträge folgen den regulären Breakout-Bedingungen.
Verwenden Sie QuiesceNow, wenn Sie die Strategie geladen, aber inaktiv lassen möchten, nachdem sie das Buch reduziert hat.
using System;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// Rubberbands 3: Grid expansion strategy using SMA+ATR bands.
/// Enters at band extremes, adds on continuation, exits at mean.
/// </summary>
public class Rubberbands3Strategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _smaLength;
private readonly StrategyParam<int> _atrLength;
private decimal _entryPrice;
private int _gridCount;
public Rubberbands3Strategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(15).TimeFrame())
.SetDisplay("Candle Type", "Timeframe.", "General");
_smaLength = Param(nameof(SmaLength), 20)
.SetDisplay("SMA Length", "SMA period.", "Indicators");
_atrLength = Param(nameof(AtrLength), 14)
.SetDisplay("ATR Length", "ATR period.", "Indicators");
}
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
public int SmaLength
{
get => _smaLength.Value;
set => _smaLength.Value = value;
}
public int AtrLength
{
get => _atrLength.Value;
set => _atrLength.Value = value;
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_entryPrice = 0;
_gridCount = 0;
var sma = new SimpleMovingAverage { Length = SmaLength };
var atr = new AverageTrueRange { Length = AtrLength };
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(sma, atr, ProcessCandle)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, sma);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle, decimal smaVal, decimal atrVal)
{
if (candle.State != CandleStates.Finished)
return;
if (atrVal <= 0)
return;
var close = candle.ClosePrice;
var upper = smaVal + atrVal * 1.5m;
var lower = smaVal - atrVal * 1.5m;
if (Position > 0)
{
if (close >= smaVal)
{
SellMarket();
_entryPrice = 0;
_gridCount = 0;
}
else if (close <= _entryPrice - atrVal * 5m)
{
SellMarket();
_entryPrice = 0;
_gridCount = 0;
}
else if (_gridCount < 4 && close <= _entryPrice - atrVal * 0.8m)
{
_entryPrice = (_entryPrice + close) / 2m;
_gridCount++;
BuyMarket();
}
}
else if (Position < 0)
{
if (close <= smaVal)
{
BuyMarket();
_entryPrice = 0;
_gridCount = 0;
}
else if (close >= _entryPrice + atrVal * 5m)
{
BuyMarket();
_entryPrice = 0;
_gridCount = 0;
}
else if (_gridCount < 4 && close >= _entryPrice + atrVal * 0.8m)
{
_entryPrice = (_entryPrice + close) / 2m;
_gridCount++;
SellMarket();
}
}
if (Position == 0)
{
if (close <= lower)
{
_entryPrice = close;
_gridCount = 0;
BuyMarket();
}
else if (close >= upper)
{
_entryPrice = close;
_gridCount = 0;
SellMarket();
}
}
}
}
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, AverageTrueRange
from StockSharp.Algo.Strategies import Strategy
class rubberbands_3_strategy(Strategy):
def __init__(self):
super(rubberbands_3_strategy, self).__init__()
self._sma_length = self.Param("SmaLength", 20).SetDisplay("SMA Length", "SMA period", "Indicators")
self._atr_length = self.Param("AtrLength", 14).SetDisplay("ATR Length", "ATR period", "Indicators")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(15))).SetDisplay("Candle Type", "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(rubberbands_3_strategy, self).OnReseted()
self._entry_price = 0
self._grid_count = 0
def OnStarted2(self, time):
super(rubberbands_3_strategy, self).OnStarted2(time)
self._entry_price = 0
self._grid_count = 0
sma = SimpleMovingAverage()
sma.Length = self._sma_length.Value
atr = AverageTrueRange()
atr.Length = self._atr_length.Value
sub = self.SubscribeCandles(self.CandleType)
sub.Bind(sma, atr, self.OnProcess).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, sub)
self.DrawIndicator(area, sma)
self.DrawOwnTrades(area)
def OnProcess(self, candle, sma_val, atr_val):
if candle.State != CandleStates.Finished:
return
if atr_val <= 0:
return
close = float(candle.ClosePrice)
upper = sma_val + atr_val * 1.5
lower = sma_val - atr_val * 1.5
if self.Position > 0:
if close >= sma_val:
self.SellMarket()
self._entry_price = 0
self._grid_count = 0
elif close <= self._entry_price - atr_val * 5.0:
self.SellMarket()
self._entry_price = 0
self._grid_count = 0
elif self._grid_count < 4 and close <= self._entry_price - atr_val * 0.8:
self._entry_price = (self._entry_price + close) / 2.0
self._grid_count += 1
self.BuyMarket()
elif self.Position < 0:
if close <= sma_val:
self.BuyMarket()
self._entry_price = 0
self._grid_count = 0
elif close >= self._entry_price + atr_val * 5.0:
self.BuyMarket()
self._entry_price = 0
self._grid_count = 0
elif self._grid_count < 4 and close >= self._entry_price + atr_val * 0.8:
self._entry_price = (self._entry_price + close) / 2.0
self._grid_count += 1
self.SellMarket()
if self.Position == 0:
if close <= lower:
self._entry_price = close
self._grid_count = 0
self.BuyMarket()
elif close >= upper:
self._entry_price = close
self._grid_count = 0
self.SellMarket()
def CreateClone(self):
return rubberbands_3_strategy()