"""
Test script for all Python code snippets from:
  1. docs/multi-exchange.mdx
  2. docs/multi-outcome.mdx
  3. docs/wallet-analytics.mdx

Each snippet is wrapped in a function with try/except to report PASS/FAIL.
Uses paper exchange where possible. Network calls may fail due to API issues.
Does NOT fix any code - just reports results.
"""

import sys
import traceback

results = []


def report(name, passed, detail=""):
    status = "PASS" if passed else "FAIL"
    results.append((name, passed, detail))
    print(f"  [{status}] {name}")
    if detail:
        for line in detail.strip().splitlines():
            print(f"         {line}")


# ============================================================================
# MULTI-EXCHANGE (docs/multi-exchange.mdx)
# ============================================================================

# --------------------------------------------------------------------------
# ME-1: Quick Start (hz.run with exchanges=[...])
# Source: multi-exchange.mdx lines 11-25
# NOTE: hz.run() can't actually run (needs live feeds/keys), so we test
# that the types and parameters are valid.
# --------------------------------------------------------------------------
def test_me_1_quick_start():
    """ME-1: Quick Start - hz.run with exchanges list"""
    try:
        import horizon as hz

        # Test that the exchange config classes can be instantiated
        poly = hz.Polymarket(private_key="0xFAKE")
        kalshi = hz.Kalshi(api_key="fake-key")
        assert poly is not None
        assert kalshi is not None

        # Test that BinanceWS feed can be instantiated
        feed = hz.BinanceWS("btcusdt")
        assert feed is not None

        # Test that Risk can be instantiated
        risk = hz.Risk(max_position=50)
        assert risk is not None

        # Test that quotes() works (used in pipeline)
        quotes = hz.quotes(0.5, spread=0.02, size=5)
        assert isinstance(quotes, list) and len(quotes) > 0

        report("ME-1: Quick Start (exchanges, feeds, risk)", True,
               "Polymarket, Kalshi, BinanceWS, Risk, quotes() all instantiate OK.\n"
               "(hz.run() skipped - needs live feeds/keys)")

    except Exception as e:
        report("ME-1: Quick Start (exchanges, feeds, risk)", False,
               f"{type(e).__name__}: {e}\n{traceback.format_exc()}")


# --------------------------------------------------------------------------
# ME-2: Engine API - Adding exchanges
# Source: multi-exchange.mdx lines 52-58
# --------------------------------------------------------------------------
def test_me_2_engine_add_exchange():
    """ME-2: Engine(exchange_type='polymarket') + add_exchange('kalshi')"""
    try:
        import horizon as hz

        # Docs show: engine = Engine(exchange_type="polymarket", ...)
        # then engine.add_exchange(exchange_type="kalshi", exchange_key="...", api_url="...")
        # We test the API pattern with paper exchange since live exchanges need credentials.

        engine = hz.Engine(exchange_type="paper")

        # Verify add_exchange method exists and works
        assert hasattr(engine, 'add_exchange'), "Engine missing add_exchange"

        # The docs pattern: Engine(...) + add_exchange(...)
        # We verify the method signature accepts exchange_type, exchange_key, api_url
        import inspect
        sig = inspect.signature(engine.add_exchange)
        params = list(sig.parameters.keys())
        assert "exchange_type" in params, "add_exchange missing exchange_type param"

        report("ME-2: Engine add_exchange pattern", True,
               f"Engine(exchange_type='paper') works.\n"
               f"add_exchange signature: {sig}")

    except Exception as e:
        report("ME-2: Engine add_exchange pattern", False,
               f"{type(e).__name__}: {e}\n{traceback.format_exc()}")


# --------------------------------------------------------------------------
# ME-3: Querying exchanges
# Source: multi-exchange.mdx lines 63-66
# --------------------------------------------------------------------------
def test_me_3_query_exchanges():
    """ME-3: exchange_names(), exchange_count(), exchange_name()"""
    try:
        import horizon as hz

        engine = hz.Engine(exchange_type="paper")

        names = engine.exchange_names()
        count = engine.exchange_count()
        primary = engine.exchange_name()

        assert isinstance(names, list), f"exchange_names() should return list, got {type(names)}"
        assert isinstance(count, int), f"exchange_count() should return int, got {type(count)}"
        assert isinstance(primary, str), f"exchange_name() should return str, got {type(primary)}"
        assert count >= 1, f"Should have at least 1 exchange, got {count}"

        report("ME-3: exchange_names/count/name", True,
               f"names={names}, count={count}, primary='{primary}'")

    except Exception as e:
        report("ME-3: exchange_names/count/name", False,
               f"{type(e).__name__}: {e}\n{traceback.format_exc()}")


# --------------------------------------------------------------------------
# ME-4: Explicit routing (submit_order, submit_quotes with exchange= kwarg)
# Source: multi-exchange.mdx lines 71-77
# NOTE: Just test that the methods exist and accept exchange= kwarg
# --------------------------------------------------------------------------
def test_me_4_explicit_routing():
    """ME-4: submit_order/submit_quotes with exchange= parameter"""
    try:
        import horizon as hz

        engine = hz.Engine(exchange_type="paper")

        # Verify the methods exist
        assert hasattr(engine, 'submit_order'), "Engine missing submit_order"
        assert hasattr(engine, 'submit_quotes'), "Engine missing submit_quotes"
        assert hasattr(engine, 'sync_positions'), "Engine missing sync_positions"

        # Docs show:
        #   engine.submit_order(request, exchange="kalshi")
        #   engine.submit_quotes("market", quotes, Side.Yes, exchange="polymarket")
        #   engine.sync_positions(exchange="kalshi")
        # We just verify the parameter exists via introspection
        import inspect
        sig_submit = inspect.signature(engine.submit_order)
        sig_quotes = inspect.signature(engine.submit_quotes)
        sig_sync = inspect.signature(engine.sync_positions)

        report("ME-4: Explicit routing methods exist", True,
               f"submit_order sig: {sig_submit}\n"
               f"submit_quotes sig: {sig_quotes}\n"
               f"sync_positions sig: {sig_sync}")

    except Exception as e:
        report("ME-4: Explicit routing methods exist", False,
               f"{type(e).__name__}: {e}\n{traceback.format_exc()}")


