Tasks · 003-position-engine

Real-time position engine

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

Status Draft Spec 003-position-engine Design design Branch 003-position-engine Created Read time

11 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

Create position module — new package under the shared tree, no logic yet src/main/java/io/spectastic/portfolio/position/
Confirm jacoco diff gate — patch ≥ 90% on touched domain, never lower touched coverage pom.xml

3 · Phase 2 — Foundational

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

Reference shared model — read TradeEvent and PriceTick from the umbrella model owned by 001; add no duplicate types src/main/java/io/spectastic/portfolio/model/
Define Position state — aggregate row: netQty, costBasisTotal, mtmValue, unrealizedPnl, asOfSeq src/main/java/io/spectastic/portfolio/position/Position.java
Wire into AnalyticsPlatform — register PositionEngine as an @ApplicationScoped bean, gated by the umbrella portfolio.analytics.enabled flag src/main/java/io/spectastic/portfolio/AnalyticsPlatform.java

4 · Phase 3a — US1 · Net quantity and basis from fills

Tests (write & fail first)

Test net qty + VWAP basis — signed sum of fills and VWAP of open exposure, including the sign-flip reset to the crossing fill; assert bit-match to a from-zero replay src/test/java/io/spectastic/portfolio/PositionEngineTest.java

Implementation

Fold fills into aggregate state — O(1) net-qty and costBasisTotal update; proportional removal costBasisTotal*|f|/|net| and crossing-zero reset to newNet*price by exact integer arithmetic src/main/java/io/spectastic/portfolio/position/PositionEngine.java

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

5 · Phase 3b — US2 · Mark-to-market on a tick

Tests (write & fail first)

Test MTM on tick — held instrument revalues mtmValue/unrealizedPnl; a tick for an un-held instrument is a verified no-op; quantity unchanged src/test/java/io/spectastic/portfolio/PositionEngineTest.java

Implementation

Revalue held instrument on PriceTick — O(1) recompute of MTM and unrealized P&L; never touch netQty src/main/java/io/spectastic/portfolio/position/PositionEngine.java

Closes FR-003, SC-002.

6 · Phase 3c — US3 · Consistent cross-instrument snapshot

Test snapshot at sequence N — every instrument reflects state at exactly N, no torn pre-/post-event mix across instruments src/test/java/io/spectastic/portfolio/PositionEngineTest.java
Deep-copy snapshot at sequence — return all positions as of one ledger sequence N src/main/java/io/spectastic/portfolio/position/PositionEngine.java

Closes FR-004.

7 · Phase 4 — Polish

Reconcile-to-replay property test — generated fill-and-tick streams; incremental state bit-matches full replay across ≥ 1 sign-flip and ≥ 1 correction src/test/java/io/spectastic/portfolio/PositionEngineTest.java
Add Micrometer timers — update and revalue fold timers exported on Prometheus /q/metrics src/main/java/io/spectastic/portfolio/position/PositionEngine.java
Verify jacoco patch coverage — touched domain ≥ 90%, coverage of touched code not lowered pom.xml

Closes NFR-001, 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. TDD per story: US1 net qty + VWAP basis with sign-flip (T-100/T-110), US2 MTM on tick (T-200/T-210), US3 consistent snapshot (T-300/T-310); Polish adds a reconcile-to-replay test, Micrometer timers, and the jacoco gate.