feat(CORE-001A): add decimal unit value foundation

This commit is contained in:
Bu5hm4nn
2026-03-24 21:33:17 +01:00
parent 5ac66ea97b
commit a69fdf6762
5 changed files with 1153 additions and 9 deletions

View File

@@ -496,14 +496,124 @@ DATA-001 (Price Feed)
**Dependencies:** BT-001A, BT-003A
### CORE-001: Explicit Unit/Value Classes for Domain Quantities [P1, L] **[foundation]**
**As a** developer, **I want** money, weight, spot-price, and quantity values to use explicit unit-aware value classes **so that** incompatible units cannot be mixed silently in calculations.
**Acceptance Criteria:**
- Introduce explicit domain value types for at least:
- currency amount
- currency per weight
- gold/underlying quantity
- weight unit
- base currency
- All unit-bearing numeric values use decimal-based representation suitable for bookkeeping/accounting accuracy rather than binary floating point
- Each value object carries both numeric value and declared unit/currency metadata
- Implicit arithmetic between incompatible types is rejected by default
- Only explicit conversions and explicitly defined operators are allowed
- Conversions between supported weight units are implemented and tested
- Domain operations express intent clearly, e.g. multiplying `Gold` by `CurrencyPerWeight` yields `Currency`
- Existing high-risk calculation paths (overview, hedge, backtests, event comparison) are migrated away from raw `float` mixing for unit-bearing values
- Tests cover both valid conversions/operations and invalid combinations that must fail loudly
**Technical Notes:**
- Prefer small immutable value objects / dataclasses over loose primitives
- Use Python `Decimal` (or an equivalent decimal fixed-precision type) as the canonical numeric representation for money, quantities, and conversion-bearing domain values
- Add enums or equivalent typed constants for currency (`USD`, `EUR`, `CHF`, ...) and weight (`grams`, `kilograms`, `oz`)
- Make conversion APIs explicit, e.g. `to_weight(...)`, `to_currency(...)`, or named constructors
- Default operators should be conservative: fail closed unless a unit-safe operation is explicitly defined
- Start with gold/collateral and spot-price paths first, then extend to options/backtesting quantities where needed
- Define clear boundaries for interoperability with existing float-heavy libraries/services so conversion into/out of `Decimal` happens intentionally at the edges
- Use this story to remove the class of bugs caused by mixing physical-gold ounces, ETF-like units, USD notionals, and USD-per-weight spot quotes
**Dependencies:** None
### CORE-001A: Decimal Unit Value Object Foundation [P1, M] **[depends: CORE-001]**
**As a** developer, **I want** a small core set of immutable Decimal-based value objects and enums **so that** unit-aware domain modeling exists before we migrate calculation paths.
**Acceptance Criteria:**
- Introduce foundational domain types for at least:
- `BaseCurrency`
- `WeightUnit`
- `Money`
- `PricePerWeight`
- `GoldQuantity` / equivalent weight-bearing quantity type
- Core numeric fields use `Decimal` as the canonical representation
- Constructors/validators reject invalid or missing unit metadata
- Weight conversion methods are explicit and tested
- Unsupported arithmetic fails closed unless an operator is deliberately defined
- Tests cover constructors, conversions, equality/normalization expectations, and invalid operations
**Technical Notes:**
- Prefer a dedicated domain module such as `app/domain/units.py` or similar
- Keep the first slice focused on primitives and unit algebra, not page migration yet
- Add string/serialization helpers carefully so persistence remains deterministic
- See `docs/CORE-001A_DECIMAL_UNITS_ARCHITECTURE.md` for the implementation-ready design
**Dependencies:** CORE-001
### CORE-001B: Overview and Hedge Migration to Unit-Safe Types [P1, M] **[depends: CORE-001A, PORT-001A]**
**As a** developer, **I want** overview and hedge calculations to use the new unit-safe Decimal value objects **so that** the most user-visible collateral math stops depending on raw float conventions.
**Acceptance Criteria:**
- Overview calculations use unit-safe types for collateral quantity, spot price, notional values, and margin-call math
- Hedge scenario calculations use unit-safe types for starting position, option contribution framing, and equity outputs where applicable
- The incompatible live-quote fallback path remains correct under the new model
- Existing visible outputs remain browser-verified on `/overview` and `/hedge`
- Regression tests cover previously discovered unit-confusion bugs
**Technical Notes:**
- Start with calculation helpers and view-model boundaries before touching every page widget
- Convert to/from legacy float-heavy libraries only at the edges, with explicit naming
- Preserve current Lombard/domain compatibility while migrating internals
**Dependencies:** CORE-001A, PORT-001A
### CORE-001C: Backtests and Event Comparison Migration to Unit-Safe Types [P1, M] **[depends: CORE-001A, BT-001, BT-003A]**
**As a** developer, **I want** historical scenario inputs and outputs to use the new unit-safe Decimal value objects **so that** backtests stop mixing live portfolio units, historical units, and notional values implicitly.
**Acceptance Criteria:**
- Backtest scenario portfolio inputs are expressed via unit-safe Decimal types at the domain boundary
- Event-comparison scenario materialization uses explicit conversions from workspace value basis to historical units
- Historical entry spot, underlying units, and resulting notionals are no longer mixed as raw floats in core scenario setup paths
- Deterministic test/demo paths still work and remain browser-tested
- Tests cover both correct conversions and fail-closed invalid unit combinations
**Technical Notes:**
- Focus first on scenario/materialization boundaries and summary calculations rather than every chart payload
- Preserve deterministic fixture behavior while tightening the domain model
- This slice should make the current `gold_value -> historical underlying_units` conversion explicit in the type system
**Dependencies:** CORE-001A, BT-001, BT-003A
### CORE-001D: External Boundary and Persistence Cleanup for Decimal Unit Types [P2, M] **[depends: CORE-001B, CORE-001C]**
**As a** developer, **I want** persistence and service boundaries to handle Decimal unit-safe types explicitly **so that** the new model remains reliable across JSON, APIs, caches, and third-party integrations.
**Acceptance Criteria:**
- Persistence format for unit-safe values is explicit and stable
- JSON/API serialization for Decimal-bearing unit objects is documented and tested
- Float-heavy provider integrations have named conversion boundaries
- Remaining raw-float domain hotspots are identified or removed
- Developer docs note when to use unit-safe value objects vs primitive edge values
**Technical Notes:**
- Keep transport/persistence schemas boring and explicit; avoid magic implicit coercion
- Consider typed DTOs at the edges if needed to keep core domain objects strict
- This is the cleanup slice that reduces backsliding after the initial migrations
**Dependencies:** CORE-001B, CORE-001C
## Implementation Priority Queue
1. **PORT-004** - Introduce hashed workspace persistence as the new state foundation
2. **BT-001B** - Prefill backtest UIs from canonical saved portfolio settings
3. **BT-003B** - Add event-comparison drilldown and explanation of ranking outcomes
4. **PORT-003** - Historical LTV visibility and export groundwork
5. **BT-002** - Upgrade backtests to real daily options snapshots
6. **BT-001C** - Consolidate deterministic historical fixture/demo provider logic
7. **EXEC-001** - Core user workflow
8. **EXEC-002** - Execution capability
9. Remaining features
1. **CORE-001A** - Introduce Decimal-based unit/value object foundations before more calculation drift accumulates
2. **CORE-001B** - Migrate overview and hedge to unit-safe types on the most user-visible paths
3. **PORT-004** - Continue hashed workspace persistence as the new state foundation
4. **BT-001B** - Prefill backtest UIs from canonical saved portfolio settings
5. **CORE-001C** - Migrate backtests and event comparison to unit-safe scenario/value handling
6. **BT-003B** - Add event-comparison drilldown and explanation of ranking outcomes
7. **PORT-003** - Historical LTV visibility and export groundwork
8. **BT-002** - Upgrade backtests to real daily options snapshots
9. **BT-001C** - Consolidate deterministic historical fixture/demo provider logic
10. **CORE-001D** - Clean up persistence and external boundaries for Decimal unit-safe types
11. **EXEC-001** - Core user workflow
12. **EXEC-002** - Execution capability
13. Remaining features