# --------------------------------------------------------------------------
# ME-5: Netting Pairs configuration via hz.run
# Source: multi-exchange.mdx lines 86-92
# --------------------------------------------------------------------------
def test_me_5_netting_pairs_run():
    """ME-5: Netting pairs in hz.run()"""
    try:
        import horizon as hz

        # We can't call hz.run(), but verify that the netting_pairs parameter
        # concept is valid by verifying set_netting_pair / netting_pairs work on Engine
        engine = hz.Engine(exchange_type="paper")
        engine.set_netting_pair("will-btc-hit-100k", "KXBTC-25FEB16")
        pairs = engine.netting_pairs()
        assert isinstance(pairs, list), f"netting_pairs() should return list, got {type(pairs)}"
        assert len(pairs) == 1, f"Should have 1 pair, got {len(pairs)}"
        assert pairs[0] == ("will-btc-hit-100k", "KXBTC-25FEB16"), f"Unexpected pair: {pairs[0]}"

        report("ME-5: Netting pairs (set + query)", True,
               f"set_netting_pair works. netting_pairs()={pairs}")

    except Exception as e:
        report("ME-5: Netting pairs (set + query)", False,
               f"{type(e).__name__}: {e}\n{traceback.format_exc()}")


# --------------------------------------------------------------------------
# ME-6: Netting Pairs via Engine API
# Source: multi-exchange.mdx lines 97-99
# --------------------------------------------------------------------------
def test_me_6_netting_pairs_engine():
    """ME-6: engine.set_netting_pair / engine.netting_pairs()"""
    try:
        import horizon as hz

        engine = hz.Engine(exchange_type="paper")
        engine.set_netting_pair("will-btc-hit-100k", "KXBTC-25FEB16")
        pairs = engine.netting_pairs()

        assert pairs == [("will-btc-hit-100k", "KXBTC-25FEB16")], f"Unexpected: {pairs}"

        report("ME-6: Engine netting_pairs API", True, f"pairs={pairs}")

    except Exception as e:
        report("ME-6: Engine netting_pairs API", False,
               f"{type(e).__name__}: {e}\n{traceback.format_exc()}")


# --------------------------------------------------------------------------
# ME-7: Cross-Exchange Strategy Pattern (pipeline functions)
# Source: multi-exchange.mdx lines 128-149
# --------------------------------------------------------------------------
def test_me_7_cross_exchange_strategy():
    """ME-7: fair_value + quoter pipeline functions"""
    try:
        import horizon as hz
        from horizon.context import FeedData

        def fair_value(ctx: hz.Context) -> float:
            """Average price across both exchange books."""
            poly = ctx.feeds.get("poly", FeedData())
            kalshi = ctx.feeds.get("kalshi", FeedData())

            prices = []
            if poly.price > 0:
                prices.append(poly.price)
            if kalshi.price > 0:
                prices.append(kalshi.price)

            return sum(prices) / len(prices) if prices else 0.5

        def quoter(ctx: hz.Context, fair: float) -> list[hz.Quote]:
            """Tight spread when venues agree, wider when they diverge."""
            poly = ctx.feeds.get("poly", FeedData()).price or fair
            kalshi = ctx.feeds.get("kalshi", FeedData()).price or fair
            divergence = abs(poly - kalshi)

            spread = 0.02 + divergence * 0.5
            return hz.quotes(fair, spread, size=5)

        # Test with mock context
        ctx = hz.Context(feeds={
            "poly": FeedData(price=0.55),
            "kalshi": FeedData(price=0.53),
        })

        fv = fair_value(ctx)
        assert abs(fv - 0.54) < 0.001, f"Expected ~0.54, got {fv}"

        qs = quoter(ctx, fv)
        assert isinstance(qs, list) and len(qs) > 0, f"Expected non-empty quotes list"

        # Also test with empty feeds
        ctx_empty = hz.Context()
        fv_empty = fair_value(ctx_empty)
        assert fv_empty == 0.5, f"Expected 0.5 for empty feeds, got {fv_empty}"

        report("ME-7: Cross-exchange pipeline functions", True,
               f"fair_value(poly=0.55, kalshi=0.53) = {fv:.4f}\n"
               f"quoter returned {len(qs)} quote(s)\n"
               f"fair_value(empty) = {fv_empty}")

    except Exception as e:
        report("ME-7: Cross-exchange pipeline functions", False,
               f"{type(e).__name__}: {e}\n{traceback.format_exc()}")


# --------------------------------------------------------------------------
# ME-8: Unified Position Tracking
# Source: multi-exchange.mdx lines 156-159
# --------------------------------------------------------------------------
def test_me_8_position_tracking():
    """ME-8: engine.positions() iteration"""
    try:
        import horizon as hz

        engine = hz.Engine(exchange_type="paper")
        positions = engine.positions()
        assert isinstance(positions, list), f"positions() should return list, got {type(positions)}"

        # Docs show: pos.market_id, pos.exchange, pos.size, pos.avg_entry_price
        # With no fills, positions list is empty - just check the call works
        report("ME-8: engine.positions()", True,
               f"positions() returned {len(positions)} items (empty for new engine)")

    except Exception as e:
        report("ME-8: engine.positions()", False,
               f"{type(e).__name__}: {e}\n{traceback.format_exc()}")


# --------------------------------------------------------------------------
# ME-9: Fills tracking
# Source: multi-exchange.mdx lines 163-166
# --------------------------------------------------------------------------
def test_me_9_fills_tracking():
    """ME-9: engine.recent_fills() iteration"""
    try:
        import horizon as hz

        engine = hz.Engine(exchange_type="paper")
        fills = engine.recent_fills()
        assert isinstance(fills, list), f"recent_fills() should return list, got {type(fills)}"

        report("ME-9: engine.recent_fills()", True,
               f"recent_fills() returned {len(fills)} items (empty for new engine)")

    except Exception as e:
        report("ME-9: engine.recent_fills()", False,
               f"{type(e).__name__}: {e}\n{traceback.format_exc()}")


# ============================================================================
# MULTI-OUTCOME (docs/multi-outcome.mdx)
# ============================================================================

# --------------------------------------------------------------------------
# MO-1: Outcome type construction
# Source: multi-outcome.mdx lines 37-53
# --------------------------------------------------------------------------
def test_mo_1_outcome():
    """MO-1: Outcome construction and attributes"""
    try:
        from horizon import Outcome, Side

        outcome = Outcome(
            name="Trump",
            market_id="trump-wins-2024",
            yes_token_id="token_yes_123",
            no_token_id="token_no_456",
            yes_price=0.55,
        )

        assert outcome.name == "Trump", f"name: expected 'Trump', got '{outcome.name}'"
        assert outcome.market_id == "trump-wins-2024"
        assert outcome.yes_price == 0.55
        assert outcome.token_id(Side.Yes) == "token_yes_123"
        assert outcome.token_id(Side.No) == "token_no_456"

        report("MO-1: Outcome construction", True,
               f"name={outcome.name}, market_id={outcome.market_id}, "
               f"yes_price={outcome.yes_price}, "
               f"token_id(Yes)={outcome.token_id(Side.Yes)}, "
               f"token_id(No)={outcome.token_id(Side.No)}")

    except Exception as e:
        report("MO-1: Outcome construction", False,
               f"{type(e).__name__}: {e}\n{traceback.format_exc()}")


