Estratégia BarUpDn Aprimorada
A estratégia busca barras de alta ou baixa combinadas com Bollinger Bands e confirmação de tendência. Ela entra comprada em gaps de alta durante tendências de alta e vendida em gaps de baixa durante tendências de baixa. As saídas utilizam níveis de stop-loss e take-profit baseados em ATR.
Detalhes
- Critérios de entrada:
- Comprado: vela de alta com gap para cima, fechamento acima da MA de tendência e acima da banda inferior do Bollinger.
- Vendido: vela de baixa com gap para baixo, fechamento abaixo da MA de tendência e abaixo da banda superior do Bollinger.
- Comprado/Vendido: Ambos.
- Critérios de saída:
- O preço toca o stop-loss ou take-profit baseado em ATR (1,5× ATR).
- Stops: Stop e take-profit baseados em ATR.
- Valores padrão:
BbLength= 20BbMultiplier= 2MaLength= 50AtrLength= 14AtrMultiplierSl= 2AtrMultiplierTp= 3
- Filtros:
- Categoria: Seguidor de tendência
- Direção: Ambos
- Indicadores: Bollinger Bands, SMA, ATR
- Stops: Sim
- Complexidade: Baixo
- Período: Qualquer
- Sazonalidade: Não
- Redes neurais: Não
- Divergência: Não
- Nível de risco: Médio
using System;
using System.Collections.Generic;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// Enhanced BarUpDn strategy.
/// A bullish candle that opens above the previous close goes long when it closes above the trend SMA and above the lower
/// Bollinger band; a bearish candle that opens below the previous close goes short when it closes below the trend SMA and below
/// the upper band. An opposite signal reverses the position. The stop lies AtrMultiplierSl ATR and the target AtrMultiplierTp ATR
/// from the entry.
/// </summary>
public class EnhancedBarUpDnStrategy : Strategy
{
private readonly StrategyParam<int> _bbLength;
private readonly StrategyParam<decimal> _bbMultiplier;
private readonly StrategyParam<int> _maLength;
private readonly StrategyParam<int> _atrLength;
private readonly StrategyParam<decimal> _atrMultiplierSl;
private readonly StrategyParam<decimal> _atrMultiplierTp;
private readonly StrategyParam<DataType> _candleType;
private decimal? _prevClose;
private decimal _stopPrice;
private decimal _takePrice;
/// <summary>
/// Bollinger Bands length.
/// </summary>
public int BbLength
{
get => _bbLength.Value;
set => _bbLength.Value = value;
}
/// <summary>
/// Bollinger Bands deviation multiplier.
/// </summary>
public decimal BbMultiplier
{
get => _bbMultiplier.Value;
set => _bbMultiplier.Value = value;
}
/// <summary>
/// Trend SMA length.
/// </summary>
public int MaLength
{
get => _maLength.Value;
set => _maLength.Value = value;
}
/// <summary>
/// ATR length.
/// </summary>
public int AtrLength
{
get => _atrLength.Value;
set => _atrLength.Value = value;
}
/// <summary>
/// Stop loss distance in ATR.
/// </summary>
public decimal AtrMultiplierSl
{
get => _atrMultiplierSl.Value;
set => _atrMultiplierSl.Value = value;
}
/// <summary>
/// Take profit distance in ATR.
/// </summary>
public decimal AtrMultiplierTp
{
get => _atrMultiplierTp.Value;
set => _atrMultiplierTp.Value = value;
}
/// <summary>
/// Candle type.
/// </summary>
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
/// <summary>
/// Constructor.
/// </summary>
public EnhancedBarUpDnStrategy()
{
_bbLength = Param(nameof(BbLength), 20)
.SetGreaterThanZero()
.SetDisplay("BB Length", "Bollinger Bands length", "Indicators");
_bbMultiplier = Param(nameof(BbMultiplier), 2m)
.SetGreaterThanZero()
.SetDisplay("BB Multiplier", "Bollinger Bands deviation multiplier", "Indicators");
_maLength = Param(nameof(MaLength), 50)
.SetGreaterThanZero()
.SetDisplay("MA Length", "Trend SMA length", "Indicators");
_atrLength = Param(nameof(AtrLength), 14)
.SetGreaterThanZero()
.SetDisplay("ATR Length", "ATR length", "Risk");
_atrMultiplierSl = Param(nameof(AtrMultiplierSl), 2m)
.SetNotNegative()
.SetDisplay("ATR Stop", "Stop loss distance in ATR", "Risk");
_atrMultiplierTp = Param(nameof(AtrMultiplierTp), 3m)
.SetNotNegative()
.SetDisplay("ATR Target", "Take profit distance in ATR", "Risk");
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(1).TimeFrame())
.SetDisplay("Candle Type", "Type of candles to use", "General");
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType)];
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevClose = null;
_stopPrice = 0m;
_takePrice = 0m;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_prevClose = null;
var bollinger = new BollingerBands { Length = BbLength, Width = BbMultiplier };
var ma = new SimpleMovingAverage { Length = MaLength };
var atr = new AverageTrueRange { Length = AtrLength };
var subscription = SubscribeCandles(CandleType);
subscription
.BindEx(bollinger, ma, atr, ProcessCandle)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, bollinger);
DrawIndicator(area, ma);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle, IIndicatorValue bollingerValue, IIndicatorValue maValue, IIndicatorValue atrValue)
{
if (candle.State != CandleStates.Finished)
return;
var prevClose = _prevClose;
_prevClose = candle.ClosePrice;
if (!bollingerValue.IsFormed || !maValue.IsFormed || !atrValue.IsFormed)
return;
if (bollingerValue is not IBollingerBandsValue { UpBand: decimal upper, LowBand: decimal lower })
return;
if (!IsFormedAndOnlineAndAllowTrading())
return;
if (Position > 0 && ((AtrMultiplierSl > 0m && candle.LowPrice <= _stopPrice) || (AtrMultiplierTp > 0m && candle.HighPrice >= _takePrice)))
{
SellMarket(Position);
return;
}
if (Position < 0 && ((AtrMultiplierSl > 0m && candle.HighPrice >= _stopPrice) || (AtrMultiplierTp > 0m && candle.LowPrice <= _takePrice)))
{
BuyMarket(-Position);
return;
}
if (prevClose is not decimal pc)
return;
var ma = maValue.GetValue<decimal>();
var atr = atrValue.GetValue<decimal>();
var open = candle.OpenPrice;
var close = candle.ClosePrice;
var longSignal = close > open && open > pc && close > ma && close > lower;
var shortSignal = close < open && open < pc && close < ma && close < upper;
if (longSignal && Position <= 0)
{
_stopPrice = close - atr * AtrMultiplierSl;
_takePrice = close + atr * AtrMultiplierTp;
BuyMarket(Volume + Math.Abs(Position));
}
else if (shortSignal && Position >= 0)
{
_stopPrice = close + atr * AtrMultiplierSl;
_takePrice = close - atr * AtrMultiplierTp;
SellMarket(Volume + Math.Abs(Position));
}
}
}
import clr
clr.AddReference("StockSharp.Messages")
clr.AddReference("StockSharp.Algo")
clr.AddReference("StockSharp.Algo.Indicators")
clr.AddReference("StockSharp.Algo.Strategies")
from System import TimeSpan, Decimal
from StockSharp.Messages import DataType, CandleStates
from StockSharp.Algo.Indicators import BollingerBands, SimpleMovingAverage, AverageTrueRange
from StockSharp.Algo.Strategies import Strategy
class enhanced_bar_up_dn_strategy(Strategy):
"""
Enhanced BarUpDn strategy.
A bullish candle that opens above the previous close goes long when it closes above the trend SMA and above the lower
Bollinger band; a bearish candle that opens below the previous close goes short when it closes below the trend SMA and below
the upper band. An opposite signal reverses the position. The stop lies AtrMultiplierSl ATR and the target AtrMultiplierTp ATR
from the entry.
"""
def __init__(self):
super(enhanced_bar_up_dn_strategy, self).__init__()
self._bb_length = self.Param("BbLength", 20).SetGreaterThanZero().SetDisplay("BB Length", "Bollinger Bands length", "Indicators")
self._bb_multiplier = self.Param("BbMultiplier", 2.0).SetGreaterThanZero().SetDisplay("BB Multiplier", "Bollinger Bands deviation multiplier", "Indicators")
self._ma_length = self.Param("MaLength", 50).SetGreaterThanZero().SetDisplay("MA Length", "Trend SMA length", "Indicators")
self._atr_length = self.Param("AtrLength", 14).SetGreaterThanZero().SetDisplay("ATR Length", "ATR length", "Risk")
self._atr_multiplier_sl = self.Param("AtrMultiplierSl", 2.0).SetNotNegative().SetDisplay("ATR Stop", "Stop loss distance in ATR", "Risk")
self._atr_multiplier_tp = self.Param("AtrMultiplierTp", 3.0).SetNotNegative().SetDisplay("ATR Target", "Take profit distance in ATR", "Risk")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(1))).SetDisplay("Candle Type", "Type of candles to use", "General")
self._reset_state()
@property
def candle_type(self):
return self._candle_type.Value
def _reset_state(self):
self._prev_close = None
self._stop_price = 0.0
self._take_price = 0.0
def OnReseted(self):
super(enhanced_bar_up_dn_strategy, self).OnReseted()
self._reset_state()
def OnStarted2(self, time):
super(enhanced_bar_up_dn_strategy, self).OnStarted2(time)
self._reset_state()
bollinger = BollingerBands()
bollinger.Length = self._bb_length.Value
bollinger.Width = Decimal(float(self._bb_multiplier.Value))
ma = SimpleMovingAverage()
ma.Length = self._ma_length.Value
atr = AverageTrueRange()
atr.Length = self._atr_length.Value
subscription = self.SubscribeCandles(self.candle_type)
subscription.BindEx(bollinger, ma, atr, self._process_candle).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, bollinger)
self.DrawIndicator(area, ma)
self.DrawOwnTrades(area)
def _process_candle(self, candle, bollinger_value, ma_value, atr_value):
if candle.State != CandleStates.Finished:
return
prev_close = self._prev_close
close = float(candle.ClosePrice)
self._prev_close = close
if not bollinger_value.IsFormed or not ma_value.IsFormed or not atr_value.IsFormed:
return
if bollinger_value.UpBand is None or bollinger_value.LowBand is None:
return
if not self.IsFormedAndOnlineAndAllowTrading():
return
high = float(candle.HighPrice)
low = float(candle.LowPrice)
sl_mult = float(self._atr_multiplier_sl.Value)
tp_mult = float(self._atr_multiplier_tp.Value)
if self.Position > 0 and ((sl_mult > 0 and low <= self._stop_price) or (tp_mult > 0 and high >= self._take_price)):
self.SellMarket(self.Position)
return
if self.Position < 0 and ((sl_mult > 0 and high >= self._stop_price) or (tp_mult > 0 and low <= self._take_price)):
self.BuyMarket(-self.Position)
return
if prev_close is None:
return
upper = float(bollinger_value.UpBand)
lower = float(bollinger_value.LowBand)
ma = float(ma_value.GetValue[Decimal](None))
atr = float(atr_value.GetValue[Decimal](None))
open_price = float(candle.OpenPrice)
long_signal = close > open_price and open_price > prev_close and close > ma and close > lower
short_signal = close < open_price and open_price < prev_close and close < ma and close < upper
if long_signal and self.Position <= 0:
self._stop_price = close - atr * sl_mult
self._take_price = close + atr * tp_mult
self.BuyMarket(self.Volume + abs(self.Position))
elif short_signal and self.Position >= 0:
self._stop_price = close + atr * sl_mult
self._take_price = close - atr * tp_mult
self.SellMarket(self.Volume + abs(self.Position))
def CreateClone(self):
return enhanced_bar_up_dn_strategy()