AuditProtocol

Every indicator makes claims. "This signal has edge." "Price stays inside these bands." Almost none of them keep score. I built this library so keeping score becomes a three line habit: import it, register your claims, and let the tape settle them. Any indicator can wear a live, lookahead free audit of itself.
What's inside
Prequal is a prequential tracker for probability forecasts. You register a probability before the outcome and resolve it after the outcome is real, never the other way around. It tracks hit rate and the Brier score, the proper scoring rule for probability forecasts, plus Brier skill against a coin flip.
Coverage is for bands and intervals. If your band claims 90% containment, this tracks what it actually delivered, target next to realized, recent and lifetime.
Conformal learns the width multiplier that makes any band honest. Feed it your normalized residuals and ask it for k(). Your band, resized until the coverage is real. This is the split conformal quantile method, applied to whatever band you already draw.
Barrier settles setups by first touch: target barrier or stop barrier, whichever the tape hits first. A nod to triple barrier labeling. Ties inside a single bar go to the stop, conservative by design.
The Audit Score compresses it into one 0 to 100 number. Calibration earns up to 50 points. Demonstrated skill earns the other 50. So an honest indicator with zero edge sits near 50. That's the anchor: 50 is sea level, everything above it is earned, and anything well below it is miscalibrated.
The Receipt is the standard panel. Claims on the left, reality on the right.
How to use it
import YOUR_HANDLE/AuditProtocol/1 as ap
var pq = ap.newPrequal()
var c90 = ap.newCoverage(90)
if barstate.isconfirmed
ap.resolve(pq, close > close[1]) // settle yesterday's call
ap.resolveInterval(c90, close) // settle yesterday's band
ap.predict(pq, myProbabilityUp) // register today's call
ap.setInterval(c90, myLo, myHi) // register today's band
ap.panel(pq, c90, na, position.top_right)
//////////////////////////////////////////////////////////////////////
Library "AuditProtocol"
newPrequal(emaAlpha)
Creates a prequential tracker.
Parameters:
emaAlpha (float): EMA rate for the live (recent) readings. Default 0.02.
Returns: A fresh Prequal tracker.
method predict(this, p)
Registers a probability forecast (P of the outcome being TRUE) for the NEXT resolution. Call AFTER resolve() in the same confirmed-bar block.
Namespace types: Prequal
Parameters:
this (Prequal)
p (float)
method resolve(this, outcome)
Resolves the pending forecast against the realized outcome. Call once per confirmed bar BEFORE registering the next forecast.
Namespace types: Prequal
Parameters:
this (Prequal)
outcome (bool)
method hitRate(this)
Lifetime hit rate in percent, or na before any resolution.
Namespace types: Prequal
Parameters:
this (Prequal)
method skill(this)
Brier skill score vs the coin-flip baseline: 1 - Brier/0.25. 0 = no skill, 1 = perfect, negative = worse than guessing.
Namespace types: Prequal
Parameters:
this (Prequal)
newCoverage(targetPct, emaAlpha)
Creates a coverage tracker for a band claiming `targetPct` percent containment.
Parameters:
targetPct (float)
emaAlpha (float)
method setInterval(this, lo, hi)
Registers the band that should contain the NEXT observation.
Namespace types: Coverage
Parameters:
this (Coverage)
lo (float)
hi (float)
method resolveInterval(this, x)
Resolves the pending band against the realized value.
Namespace types: Coverage
Parameters:
this (Coverage)
x (float)
method realized(this)
Lifetime realized coverage in percent, or na before any resolution.
Namespace types: Coverage
Parameters:
this (Coverage)
method covError(this)
Absolute calibration error in percentage points: |realized - target|. na before any resolution.
Namespace types: Coverage
Parameters:
this (Coverage)
newConformal(targetPct, window, warmup)
Creates a conformal scaler. Feed it |realized error| / your band's unit width; ask it for k().
Parameters:
targetPct (float)
window (int)
warmup (int)
method observe(this, normResid)
Records one realized normalized residual (e.g. |close - center| / sigma).
Namespace types: Conformal
Parameters:
this (Conformal)
normResid (float)
method k(this, fallback)
The learned width multiplier: the target-quantile of observed residuals. Returns `fallback` until warm. Band = center ± k() * unitWidth delivers ~target coverage.
Namespace types: Conformal
Parameters:
this (Conformal)
fallback (float)
newBarrier()
Creates a barrier tracker for first-touch setup outcomes.
method arm(this, target, stop)
Arms a setup: which barrier must be touched first for a win (tgt) vs a loss (stp).
Namespace types: Barrier
Parameters:
this (Barrier)
target (float)
stop (float)
method check(this, barHigh, barLow)
Checks the current bar. Returns +1 (target first), -1 (stop first), 0 (still open). If both are inside one bar, the stop wins: conservative by design.
Namespace types: Barrier
Parameters:
this (Barrier)
barHigh (float)
barLow (float)
method winRate(this)
Lifetime win rate of resolved setups in percent, or na.
Namespace types: Barrier
Parameters:
this (Barrier)
score(pq, cA, cB, minN)
The composite 0-100 audit score. Calibration earns up to 50 points
(25 per coverage tracker; pass the same tracker twice if you only
have one band). Skill earns up to 50 (Brier skill vs coin flip).
Returns na until minN resolutions on the prequential tracker.
Parameters:
pq (Prequal)
cA (Coverage)
cB (Coverage)
minN (int)
panel(pq, cA, cB, pos)
Renders the Receipt, the standard audit panel. Pass na for trackers you don't use.
Parameters:
pq (Prequal)
cA (Coverage)
cB (Coverage)
pos (string)
Prequal
Fields:
pPend (series float)
accEma (series float)
brierEma (series float)
hits (series int)
n (series int)
emaA (series float)
Coverage
Fields:
target (series float)
loPend (series float)
hiPend (series float)
covEma (series float)
hits (series int)
n (series int)
emaA (series float)
Conformal
Fields:
resid (array<float>)
target (series float)
win (series int)
warm (series int)
Barrier
Fields:
tgt (series float)
stp (series float)
live (series bool)
wins (series int)
losses (series int)
Pine Bibliothek
Ganz im Sinne von TradingView hat dieser Autor seinen/ihren Pine Code als Open-Source-Bibliothek veröffentlicht. Auf diese Weise können nun auch andere Pine-Programmierer aus unserer Community den Code verwenden. Vielen Dank an den Autor! Sie können diese Bibliothek privat oder in anderen Open-Source-Veröffentlichungen verwenden. Die Nutzung dieses Codes in einer Veröffentlichung wird in unseren Hausregeln reguliert.
Haftungsausschluss
Pine Bibliothek
Ganz im Sinne von TradingView hat dieser Autor seinen/ihren Pine Code als Open-Source-Bibliothek veröffentlicht. Auf diese Weise können nun auch andere Pine-Programmierer aus unserer Community den Code verwenden. Vielen Dank an den Autor! Sie können diese Bibliothek privat oder in anderen Open-Source-Veröffentlichungen verwenden. Die Nutzung dieses Codes in einer Veröffentlichung wird in unseren Hausregeln reguliert.