Indicator · Pine Script v6 · On the chart

Vein: Execution 15m [WavesUnchained]

by casoon

Vein Execution 15m is an execution and timing overlay designed to complement higher-timeframe context.

View on GitHub

GitHub stars9on the repository
Pine versionv6current
Lines of code540
Settings24inputs
LicenceMIT
Last updateyesterday27 Oct 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

540 lines of Pine Script v6 from indicators/trend_direction/vein/vein_execution.pine, published under MIT. Keep the author's credit and licence lines when you reuse it.

vein_execution.pine
//@version=6
// ============================================================================
// Vein Execution 15m [WavesUnchained]
// Version: 0.1.8
// Author: WavesUnchained
// Build: 2026-10-12
// ============================================================================
// Lean 15m execution/timing overlay that works WITH the 4H system.
// 4H = Context (where to look). 15m = Timing (when to act).
//
// Only activates when 4H has an interesting setup. Focuses on:
//   ✓ Micro structure shifts (pivots, BOS, higher low / lower high)
//   ✓ Liquidity sweeps (springs/upthrusts on 15m)
//   ✓ Rejection candles + engulfing
//   ✓ Follow-through / tempo validation
//   ✓ Entry + invalidation signals
//   ✓ Compact micro score (0-10)
//
// Data Contract:
//   Price:     REQUIRED   chart symbol
//   Volume:    OPTIONAL   real trade volume only — relVol degrades to neutral 1.0
//   OI:        NO
//   Reference: NO
//   Verdict:   CFD-degraded
//
// ============================================================================
indicator("Vein: Execution 15m [WavesUnchained]", "Vein Exec", overlay=true, max_labels_count=200, max_lines_count=50)

// ============================================================================
// MODULE: inputs
// ============================================================================

var gHTF = "4H Context"
string htfTimeframe     = input.timeframe("240", "HTF Timeframe", group=gHTF)
float  activationThresh = input.float(2.0, "Min 4H Setup Score to Activate", minval=0.5, maxval=5.0, step=0.5, group=gHTF, tooltip="15m only works when 4H setup >= this value")
float  zoneProximityATR = input.float(0.8, "Zone Proximity (ATR)", minval=0.2, maxval=3.0, step=0.1, group=gHTF, tooltip="Max distance to 4H zone for 'near zone' bonus")

var gMicro = "Micro Structure"
int   microLeft      = input.int(2, "Micro Pivot Left Bars", minval=1, maxval=5, group=gMicro)
int   microRight     = input.int(2, "Micro Pivot Right Bars", minval=1, maxval=5, group=gMicro)
int   sweepLookback  = input.int(10, "Sweep: Lookback Bars", minval=3, maxval=30, group=gMicro)
float sweepMinDepth  = input.float(0.1, "Sweep: Min Depth (ATR)", minval=0.0, maxval=1.0, step=0.05, group=gMicro)
int   sweepMaxBars   = input.int(3, "Sweep: Max Bars to Reclaim", minval=1, maxval=8, group=gMicro)

var gCandle = "Candle Behaviour"
float rejWickThresh  = input.float(0.45, "Rejection: Min Wick Ratio", minval=0.2, maxval=0.8, step=0.05, group=gCandle)
float engBodyRatio   = input.float(0.6, "Engulfing: Min Body Ratio", minval=0.3, maxval=0.9, step=0.05, group=gCandle)

var gTempo = "Follow-Through"
int   ftWindow       = input.int(4, "Follow-Through Window (Bars)", minval=2, maxval=8, group=gTempo)
float ftMinMove      = input.float(0.3, "Follow-Through Min Move (ATR)", minval=0.1, maxval=1.0, step=0.1, group=gTempo)
float entryScoreThresh = input.float(6.0, "Entry Min Micro Score", minval=1.0, maxval=10.0, step=0.5, group=gTempo, tooltip="Role-weighted micro score required to emit an entry (with a structure trigger). Behaviour/FT contribute weight rather than acting as a hard gate. Provisional default — not yet validated on data.")

var gDisplay = "Display"
string displayMode   = input.string("Light", "Display Mode", options=["Light", "Debug"], group=gDisplay)
bool   enableEntries = input.bool(false, "Enable Entry / Invalidation Signals", group=gDisplay,
     tooltip="Default OFF: this module shows execution context/status. Turn on to emit entry and invalidation labels/alerts.")
