feat(honest-ref): sqrt-impact/spread-floor lock + real-spread snapshot reader (spec 0c)

This commit is contained in:
jgrusewski
2026-07-15 21:42:51 +02:00
parent edf7e41527
commit 5019e9ffbb
3 changed files with 37 additions and 0 deletions

View File

@@ -0,0 +1,12 @@
"""Read the current bybit_real_spread snapshot (coin -> spread_bps). Read-only; a point-in-time cross-section
(all rows share one fetched_at), used as the per-coin slippage FLOOR in the honest-reference model."""
from __future__ import annotations
from sqlalchemy import create_engine, text
def read_spread_snapshot(dsn: str) -> dict[str, float]:
eng = create_engine(dsn)
with eng.connect() as c:
rows = c.execute(text("select coin, spread_bps from bybit_real_spread")).all()
return {coin: float(bps) for coin, bps in rows if bps is not None}

View File

@@ -82,6 +82,18 @@ def test_no_cap_no_impact_reproduces_gross_reconciliation() -> None:
assert abs(out[2] - (0.4*-0.03 + -0.6*0.05)) < 1e-9
def test_impact_scales_and_floors_at_spread() -> None:
wbd = {1: {"C": (1.0, 0.0)}} # flat return -> net == -cost
turnover = {"C": {1: 1_000_000.0}}
# size $10k of $1M ADV, no cap: impact = 1*sqrt(10000/1e6)*1e4 = 1000 bps -> cost = 1*0.10
r = honest_sleeve_returns(wbd, turnover, spread_bps={}, aum=10_000.0, participation_cap=1.0, impact_k=1.0)
assert abs(r[1] - (-0.10)) < 1e-6
# spread floor: impact off, wide spread -> cost == spread fraction
r2 = honest_sleeve_returns(wbd, turnover, spread_bps={"C": 50.0}, aum=10_000.0,
participation_cap=1.0, impact_k=0.0)
assert abs(r2[1] - (-50.0/1e4)) < 1e-9
def _seed_flat_funding(store: TimescaleFeatureStore, *, days: int = 120) -> None:
"""FLAT perp price, spot == perp (zero basis), nonzero cross-sectional funding — the xsfunding sleeve's
ONLY source of return here is FUNDING. Mirrors the fixture in test_bybit_book_reconciliation.py; xsfunding

View File

@@ -0,0 +1,13 @@
from sqlalchemy import create_engine, text
from fxhnt.adapters.persistence.bybit_spread import read_spread_snapshot
def test_read_spread_snapshot_returns_coin_to_bps(tmp_path):
dsn = f"sqlite:///{tmp_path}/s.db"
eng = create_engine(dsn)
with eng.begin() as c:
c.execute(text("create table bybit_real_spread (coin text, spread_bps double, fetched_at text)"))
c.execute(text("insert into bybit_real_spread values ('BTCUSDT', 1.0, 'now'), ('PEPEUSDT', 3.5, 'now')"))
out = read_spread_snapshot(dsn)
assert out == {"BTCUSDT": 1.0, "PEPEUSDT": 3.5}