듀얼 레인지 필터 트렌드 추적 전략

저자:차오장, 날짜: 2024-02-05 11:15:28
태그:

img

전반적인 설명

듀얼 레인지 필터 트렌드 추적 전략은 트렌드 방향을 파악하고 트렌드를 추적하기 위해 듀얼 EMA 범위 필터를 활용하는 양적 거래 전략이다. 이 전략은 중장기 트렌드 방향을 효과적으로 인식하고 후속 스톱 로스로 이익을 잠금하기 위해 듀얼 이동 평균 필터링과 ATR 범위 계산을 결합합니다.

전략 논리

이 전략의 핵심은 이중 EMA 범위 필터링이다. 촛불의 ATR 범위를 계산하고 평평화한 다음 두 개의 EMA를 사용하여 촛불의 위치를 범위에 위치하여 현재 추세인지 여부를 결정합니다. 가격이 범위를 넘어서면 트렌드의 변화를 신호합니다.

구체적으로, 전략은 먼저 촛불의 ATR 범위 크기를 계산하고, 두 개의 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")


더 많은