Tasks · 004-portfolio-weights

Portfolio weight calculation

Ordered, parallelizable work. Tests precede implementation. Drive through with /spectastic.implement — one task per invocation.

Status Draft Spec 004-portfolio-weights Design design Branch 004-portfolio-weights Created Read time

13 tasks across five phases. Setup → Foundational → User stories (US1·US2·US3) → Polish. Tasks marked [P] can run in parallel — different files, no dependency. Tests for a story MUST be written and failing before its implementation tasks start.

1 · Execution strategy

Implement US1 end-to-end. Ship. Iterate to US2 and US3 only after US1 is verified.

Setup → Foundational → US1 → US2 → US3 → Polish. Each story closes its conformance before the next opens.

One team on each user story after Foundational. Coordinate at shared seams (data model, API contracts) via the spec, not Slack.

2 · Phase 1 — Setup

Scaffold the weights module — new package, no upstream ownership. src/main/java/io/spectastic/portfolio/weights/
Declare test and coverage deps — quarkus-junit5, rest-assured, jacoco diff-aware in the Maven build. pom.xml

3 · Phase 2 — Foundational

Shared infrastructure no story can ship without. Sequential where order matters.

Wire a read view of the 003 position snapshot — reference the shared model and MTM values owned by 001/003; add no new ownership. src/main/java/io/spectastic/portfolio/weights/
Define the WeightBasis enum and WeightBook shape — GROSS (default) and NET; per-instrument mtmValue, weight, stale. src/main/java/io/spectastic/portfolio/weights/WeightBasis.java

4 · Phase 3a — US1 · Weights that sum to one

Tests (write & fail first)

Assert gross-basis weights sum to one — over a two-instrument book, |Σweights − 1| ≤ 1e-9, basis explicit in the output. src/test/java/io/spectastic/portfolio/PortfolioWeightsTest.java

Implementation

Compute gross-basis weights|MV| / Σ|MV| folded O(N) on read; the one double division. src/main/java/io/spectastic/portfolio/weights/PortfolioWeights.java

Closes FR-001, FR-002, SC-001.

5 · Phase 3b — US2 · Reweight on a tick

Assert a tick reweights without a full rescan — the moved instrument and the denominator update; other weights follow from the new denominator. src/test/java/io/spectastic/portfolio/PortfolioWeightsTest.java
Reweight on a price tick — recompute affected weights and the denominator; note the running-denominator incremental maintainer (D-003, deferred). src/main/java/io/spectastic/portfolio/weights/PortfolioWeights.java

Closes FR-001, NFR-001.

6 · Phase 3c — US3 · Shorts stay well-defined

Tests (write & fail first)

Assert shorts stay well-defined — with a short present, gross weights in [0,1] sum to one; net guards a near-zero denominator; a price past the freshness bound is flagged stale. src/test/java/io/spectastic/portfolio/PortfolioWeightsTest.java

Implementation

Add the net basis, near-zero guard, and staleness flag — net ΣMV with documented sign semantics; guard instead of exploding weights; mark stale past the bound. src/main/java/io/spectastic/portfolio/weights/PortfolioWeights.java

Closes FR-002, FR-003, SC-002.

7 · Phase 4 — Polish

Add concentration rollups — top-N holdings and a Herfindahl index Σ weight² derived from the same weights. src/main/java/io/spectastic/portfolio/weights/PortfolioWeights.java
Wire observability, ship-dark — Micrometer reweight timer on /q/metrics, OpenAPI at /q/openapi; portfolio.analytics.enabled default false. src/main/java/io/spectastic/portfolio/weights/
Close the coverage gate — jacoco diff-aware plus one @QuarkusTest over /q/openapi. src/test/java/io/spectastic/portfolio/PortfolioWeightsTest.java

Closes FR-004, NFR-002, NFR-003.

8 · Dependencies

Setup           → Foundational
Foundational    → US1, US2, US3   (independent after this point)
US1, US2, US3   → Polish

9 · Change log

  1. Initial task breakdown. 13 tasks across five phases; TDD per story (US1 sum-to-one, US2 reweight-on-tick, US3 shorts + guard + staleness); polish for Herfindahl rollup, Micrometer timer, and diff-aware coverage.