# --------------------------------------------------------------------------
# MO-2: Event type construction
# Source: multi-outcome.mdx lines 59-78
# --------------------------------------------------------------------------
def test_mo_2_event():
    """MO-2: Event construction and methods"""
    try:
        from horizon import Event, Outcome

        trump = Outcome(name="Trump", market_id="trump-win", yes_token_id="t1", no_token_id="t2", yes_price=0.55)
        biden = Outcome(name="Biden", market_id="biden-win", yes_token_id="t3", no_token_id="t4", yes_price=0.30)
        desantis = Outcome(name="DeSantis", market_id="desantis-win", yes_token_id="t5", no_token_id="t6", yes_price=0.10)

        event = Event(
            id="election-2024",
            name="Who wins the 2024 election?",
            outcomes=[trump, biden, desantis],
            neg_risk=True,
            exchange="polymarket",
            condition_id="0xabc...",
        )

        assert event.outcome_count() == 3, f"Expected 3, got {event.outcome_count()}"
        assert event.outcome_names() == ["Trump", "Biden", "DeSantis"], f"Unexpected names: {event.outcome_names()}"

        trump_out = event.outcome_by_name("Trump")
        assert trump_out is not None, "outcome_by_name('Trump') returned None"
        assert trump_out.name == "Trump"

        report("MO-2: Event construction", True,
               f"outcome_count={event.outcome_count()}, "
               f"names={event.outcome_names()}, "
               f"outcome_by_name('Trump')={trump_out.name}")

    except Exception as e:
        report("MO-2: Event construction", False,
               f"{type(e).__name__}: {e}\n{traceback.format_exc()}")


# --------------------------------------------------------------------------
# MO-3: Event.to_markets()
# Source: multi-outcome.mdx lines 84-91
# --------------------------------------------------------------------------
def test_mo_3_to_markets():
    """MO-3: Event.to_markets() conversion"""
    try:
        from horizon import Event, Outcome

        trump = Outcome(name="Trump", market_id="trump-win", yes_token_id="t1", no_token_id="t2", yes_price=0.55)
        biden = Outcome(name="Biden", market_id="biden-win", yes_token_id="t3", no_token_id="t4", yes_price=0.30)
        desantis = Outcome(name="DeSantis", market_id="desantis-win", yes_token_id="t5", no_token_id="t6", yes_price=0.10)

        event = Event(
            id="election-2024",
            name="Who wins the 2024 election?",
            outcomes=[trump, biden, desantis],
            neg_risk=True,
            exchange="polymarket",
            condition_id="0xabc...",
        )

        markets = event.to_markets()
        assert isinstance(markets, list), f"to_markets() should return list, got {type(markets)}"
        assert len(markets) == 3, f"Expected 3 markets, got {len(markets)}"

        # Verify event_id and outcome_name are set (as docs describe)
        details = []
        for m in markets:
            details.append(f"  id={m.id}, event_id={m.event_id}, outcome_name={m.outcome_name}, neg_risk={m.neg_risk}")

        report("MO-3: Event.to_markets()", True,
               f"Returned {len(markets)} Market objects:\n" + "\n".join(details))

    except Exception as e:
        report("MO-3: Event.to_markets()", False,
               f"{type(e).__name__}: {e}\n{traceback.format_exc()}")


# --------------------------------------------------------------------------
# MO-4: discover_events
# Source: multi-outcome.mdx lines 99-114
# --------------------------------------------------------------------------
def test_mo_4_discover_events():
    """MO-4: discover_events('polymarket', query='election')"""
    try:
        from horizon import discover_events

        events = discover_events(
            exchange="polymarket",
            query="election",
            active=True,
            limit=10,
        )

        assert isinstance(events, list), f"Expected list, got {type(events)}"

        if len(events) == 0:
            report("MO-4: discover_events(election)", True,
                   "Returned empty list (API may have no matching events or network issue)")
            return

        details = []
        for event in events:
            details.append(f"{event.name} ({event.outcome_count()} outcomes)")
            for name in event.outcome_names():
                outcome = event.outcome_by_name(name)
                details.append(f"  {name}: {outcome.yes_price:.0%}")

        report("MO-4: discover_events(election)", True, "\n".join(details[:20]))

    except Exception as e:
        report("MO-4: discover_events(election)", False,
               f"{type(e).__name__}: {e}\n{traceback.format_exc()}")


# --------------------------------------------------------------------------
# MO-5: Engine event registration
# Source: multi-outcome.mdx lines 127-136
# --------------------------------------------------------------------------
def test_mo_5_register_event():
    """MO-5: engine.register_event()"""
    try:
        import horizon as hz

        engine = hz.Engine(exchange_type="paper")

        # Register event with its outcome market IDs
        engine.register_event("election-2024", ["trump-win", "biden-win", "desantis-win"])

        report("MO-5: engine.register_event()", True,
               "Registered 'election-2024' with 3 market IDs")

    except Exception as e:
        report("MO-5: engine.register_event()", False,
               f"{type(e).__name__}: {e}\n{traceback.format_exc()}")


# --------------------------------------------------------------------------
# MO-6: Event Exposure & Positions
# Source: multi-outcome.mdx lines 141-152
# --------------------------------------------------------------------------
def test_mo_6_event_exposure():
    """MO-6: event_exposure, event_positions, market_event_id, registered_events"""
    try:
        import horizon as hz

        engine = hz.Engine(exchange_type="paper")
        engine.register_event("election-2024", ["trump-win", "biden-win", "desantis-win"])

        # Total exposure across all outcome markets in the event
        exposure = engine.event_exposure("election-2024")
        assert isinstance(exposure, float), f"Expected float, got {type(exposure)}"

        # All positions in the event
        positions = engine.event_positions("election-2024")
        assert isinstance(positions, list), f"Expected list, got {type(positions)}"

        # Reverse lookup: which event does a market belong to?
        event_id = engine.market_event_id("trump-win")
        assert event_id == "election-2024", f"Expected 'election-2024', got {event_id}"

        # All registered events
        events = engine.registered_events()
        assert isinstance(events, dict), f"Expected dict, got {type(events)}"
        assert "election-2024" in events

        report("MO-6: Event exposure/positions/lookup", True,
               f"exposure={exposure}, positions={len(positions)}, "
               f"market_event_id('trump-win')='{event_id}', "
               f"registered_events keys={list(events.keys())}")

    except Exception as e:
        report("MO-6: Event exposure/positions/lookup", False,
               f"{type(e).__name__}: {e}\n{traceback.format_exc()}")


