Magic Key... par Franck Chambon

Pine script pour le BOBP v2.6

//@version=5

strategy("BOPB V2.6 - Bollinger Band Breakout Strategy (RSI Long/Short)", overlay=true)

// === Sélection du type de marché ===

market_type = input.string("Forex", title="Type de marché", options=["Forex", "Crypto"])

// === Paramètres des Bollinger Bands ===

bb_length = input.int(10, title="Période des BB", minval=5, maxval=50)

bb_mult = input.float(1.8, title="Multiplicateur des BB", minval=1.0, maxval=5.0, step=0.1)

use_atr_sl = input.bool(true, title="Utiliser ATR pour SL/TP")

risk_reward_ratio = input.float(2.9, title="Ratio RR", minval=1.0, maxval=5.0, step=0.1)

// === Paramètres des EMA en fonction du marché ===

ema_short_length = market_type == "Forex" ? input.int(9, title="Longueur EMA courte (Forex)") : input.int(7, title="Longueur EMA courte (Crypto)")

ema_long_length = market_type == "Forex" ? input.int(21, title="Longueur EMA longue (Forex)") : input.int(50, title="Longueur EMA longue (Crypto)")

// === Paramètres du RSI ===

use_rsi_filter = input.bool(true, title="Utiliser RSI pour filtre")

rsi_length = input.int(20, title="Longueur RSI")

rsi_long_threshold = input.int(30, title="Seuil RSI Long")

rsi_short_threshold = input.int(63, title="Seuil RSI Short")

// === Calcul des indicateurs ===

src = close

basis = ta.sma(src, bb_length)

dev = bb_mult ta.stdev(src, bb_length)

upper_band = basis + dev

lower_band = basis - dev

ema_short = ta.ema(close, ema_short_length)

ema_long = ta.ema(close, ema_long_length)

rsi_value = ta.rsi(close, rsi_length)

// === Indicateur ATR pour SL/TP dynamiques ===

atr_length = 14

atr_value = ta.atr(atr_length)

stop_mult_atr = input.float(2.3, title="Multiplicateur Stop ATR", minval=0.5, maxval=3.0, step=0.1)

// === Filtres de volatilité ===

atr_threshold = input.float(2.0, title="Seuil de volatilité ATR", minval=0.5, maxval=5.0, step=0.1)

valid_volatility = atr_value > atr_threshold

// === Conditions d’entrée avec filtre EMA et RSI ===

buy_signal = ta.crossunder(close, lower_band) and valid_volatility and ema_short > ema_long and (not use_rsi_filter or rsi_value < rsi_long_threshold)

sell_signal = ta.crossover(close, upper_band) and valid_volatility and ema_short < ema_long and (not use_rsi_filter or rsi_value > rsi_short_threshold)

// === Définition du Stop-Loss et Take-Profit ===

sl_long = close - (stop_mult_atr atr_value)

tp_long = close + (risk_reward_ratio atr_value)

sl_short = close + (stop_mult_atr atr_value)

tp_short = close - (risk_reward_ratio * atr_value)

// === Exécution des trades ===

if buy_signal

strategy.entry("Long", strategy.long)

strategy.exit("TP/SL Long", from_entry="Long", stop=sl_long, limit=tp_long)

if sell_signal

strategy.entry("Short", strategy.short)

strategy.exit("TP/SL Short", from_entry="Short", stop=sl_short, limit=tp_short)

// === Affichage des signaux Buy/Sell seulement (sans bruit visuel) ===

plotshape(buy_signal, location=location.belowbar, color=color.green, style=shape.labelup, title="BUY Signal", size=size.small)

plotshape(sell_signal, location=location.abovebar, color=color.red, style=shape.labeldown, title="SELL Signal", size=size.small)

// === Alertes de trading ===

alertcondition(buy_signal, title="BUY Alert", message="Prix sous la bande BB et tendance haussière - Achat !")

alertcondition(sell_signal, title="SELL Alert", message="Prix au-dessus de la bande BB et tendance baissière - Vente !")


Setting pour BOPB V2.6 (Gold)

Analyse visuelle pour entrer en trade :

Entrée Short :

  • le prix franchit la bande supérieure de Bollinger (signifiant une possible condition de surachat).

  • Ensuite, tu attends la confirmation avec une bougie rouge qui clôture sous la bande supérieure.

→ Cette approche est excellente, elle réduit énormément les faux signaux.

