볼링거 밴드 추진 동향 전략

저자:차오장, 날짜: 2023-12-26 11:21:10
태그:

img

전반적인 설명

이 전략은 볼링거 밴드, 이동 평균 및 볼륨 분석에 기반한 강력한 트렌드 추적 전략을 구현합니다. 잠재적인 트렌드 반전을 포착하고 시장 추진력을 활용하는 것을 목표로합니다.

전략 논리

볼링거 밴드

  • 볼링거 대역을 활용하여 시장에서 과반 구매 및 과반 판매 조건을 식별합니다. 의사결정을 돕기 위해 상위 및 하위 대역의 명확한 시각화를 제공합니다.

  • 특정 기간 동안의 중간 값과 표준편차를 기준으로 범위를 계산합니다. 상위 또는 하위 범위를 가로질러가는 가격은 과잉 구매 또는 과잉 판매 신호를 나타냅니다.

이동 평균 필터

  • 트렌드 식별을 향상시키기 위해 이동 평균 (MA) 필터를 구현합니다. 사용자는 단순, 기하급수, 가중 된 등 다양한 MA 유형을 선택할 수 있습니다.

  • 가격이 이동 평균보다 높을 때 구매 (판매) 신호를 생성합니다.

용량 분석

  • 사용자가 증강된 신호 확인을 위한 전략에 볼륨 분석을 통합할 수 있게 한다. 색상 코딩된 볼륨 바는 볼륨이 평균보다 높거나 낮는지 나타낸다.

  • 부피 크로싱 평균은 가격 신호를 확인하는 데 사용할 수 있습니다.

장점

강력 한 추세

  • 볼링거 밴드, 이동 평균 및 볼륨에 기초한 시장 트렌드 반전을 식별합니다.

  • 트렌드 트레이딩을 위해 가격 동향을 적시에 포착합니다.

유연성 및 사용자 정의

  • 사용자들은 BB 기간, MA 유형 및 길이와 같은 매개 변수를 최적화 할 수 있습니다.

  • 긴 포지션과 짧은 포지션은 별도로 제어 할 수 있습니다.

시각화 및 확인

  • MA와 볼륨을 사용하여 가격 신호를 확인하는 이중 신호 메커니즘.

  • 이동 평균, 스톱 로스 레벨과 같은 주요 거래 신호의 직관적인 표시

위험 관리

  • ATR을 기반으로 스톱 로스를 계산합니다. 사용자 정의 가능한 ATR 기간과 곱셈자.

  • 단일 거래 손실을 통제하기 위해 위험 당 주식의 비율을 기반으로 위치 크기를 조정합니다.

위험성

백테스트 기간 위험

  • 성능은 서로 다른 역사적 기간에 따라 달라질 수 있습니다. 내구성은 여러 기간 역 테스트를 통해 검증되어야합니다.

트렌드 반전 위험

  • 범위에 묶인 시장에서 스톱 로스 트리거가 증가합니다. MA 매개 변수를 최적화함으로써 완화 할 수 있습니다.

과도한 최적화

  • 여러 매개 변수 최적화는 과도한 부착으로 이어질 수 있습니다. 다양한 매개 변수 세트에 걸쳐 견고성을 확인해야합니다.

지표 후퇴 위험

  • 지표는 내재적인 지연을 가지고 있습니다. 가격 액션은 지표 신호를 보완해야합니다.

더 나은 기회

매개 변수 최적화

  • BB, MA, ATR 매개 변수를 다양한 제품과 시간 프레임에 최적화합니다.

위치 최적화

  • 위험 수준에서 다른 주식 비율을 테스트하고, 스톱 로스 곱셈을 합니다.

신호 최적화

  • KD, MACD와 같은 추가 필터를 도입하여 입출 신호를 보완합니다.

코드 최적화

  • 불필요한 트레이드를 피하기 위해 신호 논리를 정제하고 확장성을 위해 OOP를 채택하십시오.

결론

이 전략은 볼링거 밴드, 이동 평균 및 볼륨 분석을 기계적 트렌드 거래 시스템으로 통합합니다. 그것의 강점은 강력한 신호 확인 및 위험 제어 메커니즘에 있습니다. 안정성과 수익성을 향상시키기 위해 매개 변수 및 신호 최적화를 통해 추가 개선이 가능합니다. 전략 방법론은 트렌드 추종자들에게 참조 역할을합니다.


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

// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © sosacur01

//@version=5
strategy(title="Bollinger Band | Trend Following", overlay=true, pyramiding=1, commission_type=strategy.commission.percent, commission_value=0.2, initial_capital=10000)

//--------------------------------------

//BACKTEST RANGE
useDateFilter = input.bool(true, title="Filter Date Range of Backtest",
     group="Backtest Time Period")
backtestStartDate = input(timestamp("1 jan 2017"), 
     title="Start Date", group="Backtest Time Period",
     tooltip="This start date is in the time zone of the exchange " + 
     "where the chart's instrument trades. It doesn't use the time " + 
     "zone of the chart or of your computer.")
backtestEndDate = input(timestamp("1 jul 2100"),
     title="End Date", group="Backtest Time Period",
     tooltip="This end date is in the time zone of the exchange " + 
     "where the chart's instrument trades. It doesn't use the time " + 
     "zone of the chart or of your computer.")
inTradeWindow = true
if not inTradeWindow and inTradeWindow[1]
    strategy.cancel_all()
    strategy.close_all(comment="Date Range Exit")

//--------------------------------------

//LONG/SHORT POSITION ON/OFF INPUT
LongPositions   = input.bool(title='On/Off Long Postion', defval=true, group="Long & Short Position")
ShortPositions  = input.bool(title='On/Off Short Postion', defval=true, group="Long & Short Position")

//--------------------------------------
//MA INPUTS
averageType1    = input.string(defval="WMA", group="MA", title="MA Type", options=["SMA", "EMA", "WMA", "HMA", "RMA", "SWMA", "ALMA", "VWMA", "VWAP"])
averageLength1  = input.int(defval=99, title="MA Lenght", group="MA")
averageSource1  = input(close, title="MA Source", group="MA")

//MA TYPE
MovAvgType1(averageType1, averageSource1, averageLength1) =>
	switch str.upper(averageType1)
        "SMA"  => ta.sma(averageSource1, averageLength1)
        "EMA"  => ta.ema(averageSource1, averageLength1)
        "WMA"  => ta.wma(averageSource1, averageLength1)
        "HMA"  => ta.hma(averageSource1, averageLength1)
        "RMA"  => ta.rma(averageSource1, averageLength1)
        "SWMA" => ta.swma(averageSource1)
        "ALMA" => ta.alma(averageSource1, averageLength1, 0.85, 6)
        "VWMA" => ta.vwma(averageSource1, averageLength1)
        "VWAP" => ta.vwap(averageSource1)
        => runtime.error("Moving average type '" + averageType1 + 
             "' not found!"), na


//MA VALUES
ma  = MovAvgType1(averageType1, averageSource1, averageLength1)

//MA CONDITIONS
bullish_ma = close > ma
bearish_ma = close < ma

//PLOT COLOR
ma_plot    = if close > ma
    color.navy
else
    color.rgb(49, 27, 146, 40)

//MA PLOT
plot(ma,color=ma_plot, linewidth=2, title="MA")

//--------------------------------------
//BB INPUTS
length  = input.int(20, minval=1, group="BB")
src     = input(close, title="Source", group="BB")
mult    = input.float(2.0, minval=0.001, maxval=50, title="StdDev", group="BB")

//BB VALUES
basis = ta.sma(src, length)
dev = mult * ta.stdev(src, length)
upper = basis + dev
lower = basis - dev
offset = input.int(0, "Offset", minval = -500, maxval = 500)