# --------------------------------------------------------------------------
# MO-7: Event Parity Check
# Source: multi-outcome.mdx lines 158-162
# --------------------------------------------------------------------------
def test_mo_7_parity_check():
    """MO-7: engine.event_parity_check()"""
    try:
        import horizon as hz

        engine = hz.Engine(exchange_type="paper")
        engine.register_event("election-2024", ["trump-win", "biden-win", "desantis-win"])

        result = engine.event_parity_check("election-2024", threshold=0.02)
        # Result may be None if no feed data (expected for paper with no feeds started)
        if result is not None:
            _ = result.is_violation
            _ = result.yes_price
            _ = result.deviation
            report("MO-7: event_parity_check()", True,
                   f"is_violation={result.is_violation}, yes_price={result.yes_price}, deviation={result.deviation}")
        else:
            report("MO-7: event_parity_check()", True,
                   "Returned None (no feed data - expected for paper engine)")

    except Exception as e:
        report("MO-7: event_parity_check()", False,
               f"{type(e).__name__}: {e}\n{traceback.format_exc()}")


# --------------------------------------------------------------------------
# MO-8: Event Risk Limits - RiskConfig with max_position_per_event
# Source: multi-outcome.mdx lines 180-185
# --------------------------------------------------------------------------
def test_mo_8_risk_config_event():
    """MO-8: RiskConfig with max_position_per_event"""
    try:
        from horizon import RiskConfig

        config = RiskConfig(
            max_position_per_market=100.0,
            max_position_per_event=200.0,
        )

        assert config.max_position_per_market == 100.0
        assert config.max_position_per_event == 200.0

        # Test default (None)
        config_default = RiskConfig()
        assert config_default.max_position_per_event is None, \
            f"Default should be None, got {config_default.max_position_per_event}"

        report("MO-8: RiskConfig max_position_per_event", True,
               f"max_position_per_market={config.max_position_per_market}, "
               f"max_position_per_event={config.max_position_per_event}, "
               f"default max_position_per_event={config_default.max_position_per_event}")

    except Exception as e:
        report("MO-8: RiskConfig max_position_per_event", False,
               f"{type(e).__name__}: {e}\n{traceback.format_exc()}")


# --------------------------------------------------------------------------
# MO-9: Running with Events (hz.run pattern)
# Source: multi-outcome.mdx lines 198-221
# NOTE: hz.run() skipped, test the pipeline functions and type instantiation
# --------------------------------------------------------------------------
def test_mo_9_run_with_events():
    """MO-9: hz.run with events= parameter (type checks only)"""
    try:
        import horizon as hz
        from horizon.context import FeedData

        # Verify the pipeline functions from docs compile and work
        def fair_value(ctx: hz.Context) -> float:
            feed = ctx.feeds.get("poly", FeedData())
            return feed.price

        def quoter(ctx: hz.Context, fair: float) -> list[hz.Quote]:
            if ctx.event:
                _ = f"Quoting {ctx.market.outcome_name} in {ctx.event.name}"
            return hz.quotes(fair, spread=0.04, size=5)

        # Create a mock context with an event
        trump = hz.Outcome(name="Trump", market_id="trump-win", yes_token_id="t1", no_token_id="t2", yes_price=0.55)
        event = hz.Event(
            id="election-2024",
            name="Who wins?",
            outcomes=[trump],
        )
        market = event.to_markets()[0]

        ctx = hz.Context(
            feeds={"poly": FeedData(price=0.55)},
            market=market,
            event=event,
        )

        fv = fair_value(ctx)
        assert fv == 0.55
        qs = quoter(ctx, fv)
        assert isinstance(qs, list) and len(qs) > 0

        report("MO-9: hz.run events= pattern", True,
               f"Pipeline functions work with event context.\n"
               f"fair_value={fv}, quoter returned {len(qs)} quote(s)\n"
               f"(hz.run() skipped - needs live feeds)")

    except Exception as e:
        report("MO-9: hz.run events= pattern", False,
               f"{type(e).__name__}: {e}\n{traceback.format_exc()}")


# --------------------------------------------------------------------------
# MO-10: Arbitrage Detection (event_parity_check for arb)
# Source: multi-outcome.mdx lines 239-249
# --------------------------------------------------------------------------
def test_mo_10_arbitrage_detection():
    """MO-10: EventArbitrageOpportunity / event_parity_check arb pattern"""
    try:
        from horizon import EventArbitrageOpportunity

        # Just verify the type is importable (docs reference it)
        assert EventArbitrageOpportunity is not None

        # The docs show engine.event_parity_check usage for arb - tested in MO-7
        report("MO-10: EventArbitrageOpportunity import", True,
               "EventArbitrageOpportunity imported successfully")

    except Exception as e:
        report("MO-10: EventArbitrageOpportunity import", False,
               f"{type(e).__name__}: {e}\n{traceback.format_exc()}")


# --------------------------------------------------------------------------
# MO-11: Multi-Outcome Market Maker (full example)
# Source: multi-outcome.mdx lines 263-300
# --------------------------------------------------------------------------
def test_mo_11_multi_outcome_mm():
    """MO-11: Multi-outcome market maker pipeline functions"""
    try:
        import horizon as hz
        from horizon.context import FeedData, InventorySnapshot

        def fair_value(ctx: hz.Context) -> float:
            """Use feed price as fair value for each outcome."""
            feed = ctx.feeds.get(ctx.market.id, FeedData())
            if feed.price > 0:
                return feed.price
            return 0.5

        def event_aware_quoter(ctx: hz.Context, fair: float) -> list[hz.Quote]:
            """Quote with event-aware inventory management."""
            market_pos = ctx.inventory.net_for_market(ctx.market.id)

            event_pos = 0.0
            if ctx.event:
                event_market_ids = [o.market_id for o in ctx.event.outcomes]
                event_pos = ctx.inventory.net_for_event(event_market_ids)

            skew = market_pos * 0.002 + event_pos * 0.001
            spread = 0.04

            return hz.quotes(fair - skew, spread, size=5)

        # Build test context
        trump = hz.Outcome(name="Trump", market_id="trump-win", yes_token_id="t1", no_token_id="t2", yes_price=0.55)
        biden = hz.Outcome(name="Biden", market_id="biden-win", yes_token_id="t3", no_token_id="t4", yes_price=0.30)
        event = hz.Event(id="election", name="Election", outcomes=[trump, biden])
        market = event.to_markets()[0]

        ctx = hz.Context(
            feeds={"trump-win": FeedData(price=0.55)},
            market=market,
            event=event,
            inventory=InventorySnapshot(),
        )

        fv = fair_value(ctx)
        assert abs(fv - 0.55) < 0.001
        qs = event_aware_quoter(ctx, fv)
        assert isinstance(qs, list) and len(qs) > 0

        report("MO-11: Multi-outcome MM pipeline", True,
               f"fair_value={fv:.4f}, event_aware_quoter returned {len(qs)} quote(s)")

    except Exception as e:
        report("MO-11: Multi-outcome MM pipeline", False,
               f"{type(e).__name__}: {e}\n{traceback.format_exc()}")


