Exposure: the contract percentile, per market - #64
Merged
Conversation
mspinola
force-pushed
the
claude/exposure-contracts-percentile
branch
from
August 24, 2026 21:57
bb15e2f to
0186f2a
Compare
A single market gets a sentence saying where contracts put the same week that the dollars are extreme in. A set got nothing, because that sentence reads the one member frame, so selecting two markets removed the comparison rather than doubling it. This puts it in the contributions table as a column, where it exists for every member. The report this was measured against draws gold and silver, each in contracts and in notional, each against its whole history. Its numbers reproduce here exactly on the contract side (258,418 lots at the 88th percentile for gold, 44,792 at the 52nd for silver) and within about a percent on the dollar side, where its price source differs from Norgate. With the column, those four numbers are two rows of one table: gold 100 in dollars against 88 in contracts, silver 98 against 52, so silver's extreme is almost entirely price and volatility rather than more contracts. Ranked against ALL history rather than against the Lookback control, because contribution_table ranks the dollar columns that way and two percentiles on one row measured over different stretches of time is the confusion this column removes. That the table does not follow the control while the headline does is a pre-existing inconsistency, recorded in the design doc and not fixed here. Read off the member frame, never off the aggregate: cotmetrics #21 removed the summed net_contracts because it added ES contracts to corn contracts. The signed count rides the rowData for the hover, because a percentile has no side and this column's subject is a position that has one. The dollar percentile's header tooltip now names its unit, since two columns headed "%ile" and "Contracts %ile" leave the first to be inferred. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Found while checking the column against the live board rather than against a fixture: gold reads 88 on the contract count alone and 81 inside an equities-and-metals set, because aggregate_exposure restricts every member frame to the weeks the total can price and Russell does not start until 2002. The dollar percentiles beside it have always done this, and this column follows them deliberately, so the fix is words rather than arithmetic: the header tooltip now says "over the weeks this set covers", the docstring carries the worked example, and a test pins the behaviour so nobody corrects this column into disagreeing with the two beside it. The table's own label still says "each market against its own history", which is a shade imprecise for every percentile in the table rather than for this one. Left for whoever next edits that label, which is the session fixing the Lookback inconsistency, since editing it here would collide with that change for one word. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The comment said a 52-week window would give this fixture the same answer as all history and that the assertion therefore pinned nothing about the window. Measured on the fixture itself, the three answers are 0.91 expanding, 1.92 at 52 weeks and 3.85 at 26, because the denominator is how many weeks were compared. The assertion does discriminate; the reasoning printed beside it was wrong. Found by the session stacked on this branch, which measured it rather than reading it, and reproduced here independently before changing anything. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
mspinola
force-pushed
the
claude/exposure-contracts-percentile
branch
from
August 24, 2026 22:31
7e4cada to
379bbeb
Compare
mspinola
added a commit
that referenced
this pull request
Aug 24, 2026
The headline, the band, the %ile scale and the caption all ranked over whatever Lookback resolved to. The contributions table under them ranked every member against all history whatever the control said, because contribution_table called expanding_pct_rank unconditionally. So on "52 weeks" the page said "higher than 97% of the last 52 weeks" three lines above a column headed "%ile" measured against twenty years, with both on screen at once and nothing on either saying they were different questions. Live, Gold alone on 52 weeks: headline 62nd percentile, table row 99. Now 62 and 61.5. Threading the window through rather than explaining it in copy. The expanding rank has a real claim on this page, since no unit here is stationary through time and it is the only form that can say "the most ever", but that is an argument for keeping All history as the DEFAULT, which it is, and not for ignoring a control after the reader has moved it. Copy can describe two bases; it cannot make them comparable, and the question the table answers is "which market is driving the number in the headline". Three columns move together or none of them do. The dollar percentiles ride the `window` parameter cotmetrics 0.9.0 added to contribution_table, which is why the floor moves with this: against 0.8.0 the keyword raises TypeError on every render and no setting of the control avoids it. The Contracts %ile column from #64 follows in the same change, since it was written to match whatever the dollar columns did and moving one without the other puts the row back to mixing histories by the other route. The copy that goes false the moment the arithmetic lands, all in here rather than in a follow-up: the dollar column's "Against all of it, whatever the Lookback control says", the table label, and the standing explanation, which told a reader who moved the control that the band moved with it and said nothing about the table. The label also absorbs the second imprecision #64 left for whoever next edited it, that a member's "own history" is the weeks the SET covers (gold 88 alone, 81 in a set starting in 2002 because Russell does). Both restrictions are named, and the set clause is dropped on a single market, where it has nothing to qualify. The default is asserted rather than left to a constant: attach_contracts_rank without a window reads 0.91 on the fixture against 1.92 at 52 weeks and 3.85 at 26, so the expanding assertion discriminates, and the test now says so. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
mspinola
added a commit
that referenced
this pull request
Aug 24, 2026
The headline, the band, the %ile scale and the caption all ranked over whatever Lookback resolved to. The contributions table under them ranked every member against all history whatever the control said, because contribution_table called expanding_pct_rank unconditionally. So on "52 weeks" the page said "higher than 97% of the last 52 weeks" three lines above a column headed "%ile" measured against twenty years, with both on screen at once and nothing on either saying they were different questions. Live, Gold alone on 52 weeks: headline 62nd percentile, table row 99. Now 62 and 61.5. Threading the window through rather than explaining it in copy. The expanding rank has a real claim on this page, since no unit here is stationary through time and it is the only form that can say "the most ever", but that is an argument for keeping All history as the DEFAULT, which it is, and not for ignoring a control after the reader has moved it. Copy can describe two bases; it cannot make them comparable, and the question the table answers is "which market is driving the number in the headline". Three columns move together or none of them do. The dollar percentiles ride the `window` parameter cotmetrics 0.9.0 added to contribution_table, which is why the floor moves with this: against 0.8.0 the keyword raises TypeError on every render and no setting of the control avoids it. The Contracts %ile column from #64 follows in the same change, since it was written to match whatever the dollar columns did and moving one without the other puts the row back to mixing histories by the other route. The copy that goes false the moment the arithmetic lands, all in here rather than in a follow-up: the dollar column's "Against all of it, whatever the Lookback control says", the table label, and the standing explanation, which told a reader who moved the control that the band moved with it and said nothing about the table. The label also absorbs the second imprecision #64 left for whoever next edited it, that a member's "own history" is the weeks the SET covers (gold 88 alone, 81 in a set starting in 2002 because Russell does). Both restrictions are named, and the set clause is dropped on a single market, where it has nothing to qualify. The default is asserted rather than left to a constant: attach_contracts_rank without a window reads 0.91 on the fixture against 1.92 at 52 weeks and 3.85 at 26, so the expanding assertion discriminates, and the test now says so. 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.
A gold-and-silver positioning report draws each market twice, in contracts and in dollar notional, each against its whole history. Evaluated against this page, almost all of it was already here:
Markets = Gold, Leg = Speculators, Unit = Notional, Lookback = All historyrenders the report's own chart, and our version adds the volatility panel, the Large-against-Small split and the publication lag.One thing was missing, and it was the thing the report is built on. The contract percentile lived only in the single-market sentence under the headline, because it is read off the member frame. Selecting Gold and Silver therefore removed the comparison rather than doubling it. This adds it to the contributions table as a column, joined per member.
On the live week the report's four numbers become two rows:
Which says out loud what the report leaves to the reader: silver's extreme is almost entirely price and volatility, not more contracts.
It is also a cross-check of the store against an outside source. Their contract figures (258,418 lots at the 88th percentile for gold, 44,792 at the 52nd for silver) reproduce exactly; the dollar figures differ by about a percent because they price off Stooq/FMP/Yahoo and this stack prices futures off Norgate unadjusted.
Three decisions in the column
contribution_tableranks the dollar columns that way, and two percentiles on one row measured over different stretches of time is exactly the confusion this column exists to remove. That the table does not follow the control while the headline does is a pre-existing inconsistency, recorded in the design doc and deliberately not fixed here.net_contractsbecause it added ES contracts to corn contracts; this column would have been the first thing to bring that back.The design doc gains a section evaluating the report chart by chart, including what was left behind (their "spec = mirror of commercials" label folds Small Traders into the speculator leg).
Testing
463 passed, 6 of them new,
ruff check src testsclean. Verified in the browser on Gold + Silver: the column, the values above, the hover, and no console or server errors.Note: this touches the tail of
docs/design/positioning-report-view-ideas.md, as does #63. Whichever merges second needs a one-hunk rebase there.🤖 Generated with Claude Code