Estratégia de Bollinger Bands com DEMA
Esta estratégia combina as Bollinger Bands calculadas em velas de 30 minutos com uma Média Móvel Exponencial Dupla (DEMA) de dados diários para operar rompimentos com confirmação de tendência.
Uma configuração comprada ocorre quando uma vela de alta cruza acima da banda inferior enquanto a DEMA sobe, confirmando o impulso ascendente. Uma configuração vendida ocorre quando uma vela de baixa cruza abaixo da banda superior enquanto a DEMA cai. As posições são fechadas quando uma vela de cor oposta cruza a banda exterior contra a operação.
Detalhes
- Critérios de entrada:
- Comprado: A vela fecha acima da banda inferior e abre abaixo dela E a DEMA diária está aumentando por três dias consecutivos.
- Vendido: A vela fecha abaixo da banda superior e abre acima dela E a DEMA diária está diminuindo por três dias consecutivos.
- Comprado/Vendido: Ambos.
- Critérios de saída:
- Comprado: Uma vela de baixa fecha abaixo da banda superior após abrir acima dela.
- Vendido: Uma vela de alta fecha acima da banda inferior após abrir abaixo dela.
- Stops: Nenhum.
- Valores padrão:
BollingerPeriod= 20DemaPeriod= 20Deviation= 2CandleType= Período de 30 minutos
- Filtros:
- Categoria: Reversão à média
- Direção: Ambos
- Indicadores: Bollinger Bands, DEMA
- Stops: Não
- Complexidade: Moderado
- Período: Intradiário com filtro de tendência diária
- Sazonalidade: Não
- Redes neurais: Não
- Divergência: Não
- Nível de risco: Médio
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()