malkhut(wire): fill quality as PRIMARY optimization target

Fill quality is MALKHUT's core aim. Wired end-to-end:

1. FillQuality state (state.py):
   - slippage_bps, price_improvement_bps, levels_consumed
   - is_maker_fill, rolling_fill_rate, post_fill_adverse_bps
   - fill_value_score: composite metric for optimization
   - Added to MarketWorldState.fill_quality field

2. HftBacktestCWM.transition() (hft_cwm.py):
   - _compute_fill_quality() computes all metrics per transition
   - Fill quality now tracked for every CWM step
   - Empty book guards added for safety

3. MinimalCryptoLOBCWM.transition() (core.py):
   - Same fill quality computation for deterministic fallback
   - Empty book guards added

4. Reward function (hft_cwm.py):
   - fill_quality_reward = w_fill_probability * fill_value_score (PRIMARY)
   - Bonus for maker fills that improve price
   - Penalty for adverse selection after fill
   - Base reward (PnL, adverse selection, fees) preserved

5. PerformanceMatrix (selector.py):
   - RegimeStrategyScore: 4 new fill quality fields
   - record(): accepts fill_rate, slippage, price_improvement, fill_value_score
   - EMA updates for all fill quality metrics

6. EpisodeResult (cma_trainer.py):
   - avg_fill_value_score, avg_price_improvement_bps, avg_post_fill_adverse_bps
   - Accumulated per-step during _run_episode
   - Recorded to PerformanceMatrix in evaluate_candidate

All 1379+ tests green.
This commit is contained in:
Codex
2026-07-15 15:22:25 +02:00
parent fa76070c79
commit 618ad723e3
5 changed files with 284 additions and 29 deletions

View File

@@ -267,6 +267,42 @@ class ExecutionIntent:
reason: str
@dataclass(frozen=True, slots=True)
class FillQuality:
"""Fill quality metrics — the CORE optimization target of MALKHUT.
MALKHUT is an execution improvement engine. Fill quality IS the primary aim.
Every transition records these metrics. The reward function weights them heavily.
The PerformanceMatrix tracks them per (regime, strategy, venue).
"""
filled: bool = False
fill_qty: float = 0.0
fill_price: float = 0.0
requested_qty: float = 0.0
# How close to mid did we fill? (for aggressive: positive = slipped)
slippage_bps: float = 0.0
# For passive fills: how much better than best bid/ask? (positive = improvement)
price_improvement_bps: float = 0.0
# How many levels deep was the fill?
levels_consumed: int = 0
# Was this a maker (passive) or taker (aggressive) fill?
is_maker_fill: bool = False
# Fill rate rolling window (updated each transition)
rolling_fill_rate: float = 0.0
# Adverse selection: price movement after fill (negative = adverse)
post_fill_adverse_bps: float = 0.0
# Fill value score: composite metric for optimization
# = fill_rate * price_quality - adverse_selection - slippage
fill_value_score: float = 0.0
@dataclass(frozen=True, slots=True)
class MarketWorldState:
"""Complete CWM root state. Immutable for safe tree search."""
@@ -287,6 +323,8 @@ class MarketWorldState:
order_latency_ms: float = 0.0
rng_seed: int = 0
fill_quality: Optional[FillQuality] = None
@dataclass(frozen=True, slots=True)
class FulfilmentPolicyParams: