La stratégie de négociation quantitative du MACD inverse à double voie ergotique

Auteur:ChaoZhang est là., Date: 2023-12-21 11h07 et 51 min
Les étiquettes:

img

Résumé

Cette stratégie est une stratégie de trading quantitative MACD inverse à double rails. Elle s'appuie sur les indicateurs techniques décrits par William Blau dans son livre Momentum, Direction and Divergence et les élargit.

Principaux

L'indicateur de base de cette stratégie est le MACD. Il calcule la moyenne mobile rapide EMA® et la moyenne mobile lente EMA ((slowMALen), puis calcule leur différence xmacd. Il calcule également l'EMA ((signalLength) de xmacd pour obtenir xMA_MACD. Un signal long est déclenché lorsque xmacd traverse au-dessus de xMA_MACD, et un signal court est déclenché sur un croisement en dessous. L'aspect clé de cette stratégie est les signaux de trading inversés, c'est-à-dire que la relation entre xmacd et xMA_MACD est opposée à celle de l'indicateur MACD conventionnel, d'où vient également le nom Reverse MACD.

En outre, la stratégie intègre des filtres de tendance. Lorsqu'un signal long s'allume, si le filtre de tendance haussière est configuré, il vérifiera si le prix augmente. De même, le signal court vérifie une tendance à la baisse des prix.

Analyse des avantages

Le plus grand avantage de cette stratégie est les puissantes capacités de backtesting. Vous pouvez choisir différents instruments de trading, définir le délai de backtest et optimiser les paramètres de stratégie basés sur des données d'instruments spécifiques. Par rapport à une stratégie MACD simple, elle intègre une analyse de tendance et de surachat/survente pour filtrer certains signaux identiques. Le MACD inverse à double rails est différent du MACD traditionnel, lui permettant de capitaliser sur certaines opportunités que le MACD traditionnel peut manquer.

Analyse des risques

Le risque principal de cette stratégie provient de la logique de négociation inverse. Bien que les signaux inversés puissent capturer certaines opportunités manquées par les signaux traditionnels, cela signifie également perdre certains points d'entrée MACD conventionnels, nécessitant une évaluation minutieuse.

Pour atténuer les risques, les paramètres peuvent être optimisés - en ajustant les longueurs de moyenne mobile; en combinant les tendances et les filtres d'indicateurs, on évite les signaux sur les marchés agités; en augmentant les distances de stop loss, on assure des pertes plafonnées sur les transactions individuelles.

Directions d'optimisation

La stratégie peut être améliorée sous plusieurs aspects:

  1. Ajustez les paramètres des rails rapides et lents, optimisez les longueurs moyennes mobiles, testez en arrière pour trouver des ensembles de paramètres optimaux pour des instruments spécifiques
  2. Ajoutez ou ajustez des filtres de tendance, jugez à partir des résultats des backtests si cela améliore le rendement
  3. Testez différents mécanismes de stop loss, fixes ou à retardement, pour déterminer le meilleur
  4. Essayez de combiner d'autres indicateurs comme KD, Bollinger Bands pour définir des conditions de filtrage supplémentaires et assurer la qualité du signal

Résumé

La stratégie quantitative MACD inverse à double rails s'appuie sur l'indicateur MACD classique avec des extensions et des améliorations. Avec des configurations de paramètres flexibles, des choix de filtres abondants et une fonctionnalité de backtesting puissante, elle peut être ajustée pour s'adapter à différents instruments de trading. C'est donc une stratégie de trading quantitative intrigante et prometteuse digne d'une exploration plus approfondie.


/*backtest
start: 2023-11-20 00:00:00
end: 2023-12-20 00:00:00
period: 1h
basePeriod: 15m
exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}]
*/

//@version = 3
////////////////////////////////////////////////////////////
//  Copyright by HPotter v1.0 09/12/2016
// This is one of the techniques described by William Blau in his book
// "Momentum, Direction and Divergence" (1995). If you like to learn more,
// we advise you to read this book. His book focuses on three key aspects
// of trading: momentum, direction and divergence. Blau, who was an electrical
// engineer before becoming a trader, thoroughly examines the relationship 
// between price and momentum in step-by-step examples. From this grounding,
// he then looks at the deficiencies in other oscillators and introduces some
// innovative techniques, including a fresh twist on Stochastics. On directional 
// issues, he analyzes the intricacies of ADX and offers a unique approach to help 
// define trending and non-trending periods.
// Blau`s indicator is like usual MACD, but it plots opposite of meaningof
// stndard MACD indicator. 
//
// You can change long to short in the Input Settings
// Please, use it only for learning or paper trading. Do not for real trading.
//
//
// 2018-09 forked by Khalid Salomão
// - Backtesting
// - Added filters: RSI, MFI, Price trend
// - Trailing Stop Loss
// - Other minor adjustments
//
////////////////////////////////////////////////////////////
strategy(title="Ergotic MACD Backtester [forked from HPotter]", shorttitle="Ergotic MACD Backtester", overlay=true, pyramiding=0, default_qty_type=strategy.cash, default_qty_value=25000, initial_capital=50000, commission_type=strategy.commission.percent, commission_value=0.15, slippage=3)


// === BACKTESTING: INPUT BACKTEST RANGE ===
source = input(close)
strategyType = input(defval="Long Only", options=["Long & Short", "Long Only", "Short Only"])

FromMonth = input(defval = 7, title = "From Month", minval = 1, maxval = 12)
FromDay   = input(defval = 1, title = "From Day", minval = 1, maxval = 31)
FromYear  = input(defval = 2018, title = "From Year", minval = 2017)
ToMonth   = input(defval = 12, title = "To Month", minval = 1, maxval = 12)
ToDay     = input(defval = 1, title = "To Day", minval = 1, maxval = 31)
ToYear    = input(defval = 2030, title = "To Year", minval = 2017)

start     = timestamp(FromYear, FromMonth, FromDay, 00, 00)  
finish    = timestamp(ToYear, ToMonth, ToDay, 23, 59)        
window()  => true // window of time verification

// === STRATEGY ===

r = input(144, minval=1, title="R (32,55,89,100,144,200)") // default 32
slowMALen = input(6, minval=1) // default 32
signalLength = input(6, minval=1)
reverse = input(false, title="Trade reverse (long/short switch)")

//hline(0, color=blue, linestyle=line)

fastMA = ema(source, r)
slowMA = ema(source, slowMALen)
xmacd = fastMA - slowMA
xMA_MACD = ema(xmacd, signalLength)

pos = 0
pos := iff(xmacd < xMA_MACD, 1,
	   iff(xmacd > xMA_MACD, -1, nz(pos[1], 0))) 
possig = 0
possig := iff(reverse and pos == 1, -1,
          iff(reverse and pos == -1, 1, pos))

// === FILTER: price trend ====
trending_price_long = input(true, title="Long only if price has increased" )
trending_price_short = input(false, title="Short only if price has decreased" )
trending_price_length = input( 2, minval=1 )
trending_price_with_ema = input( false )
trending_price_ema = input( 3, minval=1 )
price_trend = trending_price_with_ema ? ema(source, trending_price_ema) : source
priceLongTrend() => (trending_price_long ? rising(price_trend, trending_price_length) : true)
priceShortTrend() => (trending_price_short ? falling(price_trend, trending_price_length) : true)

// === FILTER: RSI ===
rsi_length = input( 14, minval=1 )
rsi_overSold = input( 14, minval=0, title="RSI Sell Cutoff (Sell only if >= #)" )
rsi_overBought = input( 82, minval=0, title="RSI Buy Cutoff (Buy only if <= #)" )

vrsi = rsi(source, rsi_length)
rsiOverbought() => vrsi > rsi_overBought
rsiOversold() => vrsi < rsi_overSold

trending_rsi_long = input(false, title="Long only if RSI has increased" )
trending_rsi_length = input( 2 )
rsiLongTrend() => trending_rsi_long ? rising(vrsi, trending_rsi_length) : true

// === FILTER: MFI ===
mfi_length = input(14, minval=1)
mfi_lower = input(14, minval=0, maxval=50)
mfi_upper = input(82, minval=50, maxval=100)
upper_s = sum(volume * (change(source) <= 0 ? 0 : source), mfi_length)
lower_s = sum(volume * (change(source) >= 0 ? 0 : source), mfi_length)
mf = rsi(upper_s, lower_s)

mfiOverbought() => (mf > mfi_upper)
mfiOversold() => (mf < mfi_lower)

trending_mfi_long = input(false, title="Long only if MFI has increased" )
trending_mfi_length = input( 2 )
mfiLongTrend() => trending_mfi_long ? rising(mf, trending_mfi_length) : true

// === SIGNAL CALCULATION ===
long  = window() and possig == 1 and rsiLongTrend() and mfiLongTrend() and not rsiOverbought() and not mfiOverbought() and priceLongTrend()
short = window() and possig == -1 and not rsiOversold() and not mfiOversold() and priceShortTrend()

// === trailing stop
tslSource=input(hlc3,title="TSL source")
//suseCurrentRes = input(true, title="Use current chart resolution for stop trigger?")
tslResolution = input(title="Use different timeframe for stop trigger? Uncheck box above.", defval="5")
tslTrigger = input(3.0) / 100
tslStop = input(0.6) / 100

currentPrice = request.security(syminfo.tickerid, tslResolution, tslSource, barmerge.gaps_off, barmerge.lookahead_off)

isLongOpen = false
isLongOpen := nz(isLongOpen[1], false)
entryPrice=0.0
entryPrice:= nz(entryPrice[1], 0.0)
trailPrice=0.0
trailPrice:=nz(trailPrice[1], 0.0)

// update TSL high mark
if (isLongOpen )
    if (not trailPrice and currentPrice >= entryPrice * (1 + tslTrigger))
        trailPrice := currentPrice
    else 
        if (trailPrice and currentPrice > trailPrice)
            trailPrice := currentPrice

if (trailPrice and currentPrice <= trailPrice * (1 - tslStop))
    // FIRE TSL SIGNAL
    short:=true // <===
    long := false

// if short clean up
if (short)
    isLongOpen := false
    entryPrice := 0.0
    trailPrice := 0.0

if (long)
    isLongOpen := true
    if (not entryPrice)
        entryPrice := currentPrice

// === BACKTESTING: ENTRIES ===
if long
    if (strategyType == "Short Only")
        strategy.close("Short")
    else
        strategy.entry("Long", strategy.long, comment="Long")

if short
    if (strategyType == "Long Only")
        strategy.close("Long")
    else
        strategy.entry("Short", strategy.short, comment="Short")	  
    
//barcolor(possig == -1 ? red: possig == 1 ? green : blue )
//plot(xmacd, color=green, title="Ergotic MACD")
//plot(xMA_MACD, color=red, title="SigLin")

plotshape(trailPrice ? trailPrice : na, style=shape.circle, location=location.absolute, color=blue, size=size.tiny)

plotshape(long, style=shape.triangleup, location=location.belowbar, color=green, size=size.tiny)
plotshape(short, style=shape.triangledown, location=location.abovebar, color=red, size=size.tiny)

// === Strategy Alert ===
alertcondition(long, title='BUY - Ergotic MACD Long Entry', message='Go Long!')
alertcondition(short, title='SELL - Ergotic MACD Long Entry', message='Go Short!')

// === BACKTESTING: EXIT strategy ===
sl_inp = input(7, title='Stop Loss %', type=float)/100
tp_inp = input(1.8, title='Take Profit %', type=float)/100

stop_level = strategy.position_avg_price * (1 - sl_inp)
take_level = strategy.position_avg_price * (1 + tp_inp)

strategy.exit("Stop Loss/Profit", "Long", stop=stop_level, limit=take_level)

Plus de