Volumetric Sweep Gravity Engine [PhenLabs]📊 Volumetric Sweep Gravity Engine
Version: PineScript™ v6
📌 Description
The Volumetric Sweep Gravity Engine detects true liquidity stop-hunts and only keeps the ones backed by real volume absorption. Instead of marking every wick beyond a swing, VSGE scores each sweep with volume expansion, wick geometry, and a candle delta proxy — then projects a Fibonacci golden-zone magnet where price is most likely to get pulled next.
Traders get a clean, high-contrast chart: absorption boxes that intensify with score strength, gold-tinted gravity zones, dotted magnet lines, dual glow signal markers, and a live PhenLabs command dashboard. Built for fast visual reads on crypto, indices, FX, and metals without clutter.
🚀 Points of Innovation
Triple-factor absorption score (volume × wick ratio × delta proxy) filters weak fake sweeps
Liquidity pool tracking from confirmed swing highs/lows with ATR-buffered sweep rules
Automatic Fibonacci golden-zone gravity targets (0.618–0.786) after valid sweeps
Score-reactive zone transparency — stronger absorption draws hotter, more opaque boxes
Dotted magnet projection lines from signal price into the golden-zone midpoint
Live VSGE dashboard with bias, last event, ABS score, GZ magnet, BSL/SSL pools, and vol pulse
🔧 Core Components
Liquidity Pool Engine: Confirms swing highs (BSL) and swing lows (SSL), then watches for wick violations with optional close-back-inside stop-hunt logic
Absorption Scorer: Composites volume-vs-SMA, wick-to-body geometry, and signed volume delta into a 0–100 score with configurable weights
Gravity Projector: Measures the impulse leg and maps the 61.8–78.6 golden zone as the expected rebalance magnet
Visual Command Layer: Absorption boxes, golden zones, magnet lines, glow markers, pool rails, and a gold-framed dashboard
🔥 Key Features
Bullish and bearish volumetric sweep signals with min score gate
Optional EMA trend filter and ATR volatility floor to skip dead markets
Toggleable pool lines, absorption boxes, labels, bar coloring, and magnet lines
Max active zone cap to keep charts clean on lower timeframes
Alert conditions for bull sweeps, bear sweeps, and any sweep
Fully open-source Pine v6 with organized input groups and tooltips
🎨 Visualization
Neon triangle + soft glow circle markers tagged “VSGE” for screenshot-ready signals
Absorption boxes labeled with live ABS % and opacity scaled to conviction
Dashed golden-zone rectangles with centered GOLDEN ZONE text
Dotted gold magnet lines pulling toward the zone midpoint
BSL/SSL pool rails in bear/bull tints for structural context
Top-right dark dashboard with gold border, bias coloring, and vol pulse readout
📖 Usage Guidelines
Swing Lookback — Default: 5 — Range: 2-30 — Higher = fewer, more structural pools
Sweep Buffer (ATR mult) — Default: 0.05 — Range: 0-1 — Extra wick extension required beyond the pool
Require Close Back Inside — Default: true — Enforces classic stop-hunt reclaim closes
Min Sweep Wick (ATR) — Default: 0.15 — Range: 0.05-2 — Rejects tiny liquidity nicks
Volume SMA Length — Default: 20 — Range: 5-100 — Baseline for absorption volume
Absorption Volume Mult — Default: 1.4 — Range: 1-5 — Minimum volume expansion vs SMA
Min Wick/Body Ratio — Default: 1.5 — Range: 0.5-10 — Ensures rejection-style geometry
Min Absorption Score — Default: 55 — Range: 0-100 — Composite gate for signals
Golden Zone Low/High (Fib) — Default: 0.618 / 0.786 — Retracement band for gravity targets
Impulse Lookback Bars — Default: 8 — Range: 3-40 — Bars used to size the impulse leg
Max Active Zones — Default: 6 — Range: 1-20 — Limits drawn boxes/lines/labels
EMA Trend Filter — Default: off — Optional 200 EMA directional gate
Min ATR Volatility Filter — Default: on — Skips low-volatility chop vs ATR SMA
✅ Best Use Cases
Intraday liquidity-grab reversals on crypto, Nasdaq, Gold, and major FX pairs
Confirming stop-hunts before entering toward the golden-zone magnet
Filtering pure wick noise by requiring volumetric absorption
Screenshot-friendly SMC setups for education, social posts, and journal reviews
⚠️ Limitations
Delta is a candle-geometry proxy, not true bid/ask order-flow data
Pivot pools confirm with lag equal to the swing lookback
Golden zones are probabilistic magnets, not guaranteed fill targets
Dense lower-timeframe charts may need higher min score or lower max zones
💡 What Makes This Unique
Fuses liquidity sweeps + volumetric absorption scoring + Fibonacci gravity in one engine — a combination missing from pure sweep or pure Fib tools
Score-reactive visuals make conviction readable at a glance for SEO screenshots and live trading
PhenLabs-style command dashboard turns structure, score, and magnet price into a single decision panel
🔬 How It Works
Map liquidity pools from confirmed swing highs (BSL) and swing lows (SSL)
Detect sweeps when price wicks beyond a pool by ATR buffer and optionally closes back inside
Score absorption using volume expansion, wick/body geometry, and signed delta proxy
If score clears the minimum gate, draw the absorption box and project the 0.618–0.786 golden gravity zone with a magnet line
Update the live dashboard (bias, last event, ABS score, GZ magnet, pools, vol pulse) and fire alerts
💡 Note:
Use VSGE as a confluence layer with your own risk rules, higher-timeframe bias, and position sizing. This is an analytical aid for studying liquidity and absorption behavior — not financial advice. Indicatore

Multi-Timeframe Trend Matrix [JOAT]Multi-Timeframe Trend Matrix
Reads several timeframes with several methods at once and scores their agreement into a single alignment signal — without lookahead.
What it is
Trading a single timeframe blinds you to the larger context; watching many by eye is slow and inconsistent. This indicator evaluates a grid of timeframes and trend methods, turns the whole grid into one alignment score, and signals when top-down agreement forms. It is an original multi-timeframe aggregation tool built to avoid the common pitfalls of higher-timeframe requests.
How it works
• The matrix — a set of higher and lower timeframes is each assessed by several independent trend methods (such as a moving-average relationship, a directional trend measure and a momentum read). Each cell of the grid returns simply bullish or bearish, so the picture is easy to interpret.
• No lookahead — every higher-timeframe value is pulled with lookahead disabled, so the indicator never borrows future data from an unclosed higher-timeframe bar. This is a deliberate, disclosed design choice that keeps the signals honest and non-repainting on historical bars.
• Alignment score — the grid is condensed into one signed score representing how strongly all timeframes and methods agree. Full agreement produces a strong reading; a split grid produces a weak, near-neutral one.
• State-machine signals — a Buy fires when alignment turns sufficiently bullish from a non-bullish state; a Sell is the mirror. Requiring a state change means the matrix will not re-signal the same direction repeatedly — the signals are self-spacing.
Trade levels
Each signal draws a red risk box to the ATR stop and a green reward box to the third target, with inner dividers and right-edge labels for entry, stop and each take-profit at your R multiples.
The dashboard
An adjustable alignment-matrix panel displays every timeframe-by-method cell as bullish or bearish, a bipolar alignment-score headline, the active signal, a conviction estimate, and a live first-target-before-stop tally from closed bars only. The grid shows exactly which timeframes agree and which disagree.
How to use it
• Works on any asset; pick a base timeframe and let the grid supply the higher-timeframe context.
• Favour entries when the grid is broadly aligned; be cautious when it is mixed.
• Use it as a top-down filter alongside your own entry method, or take its aligned signals directly.
Settings
The set of timeframes, the methods and their lengths, the alignment threshold, ATR risk multiple and target R multiples, plus visual and dashboard controls.
Originality and usefulness
The contribution is the aggregation framework: a disciplined, lookahead-free multi-timeframe, multi-method grid condensed into one transparent alignment score with a state-machine trigger. Seeing the full grid — not just a final arrow — is what lets a trader trust or override the signal for themselves.
Notes and limitations
• Higher-timeframe values update only as those bars close, so alignment can shift when a higher-timeframe bar completes — this is expected and prevents lookahead bias.
• Strong alignment can still precede a reversal; agreement is context, not certainty.
• The tally reflects only past bars on the current chart and is not a forecast.
• Educational and analytical tool, not financial advice.
— made with passion by officialjackofalltrades
Indicatore

