ScalpWiz Bollinger-Strategie
Überblick
Die ScalpWiz Bollinger-Strategie ist ein Gegentrendsystem, das Bollinger-Bänder verwendet, um überdehnte Preise zu erkennen. Wenn sich der Schlusskurs weit über das obere oder unter das untere Band bewegt, eröffnet die Strategie eine Position in entgegengesetzter Richtung und erwartet eine Rückkehr.
Vier Distanzebenen werden geprüft. Jede Ebene entspricht einer anderen Signalstärke und multipliziert das Handelsvolumen. Die Positionsgröße wird außerdem durch einen Risikoprozentsatz des aktuellen Portfoliowerts skaliert.
Parameter
BandsPeriod– Anzahl der Kerzen für die Berechnung der Bollinger-Bänder.BandsDeviation– Standardabweichungs-Multiplikator für die Bänder.Level1Pips…Level4Pips– Abstand vom Band in Pips, der ein Level-1–4-Signal auslöst.StrengthLevel1Multiplier…StrengthLevel4Multiplier– Volumenmultiplikatoren für jede Ebene.RiskPercent– Prozentsatz des Portfoliowerts, der pro Signal riskiert wird.CandleType– Kerzen-Zeitrahmen für die Berechnungen.
Handelslogik
- Abonnieren von Kerzen des ausgewählten Zeitrahmens und Berechnung der Bollinger-Bänder.
- Bei jeder abgeschlossenen Kerze:
- Liegt der Schlusskurs um eine konfigurierte Levelentfernung über dem oberen Band, wird eine Short-Position eröffnet.
- Liegt der Schlusskurs um eine konfigurierte Levelentfernung unter dem unteren Band, wird eine Long-Position eröffnet.
- Das Volumen wird aus dem Risikoprozentsatz und dem Signalstärke-Multiplikator berechnet.
Die Strategie wurde durch das originale MQL-Skript mcb.scalpwiz.9001.mq4 inspiriert.
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()