bool   showEntryLbl  = input.bool(true, "Show Entry Labels", group=gDisplay)
bool   showInvalLbl  = input.bool(true, "Show Invalidation Labels", group=gDisplay)
bool   showHTFLevels = input.bool(true, "Show 4H Reference Levels", group=gDisplay)
bool   showTable     = input.bool(true, "Show Status Table", group=gDisplay)

bool isDebug = displayMode == "Debug"

// ============================================================================
// MODULE: 4H context via request.security()
// ============================================================================
g_scores = "Vein Module Inputs"
htfTrendUp   = input.source(close, "Vein Trend Up Source", group=g_scores,
     tooltip="Connect to Trend module's bullish trend plot/source.")
htfTrendDown = input.source(close, "Vein Trend Down Source", group=g_scores,
     tooltip="Connect to Trend module's bearish trend plot/source.")
htfBullSetup = input.source(close, "Vein Bull Setup Score Source", group=g_scores,
     tooltip="Connect to Reversal/Structure module's bull score plot.")
htfBearSetup = input.source(close, "Vein Bear Setup Score Source", group=g_scores,
     tooltip="Connect to Reversal/Structure module's bear score plot.")

// Unconnected input.source inputs default to the chart close. When both sources of a
// pair still read close, treat the pair as not connected: setup inactive, trend neutral.
bool  setupSrcConnected = not (htfBullSetup == close and htfBearSetup == close)
bool  trendSrcConnected = not (htfTrendUp == close and htfTrendDown == close)
float bullSetupSrc = setupSrcConnected ? htfBullSetup : na
float bearSetupSrc = setupSrcConnected ? htfBearSetup : na
float trendUpSrc   = trendSrcConnected ? htfTrendUp : na
float trendDownSrc = trendSrcConnected ? htfTrendDown : na

// Reference levels pivots requested from HTF
htf_pivHi_raw = ta.pivothigh(high, 3, 3)
htf_pivLo_raw = ta.pivotlow(low, 3, 3)
htf_ema20_raw = ta.ema(close, 20)
htf_rsi_raw   = ta.rsi(close, 14)
[htfPivHi, htfPivLo, htfEma20, htfRsi] = request.security(syminfo.tickerid, htfTimeframe, [htf_pivHi_raw, htf_pivLo_raw, htf_ema20_raw, htf_rsi_raw], lookahead=barmerge.lookahead_off)

// Persist last known 4H swing levels (pivots are sparse)
var float htfSwingHi = na
var float htfSwingLo = na
if not na(htfPivHi)
    htfSwingHi := htfPivHi
if not na(htfPivLo)
    htfSwingLo := htfPivLo

// ============================================================================
// MODULE: activation gate
// ============================================================================

bool htfHasBull = not na(bullSetupSrc) and bullSetupSrc >= activationThresh
bool htfHasBear = not na(bearSetupSrc) and bearSetupSrc >= activationThresh
bool isActive   = htfHasBull or htfHasBear

// Bias: 1 = bull, -1 = bear, 0 = both/conflict
int bias = htfHasBull and not htfHasBear ? 1 : htfHasBear and not htfHasBull ? -1 : htfHasBull and htfHasBear ? 0 : 0

// ============================================================================
// MODULE: 15m base calculations
// ============================================================================

bool  volumeIsReal = (ta.cum(nz(volume)) > 0 and syminfo.volumetype != "tick") and not na(volume)
float atr15m     = ta.atr(14)
float ema9       = ta.ema(close, 9)
float avgVol     = ta.sma(volume, 20)
float relVol     = volumeIsReal and avgVol > 0 ? volume / avgVol : 1.0
float candleRange = high - low
float bodySize   = math.abs(close - open)
float upperWick  = candleRange > 0 ? (high - math.max(close, open)) / candleRange : 0.0
float lowerWick  = candleRange > 0 ? (math.min(close, open) - low) / candleRange : 0.0
float bodyRatio  = candleRange > 0 ? bodySize / candleRange : 0.0
bool  isBullBar  = close > open
bool  isBearBar  = close < open

// ============================================================================
// MODULE: micro pivots & BOS
// ============================================================================

float microPivHi = ta.pivothigh(high, microLeft, microRight)
float microPivLo = ta.pivotlow(low, microLeft, microRight)

// Persist last swing levels
var float lastMicroHi  = na
var float lastMicroLo  = na
var float prevMicroHi  = na
var float prevMicroLo  = na

if not na(microPivHi)
    prevMicroHi := lastMicroHi
    lastMicroHi := microPivHi
