Indicator · Pine Script v5 · On the chart

HTF OB M30 + LTF Entry System

by ifreddyman2014-tech· code credited to Claude AI - HTF OB M30 + LTF M1 Entry System

This multi-timeframe indicator detects order blocks on the HTF M30 timeframe and generates precise entries on the LTF M1 timeframe using break of structure, displacement, and fair value gap concepts.

View on GitHub

GitHub stars2on the repository
Pine versionv5runs as is
Lines of code708
Settings26inputs
LicenceNone statedfile: MPL-2.0
Last update8 months ago14 Feb 2026

Add It to Your TradingView Chart

  1. 1Copy the scriptPress Copy script above, or the copy button on the code below.
  2. 2Open the Pine EditorOpen a TradingView chart and choose Pine Editor at the bottom of the screen.
  3. 3Paste over the templateCreate a new indicator, select all of the template text and paste. Press Save and give it a name.
  4. 4Add it to the chartPress Add to chart, then adjust the settings with the gear icon next to its name.

Source Code

708 lines of Pine Script v5 from HTF_OB_LTF_Entry_Indicator.pine, published under MPL-2.0 (file header). Keep the author's credit and licence lines when you reuse it.

HTF_OB_LTF_Entry_Indicator.pine
// 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")

Overview

HTF OB M30 + LTF Entry System requires liquidity sweeps for confirmation and signals entries with stop loss based on swing or OB method and take profit at 1:1, 2:1, and 3:1 risk-reward ratios with partial closes. The script plots OB zones, FVG areas, and labels on the price chart while highlighting trend direction from higher timeframe analysis. Main settings adjust pivot lengths, multipliers for displacement and BOS, and visualization options. It works on forex pairs like GBPUSD but requires calibration for displacement parameters and may produce false signals in ranging markets.

Details

Published by

ifreddyman2014-tech on GitHub

Code credit

Claude AI - HTF OB M30 + LTF M1 Entry System, as written in the script's header

Type

Indicator, Pine Script v5

Draws

On the price chart

Category

SMC / ICT / price action, Support & resistance, Breakout

Markets

Forex

Timeframes

M15-H1, H4 and above

Risk Notes

No repainting, lookahead or stacked entries were found in its code or README. That says nothing about how well it works: test it first.

Settings

The inputs you can change from the gear icon on the chart. Defaults are the author's.

SettingTypeDefaultVariable
HTF Timeframe (OB Detection)timeframe30htf_timeframe
HTF Pivot Lengthint3htf_pivot_length
OB Zone ModestringWickob_mode
LTF Pivot Lengthint3ltf_pivot_length
Displacement Body Multiplierfloat1.8disp_body_mult
Body Average Lookbackint20disp_body_lookback
Displacement ATR Multiplierfloat1.5disp_atr_mult
ATR Lengthint14disp_atr_length
Close Position Thresholdfloat0.6disp_close_threshold
BOS Buffer (pips)float2.0bos_buffer_pips
BOS ATR Multiplierfloat0.5bos_atr_mult
BOS Close Position Thresholdfloat0.6bos_close_pos
Show all 26 settings
SettingTypeDefaultVariable
Use LTF OB Entrybooltrueuse_ltf_ob
Use FVG Entrybooltrueuse_fvg
Require Liquidity Sweepbooltruerequire_sweep
Sweep Buffer (pips)float1.0sweep_buffer_pips
Setup Timeout (bars)int30setup_timeout_bars
SL MethodstringSwingsl_method
TP1 (R)float1.0tp1_rr
TP2 (R)float2.0tp2_rr
TP3 (R)float3.0tp3_rr
Partial Close % at TP1float50partial_close_pct
Show HTF OB Zonesbooltrueshow_htf_ob
Show LTF OB Zonesbooltrueshow_ltf_ob
Show FVG Zonesbooltrueshow_fvg
Show Labelsbooltrueshow_labels
Third-party code. ForexR did not write, test or endorse this script, and the summary above was generated automatically from its code and README. Indicators describe the past, and a strategy's backtest can look better than live trading, especially when a script repaints. Check it in the Strategy Tester and on a demo account before you rely on it.

Similar Pine Scripts

This indicator tracks smart money market structure directly on the price chart. It calculates dual-period swing highs and swing lows to detect Changes of Character (CHoCH), Breaks of Structure (BOS), inducements, and liquidity sweeps. When structural levels ar

Indicator v5 SMC / ICT / price actionSupport & resistance
Updated 1 year ago · Apache-2.0 GitHub repository of Market Structure with Inducements & Sweeps [LuxAlgo]
24 stars

This indicator maps Smart Money Concepts (SMC) market structure directly onto the price chart. It detects internal and swing structure breaks (BOS and CHoCH), tracks bullish and bearish order blocks, identifies fair value gaps (FVG), highlights equal highs and

Indicator v5 SMC / ICT / price actionSupport & resistance Repaints
Updated 10 days ago · Custom licence GitHub repository of Smart Money Concepts [LuxAlgo] Test B
13 stars

This script identifies and visualizes bullish and bearish order blocks on the price chart. It detects low-volatility consolidation ranges followed by breakout moves accompanied by high trading volume. Users can select between Simple, Relative, or Weighted volu

Indicator v6 SMC / ICT / price actionSupport & resistance
Updated 6 months ago · MIT GitHub repository of Advanced Order Blocks with Volume

This indicator implements a Wyckoff method state machine that tracks accumulation, distribution, markup, and markdown regimes across phases A through E. It identifies structural events including springs, UTADs, SOS, SOW, LPS, LPSY, and climactic bars using ATR

Indicator v6 SMC / ICT / price actionSupport & resistance
Updated yesterday · MIT GitHub repository of Modern Wyckoff State Machine Lite [WavesUnchained]
9 stars

This multi-timeframe indicator detects and visualizes Smart Money Concepts (SMC) and ICT market structures on the price chart. It maps higher-timeframe dealing ranges, premium and discount zones, break of structure (BOS), change of character (CHoCH), order blo

Indicator v6 SMC / ICT / price actionSupport & resistance
Updated 8 months ago · None stated GitHub repository of SMC/ICT Zones Pro Generalized

More indicators

Trade Your Charts With a Regulated Broker

Compare brokers that connect to TradingView, with spreads, minimum deposits and leverage side by side.

Compare brokers