Indicator · Pine Script v6 · On the chart

Dynamic P0 Architecture Dashboard

by rosijay17-cmd

An indicator that draws a Dynamic P0 line on the price chart: a rolling volume-weighted equilibrium price computed over a window set in minutes, with a value area band around it.

View on GitHub

GitHub stars1on the repository
Pine versionv6current
Lines of code611
Settings40inputs
LicenceGPL-3.0
Last update7 days ago22 Oct 2026

Add It to Your TradingView Chart

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

Source Code

611 lines of Pine Script v6 from Dynamic_P0_Architecture_Dashboard.pine, published under GPL-3.0. Keep the author's credit and licence lines when you reuse it.

Dynamic_P0_Architecture_Dashboard.pine
//@version=6
indicator(
     title = "Dynamic P0 + Architecture Dashboard",
     shorttitle = "Dynamic P0 Dashboard",
     overlay = true,
     max_labels_count = 50,
     max_lines_count = 50
)

//=============================================================================
// WHAT THIS IS
//-----------------------------------------------------------------------------
// A trimmed-down INDICATOR extracted from P0_Delta_DBR_ChangePoint_Merged_
// Strategy.pine, containing ONLY the two pieces requested:
//   - The Dynamic P0 line (+ its Value Area band) -- a rolling, volume-
//     weighted equilibrium price, recomputed every bar over a lookback
//     window sized in real minutes (Equilibrium Window), not bars.
//   - The Architecture dashboard table -- the same Acceptance/Rejection
//     scoring readout as the merged strategy (rows 0-9 there), built from
//     P0 migration/catch-up, new-location volume, value-area migration,
//     delta alignment/persistence, price/delta efficiency, dwell/return,
//     and profile coherence.
//
// Everything else from the merged strategy -- the Structural Profile (POC/
// VAH/VAL/Support/Resistance/Liquidity Zones), the Anchor Trail entry
// engine, the whole DBR Change-Point engine (CUSUM/MTF/retest/DeltaFlow),
// and all order/alert logic -- is NOT here. This is a pure indicator: no
// strategy.entry/exit calls, no alertcondition()s, nothing that places or
// simulates a trade. It only computes and displays.
//
// Pine does not expose native bid/ask aggressor volume here. Delta is
// estimated from OHLCV candle pressure, same as in the merged strategy.
//=============================================================================


//=============================================================================
// 01 — Master Visibility
//=============================================================================

string G_MASTER = "01 — Master Visibility"

bool showAllChartObjectsInput = input.bool(true, "Show All Chart Objects", tooltip = "Master switch for everything this script draws on the chart pane -- the Dynamic P0 line, its Value Area fill, the P0 label, and the Architecture dashboard table. Uncheck to hide all of it at once instead of unticking every individual 'Show ...' toggle below.", group = G_MASTER)


//=============================================================================
// 02 — Dynamic P0
//=============================================================================

string G_P0 = "02 — Dynamic P0"

int equilibriumMinutes = input.int(240, "Equilibrium Window (Minutes)", minval = 60, maxval = 1440, step = 30, tooltip = "Measured in real minutes, not bars. On a fast chart timeframe this can be a very large number of bars (e.g. 240 minutes = 120 bars on a 2-minute chart) -- if P0 and the dashboard feel sluggish/unresponsive, lower this to something proportionate to your chart's timeframe.", group = G_P0)
int equilibriumRows = input.int(32, "Dynamic P0 Price Rows", minval = 16, maxval = 64, group = G_P0)
int maximumEquilibriumBars = input.int(500, "Maximum Bars In Dynamic Profile", minval = 50, maxval = 1000, group = G_P0)
float dynamicValueAreaPercent = input.float(70.0, "Dynamic Value Area %", minval = 50.0, maxval = 95.0, step = 1.0, group = G_P0)
int coherenceRadius = input.int(2, "P0 Coherence Radius (Rows)", minval = 1, maxval = 5, group = G_P0)
float equilibriumBandATR = input.float(0.35, "Equilibrium Band (ATR)", minval = 0.10, maxval = 1.0, step = 0.05, group = G_P0)
float minimumDistanceATR = input.float(0.80, "Minimum Meaningful Displacement (ATR)", minval = 0.25, maxval = 3.0, step = 0.05, tooltip = "Minimum distance from P0 (in ATR) before the dashboard's TOTAL/marketState read treats price as meaningfully displaced at all. Purely informational here -- there is no entry engine in this file for it to gate.", group = G_P0)


//=============================================================================
// 03 — Acceptance / Rejection Metrics
//=============================================================================

string G_METRICS = "03 — Acceptance / Rejection Metrics"

