Correlation matrix and per-asset statistics - #16
Merged
Merged
Conversation
Both bundled in one PR since they share the grid-row table pattern PR 5 already built (.mw-table/.mw-grid-row/.mw-num), and neither has any interactive state of its own — no drag, no slider — so both are plain full-rebuild-on-render sections, unlike frontier/allocation. frontend/app.js: - correlationSectionHtml(): a CSS-grid matrix (not a <table>, matching the rest of the report), cell color linearly interpolated in RGB from neutral-900 to accent-600. Text stays ink-dark at every value — this ramp (unlike the mobile design's) never needs a light/dark contrast threshold, since it tops out light enough that dark text stays correct throughout. The least/most-correlated-pair callout scans only the upper triangle so each pair is considered once. - assetStatsSectionHtml(): standalone per-asset expected return/ volatility (from asset_statistics — independent of any portfolio), a client-computed standalone Sharpe, and the Weight column reads through selectedPortfolio() — so, matching the handoff, it updates live as the frontier selection is dragged, not just at the tangency default. Zero/near-zero weights dim to neutral-600 rather than being hidden, so an asset the optimizer declined stays visible. Verified with headless Chromium against a synthetic /api/analyze response: the matrix diagonal is 1.00 everywhere, the least/most correlated pairs match a manual scan of the input matrix, and the per-asset Weight column changes when jumping to the minimum-variance point on the frontier (confirming it tracks selection, not a fixed snapshot) — plus a full-page screenshot checked against the handoff. Co-Authored-By: Claude Sonnet 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.
Context
PR 6 of the widescreen "analytical workstation" report redesign. Stacked on #15 (targets that branch, not
main).What's here
Both sections bundled in one PR since they share the grid-row table pattern #15 already built (
.mw-table/.mw-grid-row/.mw-num), and neither has any interactive state of its own — no drag, no slider — so both are plain full-rebuild-on-render sections, unlike the frontier chart or allocation's cash slider.<table>, matching the rest of the report), cell color linearly interpolated in RGB from neutral-900 to accent-600. Text stays ink-dark at every value — this ramp, unlike the earlier mobile design's, never needs a light/dark contrast threshold, since it tops out light enough that dark text stays correct throughout. The least/most-correlated-pair callout scans only the upper triangle so each pair is considered once.asset_statistics— independent of any portfolio weighting), a client-computed standalone Sharpe, and a Weight column that reads throughselectedPortfolio()— so, matching the handoff, it updates live as the frontier selection is dragged, not just at the tangency default. Zero/near-zero weights dim to neutral-600 rather than being hidden, so an asset the optimizer declined stays visible.Verification
Headless Chromium against a synthetic
/api/analyzeresponse: the matrix diagonal is 1.00 everywhere, the least/most correlated pairs match a manual scan of the input matrix, and the per-asset Weight column changes when jumping to the minimum-variance point on the frontier (confirming it tracks selection, not a fixed snapshot) — plus a full-page screenshot checked against the handoff.🤖 Generated with Claude Code