Estratégia ScalpWiz Bollinger
Visão geral
A Estratégia ScalpWiz Bollinger é um sistema contra-tendência que usa Bandas de Bollinger para detectar preços estendidos. Quando o preço de fechamento se afasta muito da banda superior ou inferior, a estratégia abre uma posição na direção oposta esperando uma reversão.
Quatro níveis de distância são verificados. Cada nível corresponde a uma força de sinal diferente e multiplica o volume da operação. O tamanho da posição também é escalado por um percentual de risco do valor atual da carteira.
Parâmetros
BandsPeriod– número de velas usadas para calcular as Bandas de Bollinger.BandsDeviation– multiplicador de desvio padrão para as bandas.Level1Pips…Level4Pips– distância da banda em pips que aciona um sinal de nível 1–4.StrengthLevel1Multiplier…StrengthLevel4Multiplier– multiplicadores de volume para cada nível.RiskPercent– percentual do valor da carteira arriscado por sinal.CandleType– período de velas utilizado para os cálculos.
Lógica de trading
- Assinar velas do período selecionado e calcular as Bandas de Bollinger.
- Em cada vela finalizada:
- Se o fechamento estiver acima da banda superior por uma distância de nível configurada, abrir uma posição vendida.
- Se o fechamento estiver abaixo da banda inferior por uma distância de nível configurada, abrir uma posição comprada.
- O volume é calculado a partir do percentual de risco e do multiplicador de força do sinal.
A estratégia foi inspirada pelo script MQL original mcb.scalpwiz.9001.mq4.
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>
/// Bollinger-based reverse scalping strategy.
/// Places counter-trend orders when price deviates from the bands.
/// Position size scales with signal strength and risk percentage.
/// </summary>
public class ScalpWizBollingerStrategy : Strategy
{
private readonly StrategyParam<int> _bandsPeriod;
private readonly StrategyParam<decimal> _bandsDeviation;
private readonly StrategyParam<decimal> _level1Pips;
private readonly StrategyParam<decimal> _level2Pips;
private readonly StrategyParam<decimal> _level3Pips;
private readonly StrategyParam<decimal> _level4Pips;
private readonly StrategyParam<int> _multiplier1;
private readonly StrategyParam<int> _multiplier2;
private readonly StrategyParam<int> _multiplier3;
private readonly StrategyParam<int> _multiplier4;
private readonly StrategyParam<int> _riskPercent;
private readonly StrategyParam<DataType> _candleType;
public int BandsPeriod { get => _bandsPeriod.Value; set => _bandsPeriod.Value = value; }
public decimal BandsDeviation { get => _bandsDeviation.Value; set => _bandsDeviation.Value = value; }
public decimal Level1Pips { get => _level1Pips.Value; set => _level1Pips.Value = value; }
public decimal Level2Pips { get => _level2Pips.Value; set => _level2Pips.Value = value; }
public decimal Level3Pips { get => _level3Pips.Value; set => _level3Pips.Value = value; }
public decimal Level4Pips { get => _level4Pips.Value; set => _level4Pips.Value = value; }
public int StrengthLevel1Multiplier { get => _multiplier1.Value; set => _multiplier1.Value = value; }
public int StrengthLevel2Multiplier { get => _multiplier2.Value; set => _multiplier2.Value = value; }
public int StrengthLevel3Multiplier { get => _multiplier3.Value; set => _multiplier3.Value = value; }
public int StrengthLevel4Multiplier { get => _multiplier4.Value; set => _multiplier4.Value = value; }
public int RiskPercent { get => _riskPercent.Value; set => _riskPercent.Value = value; }
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
/// <summary>
/// Constructor.
/// </summary>
public ScalpWizBollingerStrategy()
{
_bandsPeriod = Param(nameof(BandsPeriod), 30)
.SetGreaterThanZero()
.SetDisplay("Bands Period", "Number of candles for Bollinger calculation", "Bollinger")
.SetOptimize(20, 40, 5);
_bandsDeviation = Param(nameof(BandsDeviation), 2m)
.SetGreaterThanZero()
.SetDisplay("Bands Deviation", "Standard deviation multiplier", "Bollinger")
.SetOptimize(1m, 3m, 0.5m);
_level1Pips = Param(nameof(Level1Pips), 1m)
.SetGreaterThanZero()
.SetDisplay("Level1 Pips", "Deviation from band for weakest signal", "Levels");
_level2Pips = Param(nameof(Level2Pips), 5m)
.SetGreaterThanZero()
.SetDisplay("Level2 Pips", "Deviation from band for level 2", "Levels");
_level3Pips = Param(nameof(Level3Pips), 10m)
.SetGreaterThanZero()
.SetDisplay("Level3 Pips", "Deviation from band for level 3", "Levels");
_level4Pips = Param(nameof(Level4Pips), 20m)
.SetGreaterThanZero()
.SetDisplay("Level4 Pips", "Deviation from band for strongest signal", "Levels");
_multiplier1 = Param(nameof(StrengthLevel1Multiplier), 1)
.SetGreaterThanZero()
.SetDisplay("Strength 1 Multiplier", "Volume multiplier for level 1", "Strength");
_multiplier2 = Param(nameof(StrengthLevel2Multiplier), 2)
.SetGreaterThanZero()
.SetDisplay("Strength 2 Multiplier", "Volume multiplier for level 2", "Strength");
_multiplier3 = Param(nameof(StrengthLevel3Multiplier), 3)
.SetGreaterThanZero()
.SetDisplay("Strength 3 Multiplier", "Volume multiplier for level 3", "Strength");
_multiplier4 = Param(nameof(StrengthLevel4Multiplier), 4)
.SetGreaterThanZero()
.SetDisplay("Strength 4 Multiplier", "Volume multiplier for level 4", "Strength");
_riskPercent = Param(nameof(RiskPercent), 2)
.SetGreaterThanZero()
.SetDisplay("Risk %", "Risk percentage per trade", "General");
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).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();
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var bollinger = new BollingerBands
{
Length = BandsPeriod,
Width = BandsDeviation
};
var subscription = SubscribeCandles(CandleType);
subscription
.BindEx(bollinger, ProcessCandle)
.Start();
}
private void ProcessCandle(ICandleMessage candle, IIndicatorValue value)
{
if (candle.State != CandleStates.Finished)
return;
if (!IsFormedAndOnlineAndAllowTrading())
return;
var bb = (BollingerBandsValue)value;
if (bb.UpBand is not decimal upper || bb.LowBand is not decimal lower)
return;
var step = Security?.PriceStep ?? 0.0001m;
var close = candle.ClosePrice;
if (close - upper > Level4Pips * step)
{
SellByStrength(StrengthLevel4Multiplier, close);
}
else if (close - upper > Level3Pips * step)
{
SellByStrength(StrengthLevel3Multiplier, close);
}
else if (close - upper > Level2Pips * step)
{
SellByStrength(StrengthLevel2Multiplier, close);
}
else if (close - upper > Level1Pips * step)
{
SellByStrength(StrengthLevel1Multiplier, close);
}
else if (lower - close > Level4Pips * step)
{
BuyByStrength(StrengthLevel4Multiplier, close);
}
else if (lower - close > Level3Pips * step)
{
BuyByStrength(StrengthLevel3Multiplier, close);
}
else if (lower - close > Level2Pips * step)
{
BuyByStrength(StrengthLevel2Multiplier, close);
}
else if (lower - close > Level1Pips * step)
{
BuyByStrength(StrengthLevel1Multiplier, close);
}
}
private void BuyByStrength(int strength, decimal price)
{
BuyMarket();
}
private void SellByStrength(int strength, decimal price)
{
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 BollingerBands
from StockSharp.Algo.Strategies import Strategy
class scalp_wiz_bollinger_strategy(Strategy):
def __init__(self):
super(scalp_wiz_bollinger_strategy, self).__init__()
self._bands_period = self.Param("BandsPeriod", 30) \
.SetDisplay("Bands Period", "Number of candles for Bollinger calculation", "Bollinger")
self._bands_deviation = self.Param("BandsDeviation", 2.0) \
.SetDisplay("Bands Deviation", "Standard deviation multiplier", "Bollinger")
self._level1_pips = self.Param("Level1Pips", 1.0) \
.SetDisplay("Level1 Pips", "Deviation from band for weakest signal", "Levels")
self._level2_pips = self.Param("Level2Pips", 5.0) \
.SetDisplay("Level2 Pips", "Deviation from band for level 2", "Levels")
self._level3_pips = self.Param("Level3Pips", 10.0) \
.SetDisplay("Level3 Pips", "Deviation from band for level 3", "Levels")
self._level4_pips = self.Param("Level4Pips", 20.0) \
.SetDisplay("Level4 Pips", "Deviation from band for strongest signal", "Levels")
self._multiplier1 = self.Param("StrengthLevel1Multiplier", 1) \
.SetDisplay("Strength 1 Multiplier", "Volume multiplier for level 1", "Strength")
self._multiplier2 = self.Param("StrengthLevel2Multiplier", 2) \
.SetDisplay("Strength 2 Multiplier", "Volume multiplier for level 2", "Strength")
self._multiplier3 = self.Param("StrengthLevel3Multiplier", 3) \
.SetDisplay("Strength 3 Multiplier", "Volume multiplier for level 3", "Strength")
self._multiplier4 = self.Param("StrengthLevel4Multiplier", 4) \
.SetDisplay("Strength 4 Multiplier", "Volume multiplier for level 4", "Strength")
self._risk_percent = self.Param("RiskPercent", 2) \
.SetDisplay("Risk %", "Risk percentage per trade", "General")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(4))) \
.SetDisplay("Candle Type", "Type of candles to use", "General")
@property
def bands_period(self):
return self._bands_period.Value
@property
def bands_deviation(self):
return self._bands_deviation.Value
@property
def level1_pips(self):
return self._level1_pips.Value
@property
def level2_pips(self):
return self._level2_pips.Value
@property
def level3_pips(self):
return self._level3_pips.Value
@property
def level4_pips(self):
return self._level4_pips.Value
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(scalp_wiz_bollinger_strategy, self).OnReseted()
def OnStarted2(self, time):
super(scalp_wiz_bollinger_strategy, self).OnStarted2(time)
bollinger = BollingerBands()
bollinger.Length = self.bands_period
bollinger.Width = self.bands_deviation
subscription = self.SubscribeCandles(self.candle_type)
subscription.BindEx(bollinger, self.process_candle).Start()
def process_candle(self, candle, value):
if candle.State != CandleStates.Finished:
return
upper = value.UpBand
lower = value.LowBand
if upper is None or lower is None:
return
upper = float(upper)
lower = float(lower)
step = 0.0001
if self.Security is not None and self.Security.PriceStep is not None:
step = float(self.Security.PriceStep)
close = float(candle.ClosePrice)
l1 = float(self.level1_pips) * step
l2 = float(self.level2_pips) * step
l3 = float(self.level3_pips) * step
l4 = float(self.level4_pips) * step
if close - upper > l4:
self.SellMarket()
elif close - upper > l3:
self.SellMarket()
elif close - upper > l2:
self.SellMarket()
elif close - upper > l1:
self.SellMarket()
elif lower - close > l4:
self.BuyMarket()
elif lower - close > l3:
self.BuyMarket()
elif lower - close > l2:
self.BuyMarket()
elif lower - close > l1:
self.BuyMarket()
def CreateClone(self):
return scalp_wiz_bollinger_strategy()