Stratégie de trading quantitative de croisement de trois moyennes mobiles + indicateur William


Date de création: 2023-09-28 10:58:16 Dernière modification: 2023-09-28 10:58:16
Copier: 1 Nombre de clics: 836
1
Suivre
1621
Abonnés

Aperçu

La stratégie consiste à identifier la direction de la tendance du cours d’une action en combinant trois moyennes mobiles fluctuantes, l’indice relativement faible (RSI) et l’indice William, et à rechercher des opportunités d’entrée lorsque la tendance est inversée. Lorsque les trois moyennes mobiles ascendantes (basses) sont alignées, le RSI est supérieur (inférieur) à 50, et que le signal de l’indice William descend (haut) apparaît, faites plus (vide). Le stop loss est défini comme un certain pourcentage du prix d’entrée, et le stop loss est défini comme un certain pourcentage du prix d’entrée qui se déplace dans la direction favorable.

Principe de stratégie

La stratégie utilise des moyennes mobiles à trois cycles différents, comprenant la ligne rapide, la ligne moyenne et la ligne lente. Lorsque la ligne rapide traverse la ligne moyenne, le cours de l’action est entré dans une tendance à la hausse; lorsque la ligne rapide traverse la ligne moyenne, le prix est entré dans une tendance à la baisse.

Plus précisément, une fois que le cours de l’action est entré dans une tendance à la hausse, la stratégie attend que les cinq conditions suivantes soient réunies avant d’ouvrir des positions supplémentaires:

  1. La ligne rapide, la ligne moyenne et la ligne lente sont toutes vers le haut.
  2. Le RSI est supérieur à 50.
  3. La forme descendante de l’indicateur William;
  4. Le prix des actions a été réduit.
  5. Aucune position actuellement.

Une fois que le cours de l’action est entré dans une tendance à la baisse, la stratégie attend que les cinq conditions suivantes soient réunies pour ouvrir une position en short:

  1. La ligne rapide, la ligne moyenne et la ligne lente sont toutes orientées vers le bas.
  2. Le RSI est inférieur à 50.
  3. La forme ascendante de l’indicateur William;
  4. Le prix de l’action a baissé.
  5. Aucune position actuellement.

Une fois que vous avez effectué un short, la stratégie définit des points d’arrêt et d’arrêt pour contrôler le risque. Plus précisément, le point d’arrêt est un certain pourcentage du prix d’entrée et le point d’arrêt est le prix après que le prix d’entrée se déplace dans la direction favorable.

Avantages stratégiques

  1. La combinaison de plusieurs indicateurs de confirmation d’entrée permet d’éviter efficacement les fausses ruptures. Trois lignes uniformes déterminent la direction de la tendance, l’indicateur William capte les signaux de revers et le RSI filtre les mouvements de choc, ce qui améliore la précision de l’entrée.

  2. Le stop loss permet de bien contrôler le rapport risque/bénéfice de chaque transaction, ce qui garantit que les transactions rentables sont supérieures aux transactions perdantes.

  3. La logique de la stratégie est claire et compréhensible, les paramètres sont raisonnables et conviennent aux traders de tous niveaux.

Risque stratégique

  1. En cas d’oscillation, l’indicateur peut émettre un mauvais signal, entraînant une entrée inutile. Il est possible de filtrer une partie de l’oscillation en optimisant les paramètres du RSI.

  2. Les fausses ruptures peuvent se produire lors de la traversée de la ligne médiane de la ligne rapide et devraient être utilisées en conjonction avec d’autres indicateurs. L’ajout d’un indicateur de trafic peut être envisagé.

  3. Si le stop-loss est trop proche du prix d’entrée, il est possible que le stop-loss soit éliminé. Le paramètre du stop-loss doit être ajusté à la position appropriée.

  4. Si le point d’arrêt est trop éloigné du prix d’entrée, il peut ne pas être possible d’arrêter la sortie, et le point d’arrêt doit être ajusté à la bonne position.

Orientation de l’optimisation de la stratégie

  1. Il est possible de tester des combinaisons de paramètres de différentes périodes, d’optimiser les paramètres des trois moyennes et du RSI.

  2. D’autres indicateurs peuvent être ajoutés, tels que l’indicateur de volume de transaction, pour déterminer si le volume de transaction est important avant la rupture.

  3. Les paramètres de la stratégie peuvent être testés pour différentes variétés.

  4. La courbe des gains peut être tracée en fonction des résultats de la rétro-analyse et les paramètres de stop-loss peuvent être testés.

  5. Il est possible d’essayer de simuler des transactions et d’optimiser les paramètres avant le lancement.

Résumer

L’ensemble de la stratégie est logique, l’utilisation d’une combinaison d’indicateurs pour l’entrée et la sortie peut effectivement contrôler le risque. Il y a beaucoup de place pour l’optimisation des paramètres de la stratégie.

