Bollinger Band Breakout-Strategie

Schriftsteller:ChaoZhang, Datum: 2023-11-13 11:26:50
Tags:

img

Übersicht

Diese Strategie nutzt die dynamischen oberen und unteren Bands von Bollinger Bands, um lange zu gehen, wenn der Preis über das obere Band bricht und die Position zu schließen, wenn der Preis unter das untere Band fällt. Im Gegensatz zu traditionellen Breakout-Strategien mit festen Niveaus ändern sich die Bands von Bollinger Bands dynamisch basierend auf der historischen Volatilität, was es besser macht, überkaufte und überverkaufte Bedingungen zu identifizieren.

Strategie Logik

Die Strategie stützt sich hauptsächlich auf den Bollinger Bands Indikator, um Ausbrüche zu identifizieren.

  1. Mittellinie: gleitender Durchschnitt für n Perioden
  2. Oberer Band: Mittellinie + k * n-Zeitstandardabweichung
  3. Unterer Band: Mittellinie - k * n-Zeitstandardabweichung

Wenn der Preis über das obere Band steigt, gilt der Markt als überkauft und eine Long-Position kann eingeleitet werden.

Die Strategie erlaubt die Anpassung der Bollinger Bands-Parameter: der gleitende Durchschnittsperiode n und der Standardabweichungsmultiplikator k. Die Standardwerte sind 20 Perioden für den gleitenden Durchschnitt und 2 für den Standardabweichungsmultiplikator.

Die Strategie überprüft, ob der Schlusskurs nach jedem Handelstag über das obere Band bricht. Wenn dies der Fall ist, wird am nächsten Tag ein Long-Signal ausgelöst. Einmal lang überwacht die Strategie, ob der Preis in Echtzeit unter das untere Band bricht und schließt die Position, wenn dies der Fall ist.

Die Strategie beinhaltet auch einen gleitenden Durchschnittsfilter, der nur Kaufsignale erzeugt, wenn der Preis über der gleitenden Durchschnittslinie liegt.

Es gibt zwei Stop-Loss-Optionen: Festprozentsatz-Stop-Loss oder das Verfolgen des unteren Bandes.

Vorteile der Strategie

  • Verwenden Sie Bollinger-Bänder, um überkauft/überverkauft zu beurteilen
  • Der gleitende Durchschnittsfilter vermeidet den gegen den Trend gerichteten Handel
  • Anpassungsfähige Bollinger-Band-Parameter für verschiedene Zeiträume
  • Wahl zwischen zwei Stop-Loss-Methoden
  • Backtesting ermöglicht die Optimierung von Parametern und die Verifizierung außerhalb der Stichprobe

Risiken der Strategie

  • Bollinger-Bänder können nicht vollständig überkauft/überverkauft ermitteln
  • Bewegliche Durchschnittsfilter können schnellere Ausbrüche verpassen
  • Festgesetzte Stop-Loss kann zu konservativ sein, Trailing Stop kann zu aggressiv sein
  • Parameter müssen für verschiedene Produkte und Zeitrahmen optimiert werden
  • Nicht in der Lage, die Größe der Verluste zu begrenzen, müssen Geldmanagement in Betracht ziehen

Optimierungsrichtlinien

  • Verschiedene Kombinationen von gleitenden Durchschnittsparametern testen
  • Versuchen Sie andere Bollinger-Band-Parameter
  • Vergleichen Sie den festgelegten Stop-Loss-Prozentsatz mit dem niedrigeren Rückstandsband.
  • Hinzufügen des Geldmanagement-Moduls zum Limit pro Handelsverlust
  • Hinzufügen anderer Indikatoren zur Bestätigung des Bollinger Bands Signals

Schlussfolgerung

