Strategi Pelacakan Tren Filter Dual Range

Penulis:ChaoZhang, Tanggal: 2024-02-05 11:15:28
Tag:

img

Gambaran umum

Strategi Pelacakan Tren Dual Range Filter adalah strategi perdagangan kuantitatif yang memanfaatkan penyaringan rentang EMA ganda untuk mengidentifikasi arah tren dan melacak tren.

Logika Strategi

Inti dari strategi ini adalah penyaringan kisaran EMA ganda. Ini menghitung kisaran ATR lilin dan meluruskannya, kemudian menggunakan dua EMA untuk menemukan posisi lilin dalam kisaran untuk menentukan apakah saat ini dalam tren. Ketika harga menembus kisaran, itu menandakan perubahan tren.

Secara khusus, strategi pertama menghitung ukuran kisaran ATR dari candlesticks, dan kemudian meratakan dengan dua EMA. Kisaran ATR mewakili kisaran fluktuasi normal candlesticks. Ketika harga melebihi kisaran ini, itu berarti perubahan dalam tren telah terjadi. Strategi mencatat arah ketika harga menembus kisaran EMA. Ketika arah berubah, itu berarti pembalikan tren telah terjadi, dan saat itulah ia dapat memilih untuk memasuki pasar.

Setelah memasuki pasar, strategi menggunakan stop loss mengambang untuk mengunci keuntungan. Selama periode penyimpanan, terus-menerus menilai apakah candlestick telah jatuh kembali di luar kisaran. Jika pullback terjadi, itu akan keluar dari posisi saat ini. Ini dapat secara efektif mengunci keuntungan dari perdagangan tren.

Analisis Keuntungan

Strategi Pelacakan Tren Dual Range Filter menggabungkan keuntungan dari penyaringan rata-rata bergerak dan perhitungan kisaran untuk menentukan arah tren dengan akurat dan menghindari sering memasuki dan keluar dari pasar di pasar kisaran. Keuntungan spesifik adalah:

  1. Menggunakan prinsip ATR untuk menilai rentang fluktuasi lilin, menghindari memasuki pasar tanpa arah selama rentang pasar
  2. Filter EMA ganda meningkatkan akurasi penilaian dan mengurangi sinyal palsu
  3. Real-time floating stop loss dapat secara efektif mengunci keuntungan tren
  4. Logika strategi yang sederhana dan jelas, mudah dipahami dan dioptimalkan

Analisis Risiko

Ada juga beberapa risiko dengan strategi ini, terutama dalam aspek berikut:

  1. Celah besar dapat menembus rentang ATR, sehingga masuk lebih awal
  2. Di pasar dengan tren yang kuat, stop loss dapat diaktifkan secara prematur
  3. Pengaturan parameter yang tidak benar juga mempengaruhi kinerja strategi

Untuk mengatasi risiko ini, metode seperti mengoptimalkan parameter dengan tepat, mencegah pecah palsu, menilai kekuatan tren dapat digunakan untuk menyelesaikannya.

Saran Optimalisasi

Strategi Pelacakan Tren Filter Dual Range juga memiliki potensi untuk optimasi lebih lanjut, dengan arah optimasi utama termasuk:

  1. Mengoptimalkan parameter ATR untuk merata rentang fluktuasi candlestick
  2. Masukkan indikator volume untuk menghindari pecah palsu
  3. Pertimbangkan kekuatan tren untuk membedakan satu kali pecah dan tren berkelanjutan
  4. Mengoptimalkan harga stop loss untuk melacak tren panjang sambil memastikan keuntungan

Melalui optimasi ini, strategi dapat mencapai keuntungan yang stabil di lebih banyak lingkungan pasar.

Ringkasan

Strategi Pelacakan Tren Dual Range Filter mengintegrasikan berbagai keuntungan dari penyaringan rata-rata bergerak dan penilaian rentang ATR, dan dapat secara efektif mengidentifikasi arah dan waktu masuk tren jangka menengah hingga jangka panjang yang berkelanjutan. Ini hanya memasuki pasar ketika tren berubah, dan menggunakan stop loss mengambang untuk mengunci keuntungan. Strategi ini memiliki logika yang sederhana dan jelas dan sangat cocok untuk perdagangan tren jangka menengah hingga panjang. Melalui optimasi terus-menerus parameter dan aturan penilaian, strategi ini dapat mencapai pengembalian yang baik di berbagai pasar.


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


Lebih banyak