Code source de la stratégie
/*backtest
start: 2023-08-28 00:00:00
end: 2023-09-27 00:00:00
period: 3h
basePeriod: 15m
exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}]
*/

//This script is a combination of 3 smoothed moving averages, and RSI. When moving averages are aligned upward (downward) and RSI is above (below) 50 and a down (up) William fractal appears, it enters long (short) position. Exiting from long and short entries are defined by StopLoss and TargetProfit.

//@version=5

strategy(title="3SmmaCrossUp + Fractal + RSI", overlay=true, default_qty_type=strategy.percent_of_equity, default_qty_value=100, currency=currency.USD, commission_type=strategy.commission.percent, commission_value=0.03)

///////////////////////////////////////////////////////////////////////////////////////////////////////////////// inputs

// Global
src = input(close, title="Source")
stopLoss = input.float(defval = 0.1, title = "Stop Loss %", minval = 0, maxval=100, step = 0.1)
targetProfit = input.float(defval = 0.4, title = "Target Profit %", minval = 0, maxval=100, step = 0.1)

// Smooth Moving Average
fastSmmaLen = input.int(21, minval=1, title="Fast Length", group = "Smooth Moving Average")
midSmmaLen = input.int(50, minval=1, title="Mid Length",group = "Smooth Moving Average")
slowSmmaLen = input.int(200, minval=1, title="Slow Length",group = "Smooth Moving Average")

// RSI
rsiLen = input.int(defval=14, title="length", minval=1, maxval=1000, step=1, group="RSI")

// Fractals
n = input.int(title="Periods", defval=2, minval=2, group = "Fractals")

///////////////////////////////////////////////////////////////////////////////////////////////////////////////// initialization

var waitingFirstTradeInUpwardTrend = false
var waitingFirstTradeInDownwardTrend = false

///////////////////////////////////////////////////////////////////////////////////////////////////////////////// functions

smma(ma, src, len) => 
    smma = 0.0
    smma := na(smma[1]) ? ma : (smma[1] * (len - 1) + src) / len
    smma
    
fractals(n, highs, lows) =>
    // UpFractal
    bool upflagDownFrontier = true
    bool upflagUpFrontier0 = true
    bool upflagUpFrontier1 = true
    bool upflagUpFrontier2 = true
    bool upflagUpFrontier3 = true
    bool upflagUpFrontier4 = true
    for i = 1 to n
        upflagDownFrontier := upflagDownFrontier and (highs[n-i] < highs[n])
        upflagUpFrontier0 := upflagUpFrontier0 and (highs[n+i] < highs[n])
        upflagUpFrontier1 := upflagUpFrontier1 and (highs[n+1] <= highs[n] and highs[n+i + 1] < highs[n])
        upflagUpFrontier2 := upflagUpFrontier2 and (highs[n+1] <= highs[n] and highs[n+2] <= highs[n] and highs[n+i + 2] < highs[n])
        upflagUpFrontier3 := upflagUpFrontier3 and (highs[n+1] <= highs[n] and highs[n+2] <= highs[n] and highs[n+3] <= highs[n] and highs[n+i + 3] < highs[n])
        upflagUpFrontier4 := upflagUpFrontier4 and (highs[n+1] <= highs[n] and highs[n+2] <= highs[n] and highs[n+3] <= highs[n] and highs[n+4] <= highs[n] and highs[n+i + 4] < highs[n])
    flagUpFrontier = upflagUpFrontier0 or upflagUpFrontier1 or upflagUpFrontier2 or upflagUpFrontier3 or upflagUpFrontier4
    
    upFractal = (upflagDownFrontier and flagUpFrontier)
    
    // downFractal
    bool downflagDownFrontier = true
    bool downflagUpFrontier0 = true
    bool downflagUpFrontier1 = true
    bool downflagUpFrontier2 = true
    bool downflagUpFrontier3 = true
    bool downflagUpFrontier4 = true
    
    for i = 1 to n
        downflagDownFrontier := downflagDownFrontier and (lows[n-i] > lows[n])
        downflagUpFrontier0 := downflagUpFrontier0 and (lows[n+i] > lows[n])
        downflagUpFrontier1 := downflagUpFrontier1 and (lows[n+1] >= lows[n] and lows[n+i + 1] > lows[n])
        downflagUpFrontier2 := downflagUpFrontier2 and (lows[n+1] >= lows[n] and lows[n+2] >= lows[n] and lows[n+i + 2] > lows[n])
        downflagUpFrontier3 := downflagUpFrontier3 and (lows[n+1] >= lows[n] and lows[n+2] >= lows[n] and lows[n+3] >= lows[n] and lows[n+i + 3] > lows[n])
        downflagUpFrontier4 := downflagUpFrontier4 and (lows[n+1] >= lows[n] and lows[n+2] >= lows[n] and lows[n+3] >= lows[n] and lows[n+4] >= lows[n] and lows[n+i + 4] > lows[n])
    flagDownFrontier = downflagUpFrontier0 or downflagUpFrontier1 or downflagUpFrontier2 or downflagUpFrontier3 or downflagUpFrontier4
    
    downFractal = (downflagDownFrontier and flagDownFrontier)
    [upFractal, downFractal]

