"""GLFT Market Maker on Polymarket (paper mode).

Demonstrates the full pipeline: fair value -> spread adjustment -> GLFT quoter.
Uses bid/ask spread from the feed as a toxicity proxy (wider spread = more toxic).
"""

import math

import horizon as hz


def black_scholes_binary(price: float, strike: float, vol: float, tte: float) -> float:
    """Binary option fair value: Phi(d2) where d2 = (ln(S/K) - 0.5*vol^2*T) / (vol*sqrt(T))."""
    if tte <= 0:
        return 1.0 if price >= strike else 0.0
    d2 = (math.log(price / strike) - 0.5 * vol**2 * tte) / (vol * math.sqrt(tte))
    return 0.5 * (1 + math.erf(d2 / math.sqrt(2)))


def spread_toxicity(bid: float, ask: float) -> float:
    """Spread-based toxicity proxy: wider spread = more toxic flow.

    Returns a value in [0, 1]. A typical BTC spread of ~$10 on a $100k price
    maps to low toxicity. Uses the bid-ask spread relative to mid.
    """
    if bid <= 0 or ask <= 0:
        return 0.5  # Default when no book data
    mid = (bid + ask) / 2.0
    if mid <= 0:
        return 0.5
    relative_spread = (ask - bid) / mid
    # Map relative spread to [0, 1]: 0.01% -> 0, 1% -> 1
    return min(1.0, max(0.0, relative_spread * 100.0))


def glft_spread(fair: float, tox: float, inventory: float, gamma: float = 0.1) -> float:
    """GLFT adverse selection spread.

    spread = base_spread + gamma * inventory_penalty + tox_adjustment
    """
    base = 0.02
    inv_penalty = gamma * abs(inventory) * 0.001
    tox_adj = tox * 0.04
    return base + inv_penalty + tox_adj


# Pipeline functions
def fair_value(ctx: hz.Context) -> float:
    btc_price = ctx.feeds.get("btc", hz.context.FeedData()).price or 100_000
    strike = 100_000
    vol = 0.6
    tte = 30 / 365  # 30 days to expiry
    return black_scholes_binary(btc_price, strike, vol, tte)


def toxicity(ctx: hz.Context) -> float:
    feed = ctx.feeds.get("btc", hz.context.FeedData())
    return spread_toxicity(feed.bid, feed.ask)


def quoter(ctx: hz.Context, fair: float, tox: float) -> list[hz.Quote]:
    spread = glft_spread(fair, tox, ctx.inventory.net, gamma=0.1)
    return hz.quotes(fair, spread, size=5)


if __name__ == "__main__":
    hz.run(
        name="btc_mm",
        exchange=hz.Polymarket(private_key="0x_demo_key"),
        markets=["will-btc-hit-100k-by-end-of-2025"],
        feeds={"btc": hz.BinanceWS("btcusdt")},
        pipeline=[fair_value, toxicity, quoter],
        risk=hz.Risk(max_position=100, max_drawdown_pct=5),
        interval=0.5,
        mode="paper",
        dashboard=False,
    )