int migrationLookback = input.int(4, "P0 / Value Migration Lookback", minval = 1, maxval = 20, group = G_METRICS)
float migrationTargetATR = input.float(0.15, "Strong P0 Migration (ATR)", minval = 0.02, maxval = 1.0, step = 0.01, group = G_METRICS)
float catchUpTargetPercent = input.float(40.0, "Strong P0 Catch-Up %", minval = 10.0, maxval = 100.0, step = 5.0, group = G_METRICS)
float newLocationBandATR = input.float(0.25, "New-Location Volume Band (ATR)", minval = 0.10, maxval = 1.0, step = 0.05, group = G_METRICS)
float newLocationTargetPercent = input.float(35.0, "Strong New-Location Volume %", minval = 10.0, maxval = 80.0, step = 5.0, group = G_METRICS)
int newLocationRecentBars = input.int(20, "New-Location Recency Window (Bars)", minval = 3, maxval = 100, tooltip = "New-Location Volume only counts volume from the most recent N bars, not the entire multi-hour rolling profile -- measures whether volume is NEWLY piling in at the current price right now.", group = G_METRICS)
float valueMigrationTargetATR = input.float(0.10, "Strong Value-Area Migration (ATR)", minval = 0.02, maxval = 1.0, step = 0.01, group = G_METRICS)
int deltaWindow = input.int(3, "Delta State Window", minval = 1, maxval = 10, group = G_METRICS)
int deltaPersistenceBars = input.int(3, "Delta Persistence Bars", minval = 2, maxval = 8, group = G_METRICS)
float alignedDeltaTarget = input.float(20.0, "Strong Aligned Delta %", minval = 5.0, maxval = 80.0, step = 1.0, group = G_METRICS)
float opposingDeltaTarget = input.float(20.0, "Strong Opposing Delta %", minval = 5.0, maxval = 80.0, step = 1.0, group = G_METRICS)
int efficiencyLookback = input.int(3, "Efficiency Lookback", minval = 1, maxval = 10, group = G_METRICS)
float efficiencyTargetATR = input.float(0.30, "Efficient Price Progress (ATR)", minval = 0.05, maxval = 1.50, step = 0.05, group = G_METRICS)
float absorptionDeltaTarget = input.float(25.0, "Absorption Delta Magnitude %", minval = 5.0, maxval = 100.0, step = 1.0, group = G_METRICS)
float absorptionMaximumProgressATR = input.float(0.12, "Absorption Maximum Price Progress (ATR)", minval = 0.02, maxval = 0.50, step = 0.01, group = G_METRICS)
int dwellMeasurementBars = input.int(4, "Dwell Measurement Bars", minval = 2, maxval = 12, group = G_METRICS)
float minimumCoherence = input.float(55.0, "Minimum Profile Coherence", minval = 0.0, maxval = 100.0, step = 1.0, group = G_METRICS)
float acceptanceThresholdLong = input.float(65.0, "Acceptance Score Threshold (Long)", minval = 40.0, maxval = 95.0, step = 1.0, tooltip = "Tunes only when the dashboard's TOTAL/marketState reads a BULLISH acceptance as dominant. There is no entry engine here for it to gate.", group = G_METRICS)
float acceptanceThresholdShort = input.float(65.0, "Acceptance Score Threshold (Short)", minval = 40.0, maxval = 95.0, step = 1.0, group = G_METRICS)
float rejectionThresholdLong = input.float(50.0, "Rejection Score Threshold (Long)", minval = 40.0, maxval = 95.0, step = 1.0, group = G_METRICS)
float rejectionThresholdShort = input.float(50.0, "Rejection Score Threshold (Short)", minval = 40.0, maxval = 95.0, step = 1.0, group = G_METRICS)
float scoreDominanceLong = input.float(24.0, "Required Score Dominance (Long)", minval = 0.0, maxval = 40.0, step = 1.0, group = G_METRICS)
float scoreDominanceShort = input.float(24.0, "Required Score Dominance (Short)", minval = 0.0, maxval = 40.0, step = 1.0, group = G_METRICS)
float signalStabilityMargin = input.float(0.0, "Signal Stability Margin", minval = 0.0, maxval = 20.0, step = 0.5, group = G_METRICS)


//=============================================================================
// 04 — P0 / Key Levels
//=============================================================================

string G_STYLE = "04 — P0 / Key Levels"

bool showDynamicP0 = input.bool(true, "Show Dynamic P0", group = G_STYLE)
bool showDynamicP0LabelInput = input.bool(true, "Label The Dynamic P0 Line", group = G_STYLE)
color dynamicP0Color = input.color(color.aqua, "Dynamic P0 Color", group = G_STYLE)
int dynamicP0Width = input.int(3, "Dynamic P0 Width", minval = 1, maxval = 5, group = G_STYLE)
bool showDynamicValueArea = input.bool(true, "Show Dynamic VAH / VAL", group = G_STYLE)
color dynamicValueAreaColor = input.color(color.rgb(70, 115, 255), "Dynamic Value Area Color", group = G_STYLE)


//=============================================================================
// 05 — Architecture Dashboard
//=============================================================================

string G_DASH = "05 — Architecture Dashboard"

bool showArchitectureHistogram = input.bool(true, "Show Acceptance / Rejection Dashboard", group = G_DASH)
string architecturePosition = input.string("Top Right", "Position", options = ["Top Left", "Top Right", "Bottom Left", "Bottom Right"], group = G_DASH)
string dashboardTextSize = input.string("Small", "Dashboard Text Size", options = ["Tiny", "Small", "Normal", "Large", "Huge"], group = G_DASH)
bool showLiveColumnInput = input.bool(false, "Show LIVE Value Column", group = G_DASH)
color acceptanceColor = input.color(color.rgb(0, 200, 140), "Acceptance Color", group = G_DASH)
color rejectionColor = input.color(color.rgb(245, 75, 85), "Rejection Color", group = G_DASH)


//=============================================================================
// HELPERS
//=============================================================================

