// ============================================================================
// Market Monitor — 5-Minute Optimized
// Timeframe: 5-minute (primary), compatible with 3m/10m
// Version: 1.0.0
// Author: Chris Thomas
// ============================================================================
// Directional-bias overlay purpose-built for 5-minute chart monitoring in
// multi-chart watchlist workflows (6-8 charts per window). No signal
// generation — pure context, structure, and bias assessment.
//
// Enhancements over the general-purpose Market Monitor:
// - Weighted bias scoring (structural 2x, confirmation 1x)
// - Session phase detection (Open Drive / Morning / Midday / Power Hour / Close)
// - NYSE TICK Index integration for market breadth
// - TTM Squeeze detection for volatility compression state
// - ATR regime classification (LOW / NORMAL / HIGH / EXTREME)
// - Session HOD/LOD real-time tracking
// - Opening Range levels (configurable duration)
// - Prior Day VWAP reference level
// - Anchor EMA from 15-minute timeframe (institutional trend reference)
// - Bias trend tracking (improving / deteriorating / stable)
// - Expanded dashboard (18 rows) with session context
// ============================================================================
// ============================================================================
// TradingView Pine Script v6
// ============================================================================
//@version=6
indicator(
title = "Market Monitor 5m",
shorttitle = "MM-5m",
overlay = true,
max_labels_count = 200,
max_lines_count = 300,
max_boxes_count = 100,
max_bars_back = 5000
)
// ============================================================================
// CONSTANTS
// ============================================================================
var string GP_EMA = "EMA Ribbon"
var string GP_VWAP = "VWAP"
var string GP_LEVELS = "Key Levels"
var string GP_SESSION = "Session & Time"
var string GP_BIAS = "Bias Engine"
var string GP_SQUEEZE = "TTM Squeeze"
var string GP_TICK = "NYSE TICK"
var string GP_MTF = "Multi-Timeframe"
var string GP_DASH = "Dashboard"
var string GP_VIS = "Visuals"
// Colors — dark-theme optimized, high-contrast for small tiles
var color C_BULL = #00E676
var color C_BEAR = #FF1744
var color C_NEUTRAL = #B0BEC5
var color C_YELLOW = #FFD600
var color C_ORANGE = #FF9100
var color C_CYAN = #00BCD4
var color C_PURPLE = #7C4DFF
var color C_VWAP = #FFFFFF
var color C_VWAP_BAND = color.new(#00BCD4, 60)
var color C_EMA_FAST = #FFD600
var color C_EMA_MID = #FF9100
var color C_EMA_SLOW = #FF1744
var color C_EMA_ANCHOR = #7C4DFF
var color C_CLOUD_BULL = color.new(#00E676, 85)
var color C_CLOUD_BEAR = color.new(#FF1744, 85)
var color C_CLOUD_MIX = color.new(#FFD600, 92)
var color C_PDH = #FF6E40
var color C_PDL = #64FFDA
var color C_PDC = #B0BEC5
var color C_PD_VWAP = color.new(#7C4DFF, 30)
var color C_OR_HIGH = color.new(#FFD600, 40)
var color C_OR_LOW = color.new(#FFD600, 40)
var color C_HOD = color.new(#00E676, 50)
var color C_LOD = color.new(#FF1744, 50)
var color C_DASH_BG = color.new(#1A1A2E, 5)
var color C_DASH_HEADER = #7C4DFF
var color C_DASH_TEXT = #E0E0E0
var color C_GRAY = #616161
var color C_BG_BULL = color.new(#00E676, 94)
var color C_BG_BEAR = color.new(#FF1744, 94)
var color C_SQZ_ON = #FF1744
var color C_SQZ_FIRE = #00E676
var color C_SQZ_OFF = #616161
// ============================================================================
// INPUTS
// ============================================================================
// --- EMA Ribbon ---
i_emaFastLen = input.int(9, "Fast EMA", minval=2, group=GP_EMA)
i_emaMidLen = input.int(21, "Mid EMA", minval=2, group=GP_EMA)
i_emaSlowLen = input.int(50, "Slow EMA", minval=2, group=GP_EMA)
i_showEmaCloud = input.bool(true, "Show EMA Cloud Fill", group=GP_EMA)
i_showEmas = input.bool(true, "Show EMA Lines", group=GP_EMA)
// --- VWAP ---
i_showVwap = input.bool(true, "Show VWAP", group=GP_VWAP)
i_showVwapBands = input.bool(true, "Show VWAP +/- 1 StdDev", group=GP_VWAP)
i_vwapBandMult = input.float(1.0, "VWAP Band Multiplier", minval=0.5, maxval=3.0, step=0.25, group=GP_VWAP)
// --- Key Levels ---
i_showPDLevels = input.bool(true, "Show Prev Day H/L/C", group=GP_LEVELS)
i_showPDVwap = input.bool(true, "Show Prior Day VWAP", group=GP_LEVELS,
tooltip="Previous session's closing VWAP value plotted as a reference level.")
i_showOR = input.bool(true, "Show Opening Range", group=GP_LEVELS)
i_orMinutes = input.int(15, "Opening Range Duration (min)", minval=5, maxval=60, step=5, group=GP_LEVELS,
tooltip="Number of minutes after RTH open to define the opening range. Default 15 = 3 bars on 5m.")
i_showHODLOD = input.bool(true, "Show Session HOD/LOD", group=GP_LEVELS)
i_showLevelLabels = input.bool(false, "Show Level Labels", group=GP_LEVELS,
tooltip="Labels on level lines. Disable for cleaner small tiles.")
// --- Session & Time ---
i_rthStart = input.session("0930-1600", "RTH Session", group=GP_SESSION)
i_tzOffset = input.string("America/New_York", "Timezone", group=GP_SESSION,
options=["America/New_York", "America/Chicago", "America/Los_Angeles", "UTC"])
// --- Bias Engine ---
i_rsiLen = input.int(14, "RSI Length", minval=2, group=GP_BIAS)
i_adxLen = input.int(14, "ADX Length", minval=2, group=GP_BIAS)
i_atrLen = input.int(14, "ATR Length", minval=2, group=GP_BIAS)
i_atrPctLen = input.int(100, "ATR Percentile Lookback", minval=20, maxval=500, group=GP_BIAS,
tooltip="Number of bars to compute ATR percentile ranking for regime classification.")
i_volAvgLen = input.int(20, "Volume SMA Length", minval=5, group=GP_BIAS)
i_useWeighted = input.bool(true, "Weighted Scoring", group=GP_BIAS,
tooltip="When ON, structural conditions (VWAP, EMA, Anchor EMA) score 2 points each. Confirmation conditions score 1. Max score: +/-13. When OFF, all conditions score 1 point. Max score: +/-8.")
// --- TTM Squeeze ---
i_useSqueeze = input.bool(true, "Enable TTM Squeeze", group=GP_SQUEEZE)
i_sqzBBLen = input.int(20, "BB Length", minval=5, group=GP_SQUEEZE)
i_sqzBBMult = input.float(2.0, "BB Multiplier", minval=0.5, maxval=4.0, step=0.5, group=GP_SQUEEZE)
i_sqzKCLen = input.int(20, "KC Length", minval=5, group=GP_SQUEEZE)
i_sqzKCMult = input.float(1.5, "KC Multiplier", minval=0.5, maxval=4.0, step=0.5, group=GP_SQUEEZE)
// --- NYSE TICK ---
i_useTick = input.bool(true, "Enable NYSE TICK", group=GP_TICK)
i_tickBull = input.int(500, "Bullish TICK Threshold", minval=100, maxval=1500, step=100, group=GP_TICK)
i_tickBear = input.int(-500, "Bearish TICK Threshold", minval=-1500, maxval=-100, step=100, group=GP_TICK)
// --- Multi-Timeframe ---
i_useHTF = input.bool(true, "HTF EMA Confirmation", group=GP_MTF,
tooltip="Pulls the slow EMA from the 15-minute timeframe for trend confirmation.")
i_useAnchor = input.bool(true, "Show Anchor EMA (15m 50 EMA)", group=GP_MTF,
tooltip="Plots the 50 EMA from the 15-minute chart as an institutional trend reference line.")
// --- Dashboard ---
i_showDash = input.bool(true, "Show Dashboard", group=GP_DASH)
i_dashSize = input.string("Small", "Dashboard Size", options=["Tiny", "Small", "Normal", "Large"], group=GP_DASH)
i_dashPos = input.string("Bottom Right", "Position", options=["Top Right", "Top Left", "Bottom Right", "Bottom Left"], group=GP_DASH)
// --- Visuals ---
i_showBgTint = input.bool(true, "Background Bias Tint", group=GP_VIS,
tooltip="Subtle background color indicating directional bias strength.")
i_bgThreshold = input.int(4, "Bias Threshold for Tint", minval=1, maxval=13, group=GP_VIS,
tooltip="Minimum absolute bias score to trigger background tint. Default 4 (weighted mode).")
i_showSqzDots = input.bool(true, "Show Squeeze Dots", group=GP_VIS,
tooltip="Small dots at the bottom of the chart indicating squeeze state.")
// ============================================================================
// HELPER FUNCTIONS
// ============================================================================
f2(float val) =>
str.tostring(val, "#.##")
f1(float val) =>
str.tostring(val, "#.#")
f0(float val) =>
str.tostring(val, "#")
posnegColor(float val) =>
val > 0 ? C_BULL : val < 0 ? C_BEAR : C_NEUTRAL
biasColor(int score, int maxScore) =>
float ratio = maxScore > 0 ? math.abs(score) / maxScore : 0.0
if score >= 0
ratio >= 0.6 ? C_BULL : ratio >= 0.3 ? color.new(C_BULL, 40) : C_NEUTRAL
else
ratio >= 0.6 ? C_BEAR : ratio >= 0.3 ? color.new(C_BEAR, 40) : C_NEUTRAL
biasLabel(int score, int maxScore) =>
float ratio = maxScore > 0 ? math.abs(score) / maxScore : 0.0
string dir = score >= 0 ? "BULL" : "BEAR"
if score == 0
"NEUTRAL"
else
(ratio >= 0.6 ? "STRONG " : ratio >= 0.3 ? "LEAN " : "WEAK ") + dir
// ============================================================================
// SESSION & TIME DETECTION
// ============================================================================
// Detect session boundaries using Eastern Time
int hrET = hour(time, i_tzOffset)
int minET = minute(time, i_tzOffset)
int todET = hrET * 100 + minET
bool inRTH = not na(time(timeframe.period, i_rthStart, i_tzOffset))
// Session phases (Eastern Time)
string sessionPhase = switch
todET >= 930 and todET < 1000 => "OPEN DRIVE"
todET >= 1000 and todET < 1130 => "MORNING"
todET >= 1130 and todET < 1400 => "MIDDAY"
todET >= 1400 and todET < 1530 => "POWER HOUR"
todET >= 1530 and todET < 1600 => "CLOSE"
=> "PRE/POST"
color phaseColor = switch sessionPhase
"OPEN DRIVE" => C_ORANGE
"MORNING" => C_BULL
"MIDDAY" => C_GRAY
"POWER HOUR" => C_CYAN
"CLOSE" => C_YELLOW
=> C_GRAY
// Detect new RTH session
bool newSession = inRTH and not inRTH[1]
// ============================================================================
// EMA RIBBON
// ============================================================================
emaFast = ta.ema(close, i_emaFastLen)
emaMid = ta.ema(close, i_emaMidLen)
emaSlow = ta.ema(close, i_emaSlowLen)
bool emaBullish = emaFast > emaMid and emaMid > emaSlow
bool emaBearish = emaFast < emaMid and emaMid < emaSlow
plot(i_showEmas ? emaFast : na, "EMA Fast", C_EMA_FAST, 1)
plot(i_showEmas ? emaMid : na, "EMA Mid", C_EMA_MID, 1)
pSlow = plot(i_showEmas ? emaSlow : na, "EMA Slow", C_EMA_SLOW, 2)
pFast = plot(i_showEmas ? emaFast : na, "EMA Fast Fill", color.new(chart.bg_color, 100), display=display.none)
color cloudColor = emaBullish ? C_CLOUD_BULL : emaBearish ? C_CLOUD_BEAR : C_CLOUD_MIX
fill(pFast, pSlow, i_showEmaCloud ? cloudColor : na, title="EMA Cloud")
// ============================================================================
// VWAP + BANDS (intraday)
// ============================================================================
bool intradayChart = timeframe.isintraday
var float cumTPV = 0.0
var float cumVol = 0.0
var float cumTPV2 = 0.0
if intradayChart
if ta.change(time("D")) != 0
cumTPV := 0.0
cumVol := 0.0
cumTPV2 := 0.0
float tp = hlc3
cumTPV += tp * volume
cumVol += volume
cumTPV2 += tp * tp * volume
float vwapVal = intradayChart and cumVol > 0 ? cumTPV / cumVol : na
float vwapVar = intradayChart and cumVol > 0 ? (cumTPV2 / cumVol) - (vwapVal * vwapVal) : na
float vwapStd = intradayChart and not na(vwapVar) and vwapVar > 0 ? math.sqrt(vwapVar) : na
float vwapUp = not na(vwapVal) and not na(vwapStd) ? vwapVal + vwapStd * i_vwapBandMult : na
float vwapDn = not na(vwapVal) and not na(vwapStd) ? vwapVal - vwapStd * i_vwapBandMult : na
plot(i_showVwap and intradayChart ? vwapVal : na, "VWAP", C_VWAP, 2, plot.style_line)
plot(i_showVwapBands and intradayChart ? vwapUp : na, "VWAP Upper", C_VWAP_BAND, 1, plot.style_line)
plot(i_showVwapBands and intradayChart ? vwapDn : na, "VWAP Lower", C_VWAP_BAND, 1, plot.style_line)
float vwapDist = not na(vwapVal) ? close - vwapVal : na
// ============================================================================
// PREVIOUS DAY HIGH / LOW / CLOSE
// ============================================================================
[pdHigh, pdLow, pdClose] = request.security(syminfo.tickerid, "D", [high[1], low[1], close[1]], lookahead=barmerge.lookahead_on)
plot(i_showPDLevels ? pdHigh : na, "Prev Day High", C_PDH, 1, plot.style_line)
plot(i_showPDLevels ? pdLow : na, "Prev Day Low", C_PDL, 1, plot.style_line)
plot(i_showPDLevels ? pdClose : na, "Prev Day Close", C_PDC, 1, plot.style_stepline)
// ============================================================================
// PRIOR DAY VWAP
// ============================================================================
// Pull yesterday's closing VWAP value as a static reference level for today.
// We compute VWAP on the daily timeframe using request.security. Since we
// can't directly request VWAP from a higher TF easily, we use a proxy:
// pull yesterday's VWAP close value via a helper.
//
// Method: Track session VWAP and latch the prior day's closing value.
var float pdVwap = na
if intradayChart and newSession and not na(vwapVal[1])
pdVwap := vwapVal[1]
plot(i_showPDVwap and intradayChart and not na(pdVwap) ? pdVwap : na, "Prior Day VWAP",
C_PD_VWAP, 2, plot.style_cross)
// ============================================================================
// SESSION HOD / LOD TRACKING
// ============================================================================
var float sessionHigh = na
var float sessionLow = na
if newSession
sessionHigh := high
sessionLow := low
else if inRTH
sessionHigh := math.max(nz(sessionHigh, high), high)
sessionLow := math.min(nz(sessionLow, low), low)
plot(i_showHODLOD and inRTH and not na(sessionHigh) ? sessionHigh : na, "Session HOD",
C_HOD, 1, plot.style_circles)
plot(i_showHODLOD and inRTH and not na(sessionLow) ? sessionLow : na, "Session LOD",
C_LOD, 1, plot.style_circles)
// ============================================================================
// OPENING RANGE
// ============================================================================
var float orHigh = na
var float orLow = na
var bool orLocked = false
// Number of bars in the opening range window
int orBars = math.round(i_orMinutes / timeframe.multiplier)
// Track bars since session start
var int barsSinceOpen = 0
if newSession
orHigh := high
orLow := low
orLocked := false
barsSinceOpen := 1
else if inRTH
barsSinceOpen += 1
if not orLocked
if barsSinceOpen <= orBars
orHigh := math.max(nz(orHigh, high), high)
orLow := math.min(nz(orLow, low), low)
else
orLocked := true
plot(i_showOR and inRTH and orLocked and not na(orHigh) ? orHigh : na, "OR High",
C_OR_HIGH, 1, plot.style_linebr)
plot(i_showOR and inRTH and orLocked and not na(orLow) ? orLow : na, "OR Low",
C_OR_LOW, 1, plot.style_linebr)
// ============================================================================
// RSI / ADX / ATR ENGINE
// ============================================================================
// --- RSI ---
float rsiVal = ta.rsi(close, i_rsiLen)
// --- ADX via DI+/DI- ---
[diPlus, diMinus, adxVal] = ta.dmi(i_adxLen, i_adxLen)
// --- ATR + Regime Classification ---
float atrVal = ta.atr(i_atrLen)
// ATR percentile ranking for regime classification
// Count how many of the last N ATR values are below the current ATR
int atrRank = 0
for i = 1 to i_atrPctLen
if atrVal > nz(atrVal[i])
atrRank += 1
float atrPctile = i_atrPctLen > 0 ? (atrRank / i_atrPctLen) * 100.0 : 50.0
string atrRegime = switch
atrPctile >= 90 => "EXTREME"
atrPctile >= 70 => "HIGH"
atrPctile >= 30 => "NORMAL"
=> "LOW"
color atrRegClr = switch atrRegime
"EXTREME" => C_BEAR
"HIGH" => C_ORANGE
"NORMAL" => C_BULL
=> C_CYAN
// --- Relative Volume ---
float avgVol = ta.sma(volume, i_volAvgLen)
float relVol = avgVol > 0 ? volume / avgVol : 0.0
// ============================================================================
// TTM SQUEEZE
// ============================================================================
// Bollinger Bands
float bbBasis = ta.sma(close, i_sqzBBLen)
float bbStd = ta.stdev(close, i_sqzBBLen)
float bbUpper = bbBasis + bbStd * i_sqzBBMult
float bbLower = bbBasis - bbStd * i_sqzBBMult
// Keltner Channels
float kcBasis = ta.sma(close, i_sqzKCLen)
float kcRange = ta.atr(i_sqzKCLen)
float kcUpper = kcBasis + kcRange * i_sqzKCMult
float kcLower = kcBasis - kcRange * i_sqzKCMult
// Squeeze state: BB inside KC = squeeze ON
bool sqzOn = i_useSqueeze and (bbLower > kcLower and bbUpper < kcUpper)
bool sqzOff = i_useSqueeze and not sqzOn
bool sqzFired = i_useSqueeze and sqzOff and sqzOn[1]
// Squeeze momentum (linear regression of midline momentum)
float sqzMom = ta.linreg(close - (ta.highest(high, i_sqzKCLen) + ta.lowest(low, i_sqzKCLen)) / 2.0, i_sqzKCLen, 0)
// Track bars since squeeze fired
var int sqzBarsSinceFire = 999
if sqzFired
sqzBarsSinceFire := 0
else
sqzBarsSinceFire += 1
// Squeeze dot visualization
color sqzDotColor = sqzOn ? C_SQZ_ON : sqzFired ? C_SQZ_FIRE : C_SQZ_OFF
plotshape(i_showSqzDots and i_useSqueeze ? true : false, "Squeeze Dots",
shape.circle, location.bottom, sqzDotColor, size=size.tiny)
// ============================================================================
// NYSE TICK INDEX
// ============================================================================
float tickValue = i_useTick ? request.security("USI:TICK", timeframe.period, close) : na
string tickLabel = switch
not i_useTick or na(tickValue) => "OFF"
tickValue > 1000 => "EXTREME BULL"
tickValue > i_tickBull => "BULLISH"
tickValue > 200 => "LEAN BULL"
tickValue < -1000 => "EXTREME BEAR"
tickValue < i_tickBear => "BEARISH"
tickValue < -200 => "LEAN BEAR"
=> "NEUTRAL"
color tickColor = switch
not i_useTick or na(tickValue) => C_GRAY
tickValue > 1000 => C_BULL
tickValue > i_tickBull => color.new(C_BULL, 30)
tickValue < -1000 => C_BEAR
tickValue < i_tickBear => color.new(C_BEAR, 30)
=> C_NEUTRAL
// ============================================================================
// HTF EMA CONFIRMATION (15-minute)
// ============================================================================
string htfTF = "15"
float htfEmaSlow = request.security(syminfo.tickerid, htfTF, ta.ema(close, i_emaSlowLen), lookahead=barmerge.lookahead_off)
bool htfBullish = i_useHTF ? close > htfEmaSlow : true
bool htfBearish = i_useHTF ? close < htfEmaSlow : true
// Anchor EMA (15m 50 EMA) — plotted on chart as institutional reference
plot(i_useAnchor and not na(htfEmaSlow) ? htfEmaSlow : na, "Anchor EMA (15m)",
C_EMA_ANCHOR, 2, plot.style_line)
// ============================================================================
// COMPOSITE DIRECTIONAL BIAS SCORE — WEIGHTED
// ============================================================================
// Structural conditions get 2x weight (when weighted mode enabled):
// 1. EMA alignment (fast > mid > slow = bull, inverse = bear)
// 2. Price vs VWAP (intraday)
// 3. Price vs Anchor EMA (15m 50 EMA)
//
// Confirmation conditions get 1x weight:
// 4. RSI bias (>55 = bull, <45 = bear)
// 5. DI+ vs DI- directional dominance
// 6. HTF EMA confirmation (price vs 15m slow EMA)
// 7. NYSE TICK breadth (optional)
// 8. Squeeze momentum direction (optional)
//
// Weighted max: 3*2 + 5*1 = +/-11 (or +/-13 with all optional)
// Equal max: +/-8 with all enabled
int wStructural = i_useWeighted ? 2 : 1
int wConfirm = 1
int bias = 0
// --- Structural conditions (2x weight in weighted mode) ---
// 1. EMA alignment
bias += emaBullish ? wStructural : emaBearish ? -wStructural : 0
// 2. Price vs VWAP (intraday) or price vs slow EMA (daily+)
if intradayChart and not na(vwapVal)
bias += close > vwapVal ? wStructural : close < vwapVal ? -wStructural : 0
else
bias += close > emaSlow ? wStructural : close < emaSlow ? -wStructural : 0
// 3. Price vs Anchor EMA (15m 50 EMA)
if i_useAnchor and not na(htfEmaSlow)
bias += close > htfEmaSlow ? wStructural : close < htfEmaSlow ? -wStructural : 0
// --- Confirmation conditions (1x weight) ---
// 4. RSI bias
bias += rsiVal > 55 ? wConfirm : rsiVal < 45 ? -wConfirm : 0
// 5. DI spread
bias += diPlus > diMinus ? wConfirm : diPlus < diMinus ? -wConfirm : 0
// 6. HTF confirmation
if i_useHTF
bias += htfBullish and not htfBearish ? wConfirm : htfBearish and not htfBullish ? -wConfirm : 0
// 7. NYSE TICK breadth (optional)
if i_useTick and not na(tickValue)
bias += tickValue > i_tickBull ? wConfirm : tickValue < i_tickBear ? -wConfirm : 0
// 8. Squeeze momentum direction (optional)
if i_useSqueeze and not na(sqzMom) and (sqzFired or sqzBarsSinceFire <= 3)
bias += sqzMom > 0 ? wConfirm : sqzMom < 0 ? -wConfirm : 0
// --- Maximum possible score ---
int maxScore = 3 * wStructural + 5 * wConfirm
// --- Bias trend tracking ---
// Compare current bias to rolling 3-bar average to detect improving/deteriorating bias
float biasAvg3 = ta.sma(bias, 3)
string biasTrend = bias > biasAvg3 + 0.5 ? "IMPROVING" : bias < biasAvg3 - 0.5 ? "FADING" : "STABLE"
color biasTrendClr = biasTrend == "IMPROVING" ? C_BULL : biasTrend == "FADING" ? C_BEAR : C_NEUTRAL
// ============================================================================
// BACKGROUND TINT
// ============================================================================
color bgColor = na
if i_showBgTint
if bias >= i_bgThreshold
bgColor := C_BG_BULL
else if bias <= -i_bgThreshold
bgColor := C_BG_BEAR
bgcolor(bgColor, title="Bias Background")
// ============================================================================
// DASHBOARD
// ============================================================================
if i_showDash and barstate.islast
// --- Position mapping ---
string tblYPos = str.contains(i_dashPos, "Top") ? position.top_right : position.bottom_right
if str.contains(i_dashPos, "Left")
tblYPos := str.contains(i_dashPos, "Top") ? position.top_left : position.bottom_left
string cellSize = switch i_dashSize
"Tiny" => size.tiny
"Small" => size.small
"Normal" => size.normal
"Large" => size.large
=> size.small
// 3 columns, 18 rows
var table dash = table.new(tblYPos, 3, 18,
bgcolor = C_DASH_BG,
border_width = 0,
border_color = color.new(#FFFFFF, 85),
frame_width = 1,
frame_color = color.new(#FFFFFF, 80))
// === Row 0: Header ===
table.cell(dash, 0, 0, " Market Monitor - 5m ", text_color=#FFFFFF,
bgcolor=C_DASH_HEADER, text_size=cellSize, text_halign=text.align_center)
table.cell(dash, 1, 0, "", bgcolor=C_DASH_HEADER, text_size=cellSize)
table.cell(dash, 2, 0, "", bgcolor=C_DASH_HEADER, text_size=cellSize)
table.merge_cells(dash, 0, 0, 2, 0)
// === Row 1: Bias Score ===
string biasStr = (bias > 0 ? "+" : "") + str.tostring(bias) + "/" + str.tostring(maxScore)
table.cell(dash, 0, 1, "Bias", text_color=C_DASH_TEXT, text_size=cellSize, text_halign=text.align_left)
table.cell(dash, 1, 1, biasStr, text_color=biasColor(bias, maxScore), text_size=cellSize, text_halign=text.align_right)
table.cell(dash, 2, 1, biasLabel(bias, maxScore), text_color=biasColor(bias, maxScore), text_size=cellSize, text_halign=text.align_right)
// === Row 2: Bias Trend ===
table.cell(dash, 0, 2, "Trend", text_color=C_DASH_TEXT, text_size=cellSize, text_halign=text.align_left)
table.cell(dash, 1, 2, biasTrend, text_color=biasTrendClr, text_size=cellSize, text_halign=text.align_right)
table.cell(dash, 2, 2, i_useWeighted ? "WTD" : "EQL", text_color=C_GRAY, text_size=cellSize, text_halign=text.align_right)
// === Row 3: Price / Day Change ===
float dayOpen = request.security(syminfo.tickerid, "D", open, lookahead=barmerge.lookahead_on)
float dayChg = not na(dayOpen) and dayOpen != 0 ? ((close - dayOpen) / dayOpen) * 100.0 : 0.0
string dcStr = (dayChg >= 0 ? "+" : "") + f2(dayChg) + "%"
table.cell(dash, 0, 3, "Price", text_color=C_DASH_TEXT, text_size=cellSize, text_halign=text.align_left)
table.cell(dash, 1, 3, f2(close), text_color=posnegColor(dayChg), text_size=cellSize, text_halign=text.align_right)
table.cell(dash, 2, 3, dcStr, text_color=posnegColor(dayChg), text_size=cellSize, text_halign=text.align_right)
// === Row 4: EMA Trend ===
string emaStr = emaBullish ? "BULLISH" : emaBearish ? "BEARISH" : "MIXED"
color emaClr = emaBullish ? C_BULL : emaBearish ? C_BEAR : C_YELLOW
table.cell(dash, 0, 4, "EMA", text_color=C_DASH_TEXT, text_size=cellSize, text_halign=text.align_left)
table.cell(dash, 1, 4, emaStr, text_color=emaClr, text_size=cellSize, text_halign=text.align_right)
table.cell(dash, 2, 4, str.tostring(i_emaFastLen) + "/" + str.tostring(i_emaMidLen) + "/" + str.tostring(i_emaSlowLen),
text_color=C_GRAY, text_size=cellSize, text_halign=text.align_right)
// === Row 5: RSI ===
string rsiLbl = rsiVal > 70 ? "OVERBOUGHT" : rsiVal > 55 ? "BULLISH" : rsiVal < 30 ? "OVERSOLD" : rsiVal < 45 ? "BEARISH" : "NEUTRAL"
color rsiClr = rsiVal > 70 ? C_ORANGE : rsiVal > 55 ? C_BULL : rsiVal < 30 ? C_ORANGE : rsiVal < 45 ? C_BEAR : C_NEUTRAL
table.cell(dash, 0, 5, "RSI", text_color=C_DASH_TEXT, text_size=cellSize, text_halign=text.align_left)
table.cell(dash, 1, 5, f1(rsiVal), text_color=rsiClr, text_size=cellSize, text_halign=text.align_right)
table.cell(dash, 2, 5, rsiLbl, text_color=rsiClr, text_size=cellSize, text_halign=text.align_right)
// === Row 6: ADX (Trend Strength) ===
string adxLbl = adxVal > 40 ? "STRONG" : adxVal > 25 ? "TRENDING" : adxVal > 20 ? "WEAK" : "NO TREND"
color adxClr = adxVal > 40 ? C_BULL : adxVal > 25 ? C_CYAN : adxVal > 20 ? C_YELLOW : C_GRAY
table.cell(dash, 0, 6, "ADX", text_color=C_DASH_TEXT, text_size=cellSize, text_halign=text.align_left)
table.cell(dash, 1, 6, f1(adxVal), text_color=adxClr, text_size=cellSize, text_halign=text.align_right)
table.cell(dash, 2, 6, adxLbl, text_color=adxClr, text_size=cellSize, text_halign=text.align_right)
// === Row 7: DI Spread ===
float diSpread = diPlus - diMinus
string diStr = "+" + f1(diPlus) + " / -" + f1(diMinus)
color diClr = diSpread > 0 ? C_BULL : C_BEAR
string diLbl = diSpread > 5 ? "BULLS" : diSpread < -5 ? "BEARS" : "FLAT"
table.cell(dash, 0, 7, "DI", text_color=C_DASH_TEXT, text_size=cellSize, text_halign=text.align_left)
table.cell(dash, 1, 7, diStr, text_color=diClr, text_size=cellSize, text_halign=text.align_right)
table.cell(dash, 2, 7, diLbl, text_color=diClr, text_size=cellSize, text_halign=text.align_right)
// === Row 8: ATR + Regime ===
float atrPct = close > 0 ? (atrVal / close) * 100.0 : 0.0
table.cell(dash, 0, 8, "ATR", text_color=C_DASH_TEXT, text_size=cellSize, text_halign=text.align_left)
table.cell(dash, 1, 8, f2(atrVal) + " (" + f1(atrPct) + "%)", text_color=atrRegClr, text_size=cellSize, text_halign=text.align_right)
table.cell(dash, 2, 8, atrRegime, text_color=atrRegClr, text_size=cellSize, text_halign=text.align_right)
// === Row 9: VWAP Distance ===
if intradayChart and not na(vwapDist)
float absVD = math.abs(vwapDist)
color vdClr = absVD > atrVal ? C_ORANGE : absVD > atrVal * 0.5 ? C_YELLOW : C_BULL
string vdLbl = absVD > atrVal ? "EXTENDED" : "NEAR"
table.cell(dash, 0, 9, "VWAP", text_color=C_DASH_TEXT, text_size=cellSize, text_halign=text.align_left)
table.cell(dash, 1, 9, f2(vwapDist), text_color=vdClr, text_size=cellSize, text_halign=text.align_right)
table.cell(dash, 2, 9, vdLbl, text_color=vdClr, text_size=cellSize, text_halign=text.align_right)
else
float emaDist = close - emaSlow
color edClr = emaDist > 0 ? C_BULL : C_BEAR
table.cell(dash, 0, 9, "EMA Dist", text_color=C_DASH_TEXT, text_size=cellSize, text_halign=text.align_left)
table.cell(dash, 1, 9, f2(emaDist), text_color=edClr, text_size=cellSize, text_halign=text.align_right)
table.cell(dash, 2, 9, "", text_size=cellSize)
// === Row 10: Relative Volume ===
string rvStr = f1(relVol) + "x"
color rvClr = relVol > 2.0 ? C_BULL : relVol > 1.2 ? C_YELLOW : C_GRAY
string rvLbl = relVol > 2.0 ? "SPIKE" : relVol > 1.2 ? "ABOVE" : "BELOW"
table.cell(dash, 0, 10, "RelVol", text_color=C_DASH_TEXT, text_size=cellSize, text_halign=text.align_left)
table.cell(dash, 1, 10, rvStr, text_color=rvClr, text_size=cellSize, text_halign=text.align_right)
table.cell(dash, 2, 10, rvLbl, text_color=rvClr, text_size=cellSize, text_halign=text.align_right)
// === Row 11: HTF Confirmation ===
if i_useHTF
string htfStr = htfBullish and not htfBearish ? "ABOVE" : htfBearish and not htfBullish ? "BELOW" : "AT"
color htfClr = htfBullish and not htfBearish ? C_BULL : htfBearish and not htfBullish ? C_BEAR : C_NEUTRAL
table.cell(dash, 0, 11, "HTF", text_color=C_DASH_TEXT, text_size=cellSize, text_halign=text.align_left)
table.cell(dash, 1, 11, htfStr, text_color=htfClr, text_size=cellSize, text_halign=text.align_right)
table.cell(dash, 2, 11, "15m EMA" + str.tostring(i_emaSlowLen), text_color=C_GRAY, text_size=cellSize, text_halign=text.align_right)
else
table.cell(dash, 0, 11, "HTF", text_color=C_DASH_TEXT, text_size=cellSize, text_halign=text.align_left)
table.cell(dash, 1, 11, "OFF", text_color=C_GRAY, text_size=cellSize, text_halign=text.align_right)
table.cell(dash, 2, 11, "", text_size=cellSize)
// === Row 12: TTM Squeeze ===
if i_useSqueeze
string sqzStr = sqzOn ? "SQUEEZE ON" : sqzFired ? "FIRED" : sqzBarsSinceFire <= 3 ? "FIRED (" + str.tostring(sqzBarsSinceFire) + ")" : "OFF"
color sqzClr = sqzOn ? C_SQZ_ON : (sqzFired or sqzBarsSinceFire <= 3) ? C_SQZ_FIRE : C_SQZ_OFF
string sqzDir = not na(sqzMom) ? (sqzMom > 0 ? "BULL" : "BEAR") : ""
color sqzDirClr = not na(sqzMom) ? (sqzMom > 0 ? C_BULL : C_BEAR) : C_GRAY
table.cell(dash, 0, 12, "Squeeze", text_color=C_DASH_TEXT, text_size=cellSize, text_halign=text.align_left)
table.cell(dash, 1, 12, sqzStr, text_color=sqzClr, text_size=cellSize, text_halign=text.align_right)
table.cell(dash, 2, 12, sqzDir, text_color=sqzDirClr, text_size=cellSize, text_halign=text.align_right)
else
table.cell(dash, 0, 12, "Squeeze", text_color=C_DASH_TEXT, text_size=cellSize, text_halign=text.align_left)
table.cell(dash, 1, 12, "OFF", text_color=C_GRAY, text_size=cellSize, text_halign=text.align_right)
table.cell(dash, 2, 12, "", text_size=cellSize)
// === Row 13: NYSE TICK ===
if i_useTick and not na(tickValue)
table.cell(dash, 0, 13, "TICK", text_color=C_DASH_TEXT, text_size=cellSize, text_halign=text.align_left)
table.cell(dash, 1, 13, f0(tickValue), text_color=tickColor, text_size=cellSize, text_halign=text.align_right)
table.cell(dash, 2, 13, tickLabel, text_color=tickColor, text_size=cellSize, text_halign=text.align_right)
else
table.cell(dash, 0, 13, "TICK", text_color=C_DASH_TEXT, text_size=cellSize, text_halign=text.align_left)
table.cell(dash, 1, 13, "OFF", text_color=C_GRAY, text_size=cellSize, text_halign=text.align_right)
table.cell(dash, 2, 13, "", text_size=cellSize)
// === Row 14: Prev Day Context ===
if not na(pdHigh) and not na(pdLow)
string pdPos = close > pdHigh ? "ABOVE PDH" : close < pdLow ? "BELOW PDL" : "IN RANGE"
color pdClr = close > pdHigh ? C_BULL : close < pdLow ? C_BEAR : C_YELLOW
table.cell(dash, 0, 14, "PD", text_color=C_DASH_TEXT, text_size=cellSize, text_halign=text.align_left)
table.cell(dash, 1, 14, pdPos, text_color=pdClr, text_size=cellSize, text_halign=text.align_right)
table.cell(dash, 2, 14, "", text_size=cellSize)
else
table.cell(dash, 0, 14, "PD", text_color=C_DASH_TEXT, text_size=cellSize, text_halign=text.align_left)
table.cell(dash, 1, 14, "N/A", text_color=C_GRAY, text_size=cellSize, text_halign=text.align_right)
table.cell(dash, 2, 14, "", text_size=cellSize)
// === Row 15: Opening Range Context ===
if i_showOR and orLocked and not na(orHigh) and not na(orLow)
string orPos = close > orHigh ? "ABOVE OR" : close < orLow ? "BELOW OR" : "IN OR"
color orClr = close > orHigh ? C_BULL : close < orLow ? C_BEAR : C_YELLOW
table.cell(dash, 0, 15, "OR", text_color=C_DASH_TEXT, text_size=cellSize, text_halign=text.align_left)
table.cell(dash, 1, 15, orPos, text_color=orClr, text_size=cellSize, text_halign=text.align_right)
table.cell(dash, 2, 15, f2(orHigh) + " / " + f2(orLow), text_color=C_GRAY, text_size=cellSize, text_halign=text.align_right)
else
table.cell(dash, 0, 15, "OR", text_color=C_DASH_TEXT, text_size=cellSize, text_halign=text.align_left)
table.cell(dash, 1, 15, orLocked ? "N/A" : "BUILDING", text_color=C_GRAY, text_size=cellSize, text_halign=text.align_right)
table.cell(dash, 2, 15, "", text_size=cellSize)
// === Row 16: Session HOD/LOD ===
if inRTH and not na(sessionHigh) and not na(sessionLow)
float hodDist = close - sessionHigh
float lodDist = close - sessionLow
string hodStr = "H:" + f2(sessionHigh) + " L:" + f2(sessionLow)
string sessPos = close >= sessionHigh ? "AT HOD" : close <= sessionLow ? "AT LOD" : "MID"
color sessClr = close >= sessionHigh ? C_BULL : close <= sessionLow ? C_BEAR : C_NEUTRAL
table.cell(dash, 0, 16, "Session", text_color=C_DASH_TEXT, text_size=cellSize, text_halign=text.align_left)
table.cell(dash, 1, 16, sessPos, text_color=sessClr, text_size=cellSize, text_halign=text.align_right)
table.cell(dash, 2, 16, hodStr, text_color=C_GRAY, text_size=cellSize, text_halign=text.align_right)
else
table.cell(dash, 0, 16, "Session", text_color=C_DASH_TEXT, text_size=cellSize, text_halign=text.align_left)
table.cell(dash, 1, 16, "N/A", text_color=C_GRAY, text_size=cellSize, text_halign=text.align_right)
table.cell(dash, 2, 16, "", text_size=cellSize)
// === Row 17: Prior Day VWAP ===
if intradayChart and not na(pdVwap)
float pdvDist = close - pdVwap
color pdvClr = pdvDist > 0 ? C_BULL : C_BEAR
string pdvPos = pdvDist > 0 ? "ABOVE" : "BELOW"
table.cell(dash, 0, 17, "PD VWAP", text_color=C_DASH_TEXT, text_size=cellSize, text_halign=text.align_left)
table.cell(dash, 1, 17, f2(pdVwap), text_color=pdvClr, text_size=cellSize, text_halign=text.align_right)
table.cell(dash, 2, 17, pdvPos, text_color=pdvClr, text_size=cellSize, text_halign=text.align_right)
else
table.cell(dash, 0, 17, "PD VWAP", text_color=C_DASH_TEXT, text_size=cellSize, text_halign=text.align_left)
table.cell(dash, 1, 17, "N/A", text_color=C_GRAY, text_size=cellSize, text_halign=text.align_right)
table.cell(dash, 2, 17, "", text_size=cellSize)
// ============================================================================
// ALERTS
// ============================================================================
// Threshold alerts scale with weighted mode
int strongThresh = i_useWeighted ? 7 : 5
alertcondition(bias >= strongThresh, "Strong Bullish Bias", "{{ticker}} bias score >= +" + str.tostring(strongThresh) + " on {{interval}}")
alertcondition(bias <= -strongThresh, "Strong Bearish Bias", "{{ticker}} bias score <= -" + str.tostring(strongThresh) + " on {{interval}}")
alertcondition(ta.cross(bias, 0), "Bias Crossed Neutral", "{{ticker}} bias crossed zero on {{interval}}")
alertcondition(relVol > 2.0, "Volume Spike (>2x)", "{{ticker}} relative volume > 2x on {{interval}}")
alertcondition(rsiVal > 70, "RSI Overbought", "{{ticker}} RSI > 70 on {{interval}}")
alertcondition(rsiVal < 30, "RSI Oversold", "{{ticker}} RSI < 30 on {{interval}}")
alertcondition(sqzFired, "Squeeze Fired", "{{ticker}} TTM Squeeze fired on {{interval}}")
alertcondition(not na(tickValue) and tickValue > 1000, "TICK Extreme Bull", "{{ticker}} NYSE TICK > 1000 on {{interval}}")
alertcondition(not na(tickValue) and tickValue < -1000, "TICK Extreme Bear", "{{ticker}} NYSE TICK < -1000 on {{interval}}")
// ============================================================================
// END
// ============================================================================
Overview
Market Monitor 5m calculates directional bias using exponential moving averages, VWAP, TTM Squeeze volatility state, NYSE TICK market breadth, and ATR volatility regimes. The script plots an EMA ribbon cloud, VWAP with standard deviation bands, opening range levels, session high and low bounds, and previous day key levels directly on the chart alongside an 18-row status dashboard.
The inputs you can change from the gear icon on the chart. Defaults are the author's.
Setting
Type
Default
Variable
Fast EMA
int
9
i_emaFastLen
Mid EMA
int
21
i_emaMidLen
Slow EMA
int
50
i_emaSlowLen
Show EMA Cloud Fill
bool
true
i_showEmaCloud
Show EMA Lines
bool
true
i_showEmas
Show VWAP
bool
true
i_showVwap
Show VWAP +/- 1 StdDev
bool
true
i_showVwapBands
VWAP Band Multiplier
float
1.0
i_vwapBandMult
Show Prev Day H/L/C
bool
true
i_showPDLevels
Show Prior Day VWAP
bool
true
i_showPDVwap
Show Opening Range
bool
true
i_showOR
Opening Range Duration (min)
int
15
i_orMinutes
Show all 38 settings
Setting
Type
Default
Variable
Show Session HOD/LOD
bool
true
i_showHODLOD
Show Level Labels
bool
false
i_showLevelLabels
RTH Session
session
0930-1600
i_rthStart
Timezone
string
America/New_York
i_tzOffset
RSI Length
int
14
i_rsiLen
ADX Length
int
14
i_adxLen
ATR Length
int
14
i_atrLen
ATR Percentile Lookback
int
100
i_atrPctLen
Volume SMA Length
int
20
i_volAvgLen
Weighted Scoring
bool
true
i_useWeighted
Enable TTM Squeeze
bool
true
i_useSqueeze
BB Length
int
20
i_sqzBBLen
BB Multiplier
float
2.0
i_sqzBBMult
KC Length
int
20
i_sqzKCLen
KC Multiplier
float
1.5
i_sqzKCMult
Enable NYSE TICK
bool
true
i_useTick
Bullish TICK Threshold
int
500
i_tickBull
Bearish TICK Threshold
int
-500
i_tickBear
HTF EMA Confirmation
bool
true
i_useHTF
Show Anchor EMA (15m 50 EMA)
bool
true
i_useAnchor
Show Dashboard
bool
true
i_showDash
Dashboard Size
string
Small
i_dashSize
Position
string
Bottom Right
i_dashPos
Background Bias Tint
bool
true
i_showBgTint
Bias Threshold for Tint
int
4
i_bgThreshold
Show Squeeze Dots
bool
true
i_showSqzDots
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.
This indicator overlays an intraday SPX and ES chart with a midnight session range, regular-trading-hours opening levels, and a VWAP projection box. It draws the midnight high, mid, and low, flags edge rejections within an absolute tolerance, and plots optiona
This indicator builds Market Profile Time Price Opportunity (TPO) structures across defined session timeframes directly on the main price chart. It visualizes the Point of Control (POC) and Value Area boundaries using dynamic box drawings. An integrated multi-
The Golden Bullet Strategy is an overlay signal indicator based on Smart Money Concepts and time-based liquidity models. It identifies liquidity sweeps of a designated reference session range during a specified hunt window. It then confirms Market Structure Sh
Indicatorv6SMC / ICT / price actionSessions & time
This indicator classifies the market into gamma regime types (negative gamma trend, positive gamma mean-reversion, or transition) by calculating a composite score based on daily ATR ratios, session VWAP crossover frequencies, and opening range displacement. It
This indicator marks forex trading sessions and opening ranges on the price chart. It can draw Sydney, Tokyo, Frankfurt, London, and New York session boxes or five- and fifteen-minute opening ranges, plus an optional opening channel and a day-open range. Day r