Diese Strategie kombiniert Bollinger Bands, die auf 30-Minuten-Kerzen berechnet werden, mit einem Double Exponential Moving Average (DEMA) aus Tagesdaten, um Ausbrüche mit Trendbestätigung zu handeln.
Ein Long-Setup tritt auf, wenn eine bullische Kerze das untere Band nach oben kreuzt, während die DEMA steigt und damit den Aufwärtsimpuls bestätigt. Ein Short-Setup tritt auf, wenn eine bärische Kerze das obere Band nach unten kreuzt, während die DEMA fällt. Positionen werden geschlossen, wenn eine Kerze der entgegengesetzten Farbe das äußere Band gegen die Handelsrichtung kreuzt.
Details
Einstiegskriterien:
Long: Die Kerze schließt über dem unteren Band und öffnet darunter UND die tägliche DEMA steigt drei aufeinanderfolgende Tage.
Short: Die Kerze schließt unter dem oberen Band und öffnet darüber UND die tägliche DEMA fällt drei aufeinanderfolgende Tage.
Long/Short: Beide.
Ausstiegskriterien:
Long: Eine bärische Kerze schließt unter dem oberen Band, nachdem sie darüber geöffnet hat.
Short: Eine bullische Kerze schließt über dem unteren Band, nachdem sie darunter geöffnet hat.
Stops: Keine.
Standardwerte:
BollingerPeriod = 20
DemaPeriod = 20
Deviation = 2
CandleType = 30-Minuten-Zeitrahmen
Filter:
Kategorie: Mean Reversion
Richtung: Beide
Indikatoren: Bollinger Bands, DEMA
Stops: Nein
Komplexität: Moderat
Zeitrahmen: Intraday mit täglichem Trendfilter
Saisonalität: Nein
Neuronale Netze: Nein
Divergenz: Nein
Risikolevel: Mittel
using System;
using System.Linq;
using System.Collections.Generic;
using Ecng.Common;
using Ecng.Collections;
using Ecng.Serialization;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// Strategy using Bollinger Bands for entries and DEMA for trend confirmation.
/// Enters long when a bullish candle crosses above the lower band and DEMA is rising.
/// Enters short when a bearish candle crosses below the upper band and DEMA is falling.
/// Exits long on bearish cross of the upper band and exits short on bullish cross of the lower band.
/// </summary>
public class BollingerBandsDemaStrategy : Strategy
{
private readonly StrategyParam<int> _bollingerPeriod;
private readonly StrategyParam<int> _demaPeriod;
private readonly StrategyParam<decimal> _deviation;
private readonly StrategyParam<DataType> _candleType;
private decimal? _dema0;
private decimal? _dema1;
private decimal? _dema2;
/// <summary>
/// Bollinger Bands period.
/// </summary>
public int BollingerPeriod
{
get => _bollingerPeriod.Value;
set => _bollingerPeriod.Value = value;
}
/// <summary>
/// DEMA period.
/// </summary>
public int DemaPeriod
{
get => _demaPeriod.Value;
set => _demaPeriod.Value = value;
}
/// <summary>
/// Standard deviation for Bollinger Bands.
/// </summary>
public decimal Deviation
{
get => _deviation.Value;
set => _deviation.Value = value;
}
/// <summary>
/// Candle type used by the strategy.
/// </summary>
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
/// <summary>
/// Initializes a new instance of <see cref="BollingerBandsDemaStrategy"/>.
/// </summary>
public BollingerBandsDemaStrategy()
{
_bollingerPeriod = Param(nameof(BollingerPeriod), 20)
.SetGreaterThanZero()
.SetDisplay("Bollinger Period", "Length of Bollinger Bands", "Indicators")
.SetOptimize(10, 40, 5);
_demaPeriod = Param(nameof(DemaPeriod), 20)
.SetGreaterThanZero()
.SetDisplay("DEMA Period", "Length of double EMA", "Indicators")
.SetOptimize(10, 40, 5);
_deviation = Param(nameof(Deviation), 2m)
.SetGreaterThanZero()
.SetDisplay("Deviation", "Standard deviation for Bollinger Bands", "Indicators")
.SetOptimize(1m, 3m, 0.5m);
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(30).TimeFrame())
.SetDisplay("Candle Type", "Time frame for Bollinger calculation", "General");
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType), (Security, TimeSpan.FromMinutes(5).TimeFrame())];
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_dema0 = _dema1 = _dema2 = null;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var bollinger = new BollingerBands { Length = BollingerPeriod, Width = Deviation };
var dema = new DEMA { Length = DemaPeriod };
var demaSub = SubscribeCandles(TimeSpan.FromMinutes(5).TimeFrame());
demaSub
.Bind(dema, (candle, value) =>
{
if (candle.State != CandleStates.Finished)
return;
if (!dema.IsFormed)
return;
_dema2 = _dema1;
_dema1 = _dema0;
_dema0 = value;
})
.Start();
var mainSub = SubscribeCandles(CandleType);
mainSub
.BindEx(bollinger, ProcessMain)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, mainSub);
DrawIndicator(area, bollinger);
DrawOwnTrades(area);
}
}
private void ProcessMain(ICandleMessage candle, IIndicatorValue value)
{
if (candle.State != CandleStates.Finished)
return;
var bb = (BollingerBandsValue)value;
if (bb.UpBand is not decimal upper || bb.LowBand is not decimal lower || bb.MovingAverage is not decimal middle)
return;
if (_dema0 is null || _dema1 is null || _dema2 is null)
return;
var demaUp = _dema0 > _dema1 && _dema1 > _dema2;
var demaDown = _dema0 < _dema1 && _dema1 < _dema2;
var buyCondition = candle.ClosePrice > lower && candle.OpenPrice < lower && demaUp;
var sellCondition = candle.ClosePrice < upper && candle.OpenPrice > upper && demaDown;
var buyClose = candle.ClosePrice < upper && candle.OpenPrice > upper;
var sellClose = candle.ClosePrice > lower && candle.OpenPrice < lower;
if (buyCondition && Position <= 0)
BuyMarket();
if (sellCondition && Position >= 0)
SellMarket();
if (buyClose && Position > 0)
SellMarket();
if (sellClose && Position < 0)
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 BollingerBands, DoubleExponentialMovingAverage
from StockSharp.Algo.Strategies import Strategy
class bollinger_bands_dema_strategy(Strategy):
def __init__(self):
super(bollinger_bands_dema_strategy, self).__init__()
self._bollinger_period = self.Param("BollingerPeriod", 20) \
.SetDisplay("Bollinger Period", "Length of Bollinger Bands", "Indicators")
self._dema_period = self.Param("DemaPeriod", 20) \
.SetDisplay("DEMA Period", "Length of double EMA", "Indicators")
self._deviation = self.Param("Deviation", 2.0) \
.SetDisplay("Deviation", "Standard deviation for Bollinger Bands", "Indicators")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(30))) \
.SetDisplay("Candle Type", "Time frame for Bollinger calculation", "General")
self._dema0 = None
self._dema1 = None
self._dema2 = None
@property
def bollinger_period(self):
return self._bollinger_period.Value
@property
def dema_period(self):
return self._dema_period.Value
@property
def deviation(self):
return self._deviation.Value
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(bollinger_bands_dema_strategy, self).OnReseted()
self._dema0 = None
self._dema1 = None
self._dema2 = None
def OnStarted2(self, time):
super(bollinger_bands_dema_strategy, self).OnStarted2(time)
self._dema0 = None
self._dema1 = None
self._dema2 = None
bollinger = BollingerBands()
bollinger.Length = int(self.bollinger_period)
bollinger.Width = float(self.deviation)
dema = DoubleExponentialMovingAverage()
dema.Length = int(self.dema_period)
dema_sub = self.SubscribeCandles(DataType.TimeFrame(TimeSpan.FromMinutes(5)))
dema_sub.Bind(dema, self._process_dema).Start()
main_sub = self.SubscribeCandles(self.candle_type)
main_sub.BindEx(bollinger, self._process_main).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, main_sub)
self.DrawIndicator(area, bollinger)
self.DrawOwnTrades(area)
def _process_dema(self, candle, value):
if candle.State != CandleStates.Finished:
return
value = float(value)
self._dema2 = self._dema1
self._dema1 = self._dema0
self._dema0 = value
def _process_main(self, candle, value):
if candle.State != CandleStates.Finished:
return
if not value.IsFormed:
return
upper = value.UpBand
lower = value.LowBand
middle = value.MovingAverage
if upper is None or lower is None or middle is None:
return
upper = float(upper)
lower = float(lower)
if self._dema0 is None or self._dema1 is None or self._dema2 is None:
return
dema_up = self._dema0 > self._dema1 and self._dema1 > self._dema2
dema_down = self._dema0 < self._dema1 and self._dema1 < self._dema2
close = float(candle.ClosePrice)
open_p = float(candle.OpenPrice)
buy_condition = close > lower and open_p < lower and dema_up
sell_condition = close < upper and open_p > upper and dema_down
buy_close = close < upper and open_p > upper
sell_close = close > lower and open_p < lower
if buy_condition and self.Position <= 0:
self.BuyMarket()
if sell_condition and self.Position >= 0:
self.SellMarket()
if buy_close and self.Position > 0:
self.SellMarket()
if sell_close and self.Position < 0:
self.BuyMarket()
def CreateClone(self):
return bollinger_bands_dema_strategy()