Rogue Overnight Volume ProfileRogue Overnight Volume Profile
The Rogue Overnight Volume Profile is an institutional-style overnight volume profile designed specifically for futures traders who use overnight auction structure to prepare for the Regular Trading Hours (RTH) session.
Unlike traditional session volume profiles that remain fixed throughout the day, Rogue Overnight Profile automatically builds the overnight distribution, identifies the most important price levels, and projects them into the current trading session for easy decision making.
Features:
Overnight Volume Profile
Automatically builds a complete volume profile during the overnight session.
Adjustable profile resolution with up to 1,000 price rows.
Value Area (default 70%)
Point of Control (POC)
Value Area High (OVAH)
Value Area Low (OVAL)
Customizable profile colors and placement.
Dynamic Overnight Levels
The indicator automatically calculates and plots:
OVAH (Overnight Value Area High)
OPOC (Overnight Point of Control)
OVAL (Overnight Value Area Low)
These levels begin at the start of the completed overnight profile and extend just beyond current price during the New York session, keeping the chart clean while maintaining important reference levels.
Historical overnight levels are retained for previous sessions to assist with market structure analysis.
Developing Overnight Range:
Monitor the overnight auction as it forms with an optional shaded developing range, allowing traders to visualize overnight balance before the market opens.
Weekly VWAP
Includes a built-in Weekly VWAP with customizable color and line width to provide higher-timeframe context and institutional bias.
5-Period Moving Average
A configurable 5-period moving average (EMA or SMA) can be displayed to help identify short-term momentum and trend direction.
First Touch Detection
Automatically identifies the first interaction with overnight profile levels during the New York session.
Supported first-touch signals include:
OVAH First Touch
OPOC First Touch
OVAL First Touch
These areas often act as important decision points where responsive buyers or sellers may enter the market.
Break & Retest Detection
The indicator can also detect break-and-retest setups after price establishes acceptance above or below an overnight level.
Bullish and bearish retest opportunities are labeled automatically, making it easier to identify continuation setups around key profile references.
Fully Customizable
Every major component can be enabled, disabled, or customized, including:
Session times
Profile resolution
Value Area percentage
Historical sessions displayed
Colors
Labels
Weekly VWAP
Moving Average
Touch detection
Retest detection
Designed For
Nasdaq Futures (NQ)
S&P Futures (ES)
Dow Futures (YM)
Russell Futures (RTY)
Crude Oil (CL)
Any market where overnight auction structure influences the regular session.
Best Used For
Identifying overnight support and resistance.
Planning opening scenarios.
Fade and acceptance trades around OVAH, OPOC, and OVAL.
Breakout confirmation.
Break-and-retest continuation setups.
Understanding overnight market positioning before the RTH open.
Disclaimer: This indicator is intended as a decision-support tool and does not provide financial advice. Always incorporate sound risk management and additional market context before entering any trade. Indicatore

Strategia

Indicatore

Indicatore

Indicatore

Indicatore

Indicatore