# ============================================================================
# WALLET ANALYTICS (docs/wallet-analytics.mdx)
# ============================================================================

# --------------------------------------------------------------------------
# WA-1: hz.get_market_trades
# Source: wallet-analytics.mdx lines 40-53
# --------------------------------------------------------------------------
def test_wa_1_get_market_trades():
    """WA-1: hz.get_market_trades()"""
    try:
        import horizon as hz

        trades = hz.get_market_trades(
            condition_id="0xabc123",
            limit=100,
            offset=0,
            side="BUY",
            min_size=10.0,
        )

        assert isinstance(trades, list), f"Expected list, got {type(trades)}"

        # If we got trades, test attribute access from docs
        if trades:
            t = trades[0]
            _ = t.wallet
            _ = t.side
            _ = t.size
            _ = t.price
            _ = t.market_title
            report("WA-1: get_market_trades()", True,
                   f"Returned {len(trades)} trades. First: wallet={t.wallet[:10]}...")
        else:
            report("WA-1: get_market_trades()", True,
                   "Returned empty list (fake condition_id - expected)")

    except Exception as e:
        report("WA-1: get_market_trades()", False,
               f"{type(e).__name__}: {e}\n{traceback.format_exc()}")


# --------------------------------------------------------------------------
# WA-2: hz.get_wallet_trades
# Source: wallet-analytics.mdx lines 70-78
# --------------------------------------------------------------------------
def test_wa_2_get_wallet_trades():
    """WA-2: hz.get_wallet_trades()"""
    try:
        import horizon as hz

        trades = hz.get_wallet_trades(
            address="0x1234567890abcdef1234567890abcdef12345678",
            limit=100,
            condition_id="0xabc123",
        )

        assert isinstance(trades, list), f"Expected list, got {type(trades)}"

        if trades:
            total_volume = sum(t.usdc_size for t in trades)
            report("WA-2: get_wallet_trades()", True,
                   f"Returned {len(trades)} trades, total volume: ${total_volume:,.2f}")
        else:
            report("WA-2: get_wallet_trades()", True,
                   "Returned empty list (fake address - expected)")

    except Exception as e:
        report("WA-2: get_wallet_trades()", False,
               f"{type(e).__name__}: {e}\n{traceback.format_exc()}")


# --------------------------------------------------------------------------
# WA-3: hz.get_wallet_positions
# Source: wallet-analytics.mdx lines 96-106
# --------------------------------------------------------------------------
def test_wa_3_get_wallet_positions():
    """WA-3: hz.get_wallet_positions()"""
    try:
        import horizon as hz

        positions = hz.get_wallet_positions(
            address="0x1234567890abcdef1234567890abcdef12345678",
            limit=100,
            sort_by="CASHPNL",
        )

        assert isinstance(positions, list), f"Expected list, got {type(positions)}"

        if positions:
            p = positions[0]
            _ = p.market_title
            _ = p.outcome
            _ = p.size
            _ = p.avg_price
            _ = p.current_price
            _ = p.pnl
            _ = p.pnl_percent
            report("WA-3: get_wallet_positions()", True,
                   f"Returned {len(positions)} positions. First: {p.market_title}")
        else:
            report("WA-3: get_wallet_positions()", True,
                   "Returned empty list (fake address - expected)")

    except Exception as e:
        report("WA-3: get_wallet_positions()", False,
               f"{type(e).__name__}: {e}\n{traceback.format_exc()}")


# --------------------------------------------------------------------------
# WA-4: hz.get_wallet_value
# Source: wallet-analytics.mdx lines 132-134
# --------------------------------------------------------------------------
def test_wa_4_get_wallet_value():
    """WA-4: hz.get_wallet_value()"""
    try:
        import horizon as hz

        value = hz.get_wallet_value("0x1234567890abcdef1234567890abcdef12345678")

        assert isinstance(value, (int, float)), f"Expected numeric, got {type(value)}"

        report("WA-4: get_wallet_value()", True,
               f"Portfolio value: ${value:,.2f}")

    except Exception as e:
        report("WA-4: get_wallet_value()", False,
               f"{type(e).__name__}: {e}\n{traceback.format_exc()}")


# --------------------------------------------------------------------------
# WA-5: hz.get_top_holders
# Source: wallet-analytics.mdx lines 147-156
# --------------------------------------------------------------------------
def test_wa_5_get_top_holders():
    """WA-5: hz.get_top_holders()"""
    try:
        import horizon as hz

        holders = hz.get_top_holders(
            condition_id="0xabc123",
            limit=20,
        )

        assert isinstance(holders, list), f"Expected list, got {type(holders)}"

        if holders:
            h = holders[0]
            name = h.pseudonym or h.wallet[:10] + "..."
            _ = h.amount
            _ = h.outcome_index
            report("WA-5: get_top_holders()", True,
                   f"Returned {len(holders)} holders. Top: {name} ({h.amount:,.0f} tokens)")
        else:
            report("WA-5: get_top_holders()", True,
                   "Returned empty list (fake condition_id - expected)")

    except Exception as e:
        report("WA-5: get_top_holders()", False,
               f"{type(e).__name__}: {e}\n{traceback.format_exc()}")


# --------------------------------------------------------------------------
# WA-6: hz.get_wallet_profile
# Source: wallet-analytics.mdx lines 173-181
# --------------------------------------------------------------------------
def test_wa_6_get_wallet_profile():
    """WA-6: hz.get_wallet_profile()"""
    try:
        import horizon as hz

        profile = hz.get_wallet_profile("0x1234567890abcdef1234567890abcdef12345678")

        # May return None for fake address
        if profile:
            _ = profile.pseudonym
            _ = profile.name
            _ = profile.bio
            _ = profile.x_username
            _ = profile.created_at
            report("WA-6: get_wallet_profile()", True,
                   f"Name: {profile.pseudonym or profile.name}, Bio: {profile.bio}")
        else:
            report("WA-6: get_wallet_profile()", True,
                   "Returned None (fake address or no profile - expected)")

    except Exception as e:
        report("WA-6: get_wallet_profile()", False,
               f"{type(e).__name__}: {e}\n{traceback.format_exc()}")


