볼링거 밴드 브레이크업 전략

저자:차오장, 날짜: 2023-11-13 11:26:50
태그:

img

전반적인 설명

이 전략은 볼링거 밴드의 역동적인 상위 및 하위 대역을 이용하여 가격이 상위 대역을 넘어서고 가격이 하위 대역을 넘어서면 포지션을 닫습니다. 고정 수준의 전통적인 브레이크아웃 전략과는 달리 볼링거 밴드의 대역은 역사적 변동성에 따라 역동적으로 변화하여 과잉 구매 및 과잉 판매 조건을 더 잘 식별합니다.

전략 논리

이 전략은 브레이크오웃을 식별하기 위해 주로 볼링거 밴드 지표에 의존합니다. 볼링거 밴드는 세 가지 라인으로 구성됩니다.

  1. 중간선: n 기간 이동 평균
  2. 상단역: 중간선 + k * n기준표준편차
  3. 하위 대역: 중간선 - k * n 기간 표준편차

가격이 상단 범위를 넘으면 시장이 과소매로 간주되며 긴 지위가 시작 될 수 있습니다. 가격이 하단 범위를 넘으면 시장이 과소매로 간주되며 지점이 닫아야합니다.

이 전략은 볼링거 밴드 매개 변수를 사용자 정의 할 수 있습니다: 이동 평균 기간 n 및 표준 편차 배수자 k. 기본 값은 이동 평균에 대해 20 기간, 표준 편차 배수자에 대해 2 기간입니다.

이 전략은 매 거래일 후에 폐쇄 가격이 상위 대역을 넘어서는지 여부를 확인합니다. 만약 그렇게 된다면, 다음 날 개시에 긴 신호가 트리거됩니다. 한 번 긴 경우, 전략은 가격이 하위 대역을 넘어서면 실시간으로 모니터링하고 그렇게 되면 포지션을 닫습니다.

이 전략은 또한 이동 평균 필터를 포함하고 있으며, 가격이 이동 평균 라인 이상일 때만 구매 신호를 생성합니다. 이동 평균은 입시 시기를 더 잘 제어하기 위해 현재 또는 더 높은 시간 프레임에 설정할 수 있습니다.

두 가지 스톱 로스 옵션이 제공됩니다: 고정 비율 스톱 로스 또는 하위 밴드를 추적합니다. 후자는 수익을 실행 할 수있는 더 많은 공간을 제공합니다.

전략 의 장점

  • 과잉 구매/ 과잉 판매 수준을 판단하기 위해 볼링거 밴드를 사용
  • 이동 평균 필터는 트렌드에 반대되는 거래를 피합니다.
  • 사용자 정의 가능한 볼링거 밴드 매개 변수는 다른 기간에 적합합니다.
  • 두 가지 스톱 로스 방법 중 선택
  • 백테스팅은 매개 변수 최적화 및 샘플 외부 검증을 허용합니다.

전략 의 위험

  • 볼링거 대역은 과잉 구매/ 과잉 판매를 완전히 결정할 수 없습니다.
  • 이동 평균 필터는 더 빠른 브레이크오웃을 놓칠 수 있습니다.
  • 고정 스톱 손실은 너무 보수적일 수 있습니다. 후속 스톱은 너무 공격적일 수 있습니다.
  • 매개 변수는 다른 제품과 시간 프레임에 최적화해야합니다.
  • 손실 규모를 제한 할 수 없습니다, 돈을 관리 고려해야 합니다

최적화 방향

  • 다른 이동 평균 매개 변수 조합을 테스트합니다.
  • 다른 볼링거 밴드 매개 변수를 시도해보세요.
  • 수익의 측면에서 고정 비율 스톱 손실과 후속 하위 대역을 비교하십시오.
  • 거래당 손실 제한에 화폐 관리 모듈을 추가
  • 볼링거 밴드 신호를 확인하기 위해 다른 지표를 포함합니다.

결론

이 전략은 볼링거 밴드 (Bollinger Bands) 의 동적 대역을 사용하여 과반 구매/ 과반 판매 조건을 식별하고, 이동 평균 필터를 참조하며, 자본을 보호하기 위해 스톱을 사용합니다. 전통적인 고정 레벨의 브레이크아웃과 비교하면 시장 변동에 더 잘 적응합니다. 추가 매개 변수 최적화 및 위험 통제로 전략은 더 높은 안정성과 수익을 얻을 수 있습니다. 전반적으로 볼링거 밴드의 동적 성격을 활용함으로써 전략은 브레이크아웃 전략의 장점을 포착하고 실시간 거래와 장기적인 최적화에 가치가 있습니다.


/*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



더 많은