f_clamp(float value, float lowValue, float highValue) =>
    math.max(lowValue, math.min(highValue, value))

f_delta(float o, float h, float l, float c, float v) =>
    float safeRange = math.max(h - l, syminfo.mintick)
    float pressure = f_clamp((c - o) / safeRange, -1.0, 1.0)
    v * pressure

f_score(float value, float target) =>
    target <= 0 ? 0.0 : f_clamp(value / target * 100.0, 0.0, 100.0)

f_price(float value) =>
    na(value) ? "—" : str.tostring(value, format.mintick)

f_pct(float value) =>
    na(value) ? "—" : str.tostring(value, "#.0") + "%"

f_bar(float value) =>
    int filled = int(math.round(f_clamp(value, 0.0, 100.0) / 10.0))
    string result = ""
    for i = 1 to 10
        result += i <= filled ? "█" : "·"
    result

f_rowVerdict(float acceptValue, float rejectValue, string acceptWord, string rejectWord, string neutralWord) => acceptValue >= rejectValue + 15.0 ? acceptWord : rejectValue >= acceptValue + 15.0 ? rejectWord : neutralWord

f_dashboardSize(string sizeName) =>
    (sizeName == "Tiny" ? size.tiny :
     sizeName == "Normal" ? size.normal :
     sizeName == "Large" ? size.large :
     sizeName == "Huge" ? size.huge :
     size.small)


//=============================================================================
// DYNAMIC P0 PROFILE
//=============================================================================

float atr = math.max(nz(ta.atr(14), ta.tr(true)), syminfo.mintick)
float timeframeSeconds = nz(timeframe.in_seconds(timeframe.period), 60.0)

int equilibriumBarsRaw = int(math.ceil(equilibriumMinutes * 60.0 / timeframeSeconds))
int equilibriumBars = math.max(4, math.min(maximumEquilibriumBars, equilibriumBarsRaw))

float equilibriumHigh = ta.highest(high, equilibriumBars)
float equilibriumLow = ta.lowest(low, equilibriumBars)
float equilibriumStep = math.max((equilibriumHigh - equilibriumLow) / equilibriumRows, syminfo.mintick)

array<float> dynamicTotal = array.new_float(equilibriumRows, 0.0)
array<float> dynamicBuy = array.new_float(equilibriumRows, 0.0)
array<float> dynamicSell = array.new_float(equilibriumRows, 0.0)

for i = 0 to equilibriumBars - 1
    if not na(high[i])
        float barOpen = open[i]
        float barHigh = high[i]
        float barLow = low[i]
        float barClose = close[i]
        float barVolume = nz(volume[i], 0.0)
        float barRange = barHigh - barLow
        float safeRange = math.max(barRange, syminfo.mintick)

        float pressure = f_clamp((barClose - barOpen) / safeRange, -1.0, 1.0)
        float buyShare = (1.0 + pressure) * 0.5
        float sellShare = 1.0 - buyShare

        if barRange <= syminfo.mintick
            int row = int(math.floor((barClose - equilibriumLow) / equilibriumStep))
            row := math.max(0, math.min(equilibriumRows - 1, row))

            array.set(dynamicTotal, row, array.get(dynamicTotal, row) + barVolume)
            array.set(dynamicBuy, row, array.get(dynamicBuy, row) + barVolume * buyShare)
            array.set(dynamicSell, row, array.get(dynamicSell, row) + barVolume * sellShare)

        else
            int firstRow = int(math.floor((barLow - equilibriumLow) / equilibriumStep))
            int lastRow = int(math.floor((barHigh - equilibriumLow) / equilibriumStep))

            firstRow := math.max(0, math.min(equilibriumRows - 1, firstRow))
            lastRow := math.max(0, math.min(equilibriumRows - 1, lastRow))

            for row = firstRow to lastRow
                float rowLow = equilibriumLow + row * equilibriumStep
                float rowHigh = rowLow + equilibriumStep

                float overlap = math.max(0.0, math.min(barHigh, rowHigh) - math.max(barLow, rowLow))
                float fraction = overlap / barRange

                if fraction > 0
                    float rowVolume = barVolume * fraction

                    array.set(dynamicTotal, row, array.get(dynamicTotal, row) + rowVolume)
                    array.set(dynamicBuy, row, array.get(dynamicBuy, row) + rowVolume * buyShare)
                    array.set(dynamicSell, row, array.get(dynamicSell, row) + rowVolume * sellShare)


//=============================================================================
// DYNAMIC P0 / VALUE AREA
//=============================================================================

float totalDynamicVolume = 0.0
float maximumDynamicVolume = 0.0
int dynamicP0Index = 0

for row = 0 to equilibriumRows - 1
    float rowVolume = array.get(dynamicTotal, row)
    totalDynamicVolume += rowVolume

    if rowVolume > maximumDynamicVolume
        maximumDynamicVolume := rowVolume
        dynamicP0Index := row

float dynamicP0 = equilibriumLow + (dynamicP0Index + 0.5) * equilibriumStep

int dynamicVALIndex = dynamicP0Index
int dynamicVAHIndex = dynamicP0Index

float valueAreaVolume = array.get(dynamicTotal, dynamicP0Index)
float valueAreaTarget = totalDynamicVolume * dynamicValueAreaPercent / 100.0