# --------------------------------------------------------------------------
# WA-7: hz.analyze_market_flow
# Source: wallet-analytics.mdx lines 198-217
# --------------------------------------------------------------------------
def test_wa_7_analyze_market_flow():
    """WA-7: hz.analyze_market_flow()"""
    try:
        import horizon as hz

        flow = hz.analyze_market_flow(
            condition_id="0xabc123",
            trade_limit=500,
            top_n=10,
        )

        assert isinstance(flow, hz.MarketFlow), f"Expected MarketFlow, got {type(flow)}"

        # Access all attributes from docs
        _ = flow.total_trades
        _ = flow.buy_volume
        _ = flow.sell_volume
        _ = flow.net_flow
        _ = flow.unique_wallets
        _ = flow.top_buyers
        _ = flow.top_sellers

        report("WA-7: analyze_market_flow()", True,
               f"total_trades={flow.total_trades}, buy_vol=${flow.buy_volume:,.2f}, "
               f"sell_vol=${flow.sell_volume:,.2f}, net=${flow.net_flow:+,.2f}, "
               f"wallets={flow.unique_wallets}")

    except Exception as e:
        report("WA-7: analyze_market_flow()", False,
               f"{type(e).__name__}: {e}\n{traceback.format_exc()}")


# --------------------------------------------------------------------------
# WA-8: Data Types - Trade attributes
# Source: wallet-analytics.mdx lines 231-245
# --------------------------------------------------------------------------
def test_wa_8_trade_dataclass():
    """WA-8: Trade dataclass attributes"""
    try:
        from horizon.flow import Trade

        # Construct a Trade manually to verify all doc-listed attributes exist
        trade = Trade(
            wallet="0x1234",
            side="BUY",
            outcome="Yes",
            size=100.0,
            price=0.55,
            usdc_size=55.0,
            timestamp=1700000000,
            market_slug="test-market",
            market_title="Test Market",
            condition_id="0xabc",
            token_id="tok123",
            tx_hash="0xtx",
            pseudonym="Trader1",
        )

        # Check all attributes from docs
        assert trade.wallet == "0x1234"
        assert trade.side == "BUY"
        assert trade.outcome == "Yes"
        assert trade.size == 100.0
        assert trade.price == 0.55
        assert trade.usdc_size == 55.0
        assert trade.timestamp == 1700000000
        assert trade.market_slug == "test-market"
        assert trade.market_title == "Test Market"
        assert trade.condition_id == "0xabc"
        assert trade.token_id == "tok123"
        assert trade.tx_hash == "0xtx"
        assert trade.pseudonym == "Trader1"

        report("WA-8: Trade dataclass", True,
               "All 13 documented attributes verified")

    except Exception as e:
        report("WA-8: Trade dataclass", False,
               f"{type(e).__name__}: {e}\n{traceback.format_exc()}")


# --------------------------------------------------------------------------
# WA-9: Data Types - WalletPosition (PolymarketPosition) attributes
# Source: wallet-analytics.mdx lines 249-262
# --------------------------------------------------------------------------
def test_wa_9_wallet_position_dataclass():
    """WA-9: WalletPosition/PolymarketPosition dataclass attributes"""
    try:
        import horizon as hz
        from horizon.flow import WalletPosition

        # Verify alias works
        assert hz.PolymarketPosition is WalletPosition, \
            "hz.PolymarketPosition should alias WalletPosition"

        pos = WalletPosition(
            wallet="0x1234",
            market_slug="test-market",
            market_title="Test Market",
            condition_id="0xabc",
            token_id="tok123",
            outcome="Yes",
            size=50.0,
            avg_price=0.50,
            current_price=0.60,
            current_value=30.0,
            pnl=5.0,
            pnl_percent=10.0,
        )

        assert pos.wallet == "0x1234"
        assert pos.market_slug == "test-market"
        assert pos.market_title == "Test Market"
        assert pos.condition_id == "0xabc"
        assert pos.token_id == "tok123"
        assert pos.outcome == "Yes"
        assert pos.size == 50.0
        assert pos.avg_price == 0.50
        assert pos.current_price == 0.60
        assert pos.current_value == 30.0
        assert pos.pnl == 5.0
        assert pos.pnl_percent == 10.0

        report("WA-9: WalletPosition dataclass", True,
               "All 12 documented attributes verified. hz.PolymarketPosition alias works.")

    except Exception as e:
        report("WA-9: WalletPosition dataclass", False,
               f"{type(e).__name__}: {e}\n{traceback.format_exc()}")


# --------------------------------------------------------------------------
# WA-10: Data Types - Holder attributes
# Source: wallet-analytics.mdx lines 270-277
# --------------------------------------------------------------------------
def test_wa_10_holder_dataclass():
    """WA-10: Holder dataclass attributes"""
    try:
        from horizon.flow import Holder

        holder = Holder(
            wallet="0x1234",
            amount=10000.0,
            token_id="tok123",
            outcome_index=0,
            pseudonym="BigTrader",
            name="John Doe",
        )

        assert holder.wallet == "0x1234"
        assert holder.amount == 10000.0
        assert holder.token_id == "tok123"
        assert holder.outcome_index == 0
        assert holder.pseudonym == "BigTrader"
        assert holder.name == "John Doe"

        report("WA-10: Holder dataclass", True,
               "All 6 documented attributes verified")

    except Exception as e:
        report("WA-10: Holder dataclass", False,
               f"{type(e).__name__}: {e}\n{traceback.format_exc()}")


# --------------------------------------------------------------------------
# WA-11: Data Types - WalletProfile attributes
# Source: wallet-analytics.mdx lines 281-289
# --------------------------------------------------------------------------
def test_wa_11_wallet_profile_dataclass():
    """WA-11: WalletProfile dataclass attributes"""
    try:
        from horizon.flow import WalletProfile

        profile = WalletProfile(
            wallet="0x1234",
            pseudonym="CryptoWhale",
            name="Jane Smith",
            bio="I trade prediction markets",
            profile_image="https://example.com/avatar.png",
            x_username="cryptowhale",
            created_at="2023-01-15",
        )

        assert profile.wallet == "0x1234"
        assert profile.pseudonym == "CryptoWhale"
        assert profile.name == "Jane Smith"
        assert profile.bio == "I trade prediction markets"
        assert profile.profile_image == "https://example.com/avatar.png"
        assert profile.x_username == "cryptowhale"
        assert profile.created_at == "2023-01-15"

        report("WA-11: WalletProfile dataclass", True,
               "All 7 documented attributes verified")

    except Exception as e:
        report("WA-11: WalletProfile dataclass", False,
               f"{type(e).__name__}: {e}\n{traceback.format_exc()}")


