Quantify Investment research that keeps its history

Findings

A finding is the conclusion of an investigation — neither a claim nor a piece of evidence. A claim asserts something about the world; evidence bears on one claim; a finding is what someone concluded after synthesising several pieces of evidence, and it usually touches several claims, methodologies and assumptions at once. Before findings were artifacts, that synthesis lived in prose scattered across change rationales and erratum documents, where it could be read but not queried, reviewed as a unit, or routed.

finding/declared-rules-do-not-execute@1

Concluded 2026-07-31

4 adverse relationship(s), 5 total

invalidates results of invalidates results of invalidates results of invalidates results of introduced finding/declared-rules-do-n... · methodology/hrp@1 · methodology/hrp@2 · methodology/hrp@3 · methodology/xsmom@1 · assumption/declarations-nam...
Relationships as a table
SourceRelationTargetEffectDirectnessDetail
finding/declared-rules-do-not-execute@1 invalidates results of methodology/hrp@1 blocking direct Declares min_history; the rule does not execute.
finding/declared-rules-do-not-execute@1 invalidates results of methodology/hrp@2 blocking direct Declares min_history and turnover_cap; neither rule executes.
finding/declared-rules-do-not-execute@1 invalidates results of methodology/hrp@3 blocking direct Declares concentration_cap <= 0.25, which is satisfied only because...
finding/declared-rules-do-not-execute@1 invalidates results of methodology/xsmom@1 blocking direct Declares min_history and has_full_formation_history; neither executes.
finding/declared-rules-do-not-execute@1 introduced assumption/declarations-name-th... none direct Generalised the fix into a standing principle: every declaration must...

A methodology's `rules` and `universe_filters` are declared, merged, and hashed into its identity, but no pipeline step evaluates them. They have zero references in the executor. A reader seeing rules: - id: concentration_cap expr: max_asset_weight <= 0.25 reasonably concludes the constraint is enforced by that rule. It is not. In hrp@3 the constraint happens to hold because `contract.weight_bounds.max` is also 0.25 — the rule is decorative, and the two could disagree silently. This inverts the defect class the project has found repeatedly. The usual pattern is a hidden choice that takes effect without being declared. Here a declared rule appears to take effect and does not, which is arguably worse: declaring it creates the belief that it is checked. Surfaced by adding a second methodology family. xsmom@1 declares `has_full_formation_history` and a `min_history` rule; neither runs, and the history requirement is enforced only incidentally by an ExecutionError inside compute_momentum.

Synthesised from

EvidenceKindStanceFinding

What it changed

ArtifactRelationDetail
assumption/declarations-name-their-realization@1 introduced Generalised the fix into a standing principle: every declaration must identify what realizes it, and the realization must be checkable.
methodology/hrp@1 invalidates results of Declares min_history; the rule does not execute.
methodology/hrp@2 invalidates results of Declares min_history and turnover_cap; neither rule executes.
methodology/hrp@3 invalidates results of Declares concentration_cap <= 0.25, which is satisfied only because contract.weight_bounds independently enforces the same number.
methodology/xsmom@1 invalidates results of Declares min_history and has_full_formation_history; neither executes.

Resolution

Resolved by option (c): a rule now names the field that realizes it and the property that field must have. Contracts execute, rules verify, policies interpret — three responsibilities that had blurred together. rules: - id: concentration_cap enforced_by: contract.weight_bounds.max expected: "<= 0.25" `src/methodology/verify.py` resolves each `enforced_by` path against the methodology and checks the assertion. Three drift modes now fail loudly: a contract that moves while the rule does not, a rule naming a field that does not exist, and a rule naming a pipeline stage absent from the pipeline. `universe_filters` were restructured the same way and name the stage that realizes them. An unrealized declaration is a hard blocker in the publication gate, alongside contract violation and failed reproducibility — a methodology asserting what its own fields do not support is making a claim it cannot keep. Rejected: (a) an expression evaluator, which would add a language to the spec and make rules a second execution path competing with the contract; (b) demoting rules to documentation, which would remove them from content identity and weaken versioning.

finding/hrp-degenerates-to-cash-proxy@1

Concluded 2026-07-30

3 adverse relationship(s), 6 total

refutes qualifies invalidates results of invalidates results of motivated introduced finding/hrp-degenerates-to-... · claim/hrp-diversifies-witho... · claim/hrp-outperforms-mvo-o... · methodology/hrp@1 · methodology/hrp@2 · methodology/hrp@3 · assumption/hard-bounds-beat...
Relationships as a table
SourceRelationTargetEffectDirectnessDetail
finding/hrp-degenerates-to-cash-proxy@1 refutes claim/hrp-diversifies-without-c... blocking direct The claim asserts HRP diversifies without explicit constraints. It allocated...
finding/hrp-degenerates-to-cash-proxy@1 qualifies claim/hrp-outperforms-mvo-out-o... advisory direct The source claim survives, narrowed: it holds for universes of...
finding/hrp-degenerates-to-cash-proxy@1 invalidates results of methodology/hrp@1 blocking direct Its reported Sharpe of 6.59 was cash return divided by cash volatility. The...
finding/hrp-degenerates-to-cash-proxy@1 invalidates results of methodology/hrp@2 blocking direct Same degeneracy; the turnover cap does not address concentration.
finding/hrp-degenerates-to-cash-proxy@1 motivated methodology/hrp@3 none direct Created in response, imposing a 25% per-asset ceiling — the smallest change...
finding/hrp-degenerates-to-cash-proxy@1 introduced assumption/hard-bounds-beat-sof... none direct Imposing a ceiling surfaced a conflict with the turnover cap, forcing the...

