malkhut: asset-faithful book generation with composable toggles

Three independently toggleable features:
  1. Asset-faithful depth/spread: levels sized by OB study power-law per asset
  2. Intraday volume clock: depth scales by time-of-day (peak/trough)
  3. Realistic spread: per-asset spread from OB study + Flight7

Composable via BookGenerationConfig toggles:
  use_asset_faithful_depth, use_asset_faithful_spread, use_intraday_clock,
  use_weekend_mode, use_stress_mode, use_fragility, worst_case_mode

worst_case_mode overrides everything for max adversarial learning:
  spread * stress_mult, depth * fragility, no intraday/weekend.

DuckDB registry for online updates:
  AssetRegistry: upsert/get/list/delete/query
  RuntimeProfileCache: hot-reload during CWM runs
  upsert_from_csv/export_csv: pipeline support
  upsert_all_from_asset_behaviors(): seed from OB study

Results (8 assets):
  BTC: spread 0.031 bps, depth $350M (normal) / $4.9M (worst)
  DOGE: spread 2.86 bps, depth $2M (normal) / $132K (worst)
  ADA: spread 11.8 bps, depth $10M (normal) / $511K (worst)
  Intraday: BTC peak/trough = 2.8x depth ratio

All 99 tests green (31 new + 68 existing).
This commit is contained in:
Codex
2026-07-20 19:06:24 +02:00
parent 97a770da65
commit 6990ff3bee
4 changed files with 787 additions and 2 deletions

View File

@@ -106,6 +106,8 @@ class HftBacktestCWM:
queue_model_n: int = 3,
use_dynamic_book: bool = False,
book_refresh_volatility: float = 0.1,
book_profile=None,
book_config=None,
) -> None:
self.feature_extractor = feature_extractor or DefaultFeatureExtractor()
self._tick_ns = tick_ns
@@ -113,6 +115,11 @@ class HftBacktestCWM:
self._queue_model_n = queue_model_n
self._use_dynamic_book = use_dynamic_book
self._book_refresh_vol = book_refresh_volatility
self._book_generator = None
if use_dynamic_book and book_profile is not None:
from malkhut.training.asset_book_profile import BookGenerator, BookGenerationConfig
cfg = book_config or BookGenerationConfig()
self._book_generator = BookGenerator(book_profile, cfg)
# Pre-compute fill probabilities for each level distance
if self._use_queue_model:
@@ -382,8 +389,10 @@ class HftBacktestCWM:
last_trade_side=Side.SELL,
)
# 4b. Dynamic book refresh (when use_dynamic_book=True)
if self._use_dynamic_book and book.bids and book.asks:
# 4b. Dynamic book refresh
if self._use_dynamic_book and self._book_generator:
book = self._book_generator.refresh_book(book, tick, rng)
elif self._use_dynamic_book and book.bids and book.asks:
import numpy as np
rng = np.random.RandomState(state.ts_ns % (2**31))