변동성 압축 돌파 전략


생성 날짜: 2023-11-10 11:03:25 마지막으로 수정됨: 2023-11-10 11:03:25
복사: 1 클릭수: 733
avatar of ChaoZhang ChaoZhang
1
집중하다
1617
수행원

개요

변동률 압축 돌파 전략은 부린 밴드 (Bollinger Bands, BB) 와 켈트너 채널 (Keltner Channel, KC) 을 결합한 거래 시스템이다. 가격 돌파구와 트렌드 신호를 모니터링하여 시장의 주요 움직임을 잡는 것을 목적으로 한다. 전략은 시장의 압축 기간 (low volatility) 과 그 후의 돌파구 (high volatility) 에 초점을 맞추고, 대규모 가격 움직임이 시작되기 전에 시장에 진입하려고 한다.

전략 원칙

변동률 압축 브레이크 전략의 핵심은 시장 변동률의 감소와 증가를 식별하는 것입니다. 린 벨트는 가격의 표준 편차를 계산하여 형성되며, 켈트너 채널은 평균 실제 범위를 기반으로합니다. 린 벨트가 켈트너 채널 내부에서 압축 될 때, 시장 변동률이 감소하면 대규모의 가격 돌파가 발생할 수 있음을 나타냅니다. 린 벨트가 켈트너 채널 내부에 있는지, 그리고 가격이 린 벨트의 상한 또는 하한을 뚫고 있는지 확인하여 거래 신호를 발산합니다. 또한, 전략은 지수 이동 평균선 (EMA) 의 추세 배열을 고려하여 신호의 효과를 강화합니다.

전략적 이점

이 전략의 주요 장점은 변동률 지표와 트렌드 지표가 결합되어 전체적인 시장 관점을 제공한다는 것입니다. 브린 벨트와 켈트너 통로의 조합을 통해 전략은 잠재적인 대규모 시장 움직임을 효과적으로 식별 할 수 있습니다. 또한 EMA 트렌드 배열의 사용은 시장 방향을 확인하고 잘못된 신호를 줄이는 데 도움이 될 수 있습니다.

전략적 위험

변동률 압축 뚫림 전략의 주요 위험은 가짜 뚫림 신호와 시장의 불확실성이다. 높은 변동률의 시장 조건에서, 부린 띠는 자주 뚫릴 수 있으며, 이로 인해 잘못된 신호가 생성된다. 또한, 시장 추세를 올바르게 파악하지 않으면 전략은 불리한 거래를 일으킬 수 있다. 이러한 위험을 줄이기 위해, 매개 변수를 조정하거나, 다른 지표와 결합하거나, 더 엄격한 조건을 적용하여 입시 전략을 최적화 할 수 있다.

전략 최적화 방향