# --------------------------------------------------------------------------
# WA-12: Data Types - MarketFlow attributes
# Source: wallet-analytics.mdx lines 293-302
# --------------------------------------------------------------------------
def test_wa_12_market_flow_dataclass():
    """WA-12: MarketFlow dataclass attributes"""
    try:
        from horizon.flow import MarketFlow

        flow = MarketFlow(
            condition_id="0xabc",
            total_trades=100,
            buy_volume=5000.0,
            sell_volume=3000.0,
            net_flow=2000.0,
            unique_wallets=25,
            top_buyers=[("0xbuyer1", 1000.0), ("0xbuyer2", 500.0)],
            top_sellers=[("0xseller1", 800.0)],
        )

        assert flow.condition_id == "0xabc"
        assert flow.total_trades == 100
        assert flow.buy_volume == 5000.0
        assert flow.sell_volume == 3000.0
        assert flow.net_flow == 2000.0
        assert flow.unique_wallets == 25
        assert len(flow.top_buyers) == 2
        assert len(flow.top_sellers) == 1

        report("WA-12: MarketFlow dataclass", True,
               "All 8 documented attributes verified")

    except Exception as e:
        report("WA-12: MarketFlow dataclass", False,
               f"{type(e).__name__}: {e}\n{traceback.format_exc()}")


# --------------------------------------------------------------------------
# WA-13: Whale Tracking example
# Source: wallet-analytics.mdx lines 311-325
# --------------------------------------------------------------------------
def test_wa_13_whale_tracking():
    """WA-13: Whale tracking example (live API)"""
    try:
        import horizon as hz

        # Find top holders in a market (fake condition_id)
        holders = hz.get_top_holders("0xabc123")

        assert isinstance(holders, list), f"Expected list, got {type(holders)}"

        if holders:
            for h in holders[:5]:
                profile = hz.get_wallet_profile(h.wallet)
                name = profile.pseudonym if profile else h.wallet[:10]

                trades = hz.get_wallet_trades(h.wallet, limit=20)
                recent_side = trades[0].side if trades else "N/A"

                # Just verify code runs; output is informational
            report("WA-13: Whale tracking", True,
                   f"Processed {min(5, len(holders))} holders with profile + trade lookups")
        else:
            report("WA-13: Whale tracking", True,
                   "No holders returned (fake condition_id - expected)")

    except Exception as e:
        report("WA-13: Whale tracking", False,
               f"{type(e).__name__}: {e}\n{traceback.format_exc()}")


# --------------------------------------------------------------------------
# WA-14: Smart Money Flow example
# Source: wallet-analytics.mdx lines 330-342
# --------------------------------------------------------------------------
def test_wa_14_smart_money_flow():
    """WA-14: Smart money flow example (live API)"""
    try:
        import horizon as hz

        flow = hz.analyze_market_flow("0xabc123", trade_limit=1000)

        assert isinstance(flow, hz.MarketFlow)

        if flow.net_flow > 0:
            msg = f"Bullish flow: ${flow.net_flow:,.0f} net buying"
        else:
            msg = f"Bearish flow: ${abs(flow.net_flow):,.0f} net selling"

        # Accessing top_buyers/top_sellers
        if flow.top_buyers:
            _ = f"Top buyer: {flow.top_buyers[0][0][:10]}... (${flow.top_buyers[0][1]:,.0f})"

        report("WA-14: Smart money flow", True, msg)

    except Exception as e:
        report("WA-14: Smart money flow", False,
               f"{type(e).__name__}: {e}\n{traceback.format_exc()}")


# --------------------------------------------------------------------------
# WA-15: Portfolio Snapshot example
# Source: wallet-analytics.mdx lines 347-362
# --------------------------------------------------------------------------
def test_wa_15_portfolio_snapshot():
    """WA-15: Portfolio snapshot example (live API)"""
    try:
        import horizon as hz

        address = "0x1234567890abcdef1234567890abcdef12345678"

        value = hz.get_wallet_value(address)
        positions = hz.get_wallet_positions(address, sort_by="CURRENT")
        profile = hz.get_wallet_profile(address)

        assert isinstance(value, (int, float))
        assert isinstance(positions, list)
        # profile may be None

        trader_name = profile.pseudonym if profile else address[:10]

        details = [
            f"Trader: {trader_name}",
            f"Portfolio: ${value:,.2f}",
            f"Positions: {len(positions)}",
        ]

        for p in positions[:5]:
            emoji = "+" if p.pnl > 0 else ""
            details.append(f"  {p.market_title[:40]}: {p.outcome} {p.size:.0f} @ {p.avg_price:.2f} -> PnL {emoji}${p.pnl:.2f}")

        report("WA-15: Portfolio snapshot", True, "\n".join(details))

    except Exception as e:
        report("WA-15: Portfolio snapshot", False,
               f"{type(e).__name__}: {e}\n{traceback.format_exc()}")


# --------------------------------------------------------------------------
# WA-16: Verify all wallet analytics imports from __init__.py
# Source: wallet-analytics.mdx (all referenced symbols)
# --------------------------------------------------------------------------
def test_wa_16_imports():
    """WA-16: All wallet analytics imports exist in horizon namespace"""
    try:
        import horizon as hz

        # Functions
        assert callable(hz.get_market_trades), "get_market_trades missing"
        assert callable(hz.get_wallet_trades), "get_wallet_trades missing"
        assert callable(hz.get_wallet_positions), "get_wallet_positions missing"
        assert callable(hz.get_wallet_value), "get_wallet_value missing"
        assert callable(hz.get_top_holders), "get_top_holders missing"
        assert callable(hz.get_wallet_profile), "get_wallet_profile missing"
        assert callable(hz.analyze_market_flow), "analyze_market_flow missing"

        # Types
        assert hz.Trade is not None, "Trade missing"
        assert hz.PolymarketPosition is not None, "PolymarketPosition missing"
        assert hz.Holder is not None, "Holder missing"
        assert hz.WalletProfile is not None, "WalletProfile missing"
        assert hz.MarketFlow is not None, "MarketFlow missing"

        report("WA-16: All wallet analytics imports", True,
               "7 functions + 5 types all present in horizon namespace")

    except Exception as e:
        report("WA-16: All wallet analytics imports", False,
               f"{type(e).__name__}: {e}\n{traceback.format_exc()}")