Forward P/E (MUST COMPLETE STEP 1 FOR INDICATOR TO WORK)Forward P/E Valuation Indicator (MUST COMPLETE STEP 1 FOR THE INDICATOR TO WORK)
1. Set up the indicator
Use the indicator on a 1-day chart. Its one- and three-year calculations assume daily bars.
First, add these TradingView indicators to your chart:
a. P/E forward
b. Price/earnings to growth ratio, usually shown as PEG ratio
c. Then add the custom Forward P/E Valuation indicator.
Open the "Forward P/E Valuation indicator" settings → Inputs and select:
P/E forward → Choose the P/E forward from the dropdown
Price/earnings to growth ratio → Choose the PEG ratio from the dropdown
After selecting the correct sources, click to add a checkmark to the following boxes:
a. P/E forward source linked correctly
b. PEG source linked correctly
Now, the "Forward P/E Valuation" indicator will work.
2. Recommended settings
The default settings are appropriate for most stocks:
Chart band lookback: 3 Years
Forward EPS trend threshold: 2%
Primary-driver lookback: 21 bars
Primary-driver threshold: 3%
Growth-supported premium threshold: 15%
Growth-supportive PEG: 1.5×
Use the three-year lookback for the main interpretation. Switch to one year only when you want to emphasize the stock’s recent valuation regime.
How to read the dashboard:
Read the first four rows first. They summarize the model’s conclusion.
Overall Valuation Status
This compares the current forward P/E with its selected historical range.
Rank
Status
0%–5% = Deep Discount
Above 5%–10% = Cheap
Above 10%–25% = Below Normal
Above 25%–Below 75% = Normal
75%–Below 90% = Above Normal
90%–Below 95% = Expensive
95%–100% = Extreme Expensive
A low percentile means the forward P/E is low relative to its own history. It does not automatically mean the stock is undervalued.
Valuation + Growth Signal
This combines valuation, growth, estimate direction, and PEG.
Signal
Meaning
Attractive Discount
Historically inexpensive with supportive growth or rising estimates
Potential Value
Cheap, but growth confirmation is limited
Value-Trap Risk
Cheap while growth or estimates are deteriorating
Growth-Supported Premium
Expensive, but strong growth may justify the premium
Multiple Risk
Expensive without enough growth support
High-Risk Premium
Expensive while estimates or growth are deteriorating
Improving Fundamentals
Normal valuation with rising estimates
Balanced
Normal valuation with stable estimates
The strongest favorable reading is Attractive Discount. The most concerning is High-Risk Premium.
Valuation + Estimate Direction
This gives a simpler valuation-versus-estimates interpretation.
Reading
Interpretation
Discount + Upgrades
Favorable valuation with improving estimates
Discount + Stable Estimates
Potential value, but no estimate catalyst
Discount + Cuts
Possible value trap
Normal + Upgrades
Improving fundamentals at a normal valuation
Premium + Upgrades
Expensive but supported by estimate improvement
Premium + Cuts
Highest-risk combination
Primary Driver
This explains what caused the recent movement over approximately 21 trading days.
Driver
Meaning
Earnings-Led Advance
Price rose mainly because forward EPS improved
Price + Estimate Expansion
Both estimates and the valuation multiple improved
Price-Led Multiple Expansion
Price rose without much earnings improvement
Estimate Upgrades / Price Lag
Estimates improved, but price has not responded
Price-Led Multiple Compression
Price fell more than estimates, making valuation cheaper
Estimate Cuts
Forward earnings expectations weakened
Price Up Despite Estimate Cuts
Price rose while estimates declined; caution
Stable / Consolidation
No major price, EPS, or P/E movement
The Context column shows the actual price, EPS, and P/E percentage changes used in the classification.
Supporting dashboard rows
TradingView Forward P/E
This is the directly linked TradingView forward-P/E value. It drives the historical ranks, medians, bands, and valuation status.
Implied Forward EPS
Calculated as:
Implied Forward EPS=Stock PriceForward P/E\text{Implied Forward EPS} = \frac{\text{Stock Price}}{\text{Forward P/E}}Implied Forward EPS=Forward P/EStock Price
Example:
210÷21=$10.00210\div21=\$10.00210÷21=$10.00
This is the earnings denominator implied by TradingView’s forward-P/E reading.
Current P/E Ratio
Calculated from:
Price÷Trailing-12-Month EPS\text{Price}\div\text{Trailing-12-Month EPS}Price÷Trailing-12-Month EPS
A forward P/E materially below the current P/E generally indicates expected earnings growth.
Forward EPS Growth Proxy
Compares implied forward EPS with the latest reported fiscal-year diluted EPS.
General interpretation:
Negative: expected earnings deterioration
0%–10%: limited growth
10%–15%: moderate growth
Above 15%: strong growth
This is a proxy, not a perfect analyst-consensus growth measure.
PEG Ratio
The PEG value comes from the linked TradingView PEG indicator.
Below 1.0×: low valuation relative to growth
1.0×–1.5×: generally growth supportive
1.5×–2.0×: moderate premium
Above 2.0×: valuation increasingly dependent on sustained growth
Do not use PEG alone. Cyclical or temporarily depressed earnings can distort it.
1Y / 3Y P/E Rank
Shows where the current forward P/E falls relative to its one- and three-year history.
Example:
12% / 38%
The stock is inexpensive compared with the past year, but closer to normal compared with the past three years.
1Y / 3Y Median P/E
Shows the stock’s typical forward P/E over each period.
If the current P/E is below both medians, the stock is trading below its recent historical norms.
Forward EPS Trend
Rising: latest detected revision above +2%
Stable: between −2% and +2%
Falling: below −2%
Rising estimates generally strengthen a favorable valuation signal. Falling estimates weaken it.
Estimate Freshness
Fresh: 0–100 days
Aging: 101–180 days
Stale: more than 180 days
This measures how long it has been since the model detected a meaningful change in implied forward EPS. It is not necessarily the exact analyst-revision date.
Model Confidence
High: 80%–100%
Medium: 60%–79%
Low: below 60%
Confidence reflects source links, historical coverage, available EPS data, freshness, and use of a daily chart.
Low confidence means insufficient data—not necessarily a negative stock outlook.
Two practical examples
Favorable setup
Overall Valuation: Cheap
Valuation + Growth: Attractive Discount
Valuation + Estimate Direction: Discount + Upgrades
Primary Driver: Earnings-Led Advance
Forward EPS Trend: Rising
Confidence: High
Interpretation: the stock is historically inexpensive, estimates are improving, and earnings rather than pure multiple expansion are supporting the move.
Warning setup
Overall Valuation: Expensive
Valuation + Growth: High-Risk Premium
Valuation + Estimate Direction: Premium + Cuts
Primary Driver: Price Up Despite Estimate Cuts
Forward EPS Trend: Falling
Confidence: High
Interpretation: the stock is historically expensive while earnings expectations are weakening. Price strength is being supported primarily by multiple expansion, which increases downside risk.
Best quick-reading rule
The most favorable combination is:
Discount + Upgrades + Attractive Discount + Earnings-Led Advance
The most concerning combination is:
Premium + Cuts + High-Risk Premium + Price Up Despite Estimate Cuts
Here is the code:
//@version=6
indicator("Forward P/E Linked Metrics ", shorttitle="Forward PE", overlay=false, max_bars_back=2000, precision=2)
// ============================================================================
// PURPOSE
// ============================================================================
// This version links only the TradingView plots that are available through
// input.source():
//
// Required linked sources:
// 1. TradingView "P/E forward"
// 2. TradingView "Price/earnings to growth ratio" / "PEG ratio"
//
// The regular current P/E is calculated internally:
// Current P/E = Current price / TTM EPS
//
// The model recovers the forward EPS denominator from the linked forward P/E:
// Implied forward EPS = Current price / Linked forward P/E
//
// If the linked P/E-forward plot is TradingView's live price-to-forward-EPS
// series, this inversion recovers the underlying forward EPS estimate while
// preserving an exact match with TradingView's displayed forward P/E.
//
// Use primarily on a 1D chart so 252 and 756 bars approximate 1 and 3 years.
//
// Added decision framework:
// 1. Overall Valuation Status
// 2. Valuation + Growth Signal
// 3. Valuation + Estimate Direction
// 4. Primary Driver
// ============================================================================
// 1. LINK TRADINGVIEW METRICS
// ============================================================================
grpLinks = "1. Link TradingView Metrics"
forwardPESource = input.source(
close,
"P/E forward",
tooltip="Select the plot from TradingView's built-in P/E forward indicator.",
group=grpLinks,
display=display.none)
pegRatioSource = input.source(
close,
"Price/earnings to growth ratio",
tooltip="Select the plot from TradingView's PEG ratio indicator.",
group=grpLinks,
display=display.none)
confirmForwardPELinked = input.bool(
false,
"P/E forward source linked correctly",
group=grpLinks,
display=display.none)
confirmPEGLinked = input.bool(
false,
"PEG source linked correctly",
group=grpLinks,
display=display.none)
// ============================================================================
// 2. MODEL SETTINGS
// ============================================================================
grpModel = "2. Model Settings"
minValidEPS = input.float(
0.01,
"Minimum valid implied forward EPS",
minval=0.0001,
step=0.01,
group=grpModel,
display=display.none)
maxValidEPS = input.float(
1000.0,
"Maximum valid implied forward EPS",
minval=1.0,
step=10.0,
group=grpModel,
display=display.none)
minValidPE = input.float(
0.1,
"Minimum valid P/E",
minval=0.0,
step=0.1,
group=grpModel,
display=display.none)
maxValidPE = input.float(
500.0,
"Maximum valid P/E",
minval=1.0,
step=5.0,
group=grpModel,
display=display.none)
maxValidPEG = input.float(
100.0,
"Maximum valid PEG",
minval=1.0,
step=1.0,
group=grpModel,
display=display.none)
chartLookback = input.string(
"3 Years",
"Chart band lookback",
options= ,
group=grpModel,
display=display.none)
trendThreshold = input.float(
2.0,
"Forward EPS revision trend threshold %",
minval=0.0,
step=0.25,
group=grpModel,
display=display.none)
revisionDetectionPct = input.float(
0.05,
"Minimum implied EPS change counted as a revision %",
minval=0.001,
step=0.01,
group=grpModel,
display=display.none)
freshDays = input.int(
100,
"Fresh estimate: maximum calendar days",
minval=1,
group=grpModel,
display=display.none)
staleDays = input.int(
180,
"Aging estimate: maximum calendar days",
minval=2,
group=grpModel,
display=display.none)
primaryDriverLookback = input.int(
21,
"Primary driver lookback bars",
minval=5,
maxval=252,
group=grpModel,
display=display.none)
primaryDriverThreshold = input.float(
3.0,
"Primary driver movement threshold %",
minval=0.5,
step=0.5,
group=grpModel,
display=display.none)
growthSupportThreshold = input.float(
15.0,
"Growth-supported premium threshold %",
minval=0.0,
step=1.0,
group=grpModel,
display=display.none)
attractivePEGThreshold = input.float(
1.5,
"PEG threshold considered growth supportive",
minval=0.1,
step=0.1,
group=grpModel,
display=display.none)
// ============================================================================
// 3. VISUALS & DASHBOARD
// ============================================================================
grpVisual = "3. Visuals & Dashboard"
showMedianLine = input.bool(
true,
"Show historical median",
group=grpVisual,
display=display.none)
showPercentileBands = input.bool(
true,
"Show percentile bands",
group=grpVisual,
display=display.none)
showNormalZoneFill = input.bool(
true,
"Fill normal valuation zone",
group=grpVisual,
display=display.none)
showExtremeBackground = input.bool(
false,
"Highlight 5th / 95th percentile extremes",
group=grpVisual,
display=display.none)
showDashboard = input.bool(
true,
"Show dashboard",
group=grpVisual,
display=display.none)
dashboardPosition = input.string(
"Top Right",
"Dashboard position",
options= ,
group=grpVisual,
display=display.none)
// ============================================================================
// CONSTANTS
// ============================================================================
bars1Y = 252
bars3Y = 756
dayMs = 86400000.0
selectedLength = chartLookback == "1 Year" ? bars1Y : bars3Y
// ============================================================================
// COLOR PALETTE — LIGHT CHART / DARK DASHBOARD
// ============================================================================
clrSlate0 = color.rgb(45, 52, 64)
clrSlate1 = color.rgb(55, 62, 74)
clrSlate2 = color.rgb(69, 76, 88)
clrText = color.rgb(248, 249, 251)
clrMuted = color.rgb(205, 211, 220)
clrDarkText = color.rgb(42, 49, 60)
clrGreenText = color.rgb(18, 145, 88)
clrRedText = color.rgb(211, 52, 69)
clrAmberText = color.rgb(181, 112, 8)
clrTeal = color.rgb(35, 190, 208)
clrAqua = color.rgb(70, 198, 235)
clrBlue = color.rgb(72, 116, 235)
clrGreen = color.rgb(40, 178, 109)
clrAmber = color.rgb(245, 179, 48)
clrOrange = color.rgb(245, 153, 36)
clrRed = color.rgb(235, 74, 91)
clrGrayLine = color.rgb(116, 125, 140)
clrLightCyan = color.rgb(126, 216, 233)
clrLightBlue = color.rgb(202, 232, 242)
clrLightGray = color.rgb(205, 209, 215)
clrLightMint = color.rgb(214, 241, 226)
clrLightAmber = color.rgb(250, 232, 192)
clrLightRed = color.rgb(249, 220, 225)
// ============================================================================
// HELPERS
// ============================================================================
f_valid_eps(_value) =>
not na(_value) and _value >= minValidEPS and _value <= maxValidEPS ? _value : na
f_valid_pe(_value) =>
not na(_value) and _value >= minValidPE and _value <= maxValidPE ? _value : na
f_valid_peg(_value) =>
not na(_value) and _value > 0.0 and _value <= maxValidPEG ? _value : na
f_x(_value) =>
na(_value) ? "n/a" : str.tostring(_value, "#.##") + "x"
f_pct(_value) =>
na(_value) ? "n/a" : str.tostring(_value, "#.##") + "%"
f_eps(_value) =>
na(_value) ? "n/a" : str.tostring(_value, "#.##")
f_rank_text(_value) =>
na(_value) ? "n/a" : str.tostring(_value, "#") + "%"
f_position(_selection) =>
_selection == "Top Left" ? position.top_left :
_selection == "Bottom Right" ? position.bottom_right :
_selection == "Bottom Left" ? position.bottom_left :
position.top_right
f_rank_color(_rank, _ready) =>
color _result = clrGrayLine
if _ready and not na(_rank)
if _rank >= 95
_result := clrRed
else if _rank >= 90
_result := clrOrange
else if _rank >= 75
_result := clrAmber
else if _rank <= 5
_result := clrBlue
else if _rank <= 10
_result := clrAqua
else if _rank <= 25
_result := clrTeal
else
_result := clrGrayLine
_result
f_rank_fill_color(_rank, _ready) =>
color _result = clrLightGray
if _ready and not na(_rank)
if _rank >= 95
_result := clrLightRed
else if _rank >= 75
_result := clrLightAmber
else if _rank <= 25
_result := clrLightCyan
else
_result := clrLightGray
_result
// ============================================================================
// LINKED METRICS
// ============================================================================
linkedForwardPE = confirmForwardPELinked ? f_valid_pe(forwardPESource) : na
linkedPEG = confirmPEGLinked ? f_valid_peg(pegRatioSource) : na
// Regular trailing P/E calculated internally using TradingView's documented
// price-to-TTM-EPS method.
epsTTMRaw = request.financial(
syminfo.tickerid,
"EARNINGS_PER_SHARE",
"TTM",
gaps=barmerge.gaps_off,
ignore_invalid_symbol=true,
currency=syminfo.currency)
epsTTM = f_valid_eps(epsTTMRaw)
currentPERatio = f_valid_pe(
not na(epsTTM) and epsTTM > 0.0 ? close / epsTTM : na)
// Invert TradingView's linked forward P/E to recover its implied forward EPS.
impliedForwardEPS = f_valid_eps(
not na(linkedForwardPE) and linkedForwardPE > 0.0 ? close / linkedForwardPE : na)
// Latest annual diluted EPS is used only as a baseline for a growth proxy.
priorFYDilutedEPSRaw = request.financial(
syminfo.tickerid,
"EARNINGS_PER_SHARE_DILUTED",
"FY",
gaps=barmerge.gaps_off,
ignore_invalid_symbol=true,
currency=syminfo.currency)
priorFYDilutedEPS = f_valid_eps(priorFYDilutedEPSRaw)
forwardEPSGrowthProxy =
not na(impliedForwardEPS) and not na(priorFYDilutedEPS) and priorFYDilutedEPS > 0.0 ?
((impliedForwardEPS / priorFYDilutedEPS) - 1.0) * 100.0 :
na
// The PEG identity is PEG = P/E ÷ growth rate. When both linked metrics are
// available, this recovers the growth rate implicit in TradingView's PEG.
pegImpliedGrowthPct =
not na(currentPERatio) and not na(linkedPEG) and linkedPEG > 0.0 ?
currentPERatio / linkedPEG :
na
// ============================================================================
// IMPLIED FORWARD EPS TREND AND FRESHNESS
// ============================================================================
impliedEPSChangePct =
not na(impliedForwardEPS) and
not na(impliedForwardEPS ) and
impliedForwardEPS != 0.0 ?
((impliedForwardEPS / impliedForwardEPS ) - 1.0) * 100.0 :
na
impliedEPSChanged =
not na(impliedEPSChangePct) and
math.abs(impliedEPSChangePct) >= revisionDetectionPct
var float latestPublishedEstimate = na
var float priorPublishedEstimate = na
var int lastEstimateUpdateTime = na
if impliedEPSChanged
priorPublishedEstimate := latestPublishedEstimate
latestPublishedEstimate := impliedForwardEPS
lastEstimateUpdateTime := time
// Seed the latest available estimate without falsely labeling it a revision.
if na(latestPublishedEstimate) and not na(impliedForwardEPS)
latestPublishedEstimate := impliedForwardEPS
estimateRevisionPct =
not na(latestPublishedEstimate) and
not na(priorPublishedEstimate) and
priorPublishedEstimate != 0.0 ?
((latestPublishedEstimate / priorPublishedEstimate) - 1.0) * 100.0 :
na
string estimateTrendText = "No prior revision"
color estimateTrendColor = clrMuted
if not na(estimateRevisionPct)
if estimateRevisionPct > trendThreshold
estimateTrendText := "Rising"
estimateTrendColor := clrGreen
else if estimateRevisionPct < -trendThreshold
estimateTrendText := "Falling"
estimateTrendColor := clrRed
else
estimateTrendText := "Stable"
estimateTrendColor := clrAmber
estimateAgeDays =
not na(lastEstimateUpdateTime) ?
(time - lastEstimateUpdateTime) / dayMs :
na
string freshnessText = "No revision date"
color freshnessColor = clrMuted
if not na(estimateAgeDays)
if estimateAgeDays <= freshDays
freshnessText := "Fresh"
freshnessColor := clrGreen
else if estimateAgeDays <= staleDays
freshnessText := "Aging"
freshnessColor := clrAmber
else
freshnessText := "Stale"
freshnessColor := clrRed
// ============================================================================
// HISTORICAL RANKS AND MEDIANS — 1Y / 3Y ONLY
// ============================================================================
var int validHistoryBars = 0
validHistoryBars := not na(linkedForwardPE) ? nz(validHistoryBars ) + 1 : 0
has1Y = validHistoryBars >= bars1Y
has3Y = validHistoryBars >= bars3Y
hasSelectedHistory = validHistoryBars >= selectedLength
rank1YRaw = ta.percentrank(linkedForwardPE, bars1Y)
rank3YRaw = ta.percentrank(linkedForwardPE, bars3Y)
median1YRaw = ta.percentile_linear_interpolation(linkedForwardPE, bars1Y, 50)
median3YRaw = ta.percentile_linear_interpolation(linkedForwardPE, bars3Y, 50)
rank1Y = has1Y ? rank1YRaw : na
rank3Y = has3Y ? rank3YRaw : na
median1Y = has1Y ? median1YRaw : na
median3Y = has3Y ? median3YRaw : na
selectedRankRaw = ta.percentrank(linkedForwardPE, selectedLength)
selectedP95Raw = ta.percentile_linear_interpolation(linkedForwardPE, selectedLength, 95)
selectedP90Raw = ta.percentile_linear_interpolation(linkedForwardPE, selectedLength, 90)
selectedP50Raw = ta.percentile_linear_interpolation(linkedForwardPE, selectedLength, 50)
selectedP10Raw = ta.percentile_linear_interpolation(linkedForwardPE, selectedLength, 10)
selectedP05Raw = ta.percentile_linear_interpolation(linkedForwardPE, selectedLength, 5)
selectedRank = hasSelectedHistory ? selectedRankRaw : na
selectedP95 = hasSelectedHistory ? selectedP95Raw : na
selectedP90 = hasSelectedHistory ? selectedP90Raw : na
selectedP50 = hasSelectedHistory ? selectedP50Raw : na
selectedP10 = hasSelectedHistory ? selectedP10Raw : na
selectedP05 = hasSelectedHistory ? selectedP05Raw : na
// ============================================================================
// DECISION FRAMEWORK
// ============================================================================
// Overall valuation status is based on the selected 1Y or 3Y percentile rank.
string overallValuationText = "Insufficient history"
color overallValuationColor = clrGrayLine
color overallValuationBg = clrLightGray
if not na(linkedForwardPE) and hasSelectedHistory and not na(selectedRank)
if selectedRank >= 95
overallValuationText := "Extreme Expensive"
overallValuationColor := clrRed
overallValuationBg := clrLightRed
else if selectedRank >= 90
overallValuationText := "Expensive"
overallValuationColor := clrOrange
overallValuationBg := clrLightAmber
else if selectedRank >= 75
overallValuationText := "Above Normal"
overallValuationColor := clrAmber
overallValuationBg := clrLightAmber
else if selectedRank <= 5
overallValuationText := "Deep Discount"
overallValuationColor := clrBlue
overallValuationBg := clrLightCyan
else if selectedRank <= 10
overallValuationText := "Cheap"
overallValuationColor := clrAqua
overallValuationBg := clrLightCyan
else if selectedRank <= 25
overallValuationText := "Below Normal"
overallValuationColor := clrTeal
overallValuationBg := clrLightCyan
else
overallValuationText := "Normal"
overallValuationColor := clrGrayLine
overallValuationBg := clrLightGray
cheapValuation = hasSelectedHistory and not na(selectedRank) and selectedRank <= 25
premiumValuation = hasSelectedHistory and not na(selectedRank) and selectedRank >= 75
veryExpensiveValuation = hasSelectedHistory and not na(selectedRank) and selectedRank >= 90
growthPositive =
(not na(forwardEPSGrowthProxy) and forwardEPSGrowthProxy >= 10.0) or
estimateTrendText == "Rising"
growthStrong =
(not na(forwardEPSGrowthProxy) and forwardEPSGrowthProxy >= growthSupportThreshold) or
(not na(linkedPEG) and linkedPEG <= attractivePEGThreshold)
growthWeak =
(not na(forwardEPSGrowthProxy) and forwardEPSGrowthProxy <= 0.0) or
estimateTrendText == "Falling"
// Combines valuation, expected growth, estimate direction, and linked PEG.
string valuationGrowthText = "Awaiting data"
color valuationGrowthColor = clrGrayLine
color valuationGrowthBg = clrLightGray
if hasSelectedHistory and not na(selectedRank)
if cheapValuation
if growthWeak
valuationGrowthText := "Value-Trap Risk"
valuationGrowthColor := clrRed
valuationGrowthBg := clrLightRed
else if growthPositive or growthStrong
valuationGrowthText := "Attractive Discount"
valuationGrowthColor := clrGreen
valuationGrowthBg := clrLightMint
else
valuationGrowthText := "Potential Value"
valuationGrowthColor := clrTeal
valuationGrowthBg := clrLightCyan
else if premiumValuation
if growthWeak
valuationGrowthText := "High-Risk Premium"
valuationGrowthColor := clrRed
valuationGrowthBg := clrLightRed
else if growthStrong
valuationGrowthText := "Growth-Supported Premium"
valuationGrowthColor := clrAmber
valuationGrowthBg := clrLightAmber
else
valuationGrowthText := "Multiple Risk"
valuationGrowthColor := clrOrange
valuationGrowthBg := clrLightAmber
else
if estimateTrendText == "Rising"
valuationGrowthText := "Improving Fundamentals"
valuationGrowthColor := clrGreen
valuationGrowthBg := clrLightMint
else if estimateTrendText == "Falling"
valuationGrowthText := "Estimate Deterioration"
valuationGrowthColor := clrRed
valuationGrowthBg := clrLightRed
else
valuationGrowthText := "Balanced"
valuationGrowthColor := clrGrayLine
valuationGrowthBg := clrLightGray
// A direct matrix combining the valuation regime with estimate direction.
string valuationEstimateText = "Awaiting data"
color valuationEstimateColor = clrGrayLine
color valuationEstimateBg = clrLightGray
if hasSelectedHistory and not na(selectedRank)
string valuationBucket = cheapValuation ? "Discount" : premiumValuation ? "Premium" : "Normal"
string directionBucket = estimateTrendText == "Rising" ? "Upgrades" : estimateTrendText == "Falling" ? "Cuts" : "Stable Estimates"
valuationEstimateText := valuationBucket + " + " + directionBucket
if cheapValuation and estimateTrendText == "Rising"
valuationEstimateColor := clrGreen
valuationEstimateBg := clrLightMint
else if cheapValuation and estimateTrendText == "Falling"
valuationEstimateColor := clrRed
valuationEstimateBg := clrLightRed
else if premiumValuation and estimateTrendText == "Falling"
valuationEstimateColor := clrRed
valuationEstimateBg := clrLightRed
else if premiumValuation and estimateTrendText == "Rising"
valuationEstimateColor := clrAmber
valuationEstimateBg := clrLightAmber
else if estimateTrendText == "Rising"
valuationEstimateColor := clrGreen
valuationEstimateBg := clrLightMint
else if estimateTrendText == "Falling"
valuationEstimateColor := clrRed
valuationEstimateBg := clrLightRed
else
valuationEstimateColor := clrGrayLine
valuationEstimateBg := clrLightGray
// Primary driver compares price, implied forward EPS, and forward P/E changes.
priceChangePct =
not na(close ) and close != 0.0 ?
((close / close ) - 1.0) * 100.0 :
na
forwardEPSChangePct =
not na(impliedForwardEPS) and
not na(impliedForwardEPS ) and
impliedForwardEPS != 0.0 ?
((impliedForwardEPS / impliedForwardEPS ) - 1.0) * 100.0 :
na
forwardPEChangePct =
not na(linkedForwardPE) and
not na(linkedForwardPE ) and
linkedForwardPE != 0.0 ?
((linkedForwardPE / linkedForwardPE ) - 1.0) * 100.0 :
na
string primaryDriverText = "Insufficient data"
color primaryDriverColor = clrGrayLine
color primaryDriverBg = clrLightGray
if not na(priceChangePct) and not na(forwardEPSChangePct) and not na(forwardPEChangePct)
bool priceUp = priceChangePct > primaryDriverThreshold
bool priceDown = priceChangePct < -primaryDriverThreshold
bool epsUp = forwardEPSChangePct > primaryDriverThreshold
bool epsDown = forwardEPSChangePct < -primaryDriverThreshold
bool peUp = forwardPEChangePct > primaryDriverThreshold
bool peDown = forwardPEChangePct < -primaryDriverThreshold
if priceUp and epsUp
primaryDriverText := peUp ? "Price + Estimate Expansion" : "Earnings-Led Advance"
primaryDriverColor := clrGreen
primaryDriverBg := clrLightMint
else if priceDown and epsDown
primaryDriverText := peDown ? "Price + Estimate Deterioration" : "Estimate Cuts Dominate"
primaryDriverColor := clrRed
primaryDriverBg := clrLightRed
else if priceUp and epsDown
primaryDriverText := "Price Up Despite Estimate Cuts"
primaryDriverColor := clrOrange
primaryDriverBg := clrLightAmber
else if priceDown and epsUp
primaryDriverText := "Estimate Upgrades / Price Lag"
primaryDriverColor := clrTeal
primaryDriverBg := clrLightCyan
else if peUp and priceUp
primaryDriverText := "Price-Led Multiple Expansion"
primaryDriverColor := clrAmber
primaryDriverBg := clrLightAmber
else if peDown and priceDown
primaryDriverText := "Price-Led Multiple Compression"
primaryDriverColor := clrTeal
primaryDriverBg := clrLightCyan
else if epsUp
primaryDriverText := "Estimate Upgrades"
primaryDriverColor := clrGreen
primaryDriverBg := clrLightMint
else if epsDown
primaryDriverText := "Estimate Cuts"
primaryDriverColor := clrRed
primaryDriverBg := clrLightRed
else if peUp
primaryDriverText := "Multiple Expansion"
primaryDriverColor := clrAmber
primaryDriverBg := clrLightAmber
else if peDown
primaryDriverText := "Multiple Compression"
primaryDriverColor := clrTeal
primaryDriverBg := clrLightCyan
else
primaryDriverText := "Stable / Consolidation"
primaryDriverColor := clrGrayLine
primaryDriverBg := clrLightGray
// ============================================================================
// MODEL CONFIDENCE
// ============================================================================
chartIsDaily = timeframe.isdaily and timeframe.multiplier == 1
int confidenceScore = 0
confidenceScore += not na(linkedForwardPE) ? 40 : 0
confidenceScore += has3Y ? 25 : has1Y ? 15 : 0
confidenceScore += not na(impliedForwardEPS) ? 10 : 0
// Internally calculated trailing P/E contributes to confidence when available.
confidenceScore += not na(currentPERatio) ? 5 : 0
confidenceScore += not na(linkedPEG) ? 5 : 0
confidenceScore +=
not na(estimateAgeDays) ?
estimateAgeDays <= freshDays ? 10 :
estimateAgeDays <= staleDays ? 5 : 1 :
0
confidenceScore += chartIsDaily ? 5 : 0
confidenceScore := int(math.max(0, math.min(100, confidenceScore)))
string confidenceLevel =
confidenceScore >= 80 ? "High" :
confidenceScore >= 60 ? "Medium" :
"Low"
color confidenceColor =
confidenceScore >= 80 ? clrGreen :
confidenceScore >= 60 ? clrAmber :
clrRed
historyCoverageText =
has3Y ? "Full 3Y" :
has1Y ? "1Y available" :
"Limited"
sourceStatusText =
confirmForwardPELinked and confirmPEGLinked ? "2/2 linked" :
confirmForwardPELinked ? "1/2 linked" :
"Set P/E forward source"
// ============================================================================
// DISPLAY TEXT
// ============================================================================
rankText = f_rank_text(rank1Y) + " / " + f_rank_text(rank3Y)
medianText = f_x(median1Y) + " / " + f_x(median3Y)
estimateTrendContext =
na(estimateRevisionPct) ?
"Awaiting second revision" :
"Last revision: " + f_pct(estimateRevisionPct)
freshnessContext =
na(estimateAgeDays) ?
"No implied EPS revision observed" :
str.tostring(estimateAgeDays, "#") + " calendar days"
confidenceContext =
historyCoverageText + " / " + (chartIsDaily ? "1D chart" : "Use 1D chart")
overallValuationContext =
na(selectedRank) ?
"Selected rank unavailable" :
chartLookback + " rank: " + f_rank_text(selectedRank)
valuationGrowthContext =
"Growth: " + f_pct(forwardEPSGrowthProxy) + " / PEG: " + f_x(linkedPEG)
valuationEstimateContext =
overallValuationText + " / EPS trend: " + estimateTrendText
primaryDriverContext =
"Price " + f_pct(priceChangePct) + " / EPS " + f_pct(forwardEPSChangePct) + " / P/E " + f_pct(forwardPEChangePct)
// ============================================================================
// PLOTS
// ============================================================================
lineColor = f_rank_color(selectedRank, hasSelectedHistory)
plot(
linkedForwardPE,
title="Linked TradingView Forward P/E",
color=lineColor,
linewidth=3,
display=display.pane)
medianPlot = plot(
showMedianLine ? selectedP50 : na,
title="Selected Historical Median",
color=color.new(clrGrayLine, 5),
linewidth=2,
display=display.pane)
upperPlot = plot(
showPercentileBands ? selectedP90 : na,
title="Selected 90th Percentile",
color=color.new(clrOrange, 20),
linewidth=1,
display=display.pane)
lowerPlot = plot(
showPercentileBands ? selectedP10 : na,
title="Selected 10th Percentile",
color=color.new(clrAqua, 20),
linewidth=1,
display=display.pane)
plot(
showPercentileBands ? selectedP95 : na,
title="Selected 95th Percentile",
color=color.new(clrRed, 10),
linewidth=1,
display=display.pane)
plot(
showPercentileBands ? selectedP05 : na,
title="Selected 5th Percentile",
color=color.new(clrBlue, 10),
linewidth=1,
display=display.pane)
fill(
upperPlot,
lowerPlot,
color=showPercentileBands and showNormalZoneFill ? color.new(clrAqua, 91) : na,
title="Historical Normal Zone")
isExtremeExpensive = hasSelectedHistory and selectedRank >= 95
isDeepDiscount = hasSelectedHistory and selectedRank <= 5
bgcolor(
showExtremeBackground and isExtremeExpensive ? color.new(clrRed, 90) :
showExtremeBackground and isDeepDiscount ? color.new(clrBlue, 90) :
na)
// ============================================================================
// DASHBOARD
// ============================================================================
var table dash = table.new(
f_position(dashboardPosition),
3,
15,
border_width=1,
border_color=color.new(clrMuted, 75))
if showDashboard and barstate.islast
color bgHeader = clrSlate0
color bgDark = clrSlate1
color bgMed = clrSlate2
color peBg = f_rank_fill_color(selectedRank, hasSelectedHistory)
color epsBg = clrLightGray
color currentPEBg = clrLightBlue
color growthBg = not na(forwardEPSGrowthProxy) and forwardEPSGrowthProxy >= 0 ? clrLightMint : clrLightRed
color pegBg = clrLightBlue
color rankBg = f_rank_fill_color(selectedRank, hasSelectedHistory)
color medianBg = clrLightGray
color trendBg = estimateTrendText == "Rising" ? clrLightMint : estimateTrendText == "Falling" ? clrLightRed : clrLightAmber
color freshBg = freshnessText == "Fresh" ? clrLightMint : freshnessText == "Aging" ? clrLightAmber : freshnessText == "Stale" ? clrLightRed : clrLightGray
color confBg = confidenceScore >= 80 ? clrLightMint : confidenceScore >= 60 ? clrLightAmber : clrLightRed
table.cell(dash, 0, 0, "Metric", text_color=clrText, text_size=size.small, text_halign=text.align_left, bgcolor=bgHeader)
table.cell(dash, 1, 0, "Current", text_color=clrText, text_size=size.small, text_halign=text.align_center, bgcolor=bgHeader)
table.cell(dash, 2, 0, "Context", text_color=clrText, text_size=size.small, text_halign=text.align_right, bgcolor=bgHeader)
table.cell(dash, 0, 1, "Overall Valuation Status", text_color=clrText, text_size=size.small, text_halign=text.align_left, bgcolor=bgDark)
table.cell(dash, 1, 1, overallValuationText, text_color=overallValuationColor, text_size=size.normal, text_halign=text.align_center, bgcolor=overallValuationBg)
table.cell(dash, 2, 1, overallValuationContext, text_color=clrMuted, text_size=size.small, text_halign=text.align_right, bgcolor=bgDark)
table.cell(dash, 0, 2, "Valuation + Growth Signal", text_color=clrText, text_size=size.small, text_halign=text.align_left, bgcolor=bgMed)
table.cell(dash, 1, 2, valuationGrowthText, text_color=valuationGrowthColor, text_size=size.normal, text_halign=text.align_center, bgcolor=valuationGrowthBg)
table.cell(dash, 2, 2, valuationGrowthContext, text_color=clrMuted, text_size=size.small, text_halign=text.align_right, bgcolor=bgMed)
table.cell(dash, 0, 3, "Valuation + Estimate Direction", text_color=clrText, text_size=size.small, text_halign=text.align_left, bgcolor=bgDark)
table.cell(dash, 1, 3, valuationEstimateText, text_color=valuationEstimateColor, text_size=size.normal, text_halign=text.align_center, bgcolor=valuationEstimateBg)
table.cell(dash, 2, 3, valuationEstimateContext, text_color=clrMuted, text_size=size.small, text_halign=text.align_right, bgcolor=bgDark)
table.cell(dash, 0, 4, "Primary Driver", text_color=clrText, text_size=size.small, text_halign=text.align_left, bgcolor=bgMed)
table.cell(dash, 1, 4, primaryDriverText, text_color=primaryDriverColor, text_size=size.small, text_halign=text.align_center, bgcolor=primaryDriverBg)
table.cell(dash, 2, 4, primaryDriverContext, text_color=clrMuted, text_size=size.small, text_halign=text.align_right, bgcolor=bgMed)
table.cell(dash, 0, 5, "TradingView Forward P/E", text_color=clrText, text_size=size.small, text_halign=text.align_left, bgcolor=bgDark)
table.cell(dash, 1, 5, f_x(linkedForwardPE), text_color=clrDarkText, text_size=size.normal, text_halign=text.align_center, bgcolor=peBg)
table.cell(dash, 2, 5, "Direct linked P/E forward plot", text_color=clrMuted, text_size=size.small, text_halign=text.align_right, bgcolor=bgDark)
table.cell(dash, 0, 6, "Implied Forward EPS", text_color=clrText, text_size=size.small, text_halign=text.align_left, bgcolor=bgMed)
table.cell(dash, 1, 6, f_eps(impliedForwardEPS), text_color=clrDarkText, text_size=size.normal, text_halign=text.align_center, bgcolor=epsBg)
table.cell(dash, 2, 6, "Price ÷ linked forward P/E", text_color=clrMuted, text_size=size.small, text_halign=text.align_right, bgcolor=bgMed)
table.cell(dash, 0, 7, "Current P/E Ratio", text_color=clrText, text_size=size.small, text_halign=text.align_left, bgcolor=bgDark)
table.cell(dash, 1, 7, f_x(currentPERatio), text_color=clrDarkText, text_size=size.normal, text_halign=text.align_center, bgcolor=currentPEBg)
table.cell(dash, 2, 7, "Price ÷ trailing 12M EPS", text_color=clrMuted, text_size=size.small, text_halign=text.align_right, bgcolor=bgDark)
table.cell(dash, 0, 8, "Forward EPS Growth Proxy", text_color=clrText, text_size=size.small, text_halign=text.align_left, bgcolor=bgMed)
table.cell(dash, 1, 8, f_pct(forwardEPSGrowthProxy), text_color=not na(forwardEPSGrowthProxy) and forwardEPSGrowthProxy >= 0 ? clrGreenText : clrRedText, text_size=size.normal, text_halign=text.align_center, bgcolor=growthBg)
table.cell(dash, 2, 8, "Implied forward EPS vs prior FY", text_color=clrMuted, text_size=size.small, text_halign=text.align_right, bgcolor=bgMed)
table.cell(dash, 0, 9, "PEG Ratio", text_color=clrText, text_size=size.small, text_halign=text.align_left, bgcolor=bgDark)
table.cell(dash, 1, 9, f_x(linkedPEG), text_color=clrDarkText, text_size=size.normal, text_halign=text.align_center, bgcolor=pegBg)
table.cell(dash, 2, 9, na(pegImpliedGrowthPct) ? "Direct linked PEG plot" : "TTM P/E ÷ PEG = " + f_pct(pegImpliedGrowthPct), text_color=clrMuted, text_size=size.small, text_halign=text.align_right, bgcolor=bgDark)
table.cell(dash, 0, 10, "1Y / 3Y P/E Rank", text_color=clrText, text_size=size.small, text_halign=text.align_left, bgcolor=bgMed)
table.cell(dash, 1, 10, rankText, text_color=clrDarkText, text_size=size.small, text_halign=text.align_center, bgcolor=rankBg)
table.cell(dash, 2, 10, "Lower percentile = cheaper", text_color=clrMuted, text_size=size.small, text_halign=text.align_right, bgcolor=bgMed)
table.cell(dash, 0, 11, "1Y / 3Y Median P/E", text_color=clrText, text_size=size.small, text_halign=text.align_left, bgcolor=bgDark)
table.cell(dash, 1, 11, medianText, text_color=clrDarkText, text_size=size.small, text_halign=text.align_center, bgcolor=medianBg)
table.cell(dash, 2, 11, "Linked forward P/E history", text_color=clrMuted, text_size=size.small, text_halign=text.align_right, bgcolor=bgDark)
table.cell(dash, 0, 12, "Forward EPS Trend", text_color=clrText, text_size=size.small, text_halign=text.align_left, bgcolor=bgMed)
table.cell(dash, 1, 12, estimateTrendText, text_color=estimateTrendText == "Rising" ? clrGreenText : estimateTrendText == "Falling" ? clrRedText : clrAmberText, text_size=size.normal, text_halign=text.align_center, bgcolor=trendBg)
table.cell(dash, 2, 12, estimateTrendContext, text_color=clrMuted, text_size=size.small, text_halign=text.align_right, bgcolor=bgMed)
table.cell(dash, 0, 13, "Estimate Freshness", text_color=clrText, text_size=size.small, text_halign=text.align_left, bgcolor=bgDark)
table.cell(dash, 1, 13, freshnessText, text_color=freshnessText == "Fresh" ? clrGreenText : freshnessText == "Aging" ? clrAmberText : freshnessText == "Stale" ? clrRedText : clrDarkText, text_size=size.normal, text_halign=text.align_center, bgcolor=freshBg)
table.cell(dash, 2, 13, freshnessContext, text_color=clrMuted, text_size=size.small, text_halign=text.align_right, bgcolor=bgDark)
table.cell(dash, 0, 14, "Model Confidence", text_color=clrText, text_size=size.small, text_halign=text.align_left, bgcolor=bgMed)
table.cell(dash, 1, 14, confidenceLevel + " (" + str.tostring(confidenceScore) + "%)", text_color=confidenceScore >= 80 ? clrGreenText : confidenceScore >= 60 ? clrAmberText : clrRedText, text_size=size.normal, text_halign=text.align_center, bgcolor=confBg)
table.cell(dash, 2, 14, sourceStatusText + " / " + confidenceContext, text_color=clrMuted, text_size=size.small, text_halign=text.align_right, bgcolor=bgMed)
if not showDashboard and barstate.islast
table.clear(dash, 0, 0, 2, 14)
// ============================================================================
// ALERTS
// ============================================================================
crossedAbove90 = ta.crossover(selectedRank, 90)
crossedBelow10 = ta.crossunder(selectedRank, 10)
enteredExpensive = hasSelectedHistory and crossedAbove90
enteredCheap = hasSelectedHistory and crossedBelow10
newEstimateIncrease = impliedEPSChanged and not na(estimateRevisionPct) and estimateRevisionPct > trendThreshold
newEstimateDecrease = impliedEPSChanged and not na(estimateRevisionPct) and estimateRevisionPct < -trendThreshold
newStaleEstimate =
not na(estimateAgeDays) and
not na(estimateAgeDays ) and
estimateAgeDays > staleDays and
estimateAgeDays <= staleDays
newAttractiveDiscount =
valuationGrowthText == "Attractive Discount" and
valuationGrowthText != "Attractive Discount"
newValueTrapRisk =
valuationGrowthText == "Value-Trap Risk" and
valuationGrowthText != "Value-Trap Risk"
newHighRiskPremium =
valuationGrowthText == "High-Risk Premium" and
valuationGrowthText != "High-Risk Premium"
alertcondition(
enteredExpensive,
title="Forward P/E Entered Expensive Zone",
message="Linked TradingView forward P/E entered the selected lookback's 90th-percentile expensive zone.")
alertcondition(
enteredCheap,
title="Forward P/E Entered Cheap Zone",
message="Linked TradingView forward P/E entered the selected lookback's 10th-percentile cheap zone.")
alertcondition(
newEstimateIncrease,
title="Implied Forward EPS Increased",
message="The forward EPS implied by TradingView's linked forward P/E increased by more than the configured trend threshold.")
alertcondition(
newEstimateDecrease,
title="Implied Forward EPS Decreased",
message="The forward EPS implied by TradingView's linked forward P/E decreased by more than the configured trend threshold.")
alertcondition(
newStaleEstimate,
title="Implied Forward EPS Became Stale",
message="The implied forward EPS has not changed within the configured stale-data threshold.")
alertcondition(
newAttractiveDiscount,
title="Attractive Discount Signal",
message="Forward P/E is historically discounted while growth and estimate direction remain supportive.")
alertcondition(
newValueTrapRisk,
title="Value-Trap Risk Signal",
message="Forward P/E is historically discounted, but growth or forward EPS estimates are deteriorating.")
alertcondition(
newHighRiskPremium,
title="High-Risk Premium Signal",
message="Forward P/E is historically elevated while growth or forward EPS estimates are deteriorating.")
Indicatore

