Stratégie quantitative d'ordre d'inversion ATR de la zone de momentum


Date de création: 2023-11-24 15:55:36 Dernière modification: 2023-11-24 15:55:36
Copier: 0 Nombre de clics: 646
1
Suivre
1617
Abonnés

Stratégie quantitative d’ordre d’inversion ATR de la zone de momentum

Aperçu

L’idée principale de cette stratégie est de combiner les zones d’énergie dynamique et l’indicateur ATR, de faire plus en cas de fourches dorées et de faire moins en cas de fourches mortes. En même temps, définir des prix d’arrêt et de perte.

Le principe

  1. Les signaux de plus-value sont calculés à l’aide des EMA rapides et des EMA lentes. Une EMA rapide supérieure à une EMA lente est un bullish, et vice versa.
  2. Quand il n’y a pas de place, il y a plus de fourches dorées et moins de fourches mortes.
  3. Une fois la position ouverte, si un signal de retour apparaît, la position actuelle est effacée et une nouvelle position est ouverte dans la direction opposée.
  4. Le prix d’arrêt est ajusté en fonction du canal ATR pour assurer un faible risque d’arrêt.
  5. Lorsque le prix entre dans la zone de surachat et de survente, le prix d’arrêt est ajusté au prix le plus élevé ou le prix le plus bas de la dernière ligne K pour éviter d’être piégé.

Les avantages

  1. La combinaison des zones d’énergie dynamique et de l’ATR permet d’ouvrir des positions en cours de tendance et de mettre en place des arrêts de perte.
  2. La fonction d’ordre inversé permet de changer rapidement de direction lorsque le prix est inversé, en profitant des fluctuations bidirectionnelles des prix pour obtenir des rendements plus élevés.
  3. Le mécanisme d’arrêt des pertes ATR permet de contrôler efficacement le risque d’arrêt individuel et de réaliser un taux de victoire élevé dans l’ensemble.
  4. Il est important de ne pas être pris au dépourvu par des événements imprévus.

Risques et solutions

  1. Les ordres inversés peuvent être négociés trop fréquemment dans des conditions de choc, augmentant les coûts de transaction et la probabilité d’arrêt des pertes.
    • Solution: augmenter la période de détention minimale et réduire le renversement en cas de choc.
  2. Les variations de l’ATR peuvent augmenter ou diminuer la portée du stop loss.
    • Solution: Ajustez la distance d’arrêt en temps réel en fonction de la valeur ATR.
  3. Une mauvaise configuration des paramètres peut entraîner une fréquence de transaction trop élevée ou une mauvaise efficacité du signal.
    • Solution: Choisir un ensemble de paramètres raisonnables en fonction des différentes variétés.

Direction d’optimisation

  1. Optimiser les paramètres pour trouver la meilleure combinaison de paramètres.
  2. Les filtres d’indicateurs techniques auxiliaires ont été ajoutés pour améliorer la qualité du signal.
  3. Ajout d’un module de gestion des fonds pour lier les positions aux actifs totaux du compte.
  4. Ajouter des analyses sur des périodes de temps pour améliorer l’efficacité de la stratégie grâce à plus d’informations.

Résumer

Cette stratégie intègre les avantages des zones d’énergie dynamique et des indicateurs ATR pour des transactions bidirectionnelles efficaces. Un mécanisme de retour d’ordre et un arrêt intelligent ATR permettent de tirer le meilleur parti des fluctuations de prix. La configuration de paramètres optimisés et la combinaison d’un plus grand nombre d’indicateurs peuvent améliorer encore l’efficacité de la stratégie.

Code source de la stratégie
/*backtest
start: 2023-10-24 00:00:00
end: 2023-11-23 00:00:00
period: 1h
basePeriod: 15m
exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}]
*/

// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © fenirlix

//@version=5
// Strategy parameter incl. position size, commission and initial capital
strategy("ACTIONZONE-ATR REVERSEORDER STRATEGY", "ACTIONZONEATR-REVERSEORDER", overlay=true
     )

// User Input Variable
fastMaInput     = input.int(12, "Fast MA Period", minval=2, step=1)
slowMaInput     = input.int(26, "Fast MA Period", minval=2, step=1)

atrLengthInput  = input.int(14, "ATR length", minval=2,step=1)
atrInnerMultInput = input.float(1, "atr inner multiplier", minval=0.1, step=0.1)
atrMidMultInput = input.float(2, "atr inner multiplier", minval=0.1, step=0.1) //***** MOST OF RISK MANAGEMENT LOGIC BASE ON THIS INPUT *****//
atrOuterMultInput = input.float(3, "atr inner multiplier", minval=0.1, step=0.1)

// Backtesting Date range
startYearInput      = input.int(2021, "Start Year", minval=1900, maxval=2100, step=1)
startMonthInput     = input.int(12, "Start Month", minval=1, maxval=12, step=1)
startDateInput      = input.int(1, "Start Day", minval=1, maxval=31, step=1)
setEndRangeInput    = input.bool(false, "Using Specific End Test Date") //Set specific End date or use present(end of candle) data
endYearInput        = input.int(2022, "End Year", minval=1900, maxval=2100, step=1)
endMonthInput       = input.int(1, "End Month", minval=1, maxval=12, step=1)
endDateInput        = input.int(31, "End Day", minval=1, maxval=31, step=1)

startDate = timestamp(syminfo.timezone, startYearInput, startMonthInput, startDateInput)
endDate = timestamp(syminfo.timezone, endYearInput, endMonthInput, endDateInput)
inDateRange = time >= startDate //Set backtest date range to present data
if setEndRangeInput
    inDateRange and time <= endDate //set backtest date range to specific date

