TradingView โ Pine Editor (touche /) โ Nouvel indicateur โ Colle โ Ajouter au graphique
//@version=5
indicator("SMC Order Blocks 5โ
+ Sessions", overlay=true, max_boxes_count=100, max_labels_count=100, max_lines_count=100)
// โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
// PARAMรTRES
// โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
grpOB = "Order Blocks"
grpStars = "Scoring 5โ
"
grpSess = "Sessions"
grpStyle = "Style"
dispFactor = input.float(1.8, "Facteur de dรฉplacement (ร corps moyen)", minval=1.0, step=0.1, group=grpOB)
baselinePeriod = input.int(20, "Pรฉriode de base (bougies)", minval=5, maxval=50, group=grpOB)
structBreak = input.int(3, "Break de structure (bougies)", minval=1, maxval=10, group=grpOB)
maxZones = input.int(20, "Max zones affichรฉes", minval=5, maxval=50, group=grpOB)
noiseFilter = input.float(0.03, "Filtre bruit (%)", minval=0.0, step=0.01, group=grpOB) / 100
atrLen = input.int(10, "ATR Longueur (SuperTrend)", group=grpStars)
atrMult = input.float(3.0, "ATR Multiplicateur (SuperTrend)", step=0.5, group=grpStars)
fibLo = input.float(0.618, "Fib zone d'or โ bas", step=0.001, group=grpStars)
fibHi = input.float(0.79, "Fib zone d'or โ haut", step=0.01, group=grpStars)
showSessions = input.bool(true, "Afficher les sessions", group=grpSess)
showLondon = input.bool(true, "Session Londres", group=grpSess)
showNY = input.bool(true, "Session New York", group=grpSess)
showTokyo = input.bool(true, "Session Tokyo", group=grpSess)
showSydney = input.bool(true, "Session Sydney", group=grpSess)
colBuy3 = input.color(color.new(#10b981, 80), "Buy โฅ3โ
", group=grpStyle)
colBuy5 = input.color(color.new(#059669, 60), "Buy 5โ
", group=grpStyle)
colSell3 = input.color(color.new(#ef4444, 80), "Sell โฅ3โ
", group=grpStyle)
colSell5 = input.color(color.new(#dc2626, 60), "Sell 5โ
", group=grpStyle)
colBuyBorder = input.color(#10b981, "Bordure Buy", group=grpStyle)
colSellBorder = input.color(#ef4444, "Bordure Sell", group=grpStyle)
// โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
// SUPERTREND (contexte de marchรฉ)
// โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
atr = ta.atr(atrLen)
src = hl2
up = src - atrMult * atr
dn = src + atrMult * atr
var float upBuf = na
var float dnBuf = na
var int stDir = 1
upBuf := nz(upBuf[1], up)
dnBuf := nz(dnBuf[1], dn)
upBuf := up > upBuf[1] or close[1] > upBuf[1] ? up : upBuf[1]
dnBuf := dn < dnBuf[1] or close[1] < dnBuf[1] ? dn : dnBuf[1]
stDir := stDir == 1 ? (close < dnBuf ? -1 : 1) : (close > upBuf ? 1 : -1)
stLine = stDir == 1 ? upBuf : dnBuf
// โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
// DรTECTION DES ORDER BLOCKS
// โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
body = math.abs(close - open)
avgBody = ta.sma(body, baselinePeriod)
isBullDisp = body >= dispFactor * avgBody and close >= open
isBearDisp = body >= dispFactor * avgBody and close < open
// Break de structure : close au-delร des N derniรจres bougies
var float recentHigh = na
var float recentLow = na
recentHigh := ta.highest(high, structBreak)[1]
recentLow := ta.lowest(low, structBreak)[1]
bullBreak = close > recentHigh
bearBreak = close < recentLow
// Signal de dรฉplacement
bullDisp = isBullDisp and bullBreak
bearDisp = isBearDisp and bearBreak
// Trouver l'OB = derniรจre bougie opposรฉe avant le dรฉplacement
var int lastBullOBBar = na
var int lastBearOBBar = na
var float lastBullOBTop = na
var float lastBullOBBot = na
var float lastBearOBTop = na
var float lastBearOBBot = na
if bullDisp
lastBullOBBar := na
for i = 1 to 5
if close[i] < open[i]
lastBullOBBar := bar_index - i
lastBullOBTop := high[i]
lastBullOBBot := low[i]
break
if bearDisp
lastBearOBBar := na
for i = 1 to 5
if close[i] >= open[i]
lastBearOBBar := bar_index - i
lastBearOBTop := high[i]
lastBearOBBot := low[i]
break
// โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
// FVG (Imbalance) โ gap entre bougie 1 et bougie 3
// โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
bullFVG = low > high[2] and low[1] > high[2]
bearFVG = high < low[2] and high[1] < low[2]
// โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
// SCORING 5โ
// โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
f_countStars(bool isBull, float obTop, float obBot, int obBar) =>
// โ
1 Imbalance (FVG dans la zone)
float fvgTop = isBull ? low : high
float fvgBot = isBull ? high[2] : low[2]
bool hasFVG = isBull ? bullFVG and fvgBot <= obTop and fvgTop >= obBot : bearFVG and fvgBot <= obTop and fvgTop >= obBot
// โ
2 Contexte (SuperTrend alignรฉ + stable)
bool trendAligned = isBull ? stDir == 1 : stDir == -1
// stabilitรฉ : pas de flip sur les 10 derniรจres bougies
int flips = 0
for i = 0 to math.min(9, bar_index - obBar)
if stDir[i] != stDir[i + 1]
flips += 1
bool trendStable = flips <= 1
bool contextOK = trendAligned and trendStable
// โ
3 Liquiditรฉ (sweep avant l'OB)
// Dรฉtecter si une mรจche a pris un swing puis clรดturรฉ dedans
float swingLow = ta.lowest(low, 12)[1]
float swingHigh = ta.highest(high, 12)[1]
bool sweptLow = isBull and low[1] < swingLow and close[1] > swingLow
bool sweptHigh = not isBull and high[1] > swingHigh and close[1] < swingHigh
bool liquidityOK = isBull ? sweptLow : sweptHigh
// โ
4 Fraรฎcheur (pas mitigรฉe)
bool freshOK = isBull ? close > obBot : close < obTop
// โ
5 Fibonacci (zone d'or 61.8-79% de retracement)
float lookbackHigh = ta.highest(high, 40)
float lookbackLow = ta.lowest(low, 40)
float priceRange = lookbackHigh - lookbackLow
float midOB = (obTop + obBot) / 2
float retr = isBull ? (lookbackHigh - midOB) / priceRange : (midOB - lookbackLow) / priceRange
bool fibOK = retr >= fibLo and retr <= fibHi
int stars = (hasFVG ? 1 : 0) + (contextOK ? 1 : 0) + (liquidityOK ? 1 : 0) + (freshOK ? 1 : 0) + (fibOK ? 1 : 0)
[stars, hasFVG, contextOK, liquidityOK, freshOK, fibOK]
// โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
// RENDU DES ZONES OB
// โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
var array<box> buyBoxes = array.new<box>()
var array<box> sellBoxes = array.new<box>()
var array<label> buyLabels = array.new<label>()
var array<label> sellLabels = array.new<label>()
var array<int> buyStars = array.new<int>()
var array<int> sellStars = array.new<int>()
if bullDisp and not na(lastBullOBBar)
float obTop = lastBullOBTop
float obBot = lastBullOBBot
if obTop > obBot and (obTop - obBot) / close > noiseFilter
[stars, f1, f2, f3, f4, f5] = f_countStars(true, obTop, obBot, lastBullOBBar)
if stars >= 3
color zoneCol = stars == 5 ? colBuy5 : colBuy3
box newBox = box.new(lastBullOBBar, obTop, bar_index + 10, obBot, border_color=colBuyBorder, border_width=stars >= 4 ? 2 : 1, bgcolor=zoneCol)
string starStr = stars >= 5 ? "โ
โ
โ
โ
โ
" : stars == 4 ? "โ
โ
โ
โ
" : "โ
โ
โ
"
label newLabel = label.new(lastBullOBBar, obTop, starStr, style=label.style_label_down, color=color.new(color.black, 100), textcolor=stars >= 4 ? #ffd700 : #94a3b8, size=size.small)
array.push(buyBoxes, newBox)
array.push(buyLabels, newLabel)
array.push(buyStars, stars)
if bearDisp and not na(lastBearOBBar)
float obTop = lastBearOBTop
float obBot = lastBearOBBot
if obTop > obBot and (obTop - obBot) / close > noiseFilter
[stars, f1, f2, f3, f4, f5] = f_countStars(false, obTop, obBot, lastBearOBBar)
if stars >= 3
color zoneCol = stars == 5 ? colSell5 : colSell3
box newBox = box.new(lastBearOBBar, obTop, bar_index + 10, obBot, border_color=colSellBorder, border_width=stars >= 4 ? 2 : 1, bgcolor=zoneCol)
string starStr2 = stars >= 5 ? "โ
โ
โ
โ
โ
" : stars == 4 ? "โ
โ
โ
โ
" : "โ
โ
โ
"
label newLabel = label.new(lastBearOBBar, obBot, starStr2, style=label.style_label_up, color=color.new(color.black, 100), textcolor=stars >= 4 ? #ffd700 : #94a3b8, size=size.small)
array.push(sellBoxes, newBox)
array.push(sellLabels, newLabel)
array.push(sellStars, stars)
// Nettoyer les vieilles zones
if array.size(buyBoxes) > maxZones
box.delete(array.shift(buyBoxes))
label.delete(array.shift(buyLabels))
array.shift(buyStars)
if array.size(sellBoxes) > maxZones
box.delete(array.shift(sellBoxes))
label.delete(array.shift(sellLabels))
array.shift(sellStars)
// รtendre les zones actives jusqu'ร la bougie actuelle
if barstate.islast
for i = 0 to array.size(buyBoxes) - 1
box.set_right(array.get(buyBoxes, i), bar_index + 5)
for i = 0 to array.size(sellBoxes) - 1
box.set_right(array.get(sellBoxes, i), bar_index + 5)
// โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
// SESSIONS (fuseau Europe/Brussels) โ bgcolor() doit rester au scope global
inLondon = showSessions and showLondon and hour(time, "Europe/Brussels") >= 8 and hour(time, "Europe/Brussels") < 10
inNY = showSessions and showNY and ((hour(time, "Europe/Brussels") == 15 and minute(time, "Europe/Brussels") >= 30) or hour(time, "Europe/Brussels") == 16 or (hour(time, "Europe/Brussels") == 17 and minute(time, "Europe/Brussels") < 30))
inTokyo = showSessions and showTokyo and hour(time, "Europe/Brussels") >= 2 and hour(time, "Europe/Brussels") < 8
inSydney = showSessions and showSydney and (hour(time, "Europe/Brussels") >= 23 or hour(time, "Europe/Brussels") < 6)
bgcolor(inLondon ? color.new(#3b82f6, 95) : na, title="Killzone Londres")
bgcolor(inNY ? color.new(#f59e0b, 95) : na, title="Killzone NY")
bgcolor(inTokyo ? color.new(#8b5cf6, 97) : na, title="Session Tokyo")
bgcolor(inSydney ? color.new(#10b981, 97) : na, title="Session Sydney")
// โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
// LIGNES DE SESSION (High/Low)
// โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
if showSessions and showLondon
var line londonH = na
var line londonL = na
if inLondon and not inLondon[1]
londonH := line.new(bar_index, high, bar_index, high, color=#3b82f6, style=line.style_dashed, width=1)
londonL := line.new(bar_index, low, bar_index, low, color=#3b82f6, style=line.style_dashed, width=1)
if inLondon
line.set_xy1(londonH, line.get_x1(londonH), math.max(high, line.get_y1(londonH)))
line.set_xy2(londonH, bar_index, line.get_y1(londonH))
line.set_xy1(londonL, line.get_x1(londonL), math.min(low, line.get_y1(londonL)))
line.set_xy2(londonL, bar_index, line.get_y1(londonL))
if showSessions and showNY
var line nyH = na
var line nyL = na
if inNY and not inNY[1]
nyH := line.new(bar_index, high, bar_index, high, color=#f59e0b, style=line.style_dashed, width=1)
nyL := line.new(bar_index, low, bar_index, low, color=#f59e0b, style=line.style_dashed, width=1)
if inNY
line.set_xy1(nyH, line.get_x1(nyH), math.max(high, line.get_y1(nyH)))
line.set_xy2(nyH, bar_index, line.get_y1(nyH))
line.set_xy1(nyL, line.get_x1(nyL), math.min(low, line.get_y1(nyL)))
line.set_xy2(nyL, bar_index, line.get_y1(nyL))
// โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
// ALERTES
// โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
alertcondition(bullDisp, "Bullish OB dรฉtectรฉ", "Order Block haussier dรฉtectรฉ โ check รฉtoiles")
alertcondition(bearDisp, "Bearish OB dรฉtectรฉ", "Order Block baissier dรฉtectรฉ โ check รฉtoiles")