feat(honest-ref): sqrt-impact/spread-floor lock + real-spread snapshot reader (spec 0c)
This commit is contained in:
12
src/fxhnt/adapters/persistence/bybit_spread.py
Normal file
12
src/fxhnt/adapters/persistence/bybit_spread.py
Normal 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}
|
||||
@@ -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
|
||||
|
||||
13
tests/unit/test_bybit_spread.py
Normal file
13
tests/unit/test_bybit_spread.py
Normal 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}
|
||||
Reference in New Issue
Block a user