이 전략은 여러 가지 방법으로 최적화 될 수 있습니다. 첫째, 브린 벨트와 켈트너 통로의 파라미터를 조정하여 다른 시장 조건에 맞게 조정할 수 있습니다. 둘째, 상대적으로 약한 지수 ((RSI) 또는 이동 평균의 종결 분산 ((MACD) 과 같은 다른 기술 지표를 도입하여 추가 거래 확인 신호를 제공 할 수 있습니다. 마지막으로, 이 전략을 다른 유형의 거래 시스템과 결합하여 더 포괄적이고 다양한 거래 프레임 워크를 형성하는 것이 고려 될 수 있습니다.

요약하다

변동률 압축 브레이크 전략은 부린 벨트와 켈트너 통로의 장점을 결합한 강력하고 유연한 거래 시스템입니다. 시장의 변동률과 트렌드 신호를 모니터링하여 대규모 시장 이동을 효과적으로 식별 할 수 있습니다. 전략에는 약간의 위험이 있지만 적절한 최적화와 변수 조정을 통해 효율성과 정확성을 크게 향상시킬 수 있습니다.

전략 소스 코드
/*backtest
start: 2023-01-01 00:00:00
end: 2023-11-09 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/
// © Bishnu103

//@version=4
strategy(title="Squeeze Breakout using BB and KC [v1.0][Bishnu103]",shorttitle="BB BREAKOUT",overlay=true,calc_on_every_tick=true)

// ***********************************************************************************************************************
// input variables
bbLength            = input(title="BB Length", minval=1, defval=20)
bbStdDev            = input(title="BB StdDev", minval=1, defval=2)
kcLength            = input(title="KC Length", minval=1, defval=20)
kcMult              = input(title="KC Mult", defval=1.5)
atrLength           = input(title="ATR Length", minval=1, defval=20)
entry_distance      = input(title="Entry distance from alert", minval=1, maxval=10, defval=10)
bb_squeeze_switch   = input(title="BB Squeeze Check", type=input.bool, defval=true)
bb_squeeze_width    = input(title="BB Squeeze Width", minval=1.0, defval=3.0)
bb_in_kc_switch     = input(title="BB within KC Check", type=input.bool, defval=false)
ema_trend_switch    = input(title="EMA Trend Check", type=input.bool, defval=false)
show_bb_switch      = input(title="Show BB", type=input.bool, defval=true)
show_kc_switch      = input(title="Show KC", type=input.bool, defval=true)
show_8ema_switch    = input(title="Show 8EMA", type=input.bool, defval=true)
show_emas_switch    = input(title="Show EMAs", type=input.bool, defval=false)

// ***********************************************************************************************************************
// global variables
closed_above_bb     = false
closed_below_bb     = false

// variable values available across candles
var entry_price     = 0.0  
var sl_price        = 0.0
var exit_price_8ema = 0.0
var candle_count    = 0

// ***********************************************************************************************************************
// function to return bollinger band values based on candle poition passed 
getBB(pos) =>
    float basis = sma(close[pos], bbLength)
    float dev = bbStdDev * stdev(close[pos], bbLength)
    [basis, basis + dev, basis - dev]

// function to return Keltner Channel values based on candle poition passed 
getKC(pos) => 
    mKC     = ema(close[pos],kcLength)
    range   = kcMult * atr(atrLength)[pos]
    uKC     = mKC + range
    lKC     = mKC - range
    [mKC,uKC,lKC]

// ***********************************************************************************************************************
// strategy
//
// get current bb value
[mBB_0,uBB_0,lBB_0] = getBB(0)
[mBB_1,uBB_1,lBB_1] = getBB(1)

// if a candle closes above bb and previous candle closed inside bb then it's a bullish signal
if close[0] > uBB_0
    closed_above_bb := true
    entry_price     := high[0]

// if a candle closes above bb and previous candle closed inside bb then it's a bullish signal
if close[0] < lBB_0
    closed_below_bb := true
    entry_price     := low[0]

// check if BB is in squeeze
bb_in_squeeze = bb_squeeze_switch ? ((uBB_1 - lBB_1) < (atr(20)[1] * bb_squeeze_width)) : true

// 6 candle's bb prior to the alert candle, are within keltner channel on either upper side of the bands or on lower side of the bands
// bb
[mBB_2,uBB_2,lBB_2] = getBB(2)
[mBB_3,uBB_3,lBB_3] = getBB(3)
[mBB_4,uBB_4,lBB_4] = getBB(4)
[mBB_5,uBB_5,lBB_5] = getBB(5)
[mBB_6,uBB_6,lBB_6] = getBB(6)
// kc
[mKC_1,uKC_1,lKC_1] = getKC(1)
[mKC_2,uKC_2,lKC_2] = getKC(2)
[mKC_3,uKC_3,lKC_3] = getKC(3)
[mKC_4,uKC_4,lKC_4] = getKC(4)
[mKC_5,uKC_5,lKC_5] = getKC(5)
[mKC_6,uKC_6,lKC_6] = getKC(6)
// check if either side 6 candle's bb are inside kc
lower_squeeze_is_good = uBB_1   < uKC_1 and uBB_2 < uKC_2 and uBB_3 < uKC_3 and uBB_4 < uKC_4 and uBB_5 < uKC_5 and uBB_6 < uKC_6
upper_squeeze_is_good = lBB_1   > lKC_1 and lBB_2 > lKC_2 and lBB_3 > lKC_3 and lBB_4 > lKC_4 and lBB_5 > lKC_5 and lBB_6 > lKC_6
squeeze_is_good                 = bb_in_kc_switch ? (upper_squeeze_is_good or lower_squeeze_is_good) : true

// EMAs (8, 21, 34, 55, 89) should be aligned in sequence
ema_8               = ema(close,8)
ema_21              = ema(close,21)
ema_34              = ema(close,34)
ema_55              = ema(close,55)
ema_89              = ema(close,89)
ema_trend_check1    = ema_trend_switch and closed_above_bb and ema_8 > ema_21 and ema_21 > ema_34 and ema_34 > ema_55 and ema_55 > ema_89
ema_trend_check2    = ema_trend_switch and closed_below_bb and ema_8 < ema_21 and ema_21 < ema_34 and ema_34 < ema_55 and ema_55 < ema_89
ema_trend_check     = ema_trend_switch ? (ema_trend_check1 or ema_trend_check2) : true

// ***********************************************************************************************************************
// entry conditions 
long_entry   = closed_above_bb and bb_in_squeeze and squeeze_is_good and ema_trend_check
short_entry  = closed_below_bb and bb_in_squeeze and squeeze_is_good and ema_trend_check

candle_count := candle_count + 1
if long_entry or short_entry
    candle_count := 0
    
if long_entry or short_entry
    exit_price_8ema := na

if long_entry or short_entry
    sl_price := mBB_0

// ***********************************************************************************************************************
// exit conditions
// long trade - a candle closes below 8ema and in next candle price crosses low of previous candle
// short trade - a candle closes above 8ema and in next candle price crosses high of previous candle
long_exit_8ema    = strategy.position_size > 0 and crossunder(close,ema(close,8))
short_exit_8ema   = strategy.position_size < 0 and crossover(close,ema(close,8))

if long_exit_8ema
    exit_price_8ema := low

if short_exit_8ema
    exit_price_8ema := high

// ***********************************************************************************************************************
// position sizing
price = if close[0] > 25000
    25000
else
    price = close[0]

qty = 25000/price

// ***********************************************************************************************************************
// entry
if long_entry
    strategy.entry("BUY", strategy.long, qty, stop=entry_price, comment="BUY @ "+ tostring(entry_price)) 

if short_entry and candle_count < 11
    strategy.entry("SELL", strategy.short, qty, stop=entry_price, comment="SELL @ "+ tostring(entry_price))

if candle_count > entry_distance 
    strategy.cancel("BUY",true)
    strategy.cancel("SELL",true)

// ***********************************************************************************************************************
// exit
if strategy.position_size > 0 and long_exit_8ema
    strategy.exit("EXIT using 8EMA", "BUY", stop=exit_price_8ema, comment="EXIT @ "+ tostring(exit_price_8ema))

if strategy.position_size < 0 and short_exit_8ema
    strategy.exit("EXIT using 8EMA", "SELL", stop=exit_price_8ema, comment="EXIT @ "+ tostring(exit_price_8ema))

// ***********************************************************************************************************************
// plots    
//
// plot BB
[mBBp,uBBp,lBBp] = getBB(0)
p_mBB = plot(show_bb_switch ? mBBp : na, color=color.teal)
p_uBB = plot(show_bb_switch ? uBBp : na, color=color.teal)
p_lBB = plot(show_bb_switch ? lBBp : na, color=color.teal)
fill(p_uBB,p_lBB,color=color.teal,transp=95)

// plot KC
[mKCp,uKCp,lKCp] = getKC(0)
p_uKC = plot(show_kc_switch ? uKCp : na, color=color.red)
p_lKC = plot(show_kc_switch ? lKCp : na, color=color.red)

// plot 8 ema
plot(show_8ema_switch?ema_8:na,color=color.blue)

// plot EMAs
plot(show_emas_switch ? ema_8  : na, color=color.green)
plot(show_emas_switch ? ema_21 : na, color=color.lime)
plot(show_emas_switch ? ema_34 : na, color=color.maroon)
plot(show_emas_switch ? ema_55 : na, color=color.orange)
plot(show_emas_switch ? ema_89 : na, color=color.purple)