BBStrategy ist ein Bollinger-Band-Breakout-System, das aus dem MetaTrader-Expertenberater „BBStrategy“ abgeleitet wurde. Die Strategie verfolgt zwei Sätze von Bollinger-Bändern mit demselben Zeitraum, aber unterschiedlichen Abweichungsmultiplikatoren. Wenn der Preis das äußere Band durchbricht, aktiviert der Algorithmus einen Handel, ein tatsächlicher Einstieg wird jedoch verschoben, bis der Preis wieder in das innere Band zurückkehrt. Durch dieses Verhalten wird versucht, den Kauf überzogener Ausbrüche oder den Verkauf stark überverkaufter Bedingungen zu vermeiden und gleichzeitig die Fortsetzungsbewegung nach einer Volatilitätsexpansion zu erfassen.
Kernlogik
Abonnieren Sie Kerzen und berechnen Sie zwei Bollinger-Bänder:
Äußeres Band verwendet einen konfigurierbaren Abweichungsmultiplikator (Standard 3,0).
Inneres Band verwendet eine geringere Abweichung (Standard 2,0).
Erkennen Sie, wann der Schlusskurs außerhalb des äußeren Bandes endet:
Über den oberen äußeren Bandarmen befindet sich ein langer Aufbau.
Unterhalb der unteren äußeren Bandarme ein kurzer Aufbau.
Steigen Sie nur dann ein, wenn die nächste abgeschlossene Kerze wieder innerhalb des inneren Bandes in Richtung des Ausbruchs schließt. Während der Preis darauf wartet, wieder einzusteigen, bleibt die Strategie im „Wartezustand“ auf die entsprechende Richtung.
Senden Sie eine einzelne Marktorder, wenn die Bedingungen übereinstimmen und keine offenen Positionen oder aktiven Orders vorhanden sind. Bestehende Gegenpositionen werden durch Erhöhung des Volumens der Market Order geschlossen.
Optionale Take-Profit- und Stop-Loss-Distanzen (ausgedrückt in Punkten) werden in absolute Preis-Offsets umgewandelt und über den integrierten Schutzhelfer verwaltet.
Parameter
Name
Beschreibung
Bestellvolumen
Handelsgröße für jede Position.
Bollinger Zeitraum
Anzahl der Kerzen, die für beide Bollinger-Bandberechnungen verwendet werden.
Innere Abweichung
Abweichungsmultiplikator für das innere Band, der Pullbacks validiert.
Äußere Abweichung
Abweichungsmultiplikator für das äußere Band, das Ausbrüche erkennt.
Stop-Loss-Punkte
Abstand des Schutzstopps in Punkten (0 deaktiviert den Stopp).
Take-Profit-Punkte
Take-Profit-Distanz in Punkten (0 deaktiviert das Ziel).
Kerzentyp
Kerzenzeitrahmen für Berechnungen.
Notizen
Die Strategie handelt jeweils nur eine Position und ignoriert neue Signale, solange Aufträge aktiv sind.
Für das Risikomanagement wandelt der Helfer MetaTrader „Punkte“ in tatsächliche Preiserhöhungen basierend auf der Tick-Größe des Instruments um.
Diagrammzeichnungen umfassen Kerzen, beide Bollinger-Bänder und die eigenen Trades der Strategie, um das visuelle Debuggen zu erleichtern.
using System;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// Bollinger Bands breakout strategy.
/// When price breaks above outer band, waits for re-entry into inner band then goes long.
/// When price breaks below outer band, waits for re-entry into inner band then goes short.
/// </summary>
public class BBStrategy : Strategy
{
private readonly StrategyParam<int> _bollingerPeriod;
private readonly StrategyParam<decimal> _innerDeviation;
private readonly StrategyParam<decimal> _outerDeviation;
private readonly StrategyParam<DataType> _candleType;
public int BollingerPeriod
{
get => _bollingerPeriod.Value;
set => _bollingerPeriod.Value = value;
}
public decimal InnerDeviation
{
get => _innerDeviation.Value;
set => _innerDeviation.Value = value;
}
public decimal OuterDeviation
{
get => _outerDeviation.Value;
set => _outerDeviation.Value = value;
}
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
public BBStrategy()
{
_bollingerPeriod = Param(nameof(BollingerPeriod), 20)
.SetDisplay("BB Period", "Bollinger Bands period", "Indicators");
_innerDeviation = Param(nameof(InnerDeviation), 2m)
.SetDisplay("Inner Dev", "Inner band deviations", "Indicators");
_outerDeviation = Param(nameof(OuterDeviation), 3m)
.SetDisplay("Outer Dev", "Outer band deviations", "Indicators");
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame())
.SetDisplay("Candle Type", "Candle series", "General");
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var innerBand = new BollingerBands
{
Length = BollingerPeriod,
Width = InnerDeviation
};
var outerBand = new BollingerBands
{
Length = BollingerPeriod,
Width = OuterDeviation
};
var waitDirection = 0;
var subscription = SubscribeCandles(CandleType);
subscription
.BindEx(innerBand, outerBand, (candle, innerVal, outerVal) =>
{
if (candle.State != CandleStates.Finished)
return;
if (!innerBand.IsFormed || !outerBand.IsFormed)
return;
if (innerVal.IsEmpty || outerVal.IsEmpty)
return;
var innerBb = innerVal as IBollingerBandsValue;
var outerBb = outerVal as IBollingerBandsValue;
if (innerBb == null || outerBb == null)
return;
var innerUpper = innerBb.UpBand ?? 0;
var innerLower = innerBb.LowBand ?? 0;
var outerUpper = outerBb.UpBand ?? 0;
var outerLower = outerBb.LowBand ?? 0;
if (innerUpper == 0 || innerLower == 0 || outerUpper == 0 || outerLower == 0)
return;
if (!IsFormedAndOnlineAndAllowTrading())
return;
var price = candle.ClosePrice;
var signal = 0;
// Detect outer band breakout
if (price > outerUpper)
waitDirection = 1;
else if (price < outerLower)
waitDirection = -1;
// Check re-entry into inner band
if (waitDirection > 0 && price < innerUpper && price > innerLower)
{
signal = 1;
waitDirection = 0;
}
else if (waitDirection < 0 && price > innerLower && price < innerUpper)
{
signal = -1;
waitDirection = 0;
}
if (signal == 1 && Position <= 0)
BuyMarket();
else if (signal == -1 && Position >= 0)
SellMarket();
})
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, innerBand);
DrawIndicator(area, outerBand);
DrawOwnTrades(area);
}
}
}
import clr
import math
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 bb_strategy(Strategy):
def __init__(self):
super(bb_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(5)))
self._bollinger_period = self.Param("BollingerPeriod", 20)
self._inner_deviation = self.Param("InnerDeviation", 2.0)
self._outer_deviation = self.Param("OuterDeviation", 3.0)
self._closes = []
self._wait_direction = 0
@property
def CandleType(self):
return self._candle_type.Value
@CandleType.setter
def CandleType(self, value):
self._candle_type.Value = value
@property
def BollingerPeriod(self):
return self._bollinger_period.Value
@BollingerPeriod.setter
def BollingerPeriod(self, value):
self._bollinger_period.Value = value
@property
def InnerDeviation(self):
return self._inner_deviation.Value
@InnerDeviation.setter
def InnerDeviation(self, value):
self._inner_deviation.Value = value
@property
def OuterDeviation(self):
return self._outer_deviation.Value
@OuterDeviation.setter
def OuterDeviation(self, value):
self._outer_deviation.Value = value
def OnReseted(self):
super(bb_strategy, self).OnReseted()
self._closes = []
self._wait_direction = 0
def OnStarted2(self, time):
super(bb_strategy, self).OnStarted2(time)
self._closes = []
self._wait_direction = 0
subscription = self.SubscribeCandles(self.CandleType)
subscription.Bind(self._process_candle).Start()
def _compute_bands(self, period, deviation):
if len(self._closes) < period:
return None, None, None
window = self._closes[-period:]
mean = sum(window) / period
variance = sum((x - mean) ** 2 for x in window) / period
std = math.sqrt(variance)
upper = mean + deviation * std
lower = mean - deviation * std
return mean, upper, lower
def _process_candle(self, candle):
if candle.State != CandleStates.Finished:
return
close = float(candle.ClosePrice)
period = self.BollingerPeriod
inner_dev = float(self.InnerDeviation)
outer_dev = float(self.OuterDeviation)
self._closes.append(close)
while len(self._closes) > period + 10:
self._closes.pop(0)
if len(self._closes) < period:
return
_, inner_upper, inner_lower = self._compute_bands(period, inner_dev)
_, outer_upper, outer_lower = self._compute_bands(period, outer_dev)
if inner_upper is None or outer_upper is None:
return
# Detect outer band breakout
if close > outer_upper:
self._wait_direction = 1
elif close < outer_lower:
self._wait_direction = -1
signal = 0
# Check re-entry into inner band
if self._wait_direction > 0 and close < inner_upper and close > inner_lower:
signal = 1
self._wait_direction = 0
elif self._wait_direction < 0 and close > inner_lower and close < inner_upper:
signal = -1
self._wait_direction = 0
if signal == 1 and self.Position <= 0:
self.BuyMarket()
elif signal == -1 and self.Position >= 0:
self.SellMarket()
def CreateClone(self):
return bb_strategy()