Hierarchical risk parity degenerates into a cash proxy when the universe contains a near-zero-variance instrument and no per-asset ceiling is imposed. Recursive bisection allocates inverse-variance, so an instrument whose variance approaches zero absorbs an unbounded share of the portfolio. This is a property of the method, not an implementation error, and the source paper does not address it because it demonstrates HRP on assets of comparable risk.

Synthesised from

EvidenceKindStanceFinding

What it changed

ArtifactRelationDetail
assumption/hard-bounds-beat-soft-turnover@1 introduced Imposing a ceiling surfaced a conflict with the turnover cap, forcing the precedence rule to be declared rather than resolved in executor code.
claim/hrp-diversifies-without-constraints@1 refutes The claim asserts HRP diversifies without explicit constraints. It allocated 99.6% to BIL with an effective breadth of 1.01 assets.
claim/hrp-outperforms-mvo-out-of-sample@1 qualifies The source claim survives, narrowed: it holds for universes of comparable-risk assets, not for any universe.
methodology/hrp@1 invalidates results of Its reported Sharpe of 6.59 was cash return divided by cash volatility. The figure is arithmetically correct and economically meaningless.
methodology/hrp@2 invalidates results of Same degeneracy; the turnover cap does not address concentration.
methodology/hrp@3 motivated Created in response, imposing a 25% per-asset ceiling — the smallest change that makes the allocation describe the methodology rather than describing BIL.

Resolution

Published methodology/hrp@3 with a 25% per-asset ceiling; effective breadth 6.37 assets, Sharpe 0.53, no diagnostic flags. Added result-level degeneracy diagnostics (concentration, degenerate volatility, implausible Sharpe, effective breadth) that refuse publication of a flagged result. hrp@1 and hrp@2 remain published and reachable; their results are not deleted, and the publication gate now blocks them rather than the library hiding them.

finding/joined-panel-inherits-widest-calendar@1

Concluded 2026-07-30

2 adverse relationship(s), 5 total

introduced introduced corrected invalidates results of invalidates results of finding/joined-panel-inheri... · assumption/nyse-sessions@1 · assumption/adjusted-close-i... · erratum/2026-07-30-02 · methodology/hrp@3 · erratum/2026-07-30-01
Relationships as a table
SourceRelationTargetEffectDirectnessDetail
finding/joined-panel-inherits-w... introduced assumption/nyse-sessions@1 none direct Forced the trading calendar to be declared as a referenced artifact...
finding/joined-panel-inherits-w... introduced assumption/adjusted-close-is-restated@1 none direct Investigating the panel also established that a declared date range does not...
finding/joined-panel-inherits-w... corrected erratum/2026-07-30-02 affecting direct Published as a material erratum superseding the figures it affected.
finding/joined-panel-inherits-w... invalidates results of methodology/hrp@3 blocking direct Annualized 1.3664% -> 2.2892% and volatility 3.1879% -> 4.0939% once weekend...
finding/joined-panel-inherits-w... invalidates results of erratum/2026-07-30-01 blocking direct The earlier erratum's absolute levels were computed on the contaminated...

A price panel joined across instruments with different trading calendars inherits the union of their sessions. Forward-filling a five-session instrument onto a seven-day index manufactures zero-return observations that are not market data — deflating realized volatility and mis-scaling any annualization that assumes a session count the data does not have.

Synthesised from

EvidenceKindStanceFinding

What it changed

ArtifactRelationDetail
assumption/adjusted-close-is-restated@1 introduced Investigating the panel also established that a declared date range does not identify data — only a content hash does.
assumption/nyse-sessions@1 introduced Forced the trading calendar to be declared as a referenced artifact (calendar/nyse@1) rather than assumed by the panel's accidental index.
erratum/2026-07-30-01 invalidates results of The earlier erratum's absolute levels were computed on the contaminated calendar. Its relative conclusion — that the look-ahead was the dominant correction — is unchanged.
erratum/2026-07-30-02 corrected Published as a material erratum superseding the figures it affected.
methodology/hrp@3 invalidates results of Annualized 1.3664% -> 2.2892% and volatility 3.1879% -> 4.0939% once weekend padding was removed; a further correction to 2.2094% once NYSE holidays were excluded.

Resolution

Trading calendars became versioned artifacts with rule-based holidays (calendar/nyse@1, calendar/crypto@1), each declaring the range it covers and refusing to extrapolate beyond it. Protocols reference a calendar rather than naming a rule inline, and annualization reads the session count from the calendar instead of a hardcoded 252. Erratum 2026-07-30-02 published.

Why this is separate from claims and evidence

Both findings here came out of ordinary engineering work, and each touched more than one thing at once. The cash-proxy finding refuted one claim, qualified another, invalidated the results of two methodology versions, motivated a third, and forced a constraint-precedence assumption to be declared. Recording that as five separate edits would have lost the fact that they were one conclusion.

Findings are also what an investigation produces and what a review consumes — which is what makes them the natural unit for Discovery to emit and Mission to route, without either needing to infer intent from prose.