""" Tests for sim/maker.py — market-making quoting logic. """ from sim.maker import AvellanedaStoikovMaker, GridMaker, MakerConfig, Quote class TestAvellanedaStoikovMaker: def test_initial_sigma(self): maker = AvellanedaStoikovMaker() assert maker.sigma == 0.02 # default def test_observe_updates_volatility(self): maker = AvellanedaStoikovMaker() for i in range(20): maker.observe(100000.0 + i * 100) assert maker.sigma > 0 def test_quote_no_inventory(self): maker = AvellanedaStoikovMaker() maker.observe(100000.0) q = maker.quote(mid_price=100000.0, inventory=0.0, elapsed_hours=0.0) assert q.bid > 0 assert q.ask > q.bid assert q.spread_bps >= 0 def test_quote_short_inventory_skew(self): maker = AvellanedaStoikovMaker(MakerConfig(gamma=0.5, k=1.0)) for i in range(50): maker.observe(100000.0 + i * 50 * (1 if i % 2 == 0 else -1)) q_short = maker.quote(mid_price=100000.0, inventory=-0.003, elapsed_hours=0.0) q_long = maker.quote(mid_price=100000.0, inventory=0.003, elapsed_hours=0.0) assert q_short.reservation > q_long.reservation def test_quote_long_inventory_skew(self): maker = AvellanedaStoikovMaker() maker.observe(100000.0) q = maker.quote(mid_price=100000.0, inventory=0.004, elapsed_hours=0.1) assert q.reservation < q.ask def test_quote_with_skew(self): maker = AvellanedaStoikovMaker() maker.observe(100000.0) q = maker.quote_with_skew(mid_price=100000.0, inventory=0.003, elapsed_hours=0.0, target_inventory=0.0) assert q.ask_size > q.bid_size # long → bigger asks to reduce position def test_elapsed_reduces_spread(self): maker = AvellanedaStoikovMaker() maker.observe(100000.0) q_early = maker.quote(mid_price=100000.0, inventory=0.0, elapsed_hours=0.0) q_late = maker.quote(mid_price=100000.0, inventory=0.0, elapsed_hours=0.9) # Near session end → narrower spread (less time to recover) assert q_late.spread_bps <= q_early.spread_bps + 1 class TestGridMaker: def test_grid_levels(self): gm = GridMaker(grid_levels=3, spacing_bps=10.0, size_per_level=0.001) quotes = gm.quotes(100000.0) assert len(quotes) == 6 # 3 bid + 3 ask levels def test_symmetric(self): gm = GridMaker(grid_levels=2, spacing_bps=50.0, size_per_level=0.001) quotes = gm.quotes(100000.0) bids = [q for q in quotes if q["side"] == "bid"] asks = [q for q in quotes if q["side"] == "ask"] assert len(bids) == 2 assert len(asks) == 2 for b, a in zip(bids[::-1], asks): assert a["price"] > b["price"]