if not na(microPivLo)
    prevMicroLo := lastMicroLo
    lastMicroLo := microPivLo

// Micro BOS detection
bool microBullBOS = not na(lastMicroHi) and close > lastMicroHi and close[1] <= lastMicroHi
bool microBearBOS = not na(lastMicroLo) and close < lastMicroLo and close[1] >= lastMicroLo

// Structure shift detection
bool higherLow  = not na(microPivLo) and not na(prevMicroLo) and microPivLo > prevMicroLo
bool lowerHigh  = not na(microPivHi) and not na(prevMicroHi) and microPivHi < prevMicroHi

// ============================================================================
// MODULE: liquidity sweep detection
// ============================================================================

// Find recent swing low/high within lookback for sweep reference
var float sweepRefLo = na
var float sweepRefHi = na

// Use the last confirmed micro pivot as sweep reference
sweepRefLo := nz(lastMicroLo, sweepRefLo)
sweepRefHi := nz(lastMicroHi, sweepRefHi)

// Bull sweep: wick below reference low, close back above
bool sweepBullRaw = not na(sweepRefLo) and low < sweepRefLo and close > sweepRefLo
float sweepBullDepth = sweepBullRaw and atr15m > 0 ? (sweepRefLo - low) / atr15m : 0.0
bool sweepBull = sweepBullRaw and sweepBullDepth >= sweepMinDepth

// Bear sweep: wick above reference high, close back below
bool sweepBearRaw = not na(sweepRefHi) and high > sweepRefHi and close < sweepRefHi
float sweepBearDepth = sweepBearRaw and atr15m > 0 ? (high - sweepRefHi) / atr15m : 0.0
bool sweepBear = sweepBearRaw and sweepBearDepth >= sweepMinDepth

// Track sweep confirmation (holds on next bars)
var int  sweepBullAge = 999
var int  sweepBearAge = 999
var float sweepBullLevel = na
var float sweepBearLevel = na

if sweepBull
    sweepBullAge   := 0
    sweepBullLevel := low
else
    sweepBullAge += 1

if sweepBear
    sweepBearAge   := 0
    sweepBearLevel := high
else
    sweepBearAge += 1

bool sweepBullConfirmed = sweepBullAge >= 1 and sweepBullAge <= sweepMaxBars and close > nz(sweepRefLo)
bool sweepBearConfirmed = sweepBearAge >= 1 and sweepBearAge <= sweepMaxBars and close < nz(sweepRefHi)

// ============================================================================
// MODULE: rejection & candle patterns
// ============================================================================

// Bull rejection: long lower wick, small body, bias-aligned
bool bullRejection = lowerWick >= rejWickThresh and bodyRatio < 0.4 and (bias >= 0 or not isActive)
// Bear rejection: long upper wick, small body
bool bearRejection = upperWick >= rejWickThresh and bodyRatio < 0.4 and (bias <= 0 or not isActive)

// Engulfing
float prevBody = math.abs(close[1] - open[1])
bool bullEngulfing = isBullBar and close > open[1] and open < close[1] and bodySize > prevBody * engBodyRatio and bodySize > candleRange * 0.5
bool bearEngulfing = isBearBar and close < open[1] and open > close[1] and bodySize > prevBody * engBodyRatio and bodySize > candleRange * 0.5

// Range expansion after BOS
float avgRange = ta.sma(candleRange, 14)
bool rangeExpansion = candleRange > avgRange * 1.3 and relVol > 1.0

// ============================================================================
// MODULE: follow-through / tempo
// ============================================================================

// Track triggers for follow-through check
var int  bullTriggerAge = 999
var float bullTriggerPrice = na
var int  bearTriggerAge = 999
var float bearTriggerPrice = na

// A trigger fires on sweep or BOS in bias direction
bool newBullTrigger = isActive and (bias >= 0) and (sweepBull or microBullBOS)
bool newBearTrigger = isActive and (bias <= 0) and (sweepBear or microBearBOS)

if newBullTrigger
    bullTriggerAge   := 0
    bullTriggerPrice := close
else
    bullTriggerAge += 1

if newBearTrigger
    bearTriggerAge   := 0
    bearTriggerPrice := close
else
    bearTriggerAge += 1

// Follow-through: price moved in signal direction within window
bool bullFT = bullTriggerAge > 0 and bullTriggerAge <= ftWindow and not na(bullTriggerPrice) and atr15m > 0 and (close - bullTriggerPrice) / atr15m >= ftMinMove
bool bearFT = bearTriggerAge > 0 and bearTriggerAge <= ftWindow and not na(bearTriggerPrice) and atr15m > 0 and (bearTriggerPrice - close) / atr15m >= ftMinMove