Placement du SL :

  • Placer le Stop Loss juste au-dessus de la mèche de la bougie précédente est optimal.

  • Tu utilises un niveau technique logique et non pas seulement un Multiplicateur ATR arbitraire.

→ Cela protège efficacement ton capital, tout en laissant de l'espacE au trade.

Take Profit (RR = 2 + suivi) :

  • TP initial fixé avec un RR = 2 est réaliste et optimal pour sécuriser rapidement un profit.

  • Ensuite, tu utilises un suivi pour maximiser davantage le gain.

→ Approche excellente pour optimiser le RR global.

//@version=5

indicator("Tableau SMB - Backtest Visuel", overlay=true)

// === INPUTS ===

emaLength = input.int(50, "EMA Length")

lookback = input.int(5, "Bougies pour moyenne volume / taille")

positionOption = input.string("Bottom Gauche", "Position du tableau", options=["Top Gauche", "Top Droite", "Bottom Droite", "Bottom Gauche"])

stochLongMax = input.float(60, "Stock RSI max si LONG")

stochShortMin = input.float(40, "Stock RSI min si SHORT")

rsiLongMin = input.float(40, "RSI min si LONG")

rsiShortMax = input.float(60, "RSI max si SHORT")

// === PERSONNALISATION GUI ===

bgColor = input.color(color.new(color.black, 50), "Couleur Fond Tableau")

textColor = input.color(color.white, "Couleur Texte Tableau")

fontSizeOption = input.string("small", "Taille Police", options=["tiny", "small", "normal", "large", "huge"])

// === LIMITES D'OVERRIDE STOCK RSI ===

stockRsiMaxLongForOverride = input.float(80, "Limite Stock RSI Override LONG (Max)")

stockRsiMinShortForOverride = input.float(20, "Limite Stock RSI Override SHORT (Min)")

// === CALCULS ===

ema = ta.ema(close, emaLength)

volumeMoy = ta.sma(volume, lookback)

hauteurBougie = high - low

grosseurMoy = ta.sma(hauteurBougie, lookback)

// === DIRECTION ===

breakoutHaut = high > high[1] and close > close[1] and close > open

breakoutBas = low < low[1] and close < close[1] and close < open

direction = breakoutHaut ? "Long" : breakoutBas ? "Short" : ""

// === INDICATEURS CORRIGÉS AVEC LISSAGE ===

rsi = ta.rsi(close, 14)

// Vrai Stock RSI brut classique

rsiMin = ta.lowest(rsi, 14)

rsiMax = ta.highest(rsi, 14)

stochRsiBrut = (rsi - rsiMin) / (rsiMax - rsiMin) * 100

// Lissage K identique à ton indicateur graphique (lissage simple de 3 périodes)

stochK = ta.sma(stochRsiBrut, 3)

// === VALIDATIONS ===

smb = breakoutHaut or breakoutBas

stockRSI_valide = (direction == "Long" and stochK <= stochLongMax) or (direction == "Short" and stochK >= stochShortMin)

rsi_valide = (direction == "Long" and rsi >= rsiLongMin) or (direction == "Short" and rsi <= rsiShortMax)

ema_valide = (direction == "Long" and close > ema) or (direction == "Short" and close < ema)

volume_valide = volume > volumeMoy

grosseur_valide = hauteurBougie > grosseurMoy

// Override corrigé avec limites

stockRSI_override = (not stockRSI_valide and volume_valide and grosseur_valide) and ((direction == "Long" and stochK <= stockRsiMaxLongForOverride) or (direction == "Short" and stochK >= stockRsiMinShortForOverride))

// === DÉCISION ===

valide_final = smb and (stockRSI_valide or stockRSI_override) and rsi_valide and ema_valide and volume_valide and grosseur_valide

// === POSITION DU TABLEAU ===

getPosition(p) =>

p == "Top Gauche" ? position.top_left : p == "Top Droite" ? position.top_right : p == "Bottom Droite" ? position.bottom_right : position.bottom_left

// === TABLEAU ===

var table t = table.new(getPosition(positionOption), 3, 10, bgcolor=bgColor, border_color=color.gray, border_width=1)

// Taille police dynamique

getFontSize() =>

fontSizeOption == "tiny" ? size.tiny :

fontSizeOption == "small" ? size.small :

fontSizeOption == "normal" ? size.normal :

fontSizeOption == "large" ? size.large : size.huge

