Chiến lược dừng theo ATR thích ứng


Ngày tạo: 2023-09-13 15:48:32 sửa đổi lần cuối: 2023-09-13 15:48:32
sao chép: 2 Số nhấp chuột: 1014
1
tập trung vào
1617
Người theo dõi

Chiến lược này được gọi là chiến lược dừng theo dõi ATR tự điều chỉnh. Chiến lược này sử dụng chỉ số ATR để thiết lập điểm dừng và chuyển dừng từ chặt chẽ sang nới lỏng sau khi tham gia, nhằm theo dõi xu hướng và kiểm soát rủi ro.

Chiến lược này có những logic như sau:

  1. Xác định mức giá cao nhất và mức giá thấp nhất trong một chu kỳ nhất định như là tín hiệu vào, tạo ra tín hiệu vào khi giá vượt qua phạm vi đó.

  2. Sau khi nhập cảnh, ban đầu sử dụng ATR dừng chặt chẽ, điểm dừng được cố định là 1,5 lần giá trị ATR. Điều này có thể hạn chế tổn thất sau khi nhập cảnh.

  3. Trong giai đoạn nắm giữ, dừng sẽ chuyển sang ATR thoải mái hơn gấp 4 lần. Đặt dừng tiếp tục theo dõi hoạt động của giá, nhưng có không gian lớn hơn cho phép nhu cầu tiếp tục kéo dài.

  4. Điểm dừng cuối cùng luôn theo dõi giá thấp nhất ((multi order) hoặc giá cao nhất ((blank), điều chỉnh theo biến động giá, để thực hiện hiệu quả theo dõi dừng lỗ.

  5. Khi giá giảm xuống điểm dừng lỗ (thông tin nhiều) hoặc tăng lên điểm dừng lỗ (thông tin trống) thì dừng lỗ.

Ưu điểm của chiến lược này là việc sử dụng cơ chế dừng tự thích ứng, đảm bảo kiểm soát rủi ro và tránh dừng quá sớm. Tuy nhiên, các tham số và nhân ATR cần được tối ưu hóa và sử dụng chiến lược dừng để đánh giá xu hướng.

Nhìn chung, theo dõi động lệnh dừng là một phương tiện quan trọng để cải thiện khả năng chiến lược. Sử dụng các lệnh dừng linh hoạt, tốt hơn để duy trì xu hướng lợi nhuận và kiểm soát rủi ro.

Mã nguồn chiến lược
/*backtest
start: 2023-08-13 00:00:00
end: 2023-09-12 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/
//@version=4
//@author=Takazudo

strategy("ATR trailing SL tight to slack [Takazudo]",
  overlay=true,
  default_qty_type=strategy.fixed,
  initial_capital=0,
  currency=currency.USD)


posSize = strategy.position_size
hasNoPos = posSize == 0
hasLongPos = posSize > 0
hasShortPos = posSize < 0

//============================================================================
// consts, inputs
//============================================================================

// colors

var COLOR_SL_LINE = color.new(#e0f64d, 20)
var COLOR_SL_LINE_THIN = color.new(#e0f64d, 90)
var COLOR_ENTRY_BAND = color.new(#43A6F5, 30)
var COLOR_TRANSPARENT = color.new(#000000, 100)

// Entry strategy

_g1 = 'Entry strategy'
var config_entryBandBars = input(defval = 100, title = "Entry band bar count",  minval=1, group=_g1)

_g2 = 'ATR SL'
var config_slAtr_length = input(24, title = "Trailing stop ATR Length", group=_g2)
var config_slAtr_multi1 = input(1.5, title = "Trailing stop ATR Multiple on tight", type=input.float, step=0.1, group=_g2)
var config_slAtr_multi2 = input(4, title = "Trailing stop ATR Multiple on slack", type=input.float, step=0.1, group=_g2)

_g3 = 'Backtesting range'
var config_fromYear  = input(defval = 2016, title = "From Year",  minval = 1970, group=_g3)
var config_fromMonth = input(defval = 1,    title = "From Month", minval = 1, maxval = 12, group=_g3)
var config_fromDay   = input(defval = 1,    title = "From Day",   minval = 1, maxval = 31, group=_g3)
var config_toYear  = input(defval = 2021, title = "To Year",  minval = 1970, group=_g3)
var config_toMonth = input(defval = 4,    title = "To Month", minval = 1, maxval = 12, group=_g3)
var config_toDay   = input(defval = 5,    title = "To Day",   minval = 1, maxval = 31, group=_g3)

//============================================================================
// Range Edge calculation
//============================================================================

f_calcEntryBand_high() =>
    _highest = max(open[3], close[3])
    for i = 4 to (config_entryBandBars - 1)
        _highest := max(_highest, open[i], close[i])
    _highest

f_calcEntryBand_low() =>
    _lowest = min(open[3], close[3])
    for i = 4 to (config_entryBandBars - 1)
        _lowest := min(_lowest, open[i], close[i])
    _lowest

entryBand_high = f_calcEntryBand_high()
entryBand_low = f_calcEntryBand_low()
entryBand_height = entryBand_high - entryBand_low

plot(entryBand_high, color=COLOR_ENTRY_BAND, linewidth=1)
plot(entryBand_low, color=COLOR_ENTRY_BAND, linewidth=1)

rangeBreakDetected_long = entryBand_high < close
rangeBreakDetected_short = entryBand_low > close

shouldMakeEntryLong = (strategy.position_size == 0) and rangeBreakDetected_long
shouldMakeEntryShort = (strategy.position_size == 0) and rangeBreakDetected_short

//============================================================================
// ATR based stuff
//============================================================================

sl_atrHeight_tight = atr(config_slAtr_length) * config_slAtr_multi1
sl_atrHeight_slack = atr(config_slAtr_length) * config_slAtr_multi2

sl_tight_bull = min(open, close) - sl_atrHeight_tight
sl_tight_bear = max(open, close) + sl_atrHeight_tight
sl_slack_bull = min(open, close) - sl_atrHeight_slack
sl_slack_bear = max(open, close) + sl_atrHeight_slack

plot(sl_tight_bull, color=COLOR_SL_LINE_THIN, transp=0, linewidth=1)
plot(sl_tight_bear, color=COLOR_SL_LINE_THIN, transp=0, linewidth=1)
plot(sl_slack_bull, color=COLOR_SL_LINE_THIN, transp=0, linewidth=1)
plot(sl_slack_bear, color=COLOR_SL_LINE_THIN, transp=0, linewidth=1)

//============================================================================
// Sl
//============================================================================

var trailingSl_long = hl2
var trailingSl_short = hl2

trailingSl_long := if hasLongPos
    max(trailingSl_long, sl_slack_bull)
else
    sl_tight_bull

trailingSl_short := if hasShortPos
    min(trailingSl_short, sl_slack_bear)
else
    sl_tight_bear

color_sl_long = hasLongPos ? COLOR_SL_LINE : COLOR_TRANSPARENT
color_sl_short = hasShortPos ? COLOR_SL_LINE : COLOR_TRANSPARENT

plot(trailingSl_long, color=color_sl_long, transp=0, linewidth=2)
plot(trailingSl_short, color=color_sl_short, transp=0, linewidth=2)


//============================================================================
// make entries
//============================================================================

// Calculate start/end date and time condition
startDate  = timestamp(config_fromYear, config_fromMonth, config_fromDay, 00, 00)
finishDate = timestamp(config_toYear,   config_toMonth,   config_toDay,   00, 00)

if (true)
    if shouldMakeEntryLong
        strategy.entry(id="Long", long=true, stop=close)
    if shouldMakeEntryShort
        strategy.entry(id="Short", long=false, stop=close)

strategy.exit('Long-SL/TP', 'Long', stop=trailingSl_long)
strategy.exit('Short-SL/TP', 'Short', stop=trailingSl_short)