while valueAreaVolume < valueAreaTarget and (dynamicVALIndex > 0 or dynamicVAHIndex < equilibriumRows - 1)
    float leftVolume = dynamicVALIndex > 0 ? array.get(dynamicTotal, dynamicVALIndex - 1) : -1.0
    float rightVolume = dynamicVAHIndex < equilibriumRows - 1 ? array.get(dynamicTotal, dynamicVAHIndex + 1) : -1.0

    if rightVolume > leftVolume
        dynamicVAHIndex += 1
        valueAreaVolume += array.get(dynamicTotal, dynamicVAHIndex)
    else
        if dynamicVALIndex > 0
            dynamicVALIndex -= 1
            valueAreaVolume += array.get(dynamicTotal, dynamicVALIndex)
        else if dynamicVAHIndex < equilibriumRows - 1
            dynamicVAHIndex += 1
            valueAreaVolume += array.get(dynamicTotal, dynamicVAHIndex)

float dynamicVAL = equilibriumLow + dynamicVALIndex * equilibriumStep
float dynamicVAH = equilibriumLow + (dynamicVAHIndex + 1.0) * equilibriumStep
float dynamicValueCenter = (dynamicVAH + dynamicVAL) * 0.5


//=============================================================================
// PROFILE COHERENCE
//=============================================================================

int coherenceLow = math.max(0, dynamicP0Index - coherenceRadius)
int coherenceHigh = math.min(equilibriumRows - 1, dynamicP0Index + coherenceRadius)

float coherenceVolume = 0.0

for row = coherenceLow to coherenceHigh
    coherenceVolume += array.get(dynamicTotal, row)

int coherenceRowCount = coherenceHigh - coherenceLow + 1

float coherenceShare = totalDynamicVolume > 0 ? coherenceVolume / totalDynamicVolume * 100.0 : 0.0
float uniformShare = 100.0 * coherenceRowCount / equilibriumRows

float profileCoherence = (coherenceShare + uniformShare > 0 ?
     100.0 * coherenceShare / (coherenceShare + uniformShare) :
     0.0)


//=============================================================================
// NEW-LOCATION VOLUME
//=============================================================================

float newLocationBand = atr * newLocationBandATR
float newLocationRecentVolume = 0.0
float newLocationRecentTotal = 0.0

for i = 0 to newLocationRecentBars - 1
    float barVolume = nz(volume[i], 0.0)
    newLocationRecentTotal += barVolume

    if math.abs(close[i] - close) <= newLocationBand
        newLocationRecentVolume += barVolume

float newLocationShare = (newLocationRecentTotal > 0 ?
     newLocationRecentVolume / newLocationRecentTotal * 100.0 :
     0.0)


//=============================================================================
// DELTA STATE
//=============================================================================

float aggregateDelta = 0.0
float aggregateVolume = 0.0

for i = 0 to deltaWindow - 1
    float barVolume = nz(volume[i], 0.0)
    aggregateDelta += f_delta(open[i], high[i], low[i], close[i], barVolume)
    aggregateVolume += barVolume

float deltaPercent = (aggregateVolume > 0 ? aggregateDelta / aggregateVolume * 100.0 : 0.0)
float distanceFromP0ATR = (close - dynamicP0) / atr

int displacementDirection = (distanceFromP0ATR > 0 ? 1 : distanceFromP0ATR < 0 ? -1 : 0)

int alignedDeltaBars = 0

for i = 0 to deltaPersistenceBars - 1
    float deltaBar = f_delta(open[i], high[i], low[i], close[i], nz(volume[i], 0.0))

    if displacementDirection > 0 and deltaBar > 0
        alignedDeltaBars += 1

    if displacementDirection < 0 and deltaBar < 0
        alignedDeltaBars += 1

float deltaPersistence = 100.0 * alignedDeltaBars / deltaPersistenceBars


//=============================================================================
// P0 MIGRATION / CATCH-UP
//=============================================================================

float priorP0 = dynamicP0[migrationLookback]
float priorValueCenter = dynamicValueCenter[migrationLookback]

float p0MigrationATR = (not na(priorP0) ? (dynamicP0 - priorP0) / atr : 0.0)
float valueMigrationATR = (not na(priorValueCenter) ? (dynamicValueCenter - priorValueCenter) / atr : 0.0)

bool p0MigrationAligned = displacementDirection != 0 and displacementDirection * p0MigrationATR > 0

float catchUpDenominator = (not na(priorP0) ? math.max(math.abs(close - priorP0), syminfo.mintick) : syminfo.mintick)

float p0CatchUpPercent = (p0MigrationAligned and not na(priorP0) ?
     math.abs(dynamicP0 - priorP0) / catchUpDenominator * 100.0 :
     0.0)

p0CatchUpPercent := f_clamp(p0CatchUpPercent, 0.0, 150.0)


//=============================================================================
// PRICE / DELTA EFFICIENCY
//=============================================================================

float priceProgressATR = (not na(close[efficiencyLookback]) ? (close - close[efficiencyLookback]) / atr : 0.0)

float alignedPriceProgress = displacementDirection * priceProgressATR
float alignedDeltaMagnitude = displacementDirection * deltaPercent

float alignedDeltaScore = f_score(alignedDeltaMagnitude, alignedDeltaTarget)
float opposingDeltaScore = f_score(-alignedDeltaMagnitude, opposingDeltaTarget)