Die Strategie identifiziert überkaufte/überverkaufte Bedingungen mit Bollinger Bands Dynamischen Bands, bezieht sich auf gleitende Durchschnittsfilter und verwendet Stops zum Schutz des Kapitals. Im Vergleich zu traditionellen Feststands-Breakouts passt sie besser an die Marktschwankungen an. Mit weiterer Parameteroptimierung und Risikokontrolle kann die Strategie höhere Stabilität und Renditen erzielen. Insgesamt erfasst die Strategie durch die Nutzung der dynamischen Natur von Bollinger Bands die Stärken von Breakout-Strategien und lohnt sich für Live-Handel und langfristige Optimierung.


/*backtest
start: 2022-11-06 00:00:00
end: 2023-11-12 00:00:00
period: 1d
basePeriod: 1h
exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}]
*/

//@version=5

// Revision:        1
// Author:          @millerrh
// Strategy:  
//      Entry: Buy when price breaks out of upper Bollinger Band
//      Exit: Trail a stop with the lower Bollinger Band 
// Conditions/Variables:
//    1. Can add a filter to only take setups that are above a user-defined moving average on current timeframe and/or longer timeframe (helps avoid trading counter trend) 
//    2. Manually configure which dates to back test
//    3. User-Configurable Bollinger Band Settings
//    4. Optionally use a tighter initial stop level.  Once Bollinger Band catches up, trail with lower Bollinger Band to give more breathing room.

// strategy('Donchian Breakout', overlay=true, initial_capital=100000, currency='USD', default_qty_type=strategy.percent_of_equity, calc_on_every_tick = true,
//   default_qty_value=100, commission_type=strategy.commission.percent, commission_value=0.1)

strategy('Bollinger Breakout', overlay=true, initial_capital=100000, currency='USD', default_qty_type=strategy.percent_of_equity,
  default_qty_value=100, commission_type=strategy.commission.percent, commission_value=0.0, calc_on_order_fills=true)

// === BACKTEST RANGE ===
Start = input(defval = timestamp("01 Jan 2019 06:00 +0000"), title = "Backtest Start Date", group = "backtest window")
Finish = input(defval = timestamp("01 Jan 2100 00:00 +0000"), title = "Backtest End Date", group = "backtest window")

// == INPUTS ==
// Bollinger Band Inputs
bbLength = input.int(20, minval=1, group = "Bollinger Band Settings", title="Bollinger Band Length",
  tooltip = "Bollinger Band moving average length.")
bbMultTop = input.float(2.0, minval=0.001, maxval=50, title="Standard Deviation (Top)")
bbMultBot = input.float(2.0, minval=0.001, maxval=50, title="Standard Deviation (Bottom)")