RTI Trend State + MacroCoverRTI Trend State + MacroCover
A trend-state oscillator built on the Relative Trend Index (RTI) — a stochastic-position measure of where price sits inside its recent high/low range, then EMA-smoothed:
raw = 100 * (close - lowest(low, n)) / (highest(high, n) - lowest(low, n))
RTI = EMA(raw, smooth) -> a 0-100 line
How the state works
The 0-100 RTI is converted into a persistent LONG / FLAT / SHORT state through a hysteresis band , so it does not flip on noise around the mid-line:
RTI above the upper band -> LONG
RTI below the lower band -> SHORT
in between -> holds the last state
The gap between the two bands is the hysteresis — widen it for fewer, steadier flips; narrow it for a more reactive read.
MacroCover (optional long bias)
When the state would be SHORT but price trades above a slow EMA (default 200), the short is covered to FLAT — i.e. it won't fight the higher-timeframe uptrend. Turn MacroCover off for a symmetric long/short reading.
On the chart
The RTI line (0-100) colored by state: green long, red short, gray flat.
Dashed upper/lower bands and a dotted mid-line.
State background tint and flip markers where the state changes.
A compact table with the current RTI value, state and macro side.
The RTI value plus state_-1_0_1 and ema_macro are available in the Data Window for tooltips and cross-checks.
Inputs
RTI engine — Lookback n (30), EMA smoothing (3), upper/lower bands (55 / 45).
MacroCover — on/off and macro EMA length (200).
Timeframe — use the chart timeframe, or lock the calculation to a fixed resolution.
Visual — toggle the state background, flip markers and table.
Notes
Works on any symbol and any timeframe.
Non-repainting : values are computed on confirmed bars, and the optional higher-timeframe request uses lookahead_off.
This is a discretionary / confluence tool, not financial advice or a complete trading system.
Indicatore