float efficiencyScore = (alignedDeltaMagnitude > 0 ? f_score(math.max(alignedPriceProgress, 0.0), efficiencyTargetATR) : 0.0)

float absorptionDeltaScore = f_score(math.abs(deltaPercent), absorptionDeltaTarget)

float absorptionProgressScore = (absorptionMaximumProgressATR > 0 ?
     f_clamp((absorptionMaximumProgressATR - math.max(alignedPriceProgress, 0.0)) / absorptionMaximumProgressATR * 100.0, 0.0, 100.0) :
     0.0)

float absorptionScore = absorptionDeltaScore * absorptionProgressScore / 100.0


//=============================================================================
// DWELL / RETURN
//=============================================================================

int dwellCount = 0

for i = 0 to dwellMeasurementBars - 1
    if not na(dynamicP0[i])
        float band = atr[i] * equilibriumBandATR

        if displacementDirection > 0 and close[i] > dynamicP0[i] + band
            dwellCount += 1

        if displacementDirection < 0 and close[i] < dynamicP0[i] - band
            dwellCount += 1

float dwellPercent = 100.0 * dwellCount / dwellMeasurementBars

float currentDistance = math.abs(close - dynamicP0)
float previousDistance = (not na(dynamicP0[1]) ? math.abs(close[1] - dynamicP0[1]) : currentDistance)

bool returningTowardP0 = currentDistance < previousDistance
bool candleTowardP0 = (displacementDirection > 0 ? close < open : displacementDirection < 0 ? close > open : false)

float returnTowardP0Score = (returningTowardP0 and candleTowardP0 ? 100.0 : returningTowardP0 ? 50.0 : 0.0)


//=============================================================================
// ACCEPTANCE SCORE
//=============================================================================

float acceptanceMigration = f_score(displacementDirection * p0MigrationATR, migrationTargetATR)
float acceptanceCatchUp = f_score(p0CatchUpPercent, catchUpTargetPercent)
float acceptanceNewLocation = f_score(newLocationShare, newLocationTargetPercent)
float acceptanceValueMigration = f_score(displacementDirection * valueMigrationATR, valueMigrationTargetATR)

float acceptanceDelta = (alignedDeltaScore + deltaPersistence) * 0.5
float acceptanceEfficiency = efficiencyScore

float acceptanceRaw = (
     acceptanceMigration * 0.20 +
     acceptanceCatchUp * 0.15 +
     acceptanceNewLocation * 0.20 +
     acceptanceValueMigration * 0.15 +
     acceptanceDelta * 0.15 +
     dwellPercent * 0.10 +
     acceptanceEfficiency * 0.05)

float coherenceMultiplier = 0.55 + 0.45 * profileCoherence / 100.0

float acceptanceScore = f_clamp(acceptanceRaw * coherenceMultiplier, 0.0, 100.0)


//=============================================================================
// REJECTION SCORE
//=============================================================================

float rejectionP0Stall = 100.0 - acceptanceMigration
float rejectionValueNonMigration = 100.0 - acceptanceValueMigration
float rejectionWeakNewLocation = 100.0 - acceptanceNewLocation

float rejectionRaw = (
     rejectionP0Stall * 0.20 +
     opposingDeltaScore * 0.25 +
     absorptionScore * 0.15 +
     returnTowardP0Score * 0.15 +
     rejectionValueNonMigration * 0.10 +
     rejectionWeakNewLocation * 0.15)

float rejectionScore = f_clamp(rejectionRaw * coherenceMultiplier, 0.0, 100.0)


//=============================================================================
// MARKET STATE
//=============================================================================

bool meaningfulDisplacement = math.abs(distanceFromP0ATR) >= minimumDistanceATR
bool coherenceOK = profileCoherence >= minimumCoherence

bool bullAcceptanceDominant = (acceptanceScore >= acceptanceThresholdLong + signalStabilityMargin and acceptanceScore >= rejectionScore + scoreDominanceLong)
bool bearAcceptanceDominant = (acceptanceScore >= acceptanceThresholdShort + signalStabilityMargin and acceptanceScore >= rejectionScore + scoreDominanceShort)
bool bullRejectionDominant = (rejectionScore >= rejectionThresholdLong + signalStabilityMargin and rejectionScore >= acceptanceScore + scoreDominanceLong)
bool bearRejectionDominant = (rejectionScore >= rejectionThresholdShort + signalStabilityMargin and rejectionScore >= acceptanceScore + scoreDominanceShort)

bool bullishAcceptance = (meaningfulDisplacement and coherenceOK and displacementDirection > 0 and bullAcceptanceDominant)
bool bearishAcceptance = (meaningfulDisplacement and coherenceOK and displacementDirection < 0 and bearAcceptanceDominant)
bool bullishRejection = (meaningfulDisplacement and coherenceOK and displacementDirection < 0 and bullRejectionDominant)
bool bearishRejection = (meaningfulDisplacement and coherenceOK and displacementDirection > 0 and bearRejectionDominant)

string marketState = "EQUILIBRIUM"

if meaningfulDisplacement
    marketState := "TRANSITION"

if bullishAcceptance
    marketState := "BULL ACCEPTANCE"

if bearishAcceptance
    marketState := "BEAR ACCEPTANCE"

