Stratégie de croisement de l'angle de tendance et de la moyenne mobile

Auteur:ChaoZhang est là., Date: 2024-01-25 14h35
Les étiquettes:

img

Résumé

Cette stratégie détermine la direction de la tendance en calculant l'angle de pente des moyennes mobiles, combiné à l'indicateur du taux de variation des prix pour les transactions longues et courtes.

La logique de la stratégie

La stratégie repose principalement sur les indicateurs suivants:

  1. Angle de pente de la moyenne mobile: Calculer les angles de pente de la moyenne mobile de Jurik et de la moyenne mobile exponentielle pour déterminer la direction de la tendance des prix.

  2. Taux de variation des prix: Calcule le taux de variation du prix de clôture sur les 12 dernières barres pour filtrer les signaux par volatilité.

Lorsque la pente de la moyenne mobile monte (plus grande que 0) et que le taux de variation des prix répond aux critères, passez à la vente. Lorsque la pente descend (moins de 0) et que le taux de variation des prix répond aux critères, passez à la vente.

Analyse des avantages

Les avantages de cette stratégie:

  1. Utiliser la pente MA pour déterminer la tendance est très fiable avec un bon taux de gain.

  2. L'indicateur du taux de variation des prix filtre efficacement les fluctuations de la fourchette afin d'éviter les transactions invalides.

  3. Jurik MA offre une réponse rapide à l'évolution de la tendance tandis que l'EMA offre un jugement stable de la tendance, les deux étant complémentaires.

  4. Aller à la fois long et court sur le marché tendance pourrait capturer un plus grand profit.

Analyse des risques

Quelques risques de cette stratégie:

  1. Dans les cas extrêmes, MA peut générer des signaux erronés. Cela peut être réduit par l'optimisation des paramètres.

  2. Les signaux peuvent changer fréquemment pendant la gamme, ce qui entraîne des transactions inutiles.

  3. Un stop loss plus large peut être utilisé.

Directions d'optimisation

La stratégie peut être optimisée dans les aspects suivants:

  1. Optimiser les paramètres MA pour trouver la meilleure combinaison de paramètres améliorant la stabilité.

  2. Ajouter la volatilité, les filtres de volume, etc. pour réduire davantage les transactions invalides.

  3. Incorporer d'autres indicateurs pour un positionnement stop loss plus intelligent.

  4. Développer des algorithmes adaptatifs de dimensionnement des positions pour une rentabilité plus stable.

Conclusion

Dans l'ensemble, il s'agit d'une stratégie de suivi de tendance très pratique. Elle détermine de manière fiable la tendance en utilisant l'angle de pente MA et filtre efficacement les signaux de bruit en utilisant l'indicateur de taux de variation de prix. Prendre des positions longues et courtes pourrait générer de bons profits. Avec des optimisations continues, cette stratégie peut devenir une stratégie quantitative très stable et fiable.


/*backtest
start: 2023-12-01 00:00:00
end: 2023-12-31 23:59:59
period: 1d
basePeriod: 1h
exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}]
*/

//@version=4
// Based on ma angles code by Duyck which also uses Everget Jurik MA calulation and angle calculation by KyJ
strategy("Trend Angle BF", overlay=false)

/////////////// Time Frame ///////////////
testStartYear = input(2017, "Backtest Start Year") 
testStartMonth = input(1, "Backtest Start Month")
testStartDay = input(1, "Backtest Start Day")
testPeriodStart = timestamp(testStartYear,testStartMonth,testStartDay, 0, 0)

testStopYear = input(2019, "Backtest Stop Year")
testStopMonth = input(12, "Backtest Stop Month")
testStopDay = input(31, "Backtest Stop Day")
testPeriodStop = timestamp(testStopYear,testStopMonth,testStopDay, 0, 0)

testPeriod() => true
    
src=input(ohlc4,title="source")