// ============================================================================
// MODULE: micro score (0-10)
// ============================================================================

// Distance to the 4H swing levels — kept as a control/diagnosis reference for the
// dashboard only. Per the role ruleset, proximity to a (HTF) pivot does NOT feed the
// micro score; it is shown but never scored.
float distToHTFSup = not na(htfSwingLo) and atr15m > 0 ? math.abs(close - htfSwingLo) / atr15m : 999.0
float distToHTFRes = not na(htfSwingHi) and atr15m > 0 ? math.abs(close - htfSwingHi) / atr15m : 999.0
bool nearHTFZone = (bias >= 0 and distToHTFSup <= zoneProximityATR) or (bias <= 0 and distToHTFRes <= zoneProximityATR)

// This module has ONE score: the 15m timing evidence. The 4H setup is consumed as the
// activation/context evidence (single score path) — it is NOT re-built into a parallel
// internal setup score. microScore = Evidence(4H) + Structure + Behaviour + Tempo,
// each computed 0..1 within its role, then combined with role weights (total ≈ 0..10).

// --- Evidence role (0..1) — strength of the gating 4H setup ---
float activeSetup = bias == 1 ? nz(bullSetupSrc) : bias == -1 ? nz(bearSetupSrc) : math.max(nz(bullSetupSrc), nz(bearSetupSrc))
float evidenceRole = activationThresh > 0 ? math.min(activeSetup / (activationThresh * 2.0), 1.0) : 0.0

// --- Structure role (0..1) — 15m micro events ---
float structRaw = 0.0
if bias >= 0
    structRaw += sweepBull ? 1.0 : 0.0
    structRaw += sweepBullConfirmed ? 1.0 : 0.0
    structRaw += microBullBOS ? 1.0 : 0.0
    structRaw += higherLow ? 1.0 : 0.0
if bias <= 0
    structRaw += sweepBear ? 1.0 : 0.0
    structRaw += sweepBearConfirmed ? 1.0 : 0.0
    structRaw += microBearBOS ? 1.0 : 0.0
    structRaw += lowerHigh ? 1.0 : 0.0
if bias == 0
    structRaw := structRaw / 2.0  // dampen during conflict
float structRole = math.min(structRaw / 4.0, 1.0)

// --- Behaviour role (0..1) — candle character ---
float behRaw = 0.0
if bias >= 0
    behRaw += (bullRejection or bullEngulfing) ? 1.0 : 0.0
    behRaw += (isBullBar and rangeExpansion) ? 1.0 : 0.0
if bias <= 0
    behRaw += (bearRejection or bearEngulfing) ? 1.0 : 0.0
    behRaw += (isBearBar and rangeExpansion) ? 1.0 : 0.0
if bias == 0
    behRaw := behRaw / 2.0
float behRole = math.min(behRaw / 2.0, 1.0)

// --- Tempo role (0..1) — follow-through ---
float tempoRole = 0.0
if bias >= 0 and bullFT
    tempoRole := 1.0
if bias <= 0 and bearFT
    tempoRole := 1.0

// --- Role-weighted micro score (≈0..10): Evidence 3 · Structure 4 · Behaviour 2 · Tempo 1 ---
float microScore = isActive ? 3.0 * evidenceRole + 4.0 * structRole + 2.0 * behRole + 1.0 * tempoRole : 0.0

// Component scores retained on the original scales for the status table / data window.
float setupScore  = 3.0 * evidenceRole
float structScore = 4.0 * structRole
float behScore    = 2.0 * behRole
float tempoScore  = 1.0 * tempoRole

// ============================================================================
// MODULE: status logic
// ============================================================================

bool hasStructureTrigger = (bias >= 0 and (sweepBull or sweepBullConfirmed or microBullBOS)) or (bias <= 0 and (sweepBear or sweepBearConfirmed or microBearBOS))

string microStatus = "QUIET"
if not isActive
    microStatus := "QUIET"
else if microScore >= 7.0 and hasStructureTrigger
    microStatus := "TRIGGER"
else if microScore >= 5.0 and hasStructureTrigger
    microStatus := "SETUP"
else if microScore >= 3.0
    microStatus := "WATCH"
else
    microStatus := "QUIET"