if bullishRejection
    marketState := "BULL REJECTION"

if bearishRejection
    marketState := "BEAR REJECTION"


//=============================================================================
// DYNAMIC P0 / VA DISPLAY
//=============================================================================

dynamicP0Plot = plot(showAllChartObjectsInput and showDynamicP0 ? dynamicP0 : na, title = "Dynamic P0", color = dynamicP0Color, linewidth = dynamicP0Width)

var label dynamicP0Label = na
if showAllChartObjectsInput and showDynamicP0 and showDynamicP0LabelInput
    if na(dynamicP0Label)
        dynamicP0Label := label.new(bar_index, dynamicP0, "P0 " + f_price(dynamicP0), xloc = xloc.bar_index, style = label.style_label_left, color = color.new(dynamicP0Color, 0), textcolor = color.black, size = size.small)
    else
        label.set_xy(dynamicP0Label, bar_index, dynamicP0)
        label.set_text(dynamicP0Label, "P0 " + f_price(dynamicP0))

dynamicVAHPlot = plot(showAllChartObjectsInput and showDynamicValueArea ? dynamicVAH : na, title = "Dynamic VAH", color = color.new(dynamicValueAreaColor, 25), linewidth = 1)
dynamicVALPlot = plot(showAllChartObjectsInput and showDynamicValueArea ? dynamicVAL : na, title = "Dynamic VAL", color = color.new(dynamicValueAreaColor, 25), linewidth = 1)

fill(dynamicVAHPlot, dynamicVALPlot, color = showAllChartObjectsInput and showDynamicValueArea ? color.new(dynamicValueAreaColor, 93) : na, title = "Dynamic Value Area")


//=============================================================================
// ARCHITECTURE DASHBOARD
//=============================================================================

architectureTablePosition = (
     architecturePosition == "Top Left" ?
     position.top_left :
     architecturePosition == "Bottom Left" ?
     position.bottom_left :
     architecturePosition == "Bottom Right" ?
     position.bottom_right :
     position.top_right)

var table architectureTable = table.new(architectureTablePosition, 5, 10, bgcolor = color.new(color.rgb(15, 20, 27), 10), border_width = 1)

