HTF_OB_LTF_Entry_Indicator.pine
Copy
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © Claude AI - HTF OB M30 + LTF M1 Entry System
//@version=5
indicator("HTF OB M30 + LTF Entry System", overlay=true, max_boxes_count=100, max_labels_count=100)
// ═══════════════════════════════════════════════════════════════════════════════
// INPUTS / SETTINGS
// ═══════════════════════════════════════════════════════════════════════════════
// HTF Settings
htf_timeframe = input.timeframe("30", "HTF Timeframe (OB Detection)", group="HTF Settings")
htf_pivot_length = input.int(3, "HTF Pivot Length", minval=1, maxval=10, group="HTF Settings")
ob_mode = input.string("Wick", "OB Zone Mode", options=["Wick", "Body"], group="HTF Settings")
// LTF Settings
ltf_pivot_length = input.int(3, "LTF Pivot Length", minval=1, maxval=10, group="LTF Settings")
// Displacement Settings
disp_body_mult = input.float(1.8, "Displacement Body Multiplier", minval=1.0, step=0.1, group="Displacement")
disp_body_lookback = input.int(20, "Body Average Lookback", minval=5, group="Displacement")
disp_atr_mult = input.float(1.5, "Displacement ATR Multiplier", minval=1.0, step=0.1, group="Displacement")
disp_atr_length = input.int(14, "ATR Length", minval=5, group="Displacement")
disp_close_threshold = input.float(0.6, "Close Position Threshold", minval=0.5, maxval=1.0, step=0.05, group="Displacement")
// BOS Settings (Strict BOS)
bos_buffer_pips = input.float(2.0, "BOS Buffer (pips)", minval=0, step=0.5, group="BOS Settings")
bos_atr_mult = input.float(0.5, "BOS ATR Multiplier", minval=0, step=0.1, group="BOS Settings")
bos_close_pos = input.float(0.6, "BOS Close Position Threshold", minval=0.5, maxval=1.0, step=0.05, group="BOS Settings", tooltip="Candle must close in top/bottom X% of body")
// Entry Settings
use_ltf_ob = input.bool(true, "Use LTF OB Entry", group="Entry Logic")
use_fvg = input.bool(true, "Use FVG Entry", group="Entry Logic")
require_sweep = input.bool(true, "Require Liquidity Sweep", group="Entry Logic", tooltip="Require sweep of swing low/high before BUY/SELL signal")
sweep_buffer_pips = input.float(1.0, "Sweep Buffer (pips)", minval=0, step=0.5, group="Entry Logic")
setup_timeout_bars = input.int(30, "Setup Timeout (bars)", minval=5, maxval=100, group="Entry Logic", tooltip="Invalidate setup if no signal within N bars")
// SL/TP Settings
sl_method = input.string("Swing", "SL Method", options=["Swing", "OB"], group="Risk Management")
tp1_rr = input.float(1.0, "TP1 (R)", minval=0.5, step=0.5, group="Risk Management")
tp2_rr = input.float(2.0, "TP2 (R)", minval=0.5, step=0.5, group="Risk Management")
tp3_rr = input.float(3.0, "TP3 (R)", minval=0.5, step=0.5, group="Risk Management")
partial_close_pct = input.float(50, "Partial Close % at TP1", minval=0, maxval=100, group="Risk Management")
// Visual Settings
show_htf_ob = input.bool(true, "Show HTF OB Zones", group="Visualization")
show_ltf_ob = input.bool(true, "Show LTF OB Zones", group="Visualization")
show_fvg = input.bool(true, "Show FVG Zones", group="Visualization")
show_labels = input.bool(true, "Show Labels", group="Visualization")
// ═══════════════════════════════════════════════════════════════════════════════
// HELPER FUNCTIONS
// ═══════════════════════════════════════════════════════════════════════════════
// Calculate pip size for current symbol
f_pip_size() =>
float pip = syminfo.mintick
if syminfo.type == "forex"
pip := syminfo.mintick * 10
pip
// Convert pips to price
f_pips_to_price(pips) =>
pips * f_pip_size()
// Check if price is in zone
f_in_zone(zone_top, zone_bottom) =>
(low <= zone_top and high >= zone_bottom)
// Calculate average body size
f_avg_body(lookback) =>
float sum = 0.0
for i = 0 to lookback - 1
sum := sum + math.abs(close[i] - open[i])
sum / lookback
// Check for displacement candle
f_is_displacement(is_bullish) =>
body = math.abs(close - open)
candle_range = high - low
avg_body = f_avg_body(disp_body_lookback)
atr_val = ta.atr(disp_atr_length)
// Body condition
body_cond = body >= disp_body_mult * avg_body
// Range condition
range_cond = candle_range >= disp_atr_mult * atr_val
// Close position condition
close_pos_bull = (close - low) / candle_range
close_pos_bear = (high - close) / candle_range
close_cond = is_bullish ? close_pos_bull > disp_close_threshold : close_pos_bear > disp_close_threshold
(body_cond or range_cond) and close_cond
// Detect Fair Value Gap (FVG)
f_detect_fvg() =>
// Bullish FVG: low[0] > high[2]
bull_fvg = low > high[2]
bull_fvg_top = bull_fvg ? low : na
bull_fvg_bottom = bull_fvg ? high[2] : na
// Bearish FVG: high[0] < low[2]
bear_fvg = high < low[2]
bear_fvg_top = bear_fvg ? low[2] : na
bear_fvg_bottom = bear_fvg ? high : na
[bull_fvg, bull_fvg_top, bull_fvg_bottom, bear_fvg, bear_fvg_top, bear_fvg_bottom]
// Check for engulfing pattern
f_is_engulfing(is_bullish) =>
if is_bullish
close > open and close[1] < open[1] and close > open[1] and open < close[1]
else
close < open and close[1] > open[1] and close < open[1] and open > close[1]
// Check for strong close
f_is_strong_close(is_bullish) =>
candle_range = high - low
if candle_range == 0
false
else if is_bullish
(close - low) / candle_range > 0.7
else
(high - close) / candle_range > 0.7
// ═══════════════════════════════════════════════════════════════════════════════
// HTF ORDER BLOCK DETECTION
// ═══════════════════════════════════════════════════════════════════════════════
// HTF Data via request.security (NO REPAINT)
[htf_high, htf_low, htf_close, htf_open] = request.security(syminfo.tickerid, htf_timeframe, [high, low, close, open], lookahead=barmerge.lookahead_off)
// HTF Pivot Points (Note: pivots can repaint, using confirmed pivots)
htf_pivot_high = ta.pivothigh(htf_high, htf_pivot_length, htf_pivot_length)
htf_pivot_low = ta.pivotlow(htf_low, htf_pivot_length, htf_pivot_length)
// Track last confirmed swing high/low on HTF
var float htf_last_swing_high = na
var float htf_last_swing_low = na
if not na(htf_pivot_high)
htf_last_swing_high := htf_pivot_high
if not na(htf_pivot_low)
htf_last_swing_low := htf_pivot_low
// Detect HTF BOS
htf_bull_bos = not na(htf_last_swing_high) and htf_close > htf_last_swing_high
htf_bear_bos = not na(htf_last_swing_low) and htf_close < htf_last_swing_low
// Track HTF OB zones
var float htf_bull_ob_top = na
var float htf_bull_ob_bottom = na
var int htf_bull_ob_bar = na
var bool htf_bull_ob_active = false
var float htf_bear_ob_top = na
var float htf_bear_ob_bottom = na
var int htf_bear_ob_bar = na
var bool htf_bear_ob_active = false
// Box IDs for persistent boxes (create once, update)
var box htf_bull_ob_box = na
var box htf_bear_ob_box = na
// ═══════════════════════════════════════════════════════════════════════════════
// STATE MACHINE (one signal per setup)
// ═══════════════════════════════════════════════════════════════════════════════
// States: 0=Idle, 1=HTF_OB_Active, 2=In_HTF_OB, 3=Displacement, 4=BOS_Confirmed, 5=Signal_Fired
var int bull_setup_state = 0
var int bear_setup_state = 0
var int setup_start_bar = na // For timeout tracking
// HTF Bullish OB: last bearish candle before bullish BOS
if htf_bull_bos and htf_close[1] < htf_open[1]
if ob_mode == "Body"
htf_bull_ob_top := math.max(htf_close[1], htf_open[1])
htf_bull_ob_bottom := math.min(htf_close[1], htf_open[1])
else
htf_bull_ob_top := htf_high[1]
htf_bull_ob_bottom := htf_low[1]
htf_bull_ob_bar := bar_index
htf_bull_ob_active := true
htf_bear_ob_active := false // Cancel opposite OB
bear_setup_state := 0 // Reset opposite setup state
// HTF Bearish OB: last bullish candle before bearish BOS
if htf_bear_bos and htf_close[1] > htf_open[1]
if ob_mode == "Body"
htf_bear_ob_top := math.max(htf_close[1], htf_open[1])
htf_bear_ob_bottom := math.min(htf_close[1], htf_open[1])
else
htf_bear_ob_top := htf_high[1]
htf_bear_ob_bottom := htf_low[1]
htf_bear_ob_bar := bar_index
htf_bear_ob_active := true
htf_bull_ob_active := false // Cancel opposite OB
bull_setup_state := 0 // Reset opposite setup state
// Check if price is in HTF OB
in_htf_bull_ob = htf_bull_ob_active and f_in_zone(htf_bull_ob_top, htf_bull_ob_bottom)
in_htf_bear_ob = htf_bear_ob_active and f_in_zone(htf_bear_ob_top, htf_bear_ob_bottom)
// ═══════════════════════════════════════════════════════════════════════════════
// LTF LOGIC (Current Timeframe)
// ═══════════════════════════════════════════════════════════════════════════════
// LTF Pivot Points
ltf_pivot_high = ta.pivothigh(high, ltf_pivot_length, ltf_pivot_length)
ltf_pivot_low = ta.pivotlow(low, ltf_pivot_length, ltf_pivot_length)
var float ltf_last_swing_high = na
var float ltf_last_swing_low = na
if not na(ltf_pivot_high)
ltf_last_swing_high := ltf_pivot_high
if not na(ltf_pivot_low)
ltf_last_swing_low := ltf_pivot_low
// Displacement Detection
bull_displacement = close > open and f_is_displacement(true)
bear_displacement = close < open and f_is_displacement(false)
// Track displacement
var bool ltf_bull_disp_active = false
var bool ltf_bear_disp_active = false
var int ltf_bull_disp_bar = na
var int ltf_bear_disp_bar = na
if bull_displacement and in_htf_bull_ob
ltf_bull_disp_active := true
ltf_bull_disp_bar := bar_index
ltf_bear_disp_active := false
if bear_displacement and in_htf_bear_ob
ltf_bear_disp_active := true
ltf_bear_disp_bar := bar_index
ltf_bull_disp_active := false
// LTF BOS Detection (STRICT: buffer + close position)
bos_pips_buffer = f_pips_to_price(bos_buffer_pips)
bos_atr_buffer = ta.atr(disp_atr_length) * bos_atr_mult
bos_buffer = math.max(bos_pips_buffer, bos_atr_buffer)
// Check if candle closes in strong position (top/bottom X% of body)
candle_body = math.abs(close - open)
close_position_bull = candle_body > 0 ? (close - math.min(close, open)) / candle_body : 0
close_position_bear = candle_body > 0 ? (math.max(close, open) - close) / candle_body : 0
ltf_bull_bos = ltf_bull_disp_active and not na(ltf_last_swing_high) and close > (ltf_last_swing_high + bos_buffer) and close_position_bull >= bos_close_pos
ltf_bear_bos = ltf_bear_disp_active and not na(ltf_last_swing_low) and close < (ltf_last_swing_low - bos_buffer) and close_position_bear >= bos_close_pos
// Track BOS
var bool ltf_bull_bos_confirmed = false
var bool ltf_bear_bos_confirmed = false
var int ltf_bull_bos_bar = na
var int ltf_bear_bos_bar = na
if ltf_bull_bos
ltf_bull_bos_confirmed := true
ltf_bull_bos_bar := bar_index
ltf_bear_bos_confirmed := false
if ltf_bear_bos
ltf_bear_bos_confirmed := true
ltf_bear_bos_bar := bar_index
ltf_bull_bos_confirmed := false
// ═══════════════════════════════════════════════════════════════════════════════
// LIQUIDITY SWEEP DETECTION
// ═══════════════════════════════════════════════════════════════════════════════
sweep_buffer = f_pips_to_price(sweep_buffer_pips)
// Track if sweep occurred
var bool bull_sweep_detected = false
var bool bear_sweep_detected = false
// Bull sweep: wick below swing low, but close above (inside HTF Bull OB)
if in_htf_bull_ob and not na(ltf_last_swing_low)
if low < (ltf_last_swing_low - sweep_buffer) and close > ltf_last_swing_low
bull_sweep_detected := true
// Bear sweep: wick above swing high, but close below (inside HTF Bear OB)
if in_htf_bear_ob and not na(ltf_last_swing_high)
if high > (ltf_last_swing_high + sweep_buffer) and close < ltf_last_swing_high
bear_sweep_detected := true
// Reset sweep on opposite OB
if htf_bear_ob_active and not htf_bear_ob_active[1]
bull_sweep_detected := false
if htf_bull_ob_active and not htf_bull_ob_active[1]
bear_sweep_detected := false
// ═══════════════════════════════════════════════════════════════════════════════
// LTF OB DETECTION (for entry)
// ═══════════════════════════════════════════════════════════════════════════════
var float ltf_bull_ob_top = na
var float ltf_bull_ob_bottom = na
var int ltf_bull_ob_bar = na
var bool ltf_bull_ob_valid = false
var float ltf_bear_ob_top = na
var float ltf_bear_ob_bottom = na
var int ltf_bear_ob_bar = na
var bool ltf_bear_ob_valid = false
// Box IDs for LTF OB
var box ltf_bull_ob_box = na
var box ltf_bear_ob_box = na
// Create LTF OB after displacement (last opposite candle before displacement)
if bull_displacement and in_htf_bull_ob
// Find last bearish candle before displacement
if close[1] < open[1]
if ob_mode == "Body"
ltf_bull_ob_top := math.max(close[1], open[1])
ltf_bull_ob_bottom := math.min(close[1], open[1])
else
ltf_bull_ob_top := high[1]
ltf_bull_ob_bottom := low[1]
ltf_bull_ob_bar := bar_index
ltf_bull_ob_valid := true
if bear_displacement and in_htf_bear_ob
// Find last bullish candle before displacement
if close[1] > open[1]
if ob_mode == "Body"
ltf_bear_ob_top := math.max(close[1], open[1])
ltf_bear_ob_bottom := math.min(close[1], open[1])
else
ltf_bear_ob_top := high[1]
ltf_bear_ob_bottom := low[1]
ltf_bear_ob_bar := bar_index
ltf_bear_ob_valid := true
// ═══════════════════════════════════════════════════════════════════════════════
// FVG DETECTION (for entry)
// ═══════════════════════════════════════════════════════════════════════════════
[bull_fvg, bull_fvg_top, bull_fvg_bottom, bear_fvg, bear_fvg_top, bear_fvg_bottom] = f_detect_fvg()
var float active_bull_fvg_top = na
var float active_bull_fvg_bottom = na
var int active_bull_fvg_bar = na
var bool bull_fvg_valid = false
var float active_bear_fvg_top = na
var float active_bear_fvg_bottom = na
var int active_bear_fvg_bar = na
var bool bear_fvg_valid = false
// Box IDs for FVG
var box bull_fvg_box = na
var box bear_fvg_box = na
// Track FVG after BOS
if bull_fvg and ltf_bull_bos_confirmed
active_bull_fvg_top := bull_fvg_top
active_bull_fvg_bottom := bull_fvg_bottom
active_bull_fvg_bar := bar_index
bull_fvg_valid := true
if bear_fvg and ltf_bear_bos_confirmed
active_bear_fvg_top := bear_fvg_top
active_bear_fvg_bottom := bear_fvg_bottom
active_bear_fvg_bar := bar_index
bear_fvg_valid := true
// ═══════════════════════════════════════════════════════════════════════════════
// STATE MACHINE LOGIC (One Signal Per Setup)
// ═══════════════════════════════════════════════════════════════════════════════
// States: 0=Idle, 1=HTF_OB_Active, 2=In_HTF_OB, 3=Displacement, 4=BOS_Confirmed, 5=Signal_Fired
// BULL SETUP STATE MACHINE
// State 0 -> 1: HTF Bull OB becomes active
if bull_setup_state == 0 and htf_bull_ob_active
bull_setup_state := 1
setup_start_bar := bar_index
// State 1 -> 2: Price enters HTF Bull OB
if bull_setup_state == 1 and in_htf_bull_ob
bull_setup_state := 2
// State 2 -> 3: Displacement detected
if bull_setup_state == 2 and ltf_bull_disp_active
bull_setup_state := 3
// State 3 -> 4: BOS confirmed (+ sweep if required)
if bull_setup_state == 3 and ltf_bull_bos_confirmed
if require_sweep
if bull_sweep_detected
bull_setup_state := 4
else
bull_setup_state := 4
// INVALIDATION (Bull): close below OB bottom or displacement low
var float bull_disp_low = na
if bull_setup_state == 3 and ltf_bull_disp_active
bull_disp_low := low
bull_invalidation = bull_setup_state > 0 and (close < htf_bull_ob_bottom or (not na(bull_disp_low) and close < bull_disp_low))
if bull_invalidation
bull_setup_state := 0
ltf_bull_bos_confirmed := false
ltf_bull_ob_valid := false
bull_fvg_valid := false
bull_sweep_detected := false
bull_disp_low := na
// TIMEOUT (Bull): no progress within N bars
if bull_setup_state > 0 and bull_setup_state < 5
if not na(setup_start_bar) and (bar_index - setup_start_bar) > setup_timeout_bars
bull_setup_state := 0
ltf_bull_bos_confirmed := false
ltf_bull_ob_valid := false
bull_fvg_valid := false
bull_sweep_detected := false
// BEAR SETUP STATE MACHINE
// State 0 -> 1: HTF Bear OB becomes active
if bear_setup_state == 0 and htf_bear_ob_active
bear_setup_state := 1
setup_start_bar := bar_index
// State 1 -> 2: Price enters HTF Bear OB
if bear_setup_state == 1 and in_htf_bear_ob
bear_setup_state := 2
// State 2 -> 3: Displacement detected
if bear_setup_state == 2 and ltf_bear_disp_active
bear_setup_state := 3
// State 3 -> 4: BOS confirmed (+ sweep if required)
if bear_setup_state == 3 and ltf_bear_bos_confirmed
if require_sweep
if bear_sweep_detected
bear_setup_state := 4
else
bear_setup_state := 4
// INVALIDATION (Bear): close above OB top or displacement high
var float bear_disp_high = na
if bear_setup_state == 3 and ltf_bear_disp_active
bear_disp_high := high
bear_invalidation = bear_setup_state > 0 and (close > htf_bear_ob_top or (not na(bear_disp_high) and close > bear_disp_high))
if bear_invalidation
bear_setup_state := 0
ltf_bear_bos_confirmed := false
ltf_bear_ob_valid := false
bear_fvg_valid := false
bear_sweep_detected := false
bear_disp_high := na
// TIMEOUT (Bear): no progress within N bars
if bear_setup_state > 0 and bear_setup_state < 5
if not na(setup_start_bar) and (bar_index - setup_start_bar) > setup_timeout_bars
bear_setup_state := 0
ltf_bear_bos_confirmed := false
ltf_bear_ob_valid := false
bear_fvg_valid := false
bear_sweep_detected := false
// ═══════════════════════════════════════════════════════════════════════════════
// ENTRY LOGIC
// ═══════════════════════════════════════════════════════════════════════════════
// Retest conditions
ltf_ob_retest_bull = ltf_bull_ob_valid and f_in_zone(ltf_bull_ob_top, ltf_bull_ob_bottom)
ltf_ob_retest_bear = ltf_bear_ob_valid and f_in_zone(ltf_bear_ob_top, ltf_bear_ob_bottom)
fvg_retest_bull = bull_fvg_valid and f_in_zone(active_bull_fvg_top, active_bull_fvg_bottom)
fvg_retest_bear = bear_fvg_valid and f_in_zone(active_bear_fvg_top, active_bear_fvg_bottom)
// Confirmation patterns
bull_confirmation = f_is_engulfing(true) or f_is_strong_close(true)
bear_confirmation = f_is_engulfing(false) or f_is_strong_close(false)
// Entry signals (ONE SIGNAL PER SETUP via state machine)
// Only fire signal in state 4 (BOS_Confirmed), then transition to state 5 (Signal_Fired)
buy_signal = bull_setup_state == 4 and ((use_ltf_ob and ltf_ob_retest_bull) or (use_fvg and fvg_retest_bull)) and bull_confirmation
sell_signal = bear_setup_state == 4 and ((use_ltf_ob and ltf_ob_retest_bear) or (use_fvg and fvg_retest_bear)) and bear_confirmation
// Transition to state 5 after signal fired
if buy_signal
bull_setup_state := 5
if sell_signal
bear_setup_state := 5
// Track entry for SL/TP calculation
var float entry_price = na
var float entry_sl = na
var float entry_tp1 = na
var float entry_tp2 = na
var float entry_tp3 = na
var bool is_long = na
var int entry_bar = na
if buy_signal
entry_price := close
is_long := true
entry_bar := bar_index
// Calculate SL
if sl_method == "Swing"
entry_sl := not na(ltf_last_swing_low) ? ltf_last_swing_low - f_pips_to_price(1) : low - f_pips_to_price(5)
else // OB method
entry_sl := ltf_bull_ob_bottom - f_pips_to_price(1)
// Calculate TPs
risk = entry_price - entry_sl
entry_tp1 := entry_price + (risk * tp1_rr)
entry_tp2 := entry_price + (risk * tp2_rr)
entry_tp3 := entry_price + (risk * tp3_rr)
// Reset opposite side
ltf_bear_bos_confirmed := false
ltf_bear_ob_valid := false
bear_fvg_valid := false
if sell_signal
entry_price := close
is_long := false
entry_bar := bar_index
// Calculate SL
if sl_method == "Swing"
entry_sl := not na(ltf_last_swing_high) ? ltf_last_swing_high + f_pips_to_price(1) : high + f_pips_to_price(5)
else // OB method
entry_sl := ltf_bear_ob_top + f_pips_to_price(1)
// Calculate TPs
risk = entry_sl - entry_price
entry_tp1 := entry_price - (risk * tp1_rr)
entry_tp2 := entry_price - (risk * tp2_rr)
entry_tp3 := entry_price - (risk * tp3_rr)
// Reset opposite side
ltf_bull_bos_confirmed := false
ltf_bull_ob_valid := false
bull_fvg_valid := false
// ═══════════════════════════════════════════════════════════════════════════════
// VISUALIZATION
// ═══════════════════════════════════════════════════════════════════════════════
// HTF OB Boxes (create once, update, delete)
if show_htf_ob
// HTF Bull OB
if htf_bull_ob_active and not na(htf_bull_ob_top)
if na(htf_bull_ob_box) or not htf_bull_ob_active[1]
if not na(htf_bull_ob_box)
box.delete(htf_bull_ob_box)
htf_bull_ob_box := box.new(htf_bull_ob_bar, htf_bull_ob_top, bar_index + 50, htf_bull_ob_bottom, border_color=color.new(color.green, 50), bgcolor=color.new(color.green, 90), border_width=1, text="M30 Bull OB", text_color=color.green, text_size=size.small)
else
box.set_right(htf_bull_ob_box, bar_index + 50)
box.set_top(htf_bull_ob_box, htf_bull_ob_top)
box.set_bottom(htf_bull_ob_box, htf_bull_ob_bottom)
else if not na(htf_bull_ob_box)
box.delete(htf_bull_ob_box)
htf_bull_ob_box := na
// HTF Bear OB
if htf_bear_ob_active and not na(htf_bear_ob_top)
if na(htf_bear_ob_box) or not htf_bear_ob_active[1]
if not na(htf_bear_ob_box)
box.delete(htf_bear_ob_box)
htf_bear_ob_box := box.new(htf_bear_ob_bar, htf_bear_ob_top, bar_index + 50, htf_bear_ob_bottom, border_color=color.new(color.red, 50), bgcolor=color.new(color.red, 90), border_width=1, text="M30 Bear OB", text_color=color.red, text_size=size.small)
else
box.set_right(htf_bear_ob_box, bar_index + 50)
box.set_top(htf_bear_ob_box, htf_bear_ob_top)
box.set_bottom(htf_bear_ob_box, htf_bear_ob_bottom)
else if not na(htf_bear_ob_box)
box.delete(htf_bear_ob_box)
htf_bear_ob_box := na
// LTF OB Boxes (create once, update, delete)
if show_ltf_ob
// LTF Bull OB
if ltf_bull_ob_valid and not na(ltf_bull_ob_top)
if na(ltf_bull_ob_box) or not ltf_bull_ob_valid[1]
if not na(ltf_bull_ob_box)
box.delete(ltf_bull_ob_box)
ltf_bull_ob_box := box.new(ltf_bull_ob_bar, ltf_bull_ob_top, bar_index + 20, ltf_bull_ob_bottom, border_color=color.new(color.blue, 30), bgcolor=color.new(color.blue, 85), border_width=1, text="LTF Bull OB", text_color=color.blue, text_size=size.tiny)
else
box.set_right(ltf_bull_ob_box, bar_index + 20)
box.set_top(ltf_bull_ob_box, ltf_bull_ob_top)
box.set_bottom(ltf_bull_ob_box, ltf_bull_ob_bottom)
else if not na(ltf_bull_ob_box)
box.delete(ltf_bull_ob_box)
ltf_bull_ob_box := na
// LTF Bear OB
if ltf_bear_ob_valid and not na(ltf_bear_ob_top)
if na(ltf_bear_ob_box) or not ltf_bear_ob_valid[1]
if not na(ltf_bear_ob_box)
box.delete(ltf_bear_ob_box)
ltf_bear_ob_box := box.new(ltf_bear_ob_bar, ltf_bear_ob_top, bar_index + 20, ltf_bear_ob_bottom, border_color=color.new(color.orange, 30), bgcolor=color.new(color.orange, 85), border_width=1, text="LTF Bear OB", text_color=color.orange, text_size=size.tiny)
else
box.set_right(ltf_bear_ob_box, bar_index + 20)
box.set_top(ltf_bear_ob_box, ltf_bear_ob_top)
box.set_bottom(ltf_bear_ob_box, ltf_bear_ob_bottom)
else if not na(ltf_bear_ob_box)
box.delete(ltf_bear_ob_box)
ltf_bear_ob_box := na
// FVG Boxes (create once, update, delete)
if show_fvg
// Bull FVG
if bull_fvg_valid and not na(active_bull_fvg_top)
if na(bull_fvg_box) or not bull_fvg_valid[1]
if not na(bull_fvg_box)
box.delete(bull_fvg_box)
bull_fvg_box := box.new(active_bull_fvg_bar, active_bull_fvg_top, bar_index + 15, active_bull_fvg_bottom, border_color=color.new(color.aqua, 40), bgcolor=color.new(color.aqua, 88), border_width=1, text="FVG", text_color=color.aqua, text_size=size.tiny)
else
box.set_right(bull_fvg_box, bar_index + 15)
box.set_top(bull_fvg_box, active_bull_fvg_top)
box.set_bottom(bull_fvg_box, active_bull_fvg_bottom)
else if not na(bull_fvg_box)
box.delete(bull_fvg_box)
bull_fvg_box := na
// Bear FVG
if bear_fvg_valid and not na(active_bear_fvg_top)
if na(bear_fvg_box) or not bear_fvg_valid[1]
if not na(bear_fvg_box)
box.delete(bear_fvg_box)
bear_fvg_box := box.new(active_bear_fvg_bar, active_bear_fvg_top, bar_index + 15, active_bear_fvg_bottom, border_color=color.new(color.fuchsia, 40), bgcolor=color.new(color.fuchsia, 88), border_width=1, text="FVG", text_color=color.fuchsia, text_size=size.tiny)
else
box.set_right(bear_fvg_box, bar_index + 15)
box.set_top(bear_fvg_box, active_bear_fvg_top)
box.set_bottom(bear_fvg_box, active_bear_fvg_bottom)
else if not na(bear_fvg_box)
box.delete(bear_fvg_box)
bear_fvg_box := na
// Labels
if show_labels
// In HTF OB label
if in_htf_bull_ob and not in_htf_bull_ob[1]
label.new(bar_index, high, "In HTF OB", style=label.style_label_down, color=color.new(color.green, 20), textcolor=color.white, size=size.tiny)
if in_htf_bear_ob and not in_htf_bear_ob[1]
label.new(bar_index, low, "In HTF OB", style=label.style_label_up, color=color.new(color.red, 20), textcolor=color.white, size=size.tiny)
// Displacement labels
if bull_displacement and in_htf_bull_ob
label.new(bar_index, low, "Displacement", style=label.style_label_up, color=color.new(color.blue, 30), textcolor=color.white, size=size.tiny)
if bear_displacement and in_htf_bear_ob
label.new(bar_index, high, "Displacement", style=label.style_label_down, color=color.new(color.orange, 30), textcolor=color.white, size=size.tiny)
// BOS labels
if ltf_bull_bos
label.new(bar_index, high, "BOS", style=label.style_label_down, color=color.new(color.green, 10), textcolor=color.white, size=size.small)
if ltf_bear_bos
label.new(bar_index, low, "BOS", style=label.style_label_up, color=color.new(color.red, 10), textcolor=color.white, size=size.small)
// Entry signals with arrows and detailed labels
plotshape(buy_signal, "Buy Signal", shape.triangleup, location.belowbar, color=color.new(color.lime, 0), size=size.normal)
plotshape(sell_signal, "Sell Signal", shape.triangledown, location.abovebar, color=color.new(color.red, 0), size=size.normal)
if buy_signal
risk_pips = (entry_price - entry_sl) / f_pip_size()
label_text = "BUY\nSL: " + str.tostring(math.round(risk_pips, 1)) + " pips\n" + "TP1: " + str.tostring(tp1_rr) + "R (" + str.tostring(partial_close_pct) + "%)\n" + "TP2: " + str.tostring(tp2_rr) + "R\n" + "TP3: " + str.tostring(tp3_rr) + "R"
label.new(bar_index, low, label_text, style=label.style_label_up, color=color.new(color.lime, 0), textcolor=color.black, size=size.normal)
if sell_signal
risk_pips = (entry_sl - entry_price) / f_pip_size()
label_text = "SELL\nSL: " + str.tostring(math.round(risk_pips, 1)) + " pips\n" + "TP1: " + str.tostring(tp1_rr) + "R (" + str.tostring(partial_close_pct) + "%)\n" + "TP2: " + str.tostring(tp2_rr) + "R\n" + "TP3: " + str.tostring(tp3_rr) + "R"
label.new(bar_index, high, label_text, style=label.style_label_down, color=color.new(color.red, 0), textcolor=color.white, size=size.normal)
// Plot SL/TP levels
plot(not na(entry_price) and not na(entry_sl) ? entry_sl : na, "Stop Loss", color=color.new(color.red, 0), linewidth=2, style=plot.style_linebr)
plot(not na(entry_price) and not na(entry_tp1) ? entry_tp1 : na, "TP1 (Partial)", color=color.new(color.yellow, 0), linewidth=1, style=plot.style_linebr)
plot(not na(entry_price) and not na(entry_tp2) ? entry_tp2 : na, "TP2", color=color.new(color.orange, 0), linewidth=1, style=plot.style_linebr)
plot(not na(entry_price) and not na(entry_tp3) ? entry_tp3 : na, "TP3", color=color.new(color.lime, 0), linewidth=1, style=plot.style_linebr)
// ═══════════════════════════════════════════════════════════════════════════════
// ALERTS
// ═══════════════════════════════════════════════════════════════════════════════
alertcondition(in_htf_bull_ob and not in_htf_bull_ob[1], "Price Enters HTF Bull OB", "Price has entered HTF Bullish Order Block zone")
alertcondition(in_htf_bear_ob and not in_htf_bear_ob[1], "Price Enters HTF Bear OB", "Price has entered HTF Bearish Order Block zone")
alertcondition(bull_displacement and in_htf_bull_ob, "Bullish Displacement Detected", "Bullish displacement candle detected in HTF Bull OB")
alertcondition(bear_displacement and in_htf_bear_ob, "Bearish Displacement Detected", "Bearish displacement candle detected in HTF Bear OB")
alertcondition(ltf_bull_bos, "Bullish BOS Confirmed", "LTF Bullish Break of Structure confirmed")
alertcondition(ltf_bear_bos, "Bearish BOS Confirmed", "LTF Bearish Break of Structure confirmed")
alertcondition(buy_signal, "BUY Entry Signal", "Potential BUY entry formed - all conditions met")
alertcondition(sell_signal, "SELL Entry Signal", "Potential SELL entry formed - all conditions met")
Show all 708 lines