Стратегия отслеживания тенденций фильтров двойного диапазона

Автор:Чао Чжан, Дата: 2024-02-05 11:15:28
Тэги:

img

Обзор

Стратегия Dual Range Filter Trend Tracking - это количественная стратегия торговли, которая использует двойную фильтрацию диапазона EMA для определения направления тренда и отслеживания тенденций.

Логика стратегии

Ядром этой стратегии является двойная EMA диапазон фильтрации. Он рассчитывает диапазон ATR свечей и сглаживает его, затем использует две EMA для определения позиции свечей в диапазоне, чтобы определить, находится ли он в настоящее время в тренде. Когда цена проходит через диапазон, это сигнализирует об изменении тренда.

В частности, стратегия сначала рассчитывает размер диапазона ATR свечей, а затем сглаживает его двумя EMA. Диапазон ATR представляет собой нормальный диапазон колебаний свечей. Когда цена превышает этот диапазон, это означает, что произошло изменение тренда. Стратегия записывает направление, когда цена проходит через диапазон EMA. Когда направление меняется, это означает, что произошло изменение тренда, и именно тогда он может выбрать выход на рынок.

После выхода на рынок стратегия использует плавучую стоп-лосс для блокировки прибыли. В течение периода хранения она постоянно оценивает, выпал ли свечник из диапазона. Если произойдет откат, она выйдет из текущей позиции. Это может эффективно блокировать прибыль от торговли трендом.

Анализ преимуществ

Стратегия Dual Range Filter Trend Tracking сочетает в себе преимущества фильтрации скользящей средней и расчета диапазона, чтобы точно определить направление тренда и избежать частого входа и выхода с рынка на рынках с диапазоном.

  1. Использовать принцип ATR для оценки диапазона колебаний свечей, избегает входа на рынок без направления во время диапазона рынка
  2. Двойной фильтр EMA улучшает точность суждения и уменьшает ложные сигналы
  3. Плавающий стоп-лосс в режиме реального времени может эффективно зафиксировать прибыль от тренда
  4. Простая и понятная логика стратегии, легко понятная и оптимизируемая

Анализ рисков

Эта стратегия также сопряжена с некоторыми рисками, главным образом в следующих аспектах:

  1. Большие пробелы могут прорваться через диапазон ATR, что приводит к преждевременному входу
  2. На сильно развивающихся рынках стоп-лосс может быть запущен преждевременно
  3. Неправильные параметры также влияют на эффективность стратегии

Для решения этих рисков могут использоваться такие методы, как надлежащая оптимизация параметров, предотвращение ложных прорывов, оценка силы тренда.

Советы по оптимизации

Стратегия отслеживания тенденций фильтров двойного диапазона также имеет потенциал для дальнейшей оптимизации, основные направления оптимизации включают:

  1. Оптимизировать параметры ATR для сглаживания диапазона колебаний свечей
  2. Включить показатели объема для предотвращения ложных прорывов
  3. Оценить силу тренда для различения разовых прорывов и устойчивых тенденций
  4. Оптимизировать цену стоп-лосса для отслеживания длинных тенденций при одновременном обеспечении прибыли

Благодаря этим оптимизациям стратегия может достигать устойчивой прибыли в большей рыночной среде.

Резюме

Стратегия Dual Range Filter Trend Tracking интегрирует различные преимущества фильтрации скользящей средней и суждения о диапазоне 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")


Больше