if barstate.islast

ts = getFontSize()

table.cell(t, 0, 0, "Critère", text_color=textColor, text_size=ts)

table.cell(t, 1, 0, "Valeur numérique", text_color=textColor, text_size=ts)

table.cell(t, 2, 0, "OUI/NON", text_color=textColor, text_size=ts)

table.cell(t, 0, 1, "Actif", text_color=textColor, text_size=ts)

table.cell(t, 1, 1, str.tostring(close, format.mintick) + " $", text_color=textColor, text_size=ts)

table.cell(t, 2, 1, direction, text_color=textColor, text_size=ts)

table.cell(t, 0, 2, "SMB", text_color=textColor, text_size=ts)

table.cell(t, 1, 2, smb ? "Oui" : "Non", text_color=textColor, text_size=ts)

table.cell(t, 2, 2, smb ? "OUI" : "NON", text_color=smb ? color.green : color.red, text_size=ts)

table.cell(t, 0, 3, "Stock RSI (" + str.tostring(stochLongMax) + "/" + str.tostring(stochShortMin) + ")", text_color=textColor, text_size=ts)

table.cell(t, 1, 3, str.tostring(stochK, format.mintick), text_color=textColor, text_size=ts)

table.cell(t, 2, 3, stockRSI_valide ? "OUI" : "NON", text_color=stockRSI_valide ? color.green : color.red, text_size=ts)

table.cell(t, 0, 4, "RSI (<" + str.tostring(rsiShortMax) + "/>=" + str.tostring(rsiLongMin) + ")", text_color=textColor, text_size=ts)

table.cell(t, 1, 4, str.tostring(rsi, format.mintick), text_color=textColor, text_size=ts)

table.cell(t, 2, 4, rsi_valide ? "OUI" : "NON", text_color=rsi_valide ? color.green : color.red, text_size=ts)

table.cell(t, 0, 5, "EMA", text_color=textColor, text_size=ts)

table.cell(t, 1, 5, str.tostring(ema, format.mintick) + " $", text_color=textColor, text_size=ts)

table.cell(t, 2, 5, ema_valide ? "OUI" : "NON", text_color=ema_valide ? color.green : color.red, text_size=ts)

table.cell(t, 0, 6, "Volume", text_color=textColor, text_size=ts)

table.cell(t, 1, 6, str.tostring(volume), text_color=textColor, text_size=ts)

table.cell(t, 2, 6, volume_valide ? "OUI" : "NON", text_color=volume_valide ? color.green : color.red, text_size=ts)

table.cell(t, 0, 7, "Grosseur", text_color=textColor, text_size=ts)

table.cell(t, 1, 7, str.tostring(hauteurBougie, format.mintick), text_color=textColor, text_size=ts)

table.cell(t, 2, 7, grosseur_valide ? "OUI" : "NON", text_color=grosseur_valide ? color.green : color.red, text_size=ts)

table.cell(t, 0, 8, "Décision", text_color=textColor, text_size=ts)

table.cell(t, 1, 8, "", text_color=textColor, text_size=ts)

table.cell(t, 2, 8, valide_final ? "OUI" : "NON", text_color=valide_final ? color.green : color.red, text_size=ts)

table.cell(t, 0, 9, "Override (Volume+Grosseur)", text_color=textColor, text_size=ts)

table.cell(t, 1, 9, "", text_color=textColor, text_size=ts)

table.cell(t, 2, 9, stockRSI_override ? "OUI" : "NON", text_color=stockRSI_override ? color.green : color.red, text_size=ts)

// === LABEL TEMPORAIRE POUR VALIDATION RAPIDE ===

atrValue = ta.atr(14) // ATR standard 14 périodes

labelContent = "ATR : " + str.tostring(atrValue, format.mintick) + "\n" +

"Grosseur : " + str.tostring(hauteurBougie, format.mintick) + "\n" +

"Volume : " + str.tostring(volume, format.volume) + "\n" +

"Volume Moy : " + str.tostring(volumeMoy, format.volume)

// Efface l'ancien label avant d'en créer un nouveau

var label validationLabel = na

if barstate.islast

if not na(validationLabel)

label.delete(validationLabel)

validationLabel := label.new(bar_index, high + (atrValue * 0.5), labelContent,

color=color.new(color.white, 0),

textcolor=color.black,

style=label.style_label_down,

size=size.normal)

plot(na)