if barstate.islast

    if showAllChartObjectsInput and showArchitectureHistogram

        int readCol = showLiveColumnInput ? 4 : 3

        table.cell(architectureTable, 0, 0, "ARCHITECTURE", text_color = color.white, bgcolor = color.rgb(22, 52, 86))
        table.cell(architectureTable, 1, 0, "ACCEPT", text_color = color.white, bgcolor = color.rgb(22, 52, 86))
        table.cell(architectureTable, 2, 0, "REJECT", text_color = color.white, bgcolor = color.rgb(22, 52, 86))
        if showLiveColumnInput
            table.cell(architectureTable, 3, 0, "LIVE", text_color = color.white, bgcolor = color.rgb(22, 52, 86))
        table.cell(architectureTable, readCol, 0, "READ", text_color = color.white, bgcolor = color.rgb(22, 52, 86))

        string readMigration = f_rowVerdict(acceptanceMigration, rejectionP0Stall, "MIGRATING", "STALLING", "FLAT")
        table.cell(architectureTable, 0, 1, "P0 Mig / Stall", text_color = color.white)
        table.cell(architectureTable, 1, 1, f_bar(acceptanceMigration), text_color = acceptanceColor)
        table.cell(architectureTable, 2, 1, f_bar(rejectionP0Stall), text_color = rejectionColor)
        if showLiveColumnInput
            table.cell(architectureTable, 3, 1, str.tostring(p0MigrationATR, "#.##") + "A", text_color = color.white)
        table.cell(architectureTable, readCol, 1, readMigration, text_color = readMigration == "MIGRATING" ? acceptanceColor : readMigration == "STALLING" ? rejectionColor : color.gray)

        string readCatchUp = f_rowVerdict(acceptanceCatchUp, 100.0 - acceptanceCatchUp, "CONVERGING", "LAGGING", "MIXED")
        table.cell(architectureTable, 0, 2, "Catch-Up", text_color = color.white)
        table.cell(architectureTable, 1, 2, f_bar(acceptanceCatchUp), text_color = acceptanceColor)
        table.cell(architectureTable, 2, 2, f_bar(100.0 - acceptanceCatchUp), text_color = rejectionColor)
        if showLiveColumnInput
            table.cell(architectureTable, 3, 2, f_pct(p0CatchUpPercent), text_color = color.white)
        table.cell(architectureTable, readCol, 2, readCatchUp, text_color = readCatchUp == "CONVERGING" ? acceptanceColor : readCatchUp == "LAGGING" ? rejectionColor : color.gray)

        string readNewValue = f_rowVerdict(acceptanceNewLocation, rejectionWeakNewLocation, "ACCEPTED", "REJECTED", "MIXED")
        table.cell(architectureTable, 0, 3, "New Value", text_color = color.white)
        table.cell(architectureTable, 1, 3, f_bar(acceptanceNewLocation), text_color = acceptanceColor)
        table.cell(architectureTable, 2, 3, f_bar(rejectionWeakNewLocation), text_color = rejectionColor)
        if showLiveColumnInput
            table.cell(architectureTable, 3, 3, f_pct(newLocationShare), text_color = color.white)
        table.cell(architectureTable, readCol, 3, readNewValue, text_color = readNewValue == "ACCEPTED" ? acceptanceColor : readNewValue == "REJECTED" ? rejectionColor : color.gray)

        string readVaMigration = f_rowVerdict(acceptanceValueMigration, rejectionValueNonMigration, "SHIFTING", "ANCHORED", "MIXED")
        table.cell(architectureTable, 0, 4, "VA Migration", text_color = color.white)
        table.cell(architectureTable, 1, 4, f_bar(acceptanceValueMigration), text_color = acceptanceColor)
        table.cell(architectureTable, 2, 4, f_bar(rejectionValueNonMigration), text_color = rejectionColor)
        if showLiveColumnInput
            table.cell(architectureTable, 3, 4, str.tostring(valueMigrationATR, "#.##") + "A", text_color = color.white)
        table.cell(architectureTable, readCol, 4, readVaMigration, text_color = readVaMigration == "SHIFTING" ? acceptanceColor : readVaMigration == "ANCHORED" ? rejectionColor : color.gray)

        string readDelta = f_rowVerdict(acceptanceDelta, opposingDeltaScore, "ALIGNED", "OPPOSING", "MIXED")
        table.cell(architectureTable, 0, 5, "Delta", text_color = color.white)
        table.cell(architectureTable, 1, 5, f_bar(acceptanceDelta), text_color = acceptanceColor)
        table.cell(architectureTable, 2, 5, f_bar(opposingDeltaScore), text_color = rejectionColor)
        if showLiveColumnInput
            table.cell(architectureTable, 3, 5, f_pct(deltaPercent), text_color = color.white)
        table.cell(architectureTable, readCol, 5, readDelta, text_color = readDelta == "ALIGNED" ? acceptanceColor : readDelta == "OPPOSING" ? rejectionColor : color.gray)

        string readEfficiency = f_rowVerdict(acceptanceEfficiency, absorptionScore, "EFFICIENT", "ABSORBED", "MIXED")
        table.cell(architectureTable, 0, 6, "Efficiency", text_color = color.white)
        table.cell(architectureTable, 1, 6, f_bar(acceptanceEfficiency), text_color = acceptanceColor)
        table.cell(architectureTable, 2, 6, f_bar(absorptionScore), text_color = rejectionColor)
        if showLiveColumnInput
            table.cell(architectureTable, 3, 6, str.tostring(priceProgressATR, "#.##") + "A", text_color = color.white)
        table.cell(architectureTable, readCol, 6, readEfficiency, text_color = readEfficiency == "EFFICIENT" ? acceptanceColor : readEfficiency == "ABSORBED" ? rejectionColor : color.gray)

        string readDwell = f_rowVerdict(dwellPercent, returnTowardP0Score, "HOLDING", "RETURNING", "MIXED")
        table.cell(architectureTable, 0, 7, "Dwell / Return", text_color = color.white)
        table.cell(architectureTable, 1, 7, f_bar(dwellPercent), text_color = acceptanceColor)
        table.cell(architectureTable, 2, 7, f_bar(returnTowardP0Score), text_color = rejectionColor)
        if showLiveColumnInput
            table.cell(architectureTable, 3, 7, str.tostring(dwellCount) + "/" + str.tostring(dwellMeasurementBars), text_color = color.white)
        table.cell(architectureTable, readCol, 7, readDwell, text_color = readDwell == "HOLDING" ? acceptanceColor : readDwell == "RETURNING" ? rejectionColor : color.gray)

        string readTotal = marketState == "BULL ACCEPTANCE" ? "BULL BREAK" : marketState == "BEAR ACCEPTANCE" ? "BEAR BREAK" : marketState == "BULL REJECTION" ? "BULL BOUNCE" : marketState == "BEAR REJECTION" ? "BEAR BOUNCE" : marketState
        table.cell(architectureTable, 0, 8, "TOTAL", text_color = color.white)
        table.cell(architectureTable, 1, 8, f_bar(acceptanceScore) + " " + str.tostring(acceptanceScore, "#"), text_color = acceptanceColor)
        table.cell(architectureTable, 2, 8, f_bar(rejectionScore) + " " + str.tostring(rejectionScore, "#"), text_color = rejectionColor)
        if showLiveColumnInput
            table.cell(architectureTable, 3, 8, marketState, text_color = color.white)
        table.cell(architectureTable, readCol, 8, readTotal, text_color = str.contains(readTotal, "BULL") ? acceptanceColor : str.contains(readTotal, "BEAR") ? rejectionColor : color.gray)

        table.cell(architectureTable, 0, 9, "P0 / Dist / Coh", text_color = color.white)
        table.cell(architectureTable, 1, 9, f_price(dynamicP0), text_color = dynamicP0Color)
        table.cell(architectureTable, 2, 9, str.tostring(distanceFromP0ATR, "#.##") + "A", text_color = color.white)
        if showLiveColumnInput
            table.cell(architectureTable, 3, 9, f_pct(profileCoherence), text_color = color.white)
        table.cell(architectureTable, readCol, 9, profileCoherence >= minimumCoherence ? "STRUCTURED" : "NOISY", text_color = profileCoherence >= minimumCoherence ? acceptanceColor : color.gray)

        dashboardSizeValue = f_dashboardSize(dashboardTextSize)

        for dashboardRow = 0 to 9
            for dashboardCol = 0 to 4
                table.cell_set_text_size(architectureTable, dashboardCol, dashboardRow, dashboardSizeValue)

