Chiến lược đột phá nén biến động


Ngày tạo: 2023-11-10 11:03:25 sửa đổi lần cuối: 2023-11-10 11:03:25
sao chép: 1 Số nhấp chuột: 733
1
tập trung vào
1617
Người theo dõi

Tổng quan

Chiến lược phá vỡ nén biến động là một hệ thống giao dịch kết hợp các dải Bollinger Bands (BB) và Keltner Channel (KC). Nó nhằm mục đích nắm bắt các chuyển động chính của thị trường bằng cách theo dõi các đợt phá vỡ giá và các tín hiệu xu hướng. Chiến lược này tập trung vào các giai đoạn nén của thị trường (các biến động thấp) và các đợt phá vỡ tiếp theo (các biến động cao), cố gắng tham gia thị trường trước khi chuyển động giá lớn bắt đầu.

Nguyên tắc chiến lược

Điểm cốt lõi của chiến lược nén biến động phá vỡ là xác định sự giảm và tăng biến động của thị trường. Bảng Brin được hình thành bằng cách tính toán độ lệch tiêu chuẩn của giá, trong khi Keltner Channel được dựa trên phạm vi trung bình thực tế (ATR). Khi Brin nén bên trong Keltner Channel, nó cho thấy sự giảm biến động của thị trường, có thể có một đợt phá vỡ giá lớn.

Lợi thế chiến lược

Ưu điểm chính của chiến lược này là nó kết hợp các chỉ số biến động và các chỉ số xu hướng, cung cấp một cái nhìn toàn diện về thị trường. Thông qua sự kết hợp của các băng tần Brin và kênh Keltner, chiến lược có thể xác định hiệu quả các chuyển động thị trường lớn tiềm năng. Ngoài ra, việc sử dụng các bảng xếp hạng xu hướng EMA có thể giúp xác định hướng thị trường và giảm tín hiệu sai.

Rủi ro chiến lược

Nguy cơ chính của chiến lược phá vỡ nén biến động là các tín hiệu phá vỡ giả và sự không chắc chắn của thị trường. Trong điều kiện thị trường có biến động cao, vùng Burin có thể bị phá vỡ thường xuyên, do đó tạo ra tín hiệu sai lệch. Ngoài ra, nếu không xác định đúng xu hướng thị trường, chiến lược có thể tạo ra giao dịch bất lợi. Để giảm thiểu những rủi ro này, chiến lược có thể được tối ưu hóa bằng cách điều chỉnh tham số, kết hợp với các chỉ số khác hoặc sử dụng các điều kiện nghiêm ngặt hơn.

Hướng tối ưu hóa chiến lược

Chiến lược này có thể được tối ưu hóa bằng nhiều cách. Đầu tiên, nó có thể được điều chỉnh để phù hợp với các điều kiện thị trường khác nhau bằng cách điều chỉnh các tham số của Brin Belt và Keltner Channel. Tiếp theo, các chỉ số kỹ thuật khác có thể được giới thiệu, chẳng hạn như chỉ số tương đối yếu ((RSI) hoặc sự phân tán kết thúc trung bình di chuyển ((MACD), để cung cấp tín hiệu xác nhận giao dịch bổ sung. Cuối cùng, có thể xem xét kết hợp chiến lược này với các loại hệ thống giao dịch khác để tạo ra một khung giao dịch toàn diện và đa dạng hơn.

Tóm tắt

Chiến lược phá vỡ nén biến động là một hệ thống giao dịch mạnh mẽ và linh hoạt, kết hợp các ưu điểm của Brin Belt và Keltner Channel. Bằng cách giám sát biến động thị trường và tín hiệu xu hướng, nó có thể xác định hiệu quả các chuyển động thị trường lớn. Mặc dù chiến lược có một số rủi ro, nhưng có thể cải thiện hiệu quả và độ chính xác của nó bằng cách tối ưu hóa và điều chỉnh tham số thích hợp.

Mã nguồn chiến lược
/*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)