2つの範囲フィルター トレンド追跡戦略

作者: リン・ハーンチャオチャン開催日:2024年2月5日 11:15:28
タグ:

img

概要

ダブルレンジフィルタートレンドトラッキング戦略は,トレンド方向とトレンドを追跡するためにダブル EMAレンジフィルタリングを使用する定量的な取引戦略である.この戦略は,ダブル移動平均フィルタリングとATRレンジ計算を組み合わせ,中長期トレンド方向を効果的に認識し,ストップロスを追跡して利益をロックする.

戦略の論理

この戦略の核心はダブルEMAレンジフィルタリングである.これはキャンドルスティックのATRレンジを計算し,それを滑らかにし,その後,2つのEMAを使用してキャンドルスティックの位置を範囲内に位置づけ,現在トレンド中かどうかを決定する.価格がレンジを突破すると,トレンドの変化をシグナルする.

具体的には,戦略は最初にキャンドルスティックのATRレンジのサイズを計算し,その後2つのEMAで平滑します.ATRレンジはキャンドルスティックの通常の変動範囲を表します.価格がこの範囲を超えると,トレンドの変化が起こったことを意味します.戦略は価格がEMA範囲を突破したときの方向性を記録します.方向性が変化すると,トレンド逆転が起こったことを意味します.それが市場に入ることを選択できる時です.

市場に入ると,戦略は浮遊ストップロスを利用して利益をロックする.保持期間中,キャンドルスティックが範囲外に戻ったかどうかを絶えず判断する.引き下げが発生した場合,現在のポジションを退去する.これはトレンド取引からの利益を効果的にロックすることができます.

利点分析

デュアルレンジフィルタートレンドトラッキング戦略は,移動平均フィルタリングとレンジ計算の利点を組み合わせ,トレンド方向を正確に決定し,トレンド市場に頻繁に入ったり出たりすることを避けます. 具体的な利点は以下の通りです.

  1. キャンドルスタイルの変動範囲を判断するためにATR原則を使用し,市場範囲中に方向性なく市場に参入することを避ける
  2. 二重EMAフィルターは判断の精度を向上させ 誤信号を減少させます
  3. リアルタイムの浮動ストップ損失は,効果的にトレンド利益をロックすることができます
  4. シンプルで明確な戦略論理,理解し最適化しやすい

リスク分析

この戦略には,主に次の側面において,いくつかのリスクがあります.

  1. 大幅な隙間が ATR 範囲を突破し 早期に入力する
  2. 強いトレンド市場では,ストップロスは早めに起動する可能性があります.
  3. 間違ったパラメータ設定も戦略のパフォーマンスに影響します

これらのリスクに対処するために,パラメータを適切に最適化し,偽のブレイクを防止し,トレンド強さを判断するなどの方法が使用できます.

最適化 の 提案

また,ダブルレンジフィルタートレンドトラッキング戦略はさらに最適化できる可能性があり,主な最適化方向は以下の通りである.

  1. ATR パラメータを最適化し,キャンドルスタイク波動範囲を平らにする
  2. 誤ったブレイクを避けるために,ボリューム指標を組み込む
  3. 単一のブレイクと持続的なトレンドを区別するために傾向強さを判断する
  4. ストップ・ロスの価格を最適化して,利益を確保しながら,長期トレンドを追跡する

これらの最適化によって,戦略はより多くの市場環境で安定した利益を達成することができます.

概要

ダブルレンジフィルタートレンドトラッキング戦略は,移動平均フィルタリングとATRレンジ判断の様々な利点を統合し,持続的な中長期トレンドの方向性とエントリータイミングを効果的に特定することができます.トレンドが変化するときにのみ市場に参入し,利益をロックするために浮動ストップロスを使用します.この戦略はシンプルで明確な論理を持ち,中長期トレンド取引に非常に適しています.パラメータと判断規則の継続的な最適化により,この戦略はさまざまな市場で良いリターンを達成することができます.


/*backtest
start: 2023-01-29 00:00:00
end: 2024-02-04 00:00:00
period: 1d
basePeriod: 1h
exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}]
*/

//@version=4
strategy("Range Filter [DW] & Labels", shorttitle="RF [DW] & Labels", overlay=true)