// Effective direction for signals
int signalDir = bias == 1 ? 1 : bias == -1 ? -1 : (nz(bullSetupSrc) > nz(bearSetupSrc) ? 1 : -1)

// ============================================================================
// MODULE: entry & invalidation signals
// ============================================================================

// Entry conditions — evidence scoring, not a hard AND chain.
// Trigger = a 15m structure event firing in the bias direction (timing).
// Weight   = the role-weighted micro score must clear entryScoreThresh.
// Behaviour/follow-through now contribute weight (via microScore) instead of acting
// as a separate mandatory gate, so a strong-structure entry is no longer vetoed by a
// single missing candle-character condition.
bool bullTrigger = signalDir == 1 and (sweepBull or sweepBullConfirmed or microBullBOS)
bool bearTrigger = signalDir == -1 and (sweepBear or sweepBearConfirmed or microBearBOS)
bool entryBull = enableEntries and isActive and bullTrigger and microScore >= entryScoreThresh
bool entryBear = enableEntries and isActive and bearTrigger and microScore >= entryScoreThresh

// Track active entries for invalidation
var bool  bullEntryActive = false
var float bullEntryLevel  = na
var float bullStopLevel   = na
var int   bullEntryBar    = na
var bool  bearEntryActive = false
var float bearEntryLevel  = na
var float bearStopLevel   = na
var int   bearEntryBar    = na

if entryBull and not entryBull[1]
    bullEntryActive := true
    bullEntryLevel  := close
    bullStopLevel   := not na(sweepBullLevel) ? sweepBullLevel : nz(lastMicroLo)
    bullEntryBar    := bar_index

if entryBear and not entryBear[1]
    bearEntryActive := true
    bearEntryLevel  := close
    bearStopLevel   := not na(sweepBearLevel) ? sweepBearLevel : nz(lastMicroHi)
    bearEntryBar    := bar_index

// Invalidation checks
bool bullInval = bullEntryActive and (close < nz(bullStopLevel) or microBearBOS)
bool bearInval = bearEntryActive and (close > nz(bearStopLevel) or microBullBOS)

if bullInval
    bullEntryActive := false
if bearInval
    bearEntryActive := false

// Also expire entries after extended time without follow-through
// (entry bar tracked directly — ta.valuewhen must not be called conditionally)
if bullEntryActive and not na(bullEntryBar) and bar_index - bullEntryBar > ftWindow * 3
    bullEntryActive := false
if bearEntryActive and not na(bearEntryBar) and bar_index - bearEntryBar > ftWindow * 3
    bearEntryActive := false

// ============================================================================
// MODULE: labels
// ============================================================================