//BBPLOT
//plot(basis, "Basis", color=#FF6D00, offset = offset)
p1 = plot(upper, "Upper", color=#2978ffa4, offset = offset)
p2 = plot(lower, "Lower", color=#2978ffa4, offset = offset)
fill(p1, p2, title = "Background", color=color.rgb(33, 47, 243, 97))

//BB ENTRY AND EXIT CONDITIONS
bb_long_entry  = close >= upper
bb_long_exit   = close <= lower
bb_short_entry = close <= lower
bb_short_exit  = close >= upper

//---------------------------------------------------------------
//VOLUME INPUTS
useVolumefilter  = input.bool(title='Use Volume Filter?', defval=false, group="Volume Inputs")
dailyLength      = input.int(title = "MA length", defval = 30, minval = 1, maxval = 100, group = "Volume Inputs")
lineWidth        = input.int(title = "Width of volume bars", defval = 3, minval = 1, maxval = 6, group = "Volume Inputs")
Volumefilter_display  = input.bool(title="Color bars?", defval=false, group="Volume Inputs", tooltip = "Change bar colors when Volume is above average")

//VOLUME VALUES
volumeAvgDaily = ta.sma(volume, dailyLength)

//VOLUME SIGNAL
v_trigger  = (useVolumefilter ? volume > volumeAvgDaily : inTradeWindow)

//PLOT VOLUME SIGNAL
barcolor(Volumefilter_display ? v_trigger ? color.new(#6fe477, 77):na: na, title="Volume Filter")
//---------------------------------------------------------------

//ENTRIES AND EXITS
long_entry  = if inTradeWindow and bullish_ma and bb_long_entry and v_trigger and LongPositions
    true
long_exit   = if inTradeWindow and bb_long_exit  
    true

short_entry = if inTradeWindow  and bearish_ma and bb_short_entry and v_trigger and ShortPositions
    true
short_exit  = if inTradeWindow  and bb_short_exit 
    true
    
//--------------------------------------

//RISK MANAGEMENT - SL, MONEY AT RISK, POSITION SIZING
atrPeriod                = input.int(14, "ATR Length", group="Risk Management Inputs")
sl_atr_multiplier        = input.float(title="Long Position - Stop Loss - ATR Multiplier", defval=2, group="Risk Management Inputs", step=0.5)
sl_atr_multiplier_short  = input.float(title="Short Position - Stop Loss - ATR Multiplier", defval=2, group="Risk Management Inputs", step=0.5)
i_pctStop                = input.float(2, title="% of Equity at Risk", step=.5, group="Risk Management Inputs")/100

//ATR VALUE
_atr = ta.atr(atrPeriod)

//CALCULATE LAST ENTRY PRICE
lastEntryPrice = strategy.opentrades.entry_price(strategy.opentrades - 1)

//STOP LOSS - LONG POSITIONS 
var float sl = na

//CALCULTE SL WITH ATR AT ENTRY PRICE - LONG POSITION
if (strategy.position_size[1] != strategy.position_size)
    sl := lastEntryPrice - (_atr * sl_atr_multiplier)

//IN TRADE - LONG POSITIONS
inTrade = strategy.position_size > 0

//PLOT SL - LONG POSITIONS
plot(inTrade ? sl : na, color=color.blue, style=plot.style_circles, title="Long Position - Stop Loss")

//CALCULATE ORDER SIZE - LONG POSITIONS
positionSize = (strategy.equity * i_pctStop) / (_atr * sl_atr_multiplier)

//============================================================================================

//STOP LOSS - SHORT POSITIONS 
var float sl_short = na

//CALCULTE SL WITH ATR AT ENTRY PRICE - SHORT POSITIONS 
if (strategy.position_size[1] != strategy.position_size)
    sl_short := lastEntryPrice + (_atr * sl_atr_multiplier_short)

//IN TRADE SHORT POSITIONS
inTrade_short = strategy.position_size < 0

//PLOT SL - SHORT POSITIONS
plot(inTrade_short ? sl_short : na, color=color.red, style=plot.style_circles, title="Short Position - Stop Loss")

//CALCULATE ORDER - SHORT POSITIONS
positionSize_short = (strategy.equity * i_pctStop) / (_atr * sl_atr_multiplier_short) 


//===============================================

//LONG STRATEGY
strategy.entry("Long", strategy.long, comment="Long", when = long_entry, qty=positionSize)
if (strategy.position_size > 0)
    strategy.close("Long", when = (long_exit), comment="Close Long")
    strategy.exit("Long", stop = sl, comment="Exit Long")

//SHORT STRATEGY
strategy.entry("Short", strategy.short, comment="Short", when = short_entry, qty=positionSize_short)
if (strategy.position_size < 0) 
    strategy.close("Short", when = (short_exit), comment="Close Short")
    strategy.exit("Short", stop = sl_short, comment="Exit Short")

//ONE DIRECTION TRADING COMMAND (BELLOW ONLY ACTIVATE TO CORRECT BUGS)
//strategy.risk.allow_entry_in(strategy.direction.long)


더 많은