//Conditional Sampling EMA Function 
Cond_EMA(x, cond, n)=>
    var val     = array.new_float(0)
    var ema_val = array.new_float(1)
    if cond
        array.push(val, x)
        if array.size(val) > 1
            array.remove(val, 0)
        if na(array.get(ema_val, 0))
            array.fill(ema_val, array.get(val, 0))
        array.set(ema_val, 0, (array.get(val, 0) - array.get(ema_val, 0))*(2/(n + 1)) + array.get(ema_val, 0))
    EMA = array.get(ema_val, 0)
    EMA

//Conditional Sampling SMA Function
Cond_SMA(x, cond, n)=>
    var vals = array.new_float(0)
    if cond
        array.push(vals, x)
        if array.size(vals) > n
            array.remove(vals, 0)
    SMA = array.avg(vals)
    SMA

//Standard Deviation Function
Stdev(x, n)=>
    sqrt(Cond_SMA(pow(x, 2), 1, n) - pow(Cond_SMA(x, 1, n), 2))

//Range Size Function
rng_size(x, scale, qty, n)=> 
    ATR      = Cond_EMA(tr(true), 1, n)
    AC       = Cond_EMA(abs(x - x[1]), 1, n)
    SD       = Stdev(x, n)
    rng_size = scale=="Pips" ? qty*0.0001 : scale=="Points" ? qty*syminfo.pointvalue : scale=="% of Price" ? close*qty/100 : scale=="ATR" ? qty*ATR :
               scale=="Average Change" ? qty*AC : scale=="Standard Deviation" ? qty*SD : scale=="Ticks" ? qty*syminfo.mintick : qty   

//Two Type Range Filter Function
rng_filt(h, l, rng_, n, type, smooth, sn, av_rf, av_n)=>
    rng_smooth = Cond_EMA(rng_, 1, sn)
    r          = smooth ? rng_smooth : rng_
    var rfilt  = array.new_float(2, (h + l)/2)
    array.set(rfilt, 1, array.get(rfilt, 0))
    if type=="Type 1"
        if h - r > array.get(rfilt, 1)
            array.set(rfilt, 0, h - r)
        if l + r < array.get(rfilt, 1)
            array.set(rfilt, 0, l + r)
    if type=="Type 2"
        if h >= array.get(rfilt, 1) + r
            array.set(rfilt, 0, array.get(rfilt, 1) + floor(abs(h - array.get(rfilt, 1))/r)*r)
        if l <= array.get(rfilt, 1) - r
            array.set(rfilt, 0, array.get(rfilt, 1) - floor(abs(l - array.get(rfilt, 1))/r)*r)
    rng_filt1 = array.get(rfilt, 0)
    hi_band1  = rng_filt1 + r
    lo_band1  = rng_filt1 - r
    rng_filt2 = Cond_EMA(rng_filt1, rng_filt1 != rng_filt1[1], av_n)
    hi_band2  = Cond_EMA(hi_band1, rng_filt1 != rng_filt1[1], av_n)
    lo_band2  = Cond_EMA(lo_band1, rng_filt1 != rng_filt1[1], av_n)
    rng_filt  = av_rf ? rng_filt2 : rng_filt1
    hi_band   = av_rf ? hi_band2 : hi_band1
    lo_band   = av_rf ? lo_band2 : lo_band1
    [hi_band, lo_band, rng_filt]
 
//-----------------------------------------------------------------------------------------------------------------------------------------------------------------
//Inputs
//-----------------------------------------------------------------------------------------------------------------------------------------------------------------

//Filter Type
f_type = input(defval="Type 1", options=["Type 1", "Type 2"], title="Filter Type")

//Movement Source
mov_src = input(defval="Close", options=["Wicks", "Close"], title="Movement Source")

//Range Size Inputs
rng_qty   = input(defval=2.618, minval=0.0000001, title="Range Size")
rng_scale = input(defval="Average Change", options=["Points", "Pips", "Ticks", "% of Price", "ATR", "Average Change", "Standard Deviation", "Absolute"], title="Range Scale")

//Range Period
rng_per = input(defval=14, minval=1, title="Range Period (for ATR, Average Change, and Standard Deviation)")

//Range Smoothing Inputs
smooth_range = input(defval=true, title="Smooth Range")
smooth_per   = input(defval=27, minval=1, title="Smoothing Period")

