Bollinger Bands Dynamic Trend Theo chiến lược

Tác giả:ChaoZhang, Ngày: 2023-12-26 11:21:10
Tags:

img

Tổng quan

Chiến lược này thực hiện một chiến lược theo dõi xu hướng mạnh mẽ dựa trên Bollinger Bands, đường trung bình động và phân tích khối lượng.

Chiến lược logic

Bollinger Bands

  • Sử dụng Bollinger Bands để xác định các điều kiện mua quá mức và bán quá mức trên thị trường.

  • Tính toán dải dựa trên giá trị trung bình và độ lệch chuẩn trong một khoảng thời gian nhất định. Giá vượt qua dải trên hoặc dưới cho thấy tín hiệu mua quá mức hoặc bán quá mức.

Bộ lọc trung bình di chuyển

  • Thực hiện bộ lọc trung bình động (MA) để tăng cường xác định xu hướng. Người dùng có thể chọn từ các loại MA khác nhau bao gồm đơn giản, biểu thức, cân nhắc.

  • Tạo ra tín hiệu mua (bán) khi giá vượt trên (dưới) trung bình động.

Phân tích khối lượng

  • Cho phép người dùng tích hợp phân tích âm lượng vào chiến lược để tăng cường xác nhận tín hiệu.

  • Trung bình vượt khối lượng có thể được sử dụng để xác nhận tín hiệu giá.

Ưu điểm

Xu hướng mạnh mẽ tiếp tục

  • Xác định sự đảo ngược xu hướng thị trường dựa trên Bollinger Bands, đường trung bình động và khối lượng.

  • Nhận xu hướng giá kịp thời cho giao dịch xu hướng.

Tính linh hoạt và tùy chỉnh

  • Người dùng có thể tối ưu hóa các tham số như thời gian BB, loại MA và chiều dài.

  • Các vị trí dài và ngắn có thể được điều khiển riêng biệt.

Hiển thị & xác nhận

  • Cơ chế tín hiệu kép xác nhận tín hiệu giá bằng MA và khối lượng.

  • Hiển thị trực quan các tín hiệu giao dịch chính như đường trung bình động, mức dừng lỗ.

Quản lý rủi ro

  • Tính toán stop-loss dựa trên ATR. Thời gian và nhân ATR tùy chỉnh.

  • Điều chỉnh kích thước vị trí dựa trên tỷ lệ phần trăm vốn chủ sở hữu có rủi ro để kiểm soát lỗ giao dịch duy nhất.

Rủi ro

Rủi ro trong giai đoạn thử nghiệm sau

  • Hiệu suất có thể khác nhau trong các giai đoạn lịch sử khác nhau.

Rủi ro đảo ngược xu hướng

  • Tăng kích hoạt dừng lỗ trong các thị trường giới hạn phạm vi. Có thể giảm thiểu bằng cách tối ưu hóa các thông số MA.

Tối ưu hóa quá mức

  • Tối ưu hóa nhiều tham số có thể dẫn đến quá mức.

Rủi ro về chỉ số chậm

  • Các chỉ số có sự chậm trễ vốn có. Hành động giá nên bổ sung cho các tín hiệu chỉ số.

Cơ hội gia tăng

Tối ưu hóa tham số

  • Tối ưu hóa các thông số BB, MA, ATR cho các sản phẩm và khung thời gian khác nhau.

Tối ưu hóa vị trí

  • Kiểm tra tỷ lệ phần trăm vốn chủ sở hữu khác nhau ở mức độ rủi ro, nhân dừng lỗ.

Tối ưu hóa tín hiệu

  • Đưa ra các bộ lọc bổ sung như KD, MACD để bổ sung tín hiệu vào và ra.

Tối ưu hóa mã

  • Cải thiện logic tín hiệu để tránh giao dịch không cần thiết.

Kết luận

Chiến lược này tích hợp các dải Bollinger, đường trung bình động và phân tích khối lượng vào một hệ thống giao dịch xu hướng cơ học. Sức mạnh của nó nằm trong các cơ chế xác nhận tín hiệu và kiểm soát rủi ro mạnh mẽ.


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


Thêm nữa