# --------------------------------------------------------------------------
# WA-17: Function signatures match docs
# --------------------------------------------------------------------------
def test_wa_17_signatures():
    """WA-17: Wallet analytics function signatures match docs"""
    try:
        import inspect
        import horizon as hz

        # get_market_trades: condition_id, limit, offset, side, min_size
        sig = inspect.signature(hz.get_market_trades)
        params = list(sig.parameters.keys())
        for p in ["condition_id", "limit", "offset", "side", "min_size"]:
            assert p in params, f"get_market_trades missing param: {p}"

        # get_wallet_trades: address, limit, offset, condition_id
        sig = inspect.signature(hz.get_wallet_trades)
        params = list(sig.parameters.keys())
        for p in ["address", "limit", "offset", "condition_id"]:
            assert p in params, f"get_wallet_trades missing param: {p}"

        # get_wallet_positions: address, limit, offset, condition_id, sort_by
        sig = inspect.signature(hz.get_wallet_positions)
        params = list(sig.parameters.keys())
        for p in ["address", "limit", "offset", "condition_id", "sort_by"]:
            assert p in params, f"get_wallet_positions missing param: {p}"

        # get_wallet_value: address
        sig = inspect.signature(hz.get_wallet_value)
        params = list(sig.parameters.keys())
        assert "address" in params, "get_wallet_value missing param: address"

        # get_top_holders: condition_id, limit
        sig = inspect.signature(hz.get_top_holders)
        params = list(sig.parameters.keys())
        for p in ["condition_id", "limit"]:
            assert p in params, f"get_top_holders missing param: {p}"

        # get_wallet_profile: address
        sig = inspect.signature(hz.get_wallet_profile)
        params = list(sig.parameters.keys())
        assert "address" in params, "get_wallet_profile missing param: address"

        # analyze_market_flow: condition_id, trade_limit, top_n
        sig = inspect.signature(hz.analyze_market_flow)
        params = list(sig.parameters.keys())
        for p in ["condition_id", "trade_limit", "top_n"]:
            assert p in params, f"analyze_market_flow missing param: {p}"

        report("WA-17: Function signatures match docs", True,
               "All documented parameters present in all 7 functions")

    except Exception as e:
        report("WA-17: Function signatures match docs", False,
               f"{type(e).__name__}: {e}\n{traceback.format_exc()}")


# ============================================================================
# Run all tests
# ============================================================================
if __name__ == "__main__":
    print("=" * 70)
    print("Testing code snippets from:")
    print("  1. docs/multi-exchange.mdx")
    print("  2. docs/multi-outcome.mdx")
    print("  3. docs/wallet-analytics.mdx")
    print("=" * 70)
    print()

    # --- Multi-Exchange ---
    print("=" * 70)
    print("MULTI-EXCHANGE (docs/multi-exchange.mdx)")
    print("=" * 70)

    print("\n--- ME-1: Quick Start ---")
    test_me_1_quick_start()

    print("\n--- ME-2: Engine add_exchange ---")
    test_me_2_engine_add_exchange()

    print("\n--- ME-3: Querying exchanges ---")
    test_me_3_query_exchanges()

    print("\n--- ME-4: Explicit routing ---")
    test_me_4_explicit_routing()

    print("\n--- ME-5: Netting pairs (hz.run pattern) ---")
    test_me_5_netting_pairs_run()

    print("\n--- ME-6: Netting pairs (Engine API) ---")
    test_me_6_netting_pairs_engine()

    print("\n--- ME-7: Cross-exchange strategy pattern ---")
    test_me_7_cross_exchange_strategy()

    print("\n--- ME-8: Unified position tracking ---")
    test_me_8_position_tracking()

    print("\n--- ME-9: Fills tracking ---")
    test_me_9_fills_tracking()

    # --- Multi-Outcome ---
    print()
    print("=" * 70)
    print("MULTI-OUTCOME (docs/multi-outcome.mdx)")
    print("=" * 70)

    print("\n--- MO-1: Outcome type ---")
    test_mo_1_outcome()

    print("\n--- MO-2: Event type ---")
    test_mo_2_event()

    print("\n--- MO-3: Event.to_markets() ---")
    test_mo_3_to_markets()

    print("\n--- MO-4: discover_events ---")
    test_mo_4_discover_events()

    print("\n--- MO-5: register_event ---")
    test_mo_5_register_event()

    print("\n--- MO-6: Event exposure/positions ---")
    test_mo_6_event_exposure()

    print("\n--- MO-7: Event parity check ---")
    test_mo_7_parity_check()

    print("\n--- MO-8: RiskConfig max_position_per_event ---")
    test_mo_8_risk_config_event()

    print("\n--- MO-9: hz.run with events ---")
    test_mo_9_run_with_events()

    print("\n--- MO-10: EventArbitrageOpportunity ---")
    test_mo_10_arbitrage_detection()

    print("\n--- MO-11: Multi-outcome MM ---")
    test_mo_11_multi_outcome_mm()

    # --- Wallet Analytics ---
    print()
    print("=" * 70)
    print("WALLET ANALYTICS (docs/wallet-analytics.mdx)")
    print("=" * 70)

    print("\n--- WA-1: get_market_trades ---")
    test_wa_1_get_market_trades()

    print("\n--- WA-2: get_wallet_trades ---")
    test_wa_2_get_wallet_trades()

    print("\n--- WA-3: get_wallet_positions ---")
    test_wa_3_get_wallet_positions()

    print("\n--- WA-4: get_wallet_value ---")
    test_wa_4_get_wallet_value()

    print("\n--- WA-5: get_top_holders ---")
    test_wa_5_get_top_holders()

    print("\n--- WA-6: get_wallet_profile ---")
    test_wa_6_get_wallet_profile()

    print("\n--- WA-7: analyze_market_flow ---")
    test_wa_7_analyze_market_flow()

    print("\n--- WA-8: Trade dataclass ---")
    test_wa_8_trade_dataclass()

    print("\n--- WA-9: WalletPosition dataclass ---")
    test_wa_9_wallet_position_dataclass()

    print("\n--- WA-10: Holder dataclass ---")
    test_wa_10_holder_dataclass()

    print("\n--- WA-11: WalletProfile dataclass ---")
    test_wa_11_wallet_profile_dataclass()

    print("\n--- WA-12: MarketFlow dataclass ---")
    test_wa_12_market_flow_dataclass()

    print("\n--- WA-13: Whale tracking ---")
    test_wa_13_whale_tracking()

    print("\n--- WA-14: Smart money flow ---")
    test_wa_14_smart_money_flow()

    print("\n--- WA-15: Portfolio snapshot ---")
    test_wa_15_portfolio_snapshot()

    print("\n--- WA-16: All imports ---")
    test_wa_16_imports()

    print("\n--- WA-17: Function signatures ---")
    test_wa_17_signatures()

    # Summary
    print()
    print("=" * 70)
    print("SUMMARY")
    print("=" * 70)
    passed = sum(1 for _, p, _ in results if p)
    failed = sum(1 for _, p, _ in results if not p)
    total = len(results)
    print(f"  Total: {total}  |  Passed: {passed}  |  Failed: {failed}")
    print()
    if failed:
        print("FAILED tests:")
        for name, p, detail in results:
            if not p:
                print(f"  - {name}")
                if detail:
                    for line in detail.strip().splitlines()[:5]:
                        print(f"      {line}")
    else:
        print("All tests passed!")

    sys.exit(1 if failed else 0)
