//@version=6 indicator("MACD 4/25/5 + EMA 21/50/250 + Breakout", overlay=true) //==================================================== // PARAMÈTRES //==================================================== emaFastLength = input.int(21, "EMA rapide", minval=1) emaMidLength = input.int(50, "EMA moyenne", minval=1) emaSlowLength = input.int(250, "EMA tendance", minval=1) macdFastLength = input.int(4, "MACD rapide", minval=1) macdSlowLength = input.int(25, "MACD lent", minval=1) macdSignalLength = input.int(5, "MACD signal", minval=1) //==================================================== // EMA //==================================================== ema21 = ta.ema(close, emaFastLength) ema50 = ta.ema(close, emaMidLength) ema250 = ta.ema(close, emaSlowLength) //==================================================== // STRUCTURE DE TENDANCE //==================================================== // BUY : EMA 21 > EMA 50 > EMA 250 bullTrend = ema21 > ema50 and ema50 > ema250 // SELL : EMA 21 < EMA 50 < EMA 250 bearTrend = ema21 < ema50 and ema50 < ema250 //==================================================== // MACD //==================================================== [macdLine, signalLine, histogram] = ta.macd( close, macdFastLength, macdSlowLength, macdSignalLength ) //==================================================== // CROISEMENTS //==================================================== crossDown = ta.crossunder(macdLine, signalLine) crossUp = ta.crossover(macdLine, signalLine) //==================================================== // VARIABLES BUY //==================================================== var bool buySetup = false var bool buyMACDConfirmed = false var bool buyInvalidated = false var float buyBreakLevel = na // Plus HAUTE CLÔTURE construite avant le premier croisement baissier var float buyPreviousHigh = na //==================================================== // VARIABLES SELL //==================================================== var bool sellSetup = false var bool sellMACDConfirmed = false var bool sellInvalidated = false var float sellBreakLevel = na // Plus BASSE CLÔTURE construite avant le premier croisement haussier var float sellPreviousLow = na //==================================================== // RECHERCHE DU PLUS HAUT / PLUS BAS PRÉCÉDENT //==================================================== // IMPORTANT : // On utilise CLOSE et non HIGH/LOW. // Le niveau est donc basé sur une clôture de bougie, // et non sur une mèche. var float runningHigh = na var float runningLow = na if na(runningHigh) runningHigh := close if na(runningLow) runningLow := close // Plus haute clôture runningHigh := math.max(runningHigh, close) // Plus basse clôture runningLow := math.min(runningLow, close) //==================================================== // PREMIER CROISEMENT BAISSIER → PRÉPARATION BUY //==================================================== if crossDown and bullTrend // On mémorise la plus haute clôture précédente buyPreviousHigh := runningHigh buyBreakLevel := buyPreviousHigh buySetup := true buyMACDConfirmed := false buyInvalidated := false // Réinitialisation du SELL sellSetup := false sellMACDConfirmed := false sellInvalidated := false sellBreakLevel := na sellPreviousLow := na // On recommence à chercher un nouveau sommet runningHigh := close runningLow := close //==================================================== // CONDITION ZÉRO MACD POUR BUY //==================================================== // Le MACD rapide peut passer sous 0 intrabougie. // Mais à la clôture de la bougie, il ne doit PAS être < 0. if buySetup and barstate.isconfirmed and macdLine < 0 buySetup := false buyMACDConfirmed := false buyInvalidated := true buyBreakLevel := na buyPreviousHigh := na //==================================================== // DEUXIÈME CROISEMENT HAUSSIER → BUY VALIDÉ //==================================================== if buySetup and crossUp and not buyInvalidated and bullTrend buyMACDConfirmed := true //==================================================== // PREMIER CROISEMENT HAUSSIER → PRÉPARATION SELL //==================================================== if crossUp and bearTrend // On mémorise la plus basse clôture précédente sellPreviousLow := runningLow sellBreakLevel := sellPreviousLow sellSetup := true sellMACDConfirmed := false sellInvalidated := false // Réinitialisation du BUY buySetup := false buyMACDConfirmed := false buyInvalidated := false buyBreakLevel := na buyPreviousHigh := na // On recommence à chercher les extrêmes runningHigh := close runningLow := close //==================================================== // CONDITION ZÉRO MACD POUR SELL //==================================================== // Le MACD rapide peut passer au-dessus de 0 intrabougie. // Mais il ne doit PAS clôturer au-dessus de 0. if sellSetup and barstate.isconfirmed and macdLine > 0 sellSetup := false sellMACDConfirmed := false sellInvalidated := true sellBreakLevel := na sellPreviousLow := na //==================================================== // DEUXIÈME CROISEMENT BAISSIER → SELL VALIDÉ //==================================================== if sellSetup and crossDown and not sellInvalidated and bearTrend sellMACDConfirmed := true //==================================================== // DÉCLENCHEMENT BUY //==================================================== // Le niveau de référence est maintenant une CLÔTURE, // mais le déclenchement reste basé sur la mèche, // comme dans ton script original. buyTrigger = ( buySetup and buyMACDConfirmed and not buyInvalidated and bullTrend and not na(buyBreakLevel) and high >= buyBreakLevel ) //==================================================== // DÉCLENCHEMENT SELL //==================================================== // Même principe pour le SELL. sellTrigger = ( sellSetup and sellMACDConfirmed and not sellInvalidated and bearTrend and not na(sellBreakLevel) and low <= sellBreakLevel ) //==================================================== // RESET APRÈS SIGNAL //==================================================== if buyTrigger buySetup := false buyMACDConfirmed := false buyInvalidated := false buyBreakLevel := na buyPreviousHigh := na runningHigh := close runningLow := close if sellTrigger sellSetup := false sellMACDConfirmed := false sellInvalidated := false sellBreakLevel := na sellPreviousLow := na runningHigh := close runningLow := close //==================================================== // AFFICHAGE DES EMA //==================================================== plot( ema21, title="EMA 21", color=color.green, linewidth=1 ) plot( ema50, title="EMA 50", color=color.orange, linewidth=1 ) plot( ema250, title="EMA 250", color=color.red, linewidth=2 ) //==================================================== // AFFICHAGE DU NIVEAU BUY //==================================================== plot( buySetup and not na(buyBreakLevel) ? buyBreakLevel : na, title="Niveau précédent BUY", color=color.green, linewidth=1, style=plot.style_linebr ) //==================================================== // AFFICHAGE DU NIVEAU SELL //==================================================== plot( sellSetup and not na(sellBreakLevel) ? sellBreakLevel : na, title="Niveau précédent SELL", color=color.red, linewidth=1, style=plot.style_linebr ) //==================================================== // FLÈCHE BUY //==================================================== plotshape( buyTrigger, title="BUY", style=shape.triangleup, location=location.belowbar, color=color.green, size=size.small, text="BUY" ) //==================================================== // FLÈCHE SELL //==================================================== plotshape( sellTrigger, title="SELL", style=shape.triangledown, location=location.abovebar, color=color.red, size=size.small, text="SELL" ) //==================================================== // ALERTES //==================================================== alertcondition( buyTrigger, title="BUY", message="BUY - EMA 21 > EMA 50 > EMA 250 + MACD 4/25/5 + cassure précédent plus haut" ) alertcondition( sellTrigger, title="SELL", message="SELL - EMA 21 < EMA 50 < EMA 250 + MACD 4/25/5 + cassure précédent plus bas" )