Buy/Sell Signals [WynTrader]Buy/Sell Signals
Hello dear Friend
Here is my Buy/Sell Signals indicator that may help you easily run a Buy/Sell backtest Strategy, seeing, at a glance, performance results.
█ OVERVIEW
This indicator identifies trend changes and generates Buy/Sell signals as accurately as possible. Its strength lies in the results Table, which lets you evaluate signal performance directly on the chart — compared to a simple Buy & Hold strategy — without running a full backtest.
█ CONCEPTS
This Buy/Sell Signals , compared to other tools that detect trend shifts, is simple, easy to use, and demonstrates its efficiency on its own, at a glance.
The Table results allow you to quickly evaluate signal performance, both on their own and compared to a Buy & Hold strategy. The Table calculations are fully s ynchronized with the visible chart (WYSIWYG – What You See Is What You Get). You can also scroll the chart across different date ranges to see how a stock or product performs under various market conditions.
You can adjust the variables to suit your goals. The design is simple, with clear parameters and instant readability of Buy/Sell Signals on the chart and in the Table results, without complex interpretation needed.
A Table shows the effectiveness of the signals on the current visible chart, providing immediate, realistic feedback performance. The Buy & Hold strategy results are also included for comparison with the Buy/Sell swing strategy. The Buy & Hold results start from the first Buy signal to ensure a fair comparison. Changing the parameters instantly updates the Table, giving a quick, immediate performance check.
█ FILTERS (Buy/Sell parameters)
This indicator generates Buy/Sell signals using optional and adjustable filters:
- Bollinger Bands Lookback Trend Filter
- High-Low vs Candle Range Threshold %
- Distance from Fast and Slow MAs Threshold %
Results are displayed in a Table on the chart, based on the currently visible start and end dates.
█ TABLE RESULTS (Buy/Sell signals performance)
The Results Calculation presented in the Table is based on the Current Chart Visible Range . The Table shows the:
- Calculation Results of the Buy and Sell Signals activated on the chart
- Number of Trades (Signals)
- Winning Points
- Win Rate %
The Buy & Hold calculation starts at the first Buy encountered.
█ CAUTION
The Graal Indicator, even with AI, doesn't exist yet — maybe one day, but not now — depending on the chart product, volatility, probabilities, and unpredictable market behaviour. Don't rely on this tool to make trade decision, it's only a tool to, maybe, help assess a change of trend.
Seeing Buy/Sell signals on a chart is appealing, but assessing their performance in a Table makes it even more convincing — and without running a full backtest, you get a clear overview of performance immediately.
█ WYNTRADER
My name is WynTrader. I cumulate 24 years of experience. In 2001, I took an intensive technical analysis course taught by an exceptional friend, Cyril, who taught me everything I know.
After testing thousands of TradingView indicators over these 24 years, I've found none to be 100% accurate all the time. This Buy/Sell Signals indicator may outperform some others but is still not perfect. So, just be aware, and don't be fooled by this tool.
Enjoy!
WynTrader Indicatore