// definition of "Jurik Moving Average", by Everget
jma(_src,_length,_phase,_power) =>
    phaseRatio = _phase < -100 ? 0.5 : _phase > 100 ? 2.5 : _phase / 100 + 1.5
    beta = 0.45 * (_length - 1) / (0.45 * (_length - 1) + 2)
    alpha = pow(beta, _power)
    jma = 0.0
    e0 = 0.0
    e0 := (1 - alpha) * _src + alpha * nz(e0[1])
    e1 = 0.0
    e1 := (_src - e0) * (1 - beta) + beta * nz(e1[1])
    e2 = 0.0
    e2 := (e0 + phaseRatio * e1 - nz(jma[1])) * pow(1 - alpha, 2) + pow(alpha, 2) * nz(e2[1])
    jma := e2 + nz(jma[1])

//// //// Determine Angle by KyJ //// //// 
angle(_src) =>
    rad2degree=180/3.14159265359  //pi 
    ang=rad2degree*atan((_src[0] - _src[1])/atr(14)) 

jma_line=jma(src,10,50,1)
ma=ema(src,input(56))
jma_slope=angle(jma_line)
ma_slope=angle(ma)

///////////// Rate Of Change ///////////// 
source = close
roclength = input(12, minval=1)
pcntChange = input(2, minval=1)
roc = 100 * (source - source[roclength]) / source[roclength]
emaroc = ema(roc, roclength / 2)
isMoving() => emaroc > (pcntChange / 2) or emaroc < (0 - (pcntChange / 2))

/////////////// Strategy ///////////////
long = ma_slope>=0 and isMoving()
short = ma_slope<=0 and isMoving()

last_long = 0.0
last_short = 0.0
last_long := long ? time : nz(last_long[1])
last_short := short ? time : nz(last_short[1])

long_signal = crossover(last_long, last_short)
short_signal = crossover(last_short, last_long)

last_open_long_signal = 0.0
last_open_short_signal = 0.0
last_open_long_signal := long_signal ? open : nz(last_open_long_signal[1])
last_open_short_signal := short_signal ? open : nz(last_open_short_signal[1])

last_long_signal = 0.0
last_short_signal = 0.0
last_long_signal := long_signal ? time : nz(last_long_signal[1])
last_short_signal := short_signal ? time : nz(last_short_signal[1])

in_long_signal = last_long_signal > last_short_signal
in_short_signal = last_short_signal > last_long_signal

last_high = 0.0
last_low = 0.0
last_high := not in_long_signal ? na : in_long_signal and (na(last_high[1]) or high > nz(last_high[1])) ? high : nz(last_high[1])
last_low := not in_short_signal ? na : in_short_signal and (na(last_low[1]) or low < nz(last_low[1])) ? low : nz(last_low[1])
sl_inp = input(2.0, title='Stop Loss %') / 100
tp_inp = input(900.0, title='Take Profit %') / 100 
 
take_level_l = strategy.position_avg_price * (1 + tp_inp)
take_level_s = strategy.position_avg_price * (1 - tp_inp) 

since_longEntry = barssince(last_open_long_signal != last_open_long_signal[1]) 
since_shortEntry = barssince(last_open_short_signal != last_open_short_signal[1]) 

slLong = in_long_signal ? strategy.position_avg_price * (1 - sl_inp) : na
slShort = strategy.position_avg_price * (1 + sl_inp)
long_sl = in_long_signal ? slLong : na
short_sl = in_short_signal ? slShort : na

/////////////// Execution /////////////// 
if testPeriod()
    strategy.entry("Long",  strategy.long, when=long)
    strategy.entry("Short", strategy.short, when=short)
    strategy.exit("Long Ex", "Long", stop=long_sl, limit=take_level_l, when=since_longEntry > 0)
    strategy.exit("Short Ex", "Short", stop=short_sl, limit=take_level_s, when=since_shortEntry > 0)
    
///////////// Plotting /////////////
hline(0, title='Zero line', color=color.purple, linewidth=1)
plot(ma_slope,title="ma slope", linewidth=2,color=ma_slope>=0?color.lime:color.red)
bgcolor(isMoving() ? long ? color.green : short ? color.red : na : color.white, transp=80)
bgcolor(long_signal ? color.lime : short_signal ? color.red : na, transp=30) 


Plus de