Commit Graph

2 Commits

Author SHA1 Message Date
Brummel f5e00a9c72 feat(0085): per-cycle-held accrual — CarryCost + ChargeMode (approach B)
Cycle 5 of milestone #148 (cost-model graph in R): the per-cycle-held accrual
mechanism — C10's "per-cycle-held factors accrue over the hold". A carry/funding cost
is charged for every cycle a position is held, so the net_r_equity equity curve bleeds
continuously over the hold (approach B, "ja, mach B") rather than stepping at close.

Mechanism (logged on #148): ChargeMode { AtClose, PerHeldCycle } is a property of the
cost factor, read by the one shared CostRunner (no second runner type). The AtClose arm
is the pre-cycle-5 eval tokens VERBATIM (IEEE-754 byte-identity). The PerHeldCycle arm
accrues `per` into `acc` each held cycle, dumps the accrued total into `cum` at close
(resetting acc), and marks the open position via a growing open_cost_in_r. The bleed
lives in open_cost_in_r, which the net_r_equity tap already subtracts — so summarize_r
and the CLI net_eq wiring are UNCHANGED, and the cycle-0083/0084 net_expectancy_r
goldens (-614.3134020253314 flat, -615.0304388396047 composed) + the C18 no-cost golden
stay byte-identical.

CarryCost is a ConstantCost twin differing only in charge_mode() -> PerHeldCycle (a
labelled stress parameter, the flat base of the accrual family). Wired through the
existing cost_graph/CostSum aggregation; a per-trade ConstantCost and a per-held-cycle
CarryCost compose in one run (the costs sum per-field — the composed golden is exactly
the sum of the two single-cost charges). New run-path --carry-per-cycle flag
(sweep/walkforward/mc pass None, as the existing cost flags do).

Tests: 2 RED-first unit B-proofs (open_cost grows over the hold, dumps the total at
close, acc resets between trades — the discriminator a scalar net_expectancy_r cannot
see); the CarryCost twin's 5 unit tests; 2 captured net_expectancy_r goldens
(-768.2095026600887 carry, -1383.7939051991182 composed); a net_r_equity-bleeds-over-
the-hold integration test (the terminal open hold's r_equity-net_r_equity gap strictly
grows); plus negative-rate-refused-exit-2, monotone-in-rate, and zero-rate-exactly-free
guards.

Verified: cargo test --workspace (0 failures), cargo build --workspace, cargo clippy
--workspace --all-targets -- -D warnings clean. summarize_r / aura-analysis untouched.
Deferred to later #148 cycles (logged there): notional-based carry, the calendar-aware
overnight swap, sweep-path cost.

refs #148
2026-06-29 01:00:51 +02:00
Brummel 6b53c239dd feat(0083): CostNode trait + shared cost-record contract
Lift the duplicated cost-node skeleton — shared verbatim by ConstantCost and
VolSlippageCost and locked by convention against CostSum — into one abstraction:

- A new aura-std/src/cost.rs owns the cost-record contract (COST_WIDTH,
  COST_FIELD_NAMES, GEOMETRY_WIDTH), the CostNode factor trait (one hook:
  cost_numerator, in price units), the generic CostRunner<F> adapter that holds
  the shared state (cum, out) and the co-temporality skeleton (geometry gating,
  numerator/latched R-normalization, closed/open charge, 3-field emit), and a
  cost_node_builder schema assembler.
- ConstantCost and VolSlippageCost become thin CostNode factors; their new()
  returns CostRunner<Self>, so every existing call site and unit test binds
  transparently and stays green verbatim.
- CostSum and main.rs drop their local triple consts for the shared
  COST_FIELD_NAMES — the cycle-2 audit-flagged by-convention 3-field lockstep is
  now a structural single-source contract (the four copies of the triple collapse
  to one). main.rs also reads COST_WIDTH in place of the literal slot stride.

Behaviour-preserving: the builders emit unchanged schemas (same port names), so
the wiring, the net_r_equity seam, and summarize_r are untouched; the
numerator/latched token form is preserved verbatim (IEEE-754 byte-identity). The
existing suite is the regression net — all green: the per-node unit tests pass
verbatim (0.5/1.5, 0.375/1.375), the composition E2E exact, the C18 no-cost
golden byte-identical. Two new CLI characterization goldens pin the exact
net_expectancy_r of the flat and composed cost paths (the prior tests only
asserted net < gross, which a numerator drift would pass silently). New cost.rs
runner/contract tests + the HalfSpreadCost author doctest cover the new surface.

Deviation from the plan: CostNode::name() was dropped (the plan over-specified
it) — it is dead surface, nothing consumes it (CostRunner forwards label();
cost_node_builder takes the name as an explicit arg). Removed from the trait,
both impls, the doctest, and the test stubs; build + suite + clippy green.

Verified: cargo build --workspace --all-targets clean; cargo test --workspace
0 failures; cargo clippy --workspace --all-targets -- -D warnings clean; doctest
green.

refs #148
2026-06-28 19:26:34 +02:00