適応型ATRトレーリングストップ戦略


作成日: 2023-09-13 15:48:32 最終変更日: 2023-09-13 15:48:32
コピー: 2 クリック数: 1014
1
フォロー
1617
フォロワー

この策略は,自主適応ATR追跡ストップ策略と呼ばれています. この策略はATR指標を使用してストップポイントを設定し,入場後にストップを緊固から緩やかに変更し,トレンドの運行を追跡し,リスクを制御することを目的としています.

この戦略の論理は以下の通りです.

  1. ある周期内の最高価格と最低価格の範囲を入場信号として計算し,価格がその範囲を破るときに入場信号を生成する.

  2. 入場後,最初はより緊密なATRのストップが採用され,ストップ・ロスはATRの1.5倍に固定される.これは入場後の損失を制限することができる.

  3. 持仓段階では,ストップをより緩やかなATR値に4倍に変換する.ストップは価格の動きを追跡し続けますが,より大きな空間が需要の継続を許します.

  4. 最終的なストップポイントは常に最低価格 ((多枚) または最高価格 ((空券) を追跡し,価格変動に合わせて調整し,追跡ストップ効果を実現する.

  5. 価格が止損点 (多券) を破ると止損点 (空券) を破ると止損出場する.

この戦略の優点は,自己適応のストップ・メカニズムを採用することで,リスク管理を保証するとともに,早期のストップを回避することにある.しかしATRパラメータと倍数は最適化され,トレンド判断に合わせてストップ・ストップ・戦略を使用する必要がある.

概して,ダイナミック・トラッキング・ストップは,戦略の利益の確率を向上させる重要な手段である. 柔軟なストップの使用は,トレンドの利益を維持し,リスクをコントロールするよりよい手段である.

ストラテジーソースコード
/*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)