useTightStop = input.bool(title='Use Fixed Percentage for Initial Stop?', defval=false, group = "order entry",
  tooltip = "'Keep your losers small and let winners run' is the saying.  This will allow you to use a tight initial stop
  until the lower Bollinger Band catches up.")
percStop = input.int(title="Stop", defval=8, group = "order entry", inline = "perc")
trigInput = input.string(title='Execute Trades On...', defval='Wick', options=['Wick', 'Close'], group = "order entry",
  tooltip = "Useful for comparing standing stop orders at the Bollinger Band boundary (executing on the wick) vs. waiting for candle closes prior to taking action")

// Moving Average Filtering Inputs
useMaFilter = input.bool(title='Use Moving Average for Filtering (Current Timeframe)?', defval=false, group = "moving average filtering",
  tooltip = "Signals will be ignored when price is under this moving average.  The intent is to keep you out of bear periods and only buying when 
             price is showing strength.")
maType = input.string(defval='SMA', options=['EMA', 'SMA'], title='MA Type For Filtering', group = "moving average filtering")
maLength = input.int(defval=50, title="Moving Average:    Length", minval=1, group = "moving average filtering", inline = "1ma")
ma1Color = input.color(color.new(color.green, 50), title = " Color", group = "moving average filtering", inline = "1ma")
useMaFilter2 = input.bool(title='Use Moving Average for Filtering (High Timeframe)?', defval=false, group = "moving average filtering")
tfSet = input.timeframe(defval="D", title="Timeframe of Moving Average", group = "moving average filtering",
  tooltip = "Allows you to set a different time frame for a moving average filter.  Trades will be ignored when price is under this moving average.
  The idea is to keep your eye on the larger moves in the market and stay on the right side of the longer term trends and help you be pickier about 
  the stocks you trade.")
ma2Type = input.string(defval='SMA', options=['EMA', 'SMA'], title='MA Type For Filtering', group = "moving average filtering")
ma2Length = input.int(defval=50, title="Moving Average:    Length", minval=1, group = "moving average filtering", inline = "2ma")
ma2Color = input.color(color.new(color.white, 50), title = " Color", group = "moving average filtering", inline = "2ma")


// === THE BOLLINGER BAND ===
// Logic
bbBasis = ta.sma(close, bbLength)
bbUpper = bbBasis + bbMultTop * ta.stdev(close, bbLength)
bbLower = bbBasis - bbMultBot * ta.stdev(close, bbLength)

// Plotting
plot(bbBasis, "Basis", color=color.new(color.white, 50))
p1 = plot(bbUpper, color=color.new(color.blue, 50), linewidth=1, title='Upper Bollinger Band')
p2 = plot(bbLower, color=color.new(color.blue, 50), linewidth=1, title='Lower Bollinger Band')
fill(p1, p2, title = "Background", color=color.rgb(33, 150, 243, 95))

// == FILTERING LOGIC ==
// Declare function to be able to swap out EMA/SMA
ma(maType, src, length) =>
    maType == 'EMA' ? ta.ema(src, length) : ta.sma(src, length)  //Ternary Operator (if maType equals EMA, then do ema calc, else do sma calc)
maFilter = ma(maType, close, maLength)
maFilter2 = request.security(syminfo.tickerid, tfSet, ma(ma2Type, close, ma2Length))

// Plotting
plot(useMaFilter ? maFilter : na, title='Trend Filter MA - CTF', color=ma1Color, linewidth=2, style=plot.style_line)
plot(useMaFilter2 ? maFilter2 : na, title='Trend Filter MA - HTF', color=ma2Color, linewidth=2, style=plot.style_line)


// == ENTRY AND EXIT CRITERIA ==
// Trigger stop based on candle close or High/Low (i.e. Wick)
trigResistance = trigInput == 'Close' ? close : trigInput == 'Wick' ? high : na
trigSupport = trigInput == 'Close' ? close : trigInput == 'Wick' ? low : na
buySignal = trigResistance >= bbUpper 

buyConditions = (useMaFilter ? bbUpper > maFilter : true) and
  (useMaFilter2 ? bbUpper > maFilter2 : true) 
  
// == STOP AND PRICE LEVELS ==
// Configure initial stop level
inPosition = strategy.position_size > 0
stopLevel = strategy.position_avg_price - (strategy.position_avg_price * percStop/100)
posStop = stopLevel > bbLower ? stopLevel : bbLower


// Check if using stop vs. not
stop = useTightStop ? posStop : bbLower
plot(inPosition ? stop : na, style=plot.style_linebr, color=color.new(color.red, 40), linewidth = 1, title = "Stop Levels", trackprice=false)

sellSignal = trigSupport <= stop

// == STRATEGY ENTRIES & EXITS ==
// This string of code enters and exits at the candle close
if trigInput == 'Close'
    strategy.entry('Long', strategy.long, when=buyConditions and buySignal)
    strategy.close('Long', when=sellSignal)

// This string of code enters and exits at the wick (i.e. with pre-set stops)
if trigInput == 'Wick'
    strategy.entry('Long', strategy.long, stop=bbUpper, when=buyConditions)
    strategy.exit('Exit Long', from_entry='Long', stop=stop)
strategy.cancel('Long',when= not(buyConditions)) // Resets stop level once buyConditions aren't true anymore



Mehr