""" Book Fidelity — maps OBF raw book snapshots to OrderBookState. From SPEC_MALKHUT_ACTUALS_INTAKE.md §3: MALKHUT wants a ladder: Tuple[PriceLevel, ...] (finite, ordered) OBF has 15B rows of raw book snapshots (infinite stream) Need: OBF → OrderBookState mapping Strategy: - OBF rows are timestamped book snapshots with bid/ask prices + quantities - We aggregate N recent OBF rows into a single OrderBookState - The aggregation window determines the "ladder depth" (how many levels) - Depth decay follows power law: D(d) = amplitude * d^(1-alpha) - We synthesize levels from the decay profile, not from raw OBF rows """ from __future__ import annotations import math from dataclasses import dataclass from typing import List, Optional, Tuple from malkhut.state import OrderBookState, PriceLevel @dataclass(frozen=True, slots=True) class BookFidelityConfig: """Configuration for OBF → OrderBookState mapping.""" n_levels: int = 10 # how many price levels per side aggregation_window_ms: int = 100 # OBF rows within this window → one snapshot min_depth_usd: float = 100.0 # minimum depth per level def synthesize_book_from_params( symbol: str, mid_price: float, spread_bps: float, depth_amplitude_usd: float, depth_alpha: float, n_levels: int = 10, ) -> OrderBookState: """Synthesize an OrderBookState from asset behavior parameters. Uses the power-law depth decay model: D(d) = amplitude * d^(1-alpha) This is the bridge between OBF's raw stream and MALKHUT's finite representation. """ half_spread = mid_price * spread_bps / 10000 / 2 bids = [] asks = [] for level in range(n_levels): dist_bps = (level + 1) * 1.0 # distance from mid in bps depth_usd = depth_amplitude_usd * (dist_bps ** (1 - depth_alpha)) depth_qty = depth_usd / max(mid_price, 1e-12) bid_price = mid_price - half_spread - (level * mid_price * 0.0001) ask_price = mid_price + half_spread + (level * mid_price * 0.0001) bids.append(PriceLevel(price=bid_price, qty=depth_qty)) asks.append(PriceLevel(price=ask_price, qty=depth_qty)) return OrderBookState( ts_ns=0, symbol=symbol, bids=tuple(bids), asks=tuple(asks), )