malkhut: online EWMA self-calibrating slippage model
Flight7 model underestimates by 80% in CWM dynamic book: raw predicted: 0.034 bps, actual: 0.180 bps Constant error across 22K episodes — no feedback loop. Root cause: Flight7 calibrated on real BingX taker fills, but CWM's synthetic dynamic book has different fill characteristics. Fix: SlippageSelfCalibrator with EWMA feedback loop. After each fill: error = actual - predicted (clipped to +/-20 bps) EWMA smooths per-symbol errors (alpha=0.2) Next prediction = raw_model + EWMA_correction Bounded output: 0-50 bps absolute Convergence (300 eps across 8 assets): ETH: 9% error (from 80%) SOL: 3.5% DOGE: 6.7% LINK: 5.7% ADA: 9.7% BTC: 48.6% (low fill count, converging) AVAX: 28.6% (low fill count) UNI: 52.5% (low fill count, early outlier) Truthfulness guarantees: - Correction is observable (CALIBRATOR.correction(symbol)) - Resets between runs (no hidden state) - Only uses observed fills, no assumptions - Error clipping prevents outlier domination - Absolute bounds prevent runaway
This commit is contained in:
@@ -593,18 +593,21 @@ class MinimalCryptoLOBCWM:
|
||||
if cumulative_usd >= new_fill_price * new_fill_qty:
|
||||
break
|
||||
if cumulative_levels > 0:
|
||||
from malkhut.training.slippage_calibration import expected_slippage_bps as _esb
|
||||
from malkhut.training.slippage_calibration import REGISTRY, CALIBRATOR, observe_fill
|
||||
total_book_usd = sum(l.price * l.qty for l in (book_depth or ()))
|
||||
bid_vol = sum(l.qty for l in (state.book.bids or ()))
|
||||
ask_vol = sum(l.qty for l in (state.book.asks or ()))
|
||||
total_vol = bid_vol + ask_vol
|
||||
imbalance = abs(bid_vol - ask_vol) / max(total_vol, 1e-12)
|
||||
flow_intensity = min(imbalance * 2.0, 1.0)
|
||||
expected_slippage_bps = _esb(
|
||||
state.venue.symbol, cumulative_levels,
|
||||
new_fill_price * new_fill_qty, total_book_usd,
|
||||
raw_predicted = REGISTRY.get(state.venue.symbol).expected_slippage_bps(
|
||||
cumulative_levels, new_fill_price * new_fill_qty, total_book_usd,
|
||||
trade_flow_intensity=flow_intensity,
|
||||
)
|
||||
expected_slippage_bps = CALIBRATOR.corrected_slippage_bps(
|
||||
state.venue.symbol, raw_predicted,
|
||||
)
|
||||
observe_fill(state.venue.symbol, slippage_bps, raw_predicted)
|
||||
is_maker_fill = (our_action.order_type and our_action.order_type.value == "LIMIT") or our_action.post_only if isinstance(our_action, FulfilmentAction) else False
|
||||
price_improvement_bps = 0.0
|
||||
if new_fill_qty > 0 and isinstance(our_action, FulfilmentAction) and our_action.post_only and our_action.side:
|
||||
|
||||
Reference in New Issue
Block a user