Overview

A dashboard table scores acceptance and rejection from P0 migration, new-location volume, value area migration, estimated delta alignment, price efficiency, dwell and profile coherence. Delta is estimated from candle data, not true order flow. It places no orders and has many tunable thresholds.

Details

Published by

rosijay17-cmd on GitHub

Type

Indicator, Pine Script v6

Draws

On the price chart

Category

Volume, Screeners & dashboards, Support & resistance

Markets

Any symbol

Timeframes

M15-H1

Risk Notes

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

Settings

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

SettingTypeDefaultVariable
Show All Chart ObjectsbooltrueshowAllChartObjectsInput
Equilibrium Window (Minutes)int240equilibriumMinutes
Dynamic P0 Price Rowsint32equilibriumRows
Maximum Bars In Dynamic Profileint500maximumEquilibriumBars
Dynamic Value Area %float70.0dynamicValueAreaPercent
P0 Coherence Radius (Rows)int2coherenceRadius
Equilibrium Band (ATR)float0.35equilibriumBandATR
Minimum Meaningful Displacement (ATR)float0.80minimumDistanceATR
P0 / Value Migration Lookbackint4migrationLookback
Strong P0 Migration (ATR)float0.15migrationTargetATR
Strong P0 Catch-Up %float40.0catchUpTargetPercent
New-Location Volume Band (ATR)float0.25newLocationBandATR
Show all 40 settings
SettingTypeDefaultVariable
Strong New-Location Volume %float35.0newLocationTargetPercent
New-Location Recency Window (Bars)int20newLocationRecentBars
Strong Value-Area Migration (ATR)float0.10valueMigrationTargetATR
Delta State Windowint3deltaWindow
Delta Persistence Barsint3deltaPersistenceBars
Strong Aligned Delta %float20.0alignedDeltaTarget
Strong Opposing Delta %float20.0opposingDeltaTarget
Efficiency Lookbackint3efficiencyLookback
Efficient Price Progress (ATR)float0.30efficiencyTargetATR
Absorption Delta Magnitude %float25.0absorptionDeltaTarget
Absorption Maximum Price Progress (ATR)float0.12absorptionMaximumProgressATR
Dwell Measurement Barsint4dwellMeasurementBars
Minimum Profile Coherencefloat55.0minimumCoherence
Acceptance Score Threshold (Long)float65.0acceptanceThresholdLong
Acceptance Score Threshold (Short)float65.0acceptanceThresholdShort
Rejection Score Threshold (Long)float50.0rejectionThresholdLong
Rejection Score Threshold (Short)float50.0rejectionThresholdShort
Required Score Dominance (Long)float24.0scoreDominanceLong
Required Score Dominance (Short)float24.0scoreDominanceShort
Signal Stability Marginfloat0.0signalStabilityMargin
Show Dynamic P0booltrueshowDynamicP0
Label The Dynamic P0 LinebooltrueshowDynamicP0LabelInput
Dynamic P0 Colorcolorcolor.aquadynamicP0Color
Dynamic P0 Widthint3dynamicP0Width
Show Dynamic VAH / VALbooltrueshowDynamicValueArea
Dynamic Value Area Colorcolorcolor.rgb(70, 115, 255)dynamicValueAreaColor
Show Acceptance / Rejection DashboardbooltrueshowArchitectureHistogram
PositionstringTop RightarchitecturePosition
Third-party code. ForexR did not write, test or endorse this script, and the summary above was generated automatically from its code and README. Indicators describe the past, and a strategy's backtest can look better than live trading, especially when a script repaints. Check it in the Strategy Tester and on a demo account before you rely on it.

Similar Pine Scripts

This overlay indicator builds a horizontal momentum profile over a chosen lookback. It splits price into rows and plots the average WaveTrend of each zone as a bar colored by direction, plus an optional MFI reference band that stays gray when real trade volume

Indicator v6 Oscillators & momentumVolume
Updated 2 days ago · MIT GitHub repository of Momentum Profile [WavesUnchained]
5 stars

This indicator builds a frozen volume profile over a fixed, half-open timestamp range and draws it on the price chart. It aggregates one-minute source bars into output rows sized by a chosen tick count, marks a configurable value-area percentage, and can plot

Indicator v6 VolumeSupport & resistance
Updated 3 days ago · MPL-2.0 GitHub repository of VP RSD Fixed Range Shelf Diagnostic
4 stars

This overlay indicator draws an on-chart depth-of-market table that splits volume at each price tick into estimated buy volume, sell volume, delta, and session volume. Growing text bars compare buyers and sellers, and recent bars approximate resting bid and as

Indicator v5 VolumeScreeners & dashboards
Updated 6 months ago · None stated GitHub repository of Custom DOM - Bookmap Style
4 stars

This indicator overlays an order flow intelligence suite directly on the price chart. It renders a liquidity heatmap across configured price zones, alongside an on-chart information panel displaying volume delta, cumulative volume delta, a momentum compass bas

Indicator v6 VolumeScreeners & dashboards
Updated 2 weeks ago · MIT GitHub repository of GHOST — OrderFlow Intelligence

More indicators

Trade Your Charts With a Regulated Broker

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

Compare brokers