// Entry labels
if showEntryLbl and entryBull and not entryBull[1]
    label.new(bar_index, low, "ENTRY ▲", style=label.style_label_up, color=#00e676, textcolor=color.white, size=size.small)

if showEntryLbl and entryBear and not entryBear[1]
    label.new(bar_index, high, "ENTRY ▼", style=label.style_label_down, color=#ff1744, textcolor=color.white, size=size.small)

// Invalidation labels
if showInvalLbl and bullInval and not bullInval[1]
    label.new(bar_index, high, "INVAL ✗", style=label.style_label_down, color=#ff6d00, textcolor=color.white, size=size.tiny)

if showInvalLbl and bearInval and not bearInval[1]
    label.new(bar_index, low, "INVAL ✗", style=label.style_label_up, color=#ff6d00, textcolor=color.white, size=size.tiny)

// Debug: sweep + BOS labels
if isDebug and sweepBull and bias >= 0 and isActive
    label.new(bar_index, low, "SWP", style=label.style_label_up, color=color.new(#00e676, 50), textcolor=#00e676, size=size.tiny)

if isDebug and sweepBear and bias <= 0 and isActive
    label.new(bar_index, high, "SWP", style=label.style_label_down, color=color.new(#ff1744, 50), textcolor=#ff1744, size=size.tiny)

if isDebug and microBullBOS and bias >= 0 and isActive
    label.new(bar_index, low, "BOS↑", style=label.style_label_up, color=color.new(#00e676, 70), textcolor=#00e676, size=size.tiny)

if isDebug and microBearBOS and bias <= 0 and isActive
    label.new(bar_index, high, "BOS↓", style=label.style_label_down, color=color.new(#ff1744, 70), textcolor=#ff1744, size=size.tiny)

// ============================================================================
// MODULE: 4H reference levels overlay
// ============================================================================

var line htfHiLine = na
var line htfLoLine = na
var line htfEma20Line = na

if showHTFLevels and barstate.islast
    if not na(htfHiLine)
        line.delete(htfHiLine)
    if not na(htfLoLine)
        line.delete(htfLoLine)
    if not na(htfEma20Line)
        line.delete(htfEma20Line)

    if not na(htfSwingHi)
        htfHiLine := line.new(bar_index - 50, htfSwingHi, bar_index + 5, htfSwingHi, color=color.new(#ff1744, 50), style=line.style_dashed, width=1)
    if not na(htfSwingLo)
        htfLoLine := line.new(bar_index - 50, htfSwingLo, bar_index + 5, htfSwingLo, color=color.new(#00e676, 50), style=line.style_dashed, width=1)
    if not na(htfEma20)
        htfEma20Line := line.new(bar_index - 50, htfEma20, bar_index + 5, htfEma20, color=color.new(#ffab00, 40), style=line.style_dotted, width=1)

// ============================================================================
// MODULE: background tint
// ============================================================================

color bgCol = microStatus == "TRIGGER" and signalDir == 1 ? color.new(#00e676, 92) : microStatus == "TRIGGER" and signalDir == -1 ? color.new(#ff1744, 92) : microStatus == "SETUP" ? color.new(#ffab00, 95) : na
bgcolor(bgCol)

// ============================================================================
// MODULE: status table
// ============================================================================

var table statusTbl = na
if showTable and barstate.islast
    if na(statusTbl)
        statusTbl := table.new(position.top_right, 2, 7, bgcolor=color.new(color.white, 100), border_color=color.new(color.gray, 80), border_width=0, frame_color=color.new(color.gray, 80), frame_width=0)

    // Header
    table.cell(statusTbl, 0, 0, "Vein Exec", text_color=chart.fg_color, text_size=size.normal)
    color statusCol = microStatus == "TRIGGER" ? (signalDir == 1 ? #00e676 : #ff1744) : microStatus == "SETUP" ? #e65100 : microStatus == "WATCH" ? color.new(chart.fg_color, 30) : color.new(chart.fg_color, 60)
    table.cell(statusTbl, 1, 0, microStatus, text_color=statusCol, text_size=size.normal, text_halign=text.align_right)

    // 4H Context
    string biasStr = bias == 1 ? "BULL" : bias == -1 ? "BEAR" : htfHasBull and htfHasBear ? "MIXED" : "QUIET"
    color biasCol = bias == 1 ? #00e676 : bias == -1 ? #ff1744 : htfHasBull and htfHasBear ? #e65100 : color.new(chart.fg_color, 60)
    table.cell(statusTbl, 0, 1, "4H Bias", text_color=color.new(chart.fg_color, 30), text_size=size.normal)
    table.cell(statusTbl, 1, 1, biasStr + " " + str.tostring(math.max(nz(bullSetupSrc), nz(bearSetupSrc)), "#.0"), text_color=biasCol, text_size=size.normal, text_halign=text.align_right)

    // Micro Score breakdown
    table.cell(statusTbl, 0, 2, "Micro Score", text_color=color.new(chart.fg_color, 30), text_size=size.normal)
    table.cell(statusTbl, 1, 2, str.tostring(microScore, "#.0") + " / 10", text_color=microScore >= 7 ? (signalDir == 1 ? #00e676 : #ff1744) : microScore >= 5 ? #e65100 : color.new(chart.fg_color, 60), text_size=size.normal, text_halign=text.align_right)

    // Components
    table.cell(statusTbl, 0, 3, "Set|Str|Beh|Tmp", text_color=color.new(chart.fg_color, 50), text_size=size.normal)
    table.cell(statusTbl, 1, 3, str.tostring(setupScore, "#") + " | " + str.tostring(structScore, "#") + " | " + str.tostring(behScore, "#") + " | " + str.tostring(tempoScore, "#"), text_color=color.new(chart.fg_color, 30), text_size=size.normal, text_halign=text.align_right)

    // Interpretation line
    string interpStr = ""
    if not isActive
        if not setupSrcConnected
            interpStr := "4H sources not connected"
        else if nz(trendDownSrc) > 0 and nz(htfRsi) > 40
            interpStr := "4H downtrend, no exhaustion — wait"
        else if nz(trendUpSrc) > 0 and nz(htfRsi) < 60
            interpStr := "4H uptrend, no overheating — wait"
        else if nz(bullSetupSrc) > 0 or nz(bearSetupSrc) > 0
            interpStr := "4H building (" + str.tostring(math.max(nz(bullSetupSrc), nz(bearSetupSrc)), "#.0") + ") — not yet active"
        else
            interpStr := "4H quiet — nothing to time"
    else if microStatus == "TRIGGER"
        interpStr := (signalDir == 1 ? "Bull" : "Bear") + " trigger: structure + behaviour confirmed"
    else if microStatus == "SETUP"
        interpStr := "Micro structure forming — waiting for confirmation"
    else if microStatus == "WATCH"
        interpStr := "4H active, 15m watching for structure shift"
    else
        interpStr := "Active but no micro signals yet"

    color interpCol = microStatus == "TRIGGER" ? (signalDir == 1 ? #00e676 : #ff1744) : microStatus == "SETUP" ? #e65100 : color.new(chart.fg_color, 40)
    table.cell(statusTbl, 0, 4, interpStr, text_color=interpCol, text_size=size.normal)
    table.cell(statusTbl, 1, 4, "", text_size=size.normal)

    // Entry status
    string entryStr = bullEntryActive ? "BULL ENTRY active" : bearEntryActive ? "BEAR ENTRY active" : "—"
    color entryCol = bullEntryActive ? #00e676 : bearEntryActive ? #ff1744 : color.new(chart.fg_color, 60)
    table.cell(statusTbl, 0, 5, "Signal", text_color=color.new(chart.fg_color, 30), text_size=size.normal)
    table.cell(statusTbl, 1, 5, entryStr, text_color=entryCol, text_size=size.normal, text_halign=text.align_right)

    // 4H zone distance
    float nearDist = bias >= 0 ? distToHTFSup : distToHTFRes
    string distStr = nearDist < 999 ? str.tostring(nearDist, "#.1") + " ATR" : "—"
    table.cell(statusTbl, 0, 6, "4H Zone", text_color=color.new(chart.fg_color, 30), text_size=size.normal)
    table.cell(statusTbl, 1, 6, distStr, text_color=nearDist <= zoneProximityATR ? #00e676 : color.new(chart.fg_color, 30), text_size=size.normal, text_halign=text.align_right)

// ============================================================================
// MODULE: data window plots
// ============================================================================

plot(microScore, "Micro Score [dw]", display=display.data_window, color=color.new(color.gray, 100))
plot(setupScore, "Setup Score [dw]", display=display.data_window, color=color.new(color.gray, 100))
plot(structScore, "Structure Score [dw]", display=display.data_window, color=color.new(color.gray, 100))
plot(behScore, "Behaviour Score [dw]", display=display.data_window, color=color.new(color.gray, 100))
plot(tempoScore, "Tempo Score [dw]", display=display.data_window, color=color.new(color.gray, 100))
plot(nz(bullSetupSrc), "4H Bull Setup [dw]", display=display.data_window, color=color.new(color.gray, 100))
plot(nz(bearSetupSrc), "4H Bear Setup [dw]", display=display.data_window, color=color.new(color.gray, 100))
plot(bias, "Bias [dw]", display=display.data_window, color=color.new(color.gray, 100))

// ============================================================================
// MODULE: alerts
// ============================================================================

bool alertsOnBarClose = input.bool(true, "Alerts only on bar close (confirmed)", group="Alerts")
bool alertOk = not alertsOnBarClose or barstate.isconfirmed

alertcondition(alertOk and (microStatus == "TRIGGER" and signalDir == 1), "Bull Trigger", "VEIN-EXE · TRIGGER LONG · {{ticker}} {{interval}}")
alertcondition(alertOk and (microStatus == "TRIGGER" and signalDir == -1), "Bear Trigger", "VEIN-EXE · TRIGGER SHORT · {{ticker}} {{interval}}")
alertcondition(alertOk and (enableEntries and entryBull and not entryBull[1]), "Bull Entry", "VEIN-EXE · ENTRY LONG · {{ticker}} {{interval}}")
alertcondition(alertOk and (enableEntries and entryBear and not entryBear[1]), "Bear Entry", "VEIN-EXE · ENTRY SHORT · {{ticker}} {{interval}}")
alertcondition(alertOk and (enableEntries and bullInval and not bullInval[1]), "Bull Invalidation", "VEIN-EXE · INVALIDATION LONG · {{ticker}} {{interval}}")
alertcondition(alertOk and (enableEntries and bearInval and not bearInval[1]), "Bear Invalidation", "VEIN-EXE · INVALIDATION SHORT · {{ticker}} {{interval}}")
alertcondition(alertOk and (microStatus == "SETUP" and microStatus[1] != "SETUP"), "Micro Setup", "VEIN-EXE · MICRO SETUP · {{ticker}} {{interval}}")

Overview

Vein: Execution 15m [WavesUnchained] monitors lower-timeframe micro structure shifts, liquidity sweeps, rejection candles, engulfing patterns, and follow-through momentum. The script calculates a confluence micro score from 0 to 10, plotting optional entry and invalidation labels, 4-hour reference levels, and an execution status table on the main chart. Settings allow customization of higher-timeframe activation thresholds, micro pivot lookbacks, sweep parameters, and candle behavior criteria.

Details

Published by

casoon on GitHub

Type

Indicator, Pine Script v6

Draws

On the price chart

Category

Trend, SMC / ICT / price action, Support & resistance, Screeners & dashboards

Markets

Any symbol

Timeframes

M15-H1

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.

Topics

pine-scriptpinescripttechnical-analysistrading-indicatorstrading-strategiestradingview

Settings

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

SettingTypeDefaultVariable
HTF Timeframetimeframe240htfTimeframe
Min 4H Setup Score to Activatefloat2.0activationThresh
Zone Proximity (ATR)float0.8zoneProximityATR
Micro Pivot Left Barsint2microLeft
Micro Pivot Right Barsint2microRight
Sweep: Lookback Barsint10sweepLookback
Sweep: Min Depth (ATR)float0.1sweepMinDepth
Sweep: Max Bars to Reclaimint3sweepMaxBars
Rejection: Min Wick Ratiofloat0.45rejWickThresh
Engulfing: Min Body Ratiofloat0.6engBodyRatio
Follow-Through Window (Bars)int4ftWindow
Follow-Through Min Move (ATR)float0.3ftMinMove
Show all 24 settings
SettingTypeDefaultVariable
Entry Min Micro Scorefloat6.0entryScoreThresh
Display ModestringLightdisplayMode
Enable Entry / Invalidation SignalsboolfalseenableEntries
Show Entry LabelsbooltrueshowEntryLbl
Show Invalidation LabelsbooltrueshowInvalLbl
Show 4H Reference LevelsbooltrueshowHTFLevels
Show Status TablebooltrueshowTable
Vein Trend Up SourcesourceclosehtfTrendUp
Vein Trend Down SourcesourceclosehtfTrendDown
Vein Bull Setup Score SourcesourceclosehtfBullSetup
Vein Bear Setup Score SourcesourceclosehtfBearSetup
Alerts only on bar close (confirmed)booltruealertsOnBarClose
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

53 stars

Apex Trend & Liquidity Master calculates a trend cloud using customizable moving averages expanded by a volatility multiplier directly on the main price chart. It identifies dynamic support and resistance liquidity zones from swing high and low pivots, extendi

Indicator v6 TrendSupport & resistance
Updated 2 months ago · MPL-2.0 GitHub repository of Apex Trend & Liquidity Master

Quantum Structure | jjart

by MeridianAlgo
9 stars

This indicator analyzes market structure and identifies key swing highs, swing lows, and consolidation ranges across multiple timeframes. It automatically adapts swing lengths and consolidation thresholds according to chosen profiles for scalping, intraday, or

Indicator v6 SMC / ICT / price actionSupport & resistance
Updated 4 months ago · MIT GitHub repository of Quantum Structure | jjart
7 stars

Smart Krypto Futures Daytrade Suite is an all-in-one technical indicator tailored for intraday cryptocurrency trading. It plots higher-timeframe supply and demand zones, Fair Value Gaps with optional mitigation filtering, session VWAP, dynamic moving averages,

Indicator v6 SMC / ICT / price actionSupport & resistance
Updated 3 months ago · None stated GitHub repository of Smart Krypto Futures Daytrade Suite
575 stars

This indicator detects equal highs and lows by comparing prices within user-defined left and right bars using a tolerance percentage. It plots horizontal lines on the price chart for equal highs in one color and lows in another. A screener allows input of mult

Indicator v5 Support & resistanceTrend
Updated 1 year ago · MPL-2.0 GitHub repository of ICT Equal Highs and Lows with Screener

This Pine Script indicator plots a ZigZag on the price chart. It identifies reversal points when price moves more than a set percentage from the last pivot. The script calculates forecasts using zigzag data and labels detected geometric patterns including harm

Indicator v4 TrendSupport & resistance

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