feat(monitor): measure the baseline firing rate over a recent window - #118
Merged
Conversation
The opportunity-set channel compares the live firing rate against the baseline's. The baseline's was measured over the validated log's WHOLE span, which is right for a stationary book and quietly wrong for one whose rate has trended: the full-span mean sits below what the book currently does, so the ratio reads healthy while the rate falls. Not hypothetical. On the real 40-market trend book this is measured, not argued: full span (40yr) 23.4 trades/yr last 10 years 29.2 last 7 years 33.9 last 5 years 35.3 The trend is +0.49 trades/yr per year (r=+0.63), so the rate has roughly doubled over the log. Anchored to the full span, a collapse to 30% BELOW current behaviour still scores 1.02 against the baseline and can never cross the 0.6 line. The one channel covering a signal that stops firing while its per-trade edge holds was structurally desensitised, not merely uncalibrated. from_log gains rate_window_years, and EdgeBaseline records it. The default is unchanged (whole span) so nothing moves silently for existing callers, and the window rides in the verdict's reason line because two baselines with the same rate and different windows are not making the same claim. It is a windowed measurement taken ONCE, at promotion, not a rolling one, and the distinction is the whole architecture: recomputing it later would re-fit the reference onto the drifted reality. edge_monitor still has no parameter from which a baseline or its rate could be rebuilt, pinned by a test. Two edges chosen deliberately: a window holding fewer than two trades falls back to the whole span rather than returning None, because switching the channel off entirely is worse than a stale rate the baseline's own field reveals; and an explicitly supplied trades_per_year clears the window, since recording one this code did not apply would be a lie about provenance. 386 tests pass, ruff clean. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
mspinola
added a commit
that referenced
this pull request
Aug 3, 2026
#118 has been stranded on main since 0.6.0, which matters more than a normal stranded feature: npf already depends on rate_window_years while declaring crucible>=0.6.0, and that API does not exist in 0.6.0. A PyPI install of npf could resolve a crucible that raises TypeError inside EdgeBaseline.from_log. That is the same floor bug fixed this morning, recurring within hours, and the guard written to prevent it did not catch it: it compares the pin against a hand-maintained constant, so it fires only when someone has already remembered. npf's follow-up replaces it with a check against the floor RELEASE rather than a restatement of the pin. Contents, both concerning the firing-rate channel: * rate_window_years, measuring the baseline firing rate over the last N years of the validated log rather than its whole span. On a book whose rate has trended the whole-span mean sits below current behaviour, so the channel compares live trades against a rate the book left behind. Measured on a real 40-year book: 23.4/yr full span against 33.9/yr over 7 years, which moved the trip point from 41% to 60% of current behaviour. * The record of why that channel still cannot escalate to DEGRADED. Three arrival-process detectors were built and all deliver a false-alarm rate 3x to 5x worse than stated; calibrating empirically leaves the delivered budget spanning 5.3 to 77.9 years for a stated 10. The claim that arrivals are approximately Poisson is deleted rather than softened. 390 tests pass, ruff clean, mkdocs --strict clean. python -m build then twine check both artifacts PASSED. Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The opportunity-set channel compares the live firing rate against the baseline's. The baseline's was measured over the validated log's whole span, which is right for a stationary book and quietly wrong for one whose rate has trended: the full-span mean sits below what the book currently does, so the ratio reads healthy while the rate falls.
Not hypothetical
Measured on the real 47-market trend book:
The trend is +0.49 trades/yr per year (r=+0.63), so the rate has roughly doubled over the log. Anchored to the full span, a collapse to 30% below current behaviour still scores 1.02 against the baseline and can never cross the 0.6 line. The one channel covering a signal that stops firing while its per-trade edge holds was structurally desensitised, not merely uncalibrated.
What changed
from_loggainsrate_window_years, andEdgeBaselinerecords it. The default is unchanged (whole span) so nothing moves silently for existing callers, and the window rides in the verdict's reason line, because two baselines with the same rate and different windows are not making the same claim.It is a windowed measurement taken once, at promotion, not a rolling one, and that distinction is the whole architecture: recomputing it later would re-fit the reference onto the drifted reality.
edge_monitorstill has no parameter from which a baseline or its rate could be rebuilt, pinned bytest_the_window_never_re_measures_after_promotion.Two edges chosen deliberately
None, because switching the channel off entirely is worse than a stale rate that the baseline's own field reveals as un-windowed.trades_per_yearclears the window, since recording one this code did not apply would be a lie about provenance.386 tests pass, ruff clean.
🤖 Generated with Claude Code