//Filter Value Averaging Inputs
av_vals    = input(defval=true, title="Average Filter Changes")
av_samples = input(defval=2, minval=1, title="Number Of Changes To Average")

// New inputs for take profit and stop loss
take_profit_percent = input(defval=100.0, minval=0.1, maxval=1000.0, title="Take Profit Percentage", step=0.1)
stop_loss_percent = input(defval=100, minval=0.1, maxval=1000.0, title="Stop Loss Percentage", step=0.1)

//-----------------------------------------------------------------------------------------------------------------------------------------------------------------
//Definitions
//-----------------------------------------------------------------------------------------------------------------------------------------------------------------

//High And Low Values
h_val = mov_src=="Wicks" ? high : close
l_val = mov_src=="Wicks" ? low : close

//Range Filter Values
[h_band, l_band, filt] = rng_filt(h_val, l_val, rng_size((h_val + l_val)/2, rng_scale, rng_qty, rng_per), rng_per, f_type, smooth_range, smooth_per, av_vals, av_samples)

//Direction Conditions
var fdir = 0.0
fdir    := filt > filt[1] ? 1 : filt < filt[1] ? -1 : fdir
upward   = fdir==1 ? 1 : 0
downward = fdir==-1 ? 1 : 0

//Colors
filt_color = upward ? #05ff9b : downward ? #ff0583 : #cccccc
bar_color  = upward and (close > filt) ? (close > close[1] ? #05ff9b : #00b36b) :
             downward and (close < filt) ? (close < close[1] ? #ff0583 : #b8005d) : #cccccc

//-----------------------------------------------------------------------------------------------------------------------------------------------------------------
//Outputs
//-----------------------------------------------------------------------------------------------------------------------------------------------------------------

//Filter Plot
filt_plot = plot(filt, color=filt_color, transp=0, linewidth=3,  title="Filter")

//Band Plots
h_band_plot = plot(h_band, color=#05ff9b, transp=100, title="High Band")
l_band_plot = plot(l_band, color=#ff0583, transp=100, title="Low Band")

//Band Fills
fill(h_band_plot, filt_plot, color=#00b36b, transp=85, title="High Band Fill")
fill(l_band_plot, filt_plot, color=#b8005d, transp=85, title="Low Band Fill")

//Bar Color
barcolor(bar_color)

//External Trend Output
plot(fdir, transp=100, editable=false, display=display.none, title="External Output - Trend Signal")

// Trading Conditions Logic
longCond = close > filt and close > close[1] and upward > 0 or close > filt and close < close[1] and upward > 0 
shortCond = close < filt and close < close[1] and downward > 0 or close < filt and close > close[1] and downward > 0

CondIni = 0
CondIni := longCond ? 1 : shortCond ? -1 : CondIni[1]
longCondition = longCond and CondIni[1] == -1
shortCondition = shortCond and CondIni[1] == 1

// Strategy Entry and Exit
strategy.entry("Buy", strategy.long, when = longCondition)
strategy.entry("Sell", strategy.short, when = shortCondition)

// New: Close conditions based on percentage change
long_take_profit_condition = close > strategy.position_avg_price * (1 + take_profit_percent / 100)
short_take_profit_condition = close < strategy.position_avg_price * (1 - take_profit_percent / 100)

long_stop_loss_condition = close < strategy.position_avg_price * (1 - stop_loss_percent / 100)
short_stop_loss_condition = close > strategy.position_avg_price * (1 + stop_loss_percent / 100)

strategy.close("Buy", when = shortCondition or long_take_profit_condition or long_stop_loss_condition)
strategy.close("Sell", when = longCondition or short_take_profit_condition or short_stop_loss_condition)

// Plot Buy and Sell Labels
plotshape(longCondition, title = "Buy Signal", text ="BUY", textcolor = color.white, style=shape.labelup, size = size.normal, location=location.belowbar, color = color.green, transp = 0)
plotshape(shortCondition, title = "Sell Signal", text ="SELL", textcolor = color.white, style=shape.labeldown, size = size.normal, location=location.abovebar, color = color.red, transp = 0)

// Alerts
alertcondition(longCondition, title="Buy Alert", message = "BUY")
alertcondition(shortCondition, title="Sell Alert", message = "SELL")


もっと