Breakout & Retest Entry Signals & the Break-vs-RetestOVERVIEW
"Wait for the retest" is the most repeated piece of advice in breakout trading. It is also, as far as I can tell, completely untested by the people who repeat it.
This tool settles it — on your instrument, with your settings — by taking BOTH entries on the SAME breaks and grading them against the same control:
PER-TRADE EDGE expectancy vs control · n
Break entry +0.09R +0.02R · n=412
Retest — CLEAN +0.31R +0.02R · n=118
Retest — DEEP -0.04R +0.02R · n=76
clean vs deep (t) 3.41 CLEAN IS BETTER
BUT — HOW OFTEN DO YOU GET IT?
Breaks that ever retested 47.0% (194/412)
after a run of >3 closes 31.2% vs 55.8% otherwise
False-break rate 13.3%
EXPECTED VALUE PER BREAK
Take every break +0.09R (100% of breaks)
Wait for the retest +0.06R (47% of breaks)
VERDICT NO DIFFERENCE — pick either
That last block is the entire point. A better per-trade edge is worthless if you only get the trade half the time — so the WAIT policy is scored as P(retest) x E , because on every break that never retests you get NOTHING. The two are then compared with a significance test, and the verdict is allowed to be "no difference".
It is a research and framing tool. NOT a strategy, NOT a signal service, NOT a validated edge.
WHAT IT ALREADY FOUND — measured live on NIFTY futures
timeframe breaks retested false breaks verdict
1m 334 49.4% 29.6% NO DIFFERENCE
3m 323 53.3% 13.6% NO DIFFERENCE
5m 328 53.4% 14.0% NO DIFFERENCE
15m 306 51.0% 12.7% TAKE THE BREAK
1h 274 50.0% 16.4% NO DIFFERENCE
TWO THINGS JUMP OUT.
The retest rate is 50-53% on every timeframe. Bulkowski, measuring throwbacks across 10,348 chart patterns on US daily stocks, found 50-60%. A completely different market, a completely different method, and the same number. That is a real phenomenon, not an artefact of the detector.
The false-break rate is 26.5% on the 1m and 13-15% everywhere else. THE ONE-MINUTE BREAK IS TWICE AS LIKELY TO BE A LIE. That is not folklore, it is this instrument's own number, and it is exactly the kind of thing a trader should know before choosing a timeframe.
And the verdict, on four of the five: NO DIFFERENCE — pick either. Once the geometry is honest and the test is a real one, the great break-versus-retest argument simply does not resolve on this instrument at most speeds. On the 15m it does resolve — and it says TAKE THE BREAK, which is the opposite of what almost everyone will tell you.
That is what a measurement looks like. It disagrees with the folklore on one timeframe, refuses to take a side on four others, and does not care what you were hoping for. No tool that needs to sell you a signal would ever print "NO DIFFERENCE".
THE ONE THING EVERYONE GETS BACKWARDS
Thomas Bulkowski measured throwbacks and pullbacks across 10,348 chart patterns. His finding:
"Do throwbacks hurt performance? YES: 97% of the time chart patterns with upward breakouts
perform better post-breakout WITHOUT a throwback."
"Do pullbacks hurt performance? YES: 91% of chart pattern types with downward breakouts
perform better if a pullback does NOT occur."
Read that again. The retest is not a gift. It is a SYMPTOM — evidence that the move is weak, that supply came back, that the break did not have the strength to run.
And yet "wait for the retest" is good advice for a completely different reason: it gives you a better price and a tighter stop.
BOTH ARE TRUE AT ONCE. They are two opposing effects on the same trade, and they have never been put on one scale and netted out. That is what this script does. The retest may still win — a better entry can outweigh a weaker move — but nobody has ever checked, and the answer is different on every instrument and every timeframe.
A CLEAN RETEST AND A DEEP ONE ARE NOT THE SAME EVENT
Bulkowski again, and this is his sharpest single finding on the subject: during a throwback, if price REMAINS ABOVE the breakout price the subsequent rise averages 40%. If it drops BELOW the breakout price and then recovers, the rise averages 29%. That is 400 samples versus 2,767.
Pooling those two throws away the strongest signal in the whole idea. So they are separated:
CLEAN retest — price came back and touched the level, but never CLOSED back through it.
DEEP retest — price CLOSED back through the level, then recovered.
They are graded separately, tested against each other, and labelled separately on the chart. If clean beats deep on your instrument, then "wait for the retest" is not one rule — it is two, and only one of them works.
AND CAN YOU SEE IT COMING?
The real, unpriced cost of a WAIT policy is that roughly half the time you never get filled. So it matters enormously whether you can predict which breaks will retest.
Bulkowski found that if price has more than three consecutively higher closes ending the day before the breakout, the throwback probability drops materially. So the panel reports the retest rate SPLIT BY THAT:
after a run of >3 closes 31.2% vs 55.8% otherwise
If the split is real on your instrument, then after a strong run into the break you should simply TAKE IT — because the retest you are waiting for is probably never coming.
IS YOUR VOLUME FILTER EARNING ITS KEEP?
Every trader is taught that a breakout must be confirmed by volume. Bulkowski's volume study says that after an ABOVE-average-volume breakout, FAILURES DOUBLE and the likelihood of a throwback TRIPLES, while the move itself is barely better.
That is testable — but only if the low-volume breaks are allowed into the sample. So VOLUME IS NOT A GATE ON THE RECORD. Every break is recorded; volume gates only the SIGNAL. The panel then reports what your filter is actually worth:
Break ON volume +0.11R n=246
Break OFF volume +0.06R n=166
on vs off (t) 0.82 no difference — it is doing nothing
The record is a fact about the market. The filter is a decision about the trade. They are kept apart, and this is what happens when you stop assuming and start measuring.
IDENTICAL GEOMETRY — and why this is not a detail
The target used to be THE NEXT OPPOSING LEVEL. That quietly destroyed the entire experiment.
The BREAK entry sits PAST the level (it closed through it). The RETEST entry sits BACK AT the level. So the retest is systematically FARTHER from the next opposing level, and was therefore being handed a BIGGER R:R for the SAME RISK — on every single trade, by construction. Live, that produced an R:R of 5.0 on one timeframe and 0.66 on another, and the on-chart key was cheerfully claiming "identical geometry" while the geometry was tilted toward the retest.
The trade now uses a FIXED R multiple, identical for the break, the retest and the control. The next opposing level is still drawn, and still tested — separately, as a descriptive statistic, with its hit rate reported next to its distance in R.
THE ANTI-BIAS GUARDS
ENTRY IS THE CLOSE, for both entries and for the control. Entering the retest AT the level — a better price than the close — while the break enters at its close would hand the retest a free head start on every trade, and settle the oldest argument in trading by rigging it.
THE CONTROL IS DIRECTION-MATCHED. Breaks run with the trend, so a direction-skewed event set measured against a symmetric 50/50 control inherits the drift for free and calls it an edge. Longs are compared only with control longs, shorts only with control shorts, and the control is blended back using the events' OWN direction mix.
EVERY VERDICT IS A TEST, NOT A COMPARISON. Break-vs-wait, clean-vs-deep, volume-on-vs-off — each is a Welch t-test that has to clear |t| > 1.96 before it is allowed to be a finding. For the wait policy, the variance of P(retest) x E is propagated by the delta method, because it is a product of two estimates and both carry error. A verdict that flips on a tenth of an R is not a verdict, it is noise wearing a costume.
Both barriers on one bar: the STOP is assumed first — conservative, and the only assumption that cannot flatter the result. Unresolved trades at the horizon are marked to market, not booked as losses.
THE LEVELS
Levels come from the extrema of a KERNEL-SMOOTHED price series (Nadaraya-Watson) rather than raw pivots, so they track the structure rather than the noise. A break requires a CLOSE beyond the level with displacement, not a wick. A false break is one that closes back inside quickly. All of it is computed on confirmed bars; the kernel is causal and never looks forward.
NON-REPAINT
The kernel confirms an extremum a half-window late, so a level appears some bars AFTER the swing that created it. That lag is the price of not repainting and it is paid deliberately. Levels, breaks, false breaks, retests, signals and every calibration event are computed on CONFIRMED bars only. Nothing is drawn and then moved.
DATA AND SCOPE
Any symbol, any timeframe. ATR-normalised throughout. Volume improves the SIGNAL but is not required, and it never gates the RECORD.
EXPORTS (Data Window — consume from other scripts via input.source())
EXP_Level, EXP_Break, EXP_FalseBreak, EXP_Retest, EXP_Entry, EXP_Stop, EXP_Target, EXP_NextLevel, EXP_WaitEdge
CONCEPT CREDIT
Support/resistance, polarity and the breakout-retest idea are long-standing public trading concepts with no single author; the written tradition runs through Charles Dow, Richard Wyckoff and Edwards & Magee. The formal TRADING-RANGE BREAK was first tested at scale by William Brock, Josef Lakonishok and Blake LeBaron, Journal of Finance 47(5), 1992 — and their results were later shown to be vulnerable to data-snooping (Sullivan, Timmermann and White, 1999), which is exactly why this tool measures the rule on YOUR instrument rather than asserting it.
The throwback and pullback statistics that motivate the clean/deep split, the run-length predictor and the volume test are from Thomas Bulkowski ("Encyclopedia of Chart Patterns"; thepatternsite.com). His numbers are measured on US daily stocks. Whether they hold on YOUR instrument is precisely the question this script exists to answer — and it may well answer "no".
Nadaraya-Watson kernel regression — Nadaraya and Watson (1964); its use for technical pattern recognition — Lo, Mamaysky and Wang, Journal of Finance 55(4), 2000. Triple-barrier forward labelling — Marcos Lopez de Prado. Welch's t-test — B. L. Welch. ATR — J. Welles Wilder.
The break-vs-wait availability weighting, the delta-method significance test, the clean/deep retest split, the volume-filter test and the direction-matched control are the author's own. Clean-room implementation; no third-party Pine code is reused. Not affiliated with, nor endorsed by, any of the above.
HONESTY AND LIMITATIONS
Calibration is IN-SAMPLE, with no costs or slippage, and uses overlapping windows. A proven in-sample edge is NOT a guarantee out-of-sample. Real fills, spreads and commissions will reduce it — and they will hurt the break entry more than the retest entry, because the break enters into momentum.
Bulkowski's throwback statistics are measured on US daily stocks over decades. They are the reason the questions are asked. They are NOT the answer, and this tool will tell you so if your instrument disagrees.
The verdict is allowed to be "NO DIFFERENCE — pick either", and on many instruments it will be. That is a real result. A tool that cannot report its own failure is an advertisement, not a measurement.
Nothing in this script predicts price.
DISCLAIMER
Research and educational tool only. NOT financial advice, NOT a recommendation, and NO guarantee of results. Entry, stop and target output is arithmetic, not advice. Trading carries risk of loss. Test out-of-sample and make your own decisions. The author accepts no liability for any use.
Indicatore

