Stratégie de suivi de tendance avec filtre à double plage


Date de création: 2024-02-05 11:15:28 Dernière modification: 2024-02-05 11:15:28
Copier: 1 Nombre de clics: 585
1
Suivre
1617
Abonnés

Stratégie de suivi de tendance avec filtre à double plage

Aperçu

La stratégie de suivi de tendance à double filtrage de gamme est une stratégie de trading quantitative qui utilise un filtre à double gamme EMA pour identifier la direction de la tendance et suivre la tendance. La stratégie, combinée à un filtre à double ligne égale et à un calcul de gamme ATR, permet d’identifier efficacement la direction de la tendance à la ligne moyenne et longue et d’utiliser le suivi des arrêts de perte pour bloquer les bénéfices.

Principe de stratégie

Le cœur de cette stratégie est le double filtrage de la gamme EMA. Il calcule la gamme ATR de la ligne K et la règle, puis combine les deux EMA pour localiser la ligne K dans la gamme et déterminer si elle est actuellement dans la tendance.

En particulier, la stratégie calcule d’abord la taille de la plage ATR de la ligne K, puis la combine avec deux EMA pour l’aplanir. La plage ATR représente la zone de fluctuation normale de la ligne K. Lorsque le prix dépasse cette zone, cela signifie un changement de tendance. La stratégie enregistre la direction de la rupture de la plage EMA.

Après l’entrée, la stratégie utilise un stop-loss flottant pour verrouiller les bénéfices. Pendant la tenue, elle détermine en temps réel si la ligne K est reléguée au-delà de la portée et quitte la position actuelle si elle est reléguée. Cela peut effectivement verrouiller les bénéfices de la négociation de tendance.

Analyse des avantages

La stratégie de suivi des tendances à double gamme de filtrage combine les avantages du filtrage homogène et du calcul de la gamme pour déterminer avec précision la direction de la tendance et éviter les entrées et sorties fréquentes dans des conditions de choc. Les avantages spécifiques sont les suivants:

  1. Utilisez le principe de l’ATR pour déterminer la gamme de fluctuations de la ligne K et éviter d’entrer dans le jeu sans direction dans un marché en crise
  2. Les filtres doubles EMA améliorent l’exactitude des jugements et réduisent les faux signaux
  3. Le stop-loss flottant en temps réel permet de localiser efficacement les gains de tendance
  4. La logique de la stratégie est simple, claire, facile à comprendre et à optimiser

Analyse des risques

Cette stratégie comporte également des risques, principalement liés aux aspects suivants:

  1. Les sauts en hauteur peuvent dépasser la portée de l’ATR et entraîner une entrée anticipée.
  2. Les stop loss pourraient être déclenchés trop tôt dans une tendance forte
  3. Une mauvaise configuration des paramètres peut également affecter les performances de la stratégie

Pour ces risques, il est possible d’utiliser des méthodes telles que l’optimisation appropriée des paramètres, la prévention des faux-bouts et la détermination de la force de la tendance.

Conseils d’optimisation

Les stratégies de suivi des tendances à double filtrage ont également le potentiel d’être optimisées davantage. Les principaux axes d’optimisation sont les suivants:

  1. Optimisation des paramètres ATR pour lisser la gamme de fluctuations de la ligne K
  2. Éviter les fausses ruptures en combinant les indicateurs de volume des transactions
  3. Déterminer la force de la tendance et distinguer les ruptures ponctuelles des tendances durables
  4. Optimiser le point de rupture pour suivre la tendance à la hausse tout en garantissant des bénéfices

Grâce à ces optimisations, les stratégies peuvent obtenir des rendements stables dans un environnement de marché plus large.

Résumer

La stratégie de suivi des tendances à double gamme de filtrage intègre les multiples avantages du filtrage homogène et du jugement de gamme ATR, permettant d’identifier efficacement la direction et le moment d’entrée d’une tendance durable à mi-longue ligne. Elle n’entre en jeu que lorsque la tendance change et utilise les arrêts flottants pour bloquer les bénéfices. La logique de la stratégie est simple et claire et convient parfaitement au trading de tendances à mi-longue ligne.

Code source de la stratégie
/*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")