///////////////////////////////////////////////////////////////////////////////////////////////////////////////// calcs

[upFractal, downFractal] = fractals(n, high, low)


rsiIsHigh = ta.rsi(src, rsiLen) >= 50 


slowMa = ta.sma(src, slowSmmaLen)
midMa = ta.sma(src, midSmmaLen)
fastMa = ta.sma(src, fastSmmaLen)

slowSmma = smma(slowMa ,src, slowSmmaLen)
midSmma = smma(midMa, src, midSmmaLen)
fastSmma = smma(fastMa, src, fastSmmaLen)

isFastSmmaUpward = ta.rising(fastSmma, 1)
isMidSmmaUpward = ta.rising(midSmma, 1)
isSlowSmmaUpward = ta.rising(slowSmma, 1)

isFastSmmaDownward = ta.falling(fastSmma, 1)
isMidSmmaDownward = ta.falling(midSmma, 1)
isSlowSmmaDownward = ta.falling(slowSmma, 1)

slowMovingAveragesAreUpward = isMidSmmaUpward and isSlowSmmaUpward
slowMovingAveragesAreDownward = isMidSmmaDownward and isSlowSmmaDownward

justEnteredUpwardTrend = ta.crossover(fastSmma, midSmma) ? true : false
justEnteredDownwardTrend = ta.crossunder(fastSmma, midSmma) ? true : false

waitingFirstTradeInUpwardTrend := justEnteredUpwardTrend == true ? true : (isFastSmmaDownward or isMidSmmaDownward or isSlowSmmaDownward ? false : waitingFirstTradeInUpwardTrend)
waitingFirstTradeInDownwardTrend := justEnteredDownwardTrend == true ? true : (isFastSmmaUpward or isMidSmmaUpward or isSlowSmmaUpward ? false : waitingFirstTradeInDownwardTrend)

priceCrossedOverSlowMa = ta.crossover(close, slowSmma)
priceCrossedUnderSlowMa = ta.crossunder(close, slowSmma)

enterLongCondition = barstate.isconfirmed and low > fastSmma and rsiIsHigh and (downFractal or priceCrossedOverSlowMa) and waitingFirstTradeInUpwardTrend and strategy.position_size == 0

enterShortCondition = barstate.isconfirmed and high < fastSmma and (not rsiIsHigh) and (upFractal or priceCrossedUnderSlowMa) and waitingFirstTradeInDownwardTrend and strategy.position_size == 0

///////////////////////////////////////////////////////////////////////////////////////////////////////////////// strategy

if(enterLongCondition)
    strategy.entry(id="L", direction=strategy.long)
    waitingFirstTradeInUpwardTrend := false

if(enterShortCondition)
    strategy.entry(id="S", direction=strategy.short)
    waitingFirstTradeInDownwardTrend := false
    
if(strategy.position_size > 0)
    strategy.exit(id="EL", stop=strategy.position_avg_price * (1 - stopLoss/100), limit=strategy.position_avg_price * (1+targetProfit/100)) 
if(strategy.position_size < 0)
    strategy.exit(id="ES", stop=strategy.position_avg_price * (1 + stopLoss/100), limit=strategy.position_avg_price * (1-targetProfit/100)) 

///////////////////////////////////////////////////////////////////////////////////////////////////////////////// plots

plot(series = slowSmma, title="Slow SMMA", linewidth=3)
plot(series = midSmma, title="Mid SMMA", linewidth=2)
plot(series = fastSmma, title="Fast SMMA", linewidth=1)
plotchar(series=rsiIsHigh, title='rsiIsHigh', char='')
plotchar(series=justEnteredUpwardTrend, title='justEnteredUpwardTrend', char='')
plotchar(series=justEnteredDownwardTrend, title='justEnteredDownwardTrend', char='')
plotchar(series=waitingFirstTradeInUpwardTrend, title='waitingFirstTradeInUpwardTrend', char='')
plotchar(series=waitingFirstTradeInDownwardTrend, title='waitingFirstTradeInDownwardTrend', char='')
plotchar(series=enterLongCondition, title='enterLongCondition' , char='')
plotchar(series=enterShortCondition, title='enterShortCondition' , char='')
plotshape(series=upFractal, title='upFractal', style=shape.triangleup, location=location.abovebar, color=#009688, size = size.tiny)
plotshape(series=downFractal, title='downFractal', style=shape.triangledown, location=location.belowbar, color=color.red, size = size.tiny)