// minimum position hold period (to get rid of false signal in sideway trend)
minHoldInput = input.int(8, 'Minimum position Hold Limit', minval=1, maxval=365, step=1) // Set Minimum Position Hold

var bool reverseToLong = false // Assign reverse order operator
var bool reverseToShort = false // Assign reverse order operator

// Indicator Declaration
fastEma = ta.ema(close, fastMaInput)
slowEma = ta.ema(close, slowMaInput)
atr = ta.atr(atrLengthInput)

// Declare trend of asset
isBullish = fastEma > slowEma
isBearish = fastEma <= slowEma

// Record position hold length, to limit minimum hold period(candle)
var int hold_length = 0
if strategy.opentrades > 0 or strategy.opentrades < 0
    hold_length := hold_length + 1
else
    hold_length := 0

// create permanent variable of stop price
var float longStopPrice = na
var float shortStopPrice = na
    
// Chart-Indicator COLOR declaration
REDBEAR     = color.new(color.red, 80)
GREENBULL   = color.new(color.green, 80)

greenLong = isBullish and close > fastEma
yellowLong = isBullish and close < fastEma
blueShort = isBearish and close > fastEma
redShort = isBearish and close < fastEma

// assign oversold, overbought condition(in this case, price over middle atr plus/minus fastEma)
overBand = high[1] > fastEma + (2*atr)
underBand = low[1] < fastEma - (2*atr)

// Strategy

// Main Entry Condition
goLong = isBullish and isBullish[1] == 0
goShort = isBearish and isBearish[1] == 0

inPosition = strategy.position_size != 0
minHoldPeriod = hold_length > minHoldInput ? true : false

// Entry Condition
if not inPosition and inDateRange and barstate.isconfirmed == true //compute after close of the bar to avoid repainting
    if goLong or reverseToLong // Long if longcondition or reverse order receive.
        strategy.entry('long', strategy.long)
        longStopPrice := fastEma - (atr * 2) // Set stop loss price
        reverseToLong := false // Reset reverse order status
    
    else if goShort or reverseToShort
        strategy.entry('short', strategy.short)
        shortStopPrice := fastEma + (atr * 2)
        reverseToShort := false
// Take profit and Set Higher Stop 
if inPosition and minHoldPeriod and barstate.isconfirmed == true // check if we're in position and pass minimum hold period, confirm no repainting
    if strategy.position_size > 0
        // if exit position by Sellcondition(which is the same as ShortCondition), Exit Long position and make Short order(by set reverse order to true)
        strategy.close('long', when=goShort, comment='exitLong(' + str.tostring(hold_length) + ')')
        reverseToShort := true
        if overBand //If overbought condition met, set Stop price to LAST LOW, and not reverse any position
            longStopPrice := low[1]
            reverseToShort := false
    else if strategy.position_size < 0
        strategy.close('short', when=goLong, comment='exitShort(' + str.tostring(hold_length) + ')')
        reverseToLong := true
        if underBand
            shortStopPrice := high[1]
            reverseToLong := false
// Stop Loss and Set calculate stop loss using Atr Channel
if inPosition 
    if strategy.position_size > 0
        if fastEma - (atr * atrMidMultInput) > longStopPrice // set long stop price to the higher of latest long stop price and ATR lower channel
            longStopPrice := fastEma - (atr * atrMidMultInput)
        strategy.exit('Long Stop atr ', 'long', stop=longStopPrice)
    else if strategy.position_size < 0
        if fastEma + (atr * atrMidMultInput) < shortStopPrice
            shortStopPrice := fastEma + (atr * atrMidMultInput)
        strategy.exit('Short Stop atr ', 'short', stop=shortStopPrice)

// Plotting
fastLine = plot(fastEma, title='fast ema line', linewidth=1, color=isBullish ? color.green : color.red)
slowLine = plot(slowEma, title='slow ema line', linewidth=2, color= isBullish? color.green : color.red)
atrUpperLine1 = plot(fastEma + (atr * atrInnerMultInput), title='ATR Upperline1', color=color.new(color.black,85))
atrLowerLine1 = plot(fastEma - (atr * atrInnerMultInput), title='ATR Lowerline1', color=color.new(color.black,85))
atrUpperLine2 = plot(fastEma + (atr * atrMidMultInput), title='ATR Upperline2', color=color.new(color.black,75))
atrLowerLine2 = plot(fastEma - (atr * atrMidMultInput), title='ATR Lowerline2', color=color.new(color.black,75))
atrUpperLine3 = plot(fastEma + (atr * atrOuterMultInput), title='ATR Upperline3', color=color.new(color.black,50))
atrLowerLine3 = plot(fastEma - (atr * atrOuterMultInput), title='ATR Lowerline3', color=color.new(color.black,50))

plot(longStopPrice, color=strategy.position_size > 0 ? color.red : na, linewidth=2)
plot(shortStopPrice, color=strategy.position_size < 0 ? color.red : na, linewidth=2)

//  Filling
fill(fastLine, slowLine, color=isBullish ? GREENBULL : REDBEAR)
fill(atrUpperLine3, atrLowerLine3, color=inPosition and (minHoldInput - hold_length > 0) ? color.new(color.blue,90): na)

barColor = switch
    greenLong => color.green
    yellowLong =>  color.yellow
    blueShort => color.blue
    redShort => color.red
    => color.black
barcolor(color=barColor)

// Fill background to distinguish inactive time(Zulu time)
nightTime = time(timeframe.period, "1500-0100") ? color.new(color.black, 95): na
bgcolor(nightTime)