Anchored VWAP Hand-Off 2.03Anchored VWAP Hand-Off 2.03 is a multi-leg cascading VWAP indicator. It starts with a classic Anchored VWAP from a user-selected date (Leg 1), then automatically creates new "hand-off" VWAP legs (up to 24) every time price crosses the previous VWAP. Each new leg resets its calculation from the bar of the cross, creating a dynamic chain of VWAPs that follow price action.
Key Features:
Source: Typically close (customizable).
Trigger: EMA(1) of the source (essentially price itself).
Color Logic: Each VWAP leg changes color based on whether price is above (bullish) or below (bearish) it. Supports unified color mode.
Up to 24 cascading legs (user controls how many are shown).
Visual anchor line at the start date.
Main Use Cases:
Dynamic Support & Resistance
The multiple VWAP legs act as adaptive moving support/resistance zones. Traders watch for bounces off these lines or breaks through several legs at once.
Trend Strength & Momentum
Strong trends often break multiple hand-off legs quickly.
Choppy/consolidating markets produce many frequent hand-offs (more lines clustering).
Mean Reversion Setups
Price tends to return to the nearest active VWAP legs. Useful for fade-the-extreme strategies.
Breakout / Breakdown Confirmation
When price decisively breaks through several VWAP legs in sequence, it often signals a high-probability directional move.
Intraday & Swing Trading
Particularly popular on stocks, futures, and crypto for finding "fair value" shifts after news events or strong moves. The hand-off mechanism makes it more responsive than a single static anchored VWAP.
Visual Market Structure
Helps traders see how "value" is migrating over time as new legs form.
Best Timeframes: Works on all, but especially useful on 5min to daily charts.Pro Tip: Start with 8–12 legs. Too many legs can make the chart noisy. Use the anchor date on significant events (earnings, breakout days, macro events, etc.).This indicator is an evolution of standard Anchored VWAP, designed to solve the problem of a single anchored VWAP becoming stale after big moves.
Indicatore

Indicatore

Indicatore
