"""Type stubs for the Rust _horizon extension module."""

from __future__ import annotations

class Side:
    Yes: Side
    No: Side

class OrderSide:
    Buy: OrderSide
    Sell: OrderSide

class OrderType:
    Limit: OrderType
    Market: OrderType

class TimeInForce:
    GTC: TimeInForce
    GTD: TimeInForce
    FOK: TimeInForce
    FAK: TimeInForce

class OrderStatus:
    New: OrderStatus
    Submitted: OrderStatus
    Accepted: OrderStatus
    PartiallyFilled: OrderStatus
    Filled: OrderStatus
    Canceled: OrderStatus
    Rejected: OrderStatus

class AlertLevel:
    Info: AlertLevel
    Warning: AlertLevel
    Critical: AlertLevel

class TriggerType:
    StopLoss: TriggerType
    TakeProfit: TriggerType

class Market:
    id: str
    name: str
    slug: str
    exchange: str
    expiry: str | None
    active: bool
    yes_token_id: str | None
    no_token_id: str | None
    condition_id: str | None
    neg_risk: bool
    ticker: str | None
    event_id: str | None
    outcome_name: str | None

    def __init__(
        self,
        id: str,
        name: str = "",
        slug: str = "",
        exchange: str = "paper",
        expiry: str | None = None,
        active: bool = True,
        yes_token_id: str | None = None,
        no_token_id: str | None = None,
        condition_id: str | None = None,
        neg_risk: bool = False,
        ticker: str | None = None,
        event_id: str | None = None,
        outcome_name: str | None = None,
    ) -> None: ...
    def token_id(self, side: Side) -> str | None: ...

class Outcome:
    name: str
    market_id: str
    yes_token_id: str | None
    no_token_id: str | None
    yes_price: float

    def __init__(
        self,
        name: str,
        market_id: str,
        yes_token_id: str | None = None,
        no_token_id: str | None = None,
        yes_price: float = 0.0,
    ) -> None: ...
    def token_id(self, side: Side) -> str | None: ...

class Event:
    id: str
    name: str
    condition_id: str | None
    neg_risk: bool
    exchange: str
    outcomes: list[Outcome]
    expiry: str | None

    def __init__(
        self,
        id: str,
        name: str,
        outcomes: list[Outcome],
        neg_risk: bool = False,
        exchange: str = "polymarket",
        condition_id: str | None = None,
        expiry: str | None = None,
    ) -> None: ...
    def outcome_count(self) -> int: ...
    def outcome_names(self) -> list[str]: ...
    def outcome_by_name(self, name: str) -> Outcome | None: ...
    def to_markets(self) -> list[Market]: ...

class Quote:
    bid: float
    ask: float
    size: float

    def __init__(self, bid: float, ask: float, size: float) -> None: ...
    def spread(self) -> float: ...
    def mid(self) -> float: ...

class RiskConfig:
    max_position_per_market: float
    max_portfolio_notional: float
    max_daily_drawdown_pct: float
    max_order_size: float
    rate_limit_sustained: int
    rate_limit_burst: int
    dedup_window_ms: int
    max_position_per_event: float | None

    def __init__(
        self,
        max_position_per_market: float = 100.0,
        max_portfolio_notional: float = 1000.0,
        max_daily_drawdown_pct: float = 5.0,
        max_order_size: float = 50.0,
        rate_limit_sustained: int = 50,
        rate_limit_burst: int = 300,
        dedup_window_ms: int = 1000,
        max_position_per_event: float | None = None,
    ) -> None: ...

class OrderRequest:
    market_id: str
    side: Side
    order_side: OrderSide
    size: float
    price: float
    order_type: OrderType
    time_in_force: TimeInForce
    post_only: bool
    token_id: str | None
    neg_risk: bool

    def __init__(
        self,
        market_id: str,
        side: Side,
        order_side: OrderSide,
        size: float,
        price: float,
        order_type: OrderType = ...,
        time_in_force: TimeInForce = ...,
        post_only: bool = True,
        token_id: str | None = None,
        neg_risk: bool = False,
    ) -> None: ...

class Order:
    id: str
    market_id: str
    side: Side
    order_side: OrderSide
    price: float
    size: float
    filled_size: float
    remaining_size: float
    order_type: OrderType
    time_in_force: TimeInForce
    status: OrderStatus
    created_at: float
    status_reason: str | None
    exchange: str
    amendment_count: int

    def is_open(self) -> bool: ...

class Position:
    market_id: str
    side: Side
    size: float
    avg_entry_price: float
    realized_pnl: float
    unrealized_pnl: float
    token_id: str | None
    exchange: str

    def total_pnl(self) -> float: ...
    def notional(self) -> float: ...

class Fill:
    fill_id: str
    order_id: str
    market_id: str
    side: Side
    order_side: OrderSide
    price: float
    size: float
    fee: float
    timestamp: float
    token_id: str | None
    exchange: str

    def __init__(
        self,
        fill_id: str,
        order_id: str,
        market_id: str,
        side: Side,
        order_side: OrderSide,
        price: float,
        size: float,
        fee: float = 0.0,
        timestamp: float = 0.0,
        token_id: str | None = None,
        exchange: str = "",
    ) -> None: ...

class EngineStatus:
    running: bool
    kill_switch_active: bool
    kill_switch_reason: str | None
    open_orders: int
    active_positions: int
    total_realized_pnl: float
    total_unrealized_pnl: float
    daily_pnl: float
    uptime_secs: int

    def total_pnl(self) -> float: ...

class FeedSnapshot:
    price: float
    timestamp: float
    source: str
    bid: float
    ask: float
    volume_24h: float
    last_trade_size: float
    last_trade_is_buy: bool

    def __init__(
        self,
        price: float = 0.0,
        timestamp: float = 0.0,
        source: str = "",
        bid: float = 0.0,
        ask: float = 0.0,
        volume_24h: float = 0.0,
        last_trade_size: float = 0.0,
        last_trade_is_buy: bool = False,
    ) -> None: ...

class OrderbookSnapshot:
    timestamp: float
    source: str

    def __init__(self, timestamp: float = 0.0, source: str = "") -> None: ...
    def bids(self) -> list[tuple[float, float]]: ...
    def asks(self) -> list[tuple[float, float]]: ...
    def bid_depth_levels(self) -> int: ...
    def ask_depth_levels(self) -> int: ...
    def best_bid(self) -> tuple[float, float] | None: ...
    def best_ask(self) -> tuple[float, float] | None: ...
    def spread(self) -> float: ...
    def mid(self) -> float: ...
    def vwap_mid(self, levels: int = 5) -> float: ...
    def imbalance(self, levels: int = 5) -> float: ...
    def bid_depth(self, levels: int | None = None) -> float: ...
    def ask_depth(self, levels: int | None = None) -> float: ...
    def depth_within(self, price_range: float) -> tuple[float, float]: ...

class ContingentOrder:
    id: str
    trigger_type: TriggerType
    market_id: str
    side: Side
    order_side: OrderSide
    size: float
    trigger_price: float
    trigger_pnl: float | None
    linked_order_id: str | None
    exchange: str
    triggered: bool
    child_order_id: str | None

class ParityResult:
    market_id: str
    yes_price: float
    no_price: float
    deviation: float
    is_violation: bool
    exchange: str

class ArbitrageOpportunity:
    market_id: str
    buy_exchange: str
    sell_exchange: str
    buy_price: float
    sell_price: float
    raw_edge: float
    net_edge: float
    max_size: float
    is_executable: bool

class EventArbitrageOpportunity:
    event_id: str
    exchange: str
    price_sum: float
    overround: float
    direction: str
    net_edge: float
    is_executable: bool

# Kelly criterion functions (Rust, #[inline])
def kelly(prob: float, market_price: float) -> float: ...
def kelly_no(prob: float, market_price: float) -> float: ...
def fractional_kelly(prob: float, market_price: float, fraction: float) -> float: ...
def kelly_size(
    prob: float,
    market_price: float,
    bankroll: float,
    fraction: float,
    max_size: float,
) -> float: ...
def multi_kelly(probs: list[float], prices: list[float], max_total: float) -> list[float]: ...
def liquidity_adjusted_kelly(
    prob: float,
    market_price: float,
    bankroll: float,
    fraction: float,
    available_liquidity: float,
    max_size: float,
) -> float: ...
def edge(prob: float, market_price: float) -> float: ...

# Signal functions (Rust)
def combine_signals(
    signals: list[tuple[float, float]], method: str = "weighted_avg"
) -> float: ...
def ema(values: list[float], span: int) -> float: ...
def zscore(value: float, mean: float, std: float) -> float: ...
def decay_weight(age_secs: float, half_life_secs: float) -> float: ...

# Market making functions (Rust)
def reservation_price(
    mid: float, inventory: float, gamma: float, volatility: float, time_horizon: float
) -> float: ...
def optimal_spread(
    volatility: float, inventory: float, gamma: float, kappa: float, time_horizon: float
) -> float: ...
def competitive_spread(
    base_spread: float, book_spread: float, book_imbalance: float, aggression: float
) -> float: ...
def mm_size(
    base_size: float, inventory: float, max_position: float,
    fill_rate: float, skew_factor: float,
) -> tuple[float, float]: ...
def estimate_volatility(prices: list[float]) -> float: ...

# Monte Carlo simulation (Rust)
class SimPosition:
    market_id: str
    side: str
    size: float
    entry_price: float
    current_price: float

    def __init__(
        self,
        market_id: str,
        side: str,
        size: float,
        entry_price: float,
        current_price: float,
    ) -> None: ...

class SimulationResult:
    mean_pnl: float
    median_pnl: float
    std_dev: float
    var_95: float
    var_99: float
    cvar_95: float
    max_loss: float
    max_gain: float
    win_probability: float
    scenario_pnl: list[float]
    percentiles: list[tuple[float, float]]

def monte_carlo(
    positions: list[SimPosition],
    scenarios: int = 10000,
    correlation_matrix: list[list[float]] | None = None,
    seed: int | None = None,
) -> SimulationResult: ...

class FeedMetrics:
    update_count: int
    error_count: int
    last_update_time: float
    last_error: str
    is_connected: bool
    reconnect_count: int

class Engine:
    def __init__(
        self,
        risk_config: RiskConfig | None = None,
        paper_fee_rate: float = 0.001,
        exchange_type: str = "paper",
        exchange_key: str | None = None,
        exchange_secret: str | None = None,
        exchange_passphrase: str | None = None,
        clob_url: str | None = None,
        api_url: str | None = None,
        email: str | None = None,
        password: str | None = None,
        private_key: str | None = None,
        paper_partial_fill_ratio: float = 1.0,
        db_path: str | None = None,
        api_key: str | None = None,
        fill_model: str | None = None,
        fill_lambda: float = 1.0,
        fill_kappa: float = 1.5,
        fill_queue_position: float = 0.5,
        fill_intensity: float = 1.0,
        impact_temporary_bps: float = 0.0,
        impact_permanent_fraction: float = 0.0,
        latency_ticks: int = 0,
        rng_seed: int | None = None,
    ) -> None: ...
    # Multi-exchange management
    def add_exchange(
        self,
        exchange_type: str,
        exchange_key: str | None = None,
        exchange_secret: str | None = None,
        exchange_passphrase: str | None = None,
        clob_url: str | None = None,
        api_url: str | None = None,
        email: str | None = None,
        password: str | None = None,
        private_key: str | None = None,
        paper_fee_rate: float = 0.001,
        paper_partial_fill_ratio: float = 1.0,
    ) -> str: ...
    def exchange_names(self) -> list[str]: ...
    def exchange_count(self) -> int: ...
    def set_netting_pair(self, market_a: str, market_b: str) -> None: ...
    def netting_pairs(self) -> list[tuple[str, str]]: ...
    # Feeds
    def start_feed(
        self,
        name: str,
        feed_type: str,
        symbol: str = "",
        url: str = "",
        interval: float = 5.0,
        config_json: str = "",
    ) -> None: ...
    def feed_snapshot(self, name: str) -> FeedSnapshot | None: ...
    def all_feed_snapshots(self) -> dict[str, FeedSnapshot]: ...
    def stop_feeds(self) -> None: ...
    def feed_age(self, name: str) -> float | None: ...
    def feed_metrics(self, name: str) -> FeedMetrics | None: ...
    def all_feed_metrics(self) -> dict[str, FeedMetrics]: ...
    def stop_feed(self, name: str) -> None: ...
    def restart_feed(self, name: str) -> None: ...
    def is_feed_running(self, name: str) -> bool: ...
    # Order submission (with exchange routing)
    def submit_order(
        self, request: OrderRequest, exchange: str | None = None
    ) -> str: ...
    def submit_market_order(
        self,
        market_id: str,
        side: Side,
        order_side: OrderSide,
        size: float,
        token_id: str | None = None,
        neg_risk: bool = False,
        exchange: str | None = None,
    ) -> str: ...
    def submit_quotes(
        self,
        market_id: str,
        quotes: list[Quote],
        side: Side,
        token_id: str | None = None,
        neg_risk: bool = False,
        exchange: str | None = None,
    ) -> list[str]: ...
    # Order amendment
    def amend_order(
        self,
        order_id: str,
        new_price: float | None = None,
        new_size: float | None = None,
    ) -> str: ...
    # Cancel (cross-exchange)
    def cancel(self, order_id: str) -> None: ...
    def cancel_all(self) -> int: ...
    def cancel_market(self, market_id: str) -> int: ...
    # Tick / poll (cross-exchange)
    def tick(
        self, market_id: str, mid_price: float, exchange: str | None = None
    ) -> int: ...
    def poll_fills(self) -> int: ...
    def process_fill(self, fill: Fill) -> None: ...
    # Positions / Orders / Status
    def update_mark_price(
        self, market_id: str, side: Side, mark_price: float
    ) -> None: ...
    def open_orders(self) -> list[Order]: ...
    def open_orders_for_market(self, market_id: str) -> list[Order]: ...
    def positions(self) -> list[Position]: ...
    def positions_for_market(self, market_id: str) -> list[Position]: ...
    def recent_fills(self) -> list[Fill]: ...
    def status(self) -> EngineStatus: ...
    def reset_daily_pnl(self) -> None: ...
    # Contingent orders (stop-loss / take-profit)
    def add_stop_loss(
        self,
        market_id: str,
        side: Side,
        order_side: OrderSide,
        size: float,
        trigger_price: float,
        exchange: str | None = None,
    ) -> str: ...
    def add_take_profit(
        self,
        market_id: str,
        side: Side,
        order_side: OrderSide,
        size: float,
        trigger_price: float,
        trigger_pnl: float | None = None,
        exchange: str | None = None,
    ) -> str: ...
    def submit_bracket(
        self,
        request: OrderRequest,
        stop_trigger: float,
        take_profit_trigger: float,
        take_profit_pnl: float | None = None,
        exchange: str | None = None,
    ) -> tuple[str, str, str]: ...
    def check_contingent_triggers(
        self, market_id: str, current_price: float
    ) -> int: ...
    def cancel_contingent(self, contingent_id: str) -> bool: ...
    def pending_contingent_orders(self) -> list[ContingentOrder]: ...
    # Smart order routing
    def submit_order_smart(
        self, request: OrderRequest, fallback_exchange: str | None = None
    ) -> str: ...
    # Risk controls
    def activate_kill_switch(self, reason: str) -> None: ...
    def deactivate_kill_switch(self) -> None: ...
    def update_daily_pnl(self, pnl: float) -> None: ...
    def set_daily_baseline(self, baseline: float) -> None: ...
    # Exchange info
    def exchange_name(self) -> str: ...
    def sync_positions(self, exchange: str | None = None) -> int: ...
    def evict_stale_orders(self, max_age_secs: float = 300.0) -> int: ...
    # Persistence & Recovery
    def snapshot_positions(self) -> int: ...
    def recover_state(self) -> int: ...
    def start_run(self, strategy_name: str) -> None: ...
    def end_run(self) -> None: ...
    def db_run_id(self) -> str | None: ...
    def has_persistence(self) -> bool: ...
    def db_open_order_ids(self) -> list[str]: ...
    # Multi-outcome event management
    def register_event(self, event_id: str, market_ids: list[str]) -> None: ...
    def event_exposure(self, event_id: str) -> float: ...
    def event_positions(self, event_id: str) -> list[Position]: ...
    def event_parity_check(
        self, event_id: str, threshold: float = 0.02
    ) -> ParityResult | None: ...
    def market_event_id(self, market_id: str) -> str | None: ...
    def registered_events(self) -> dict[str, list[str]]: ...
    # Parity / Arbitrage
    def parity_check(
        self, market_id: str, threshold: float = 0.02, feed_name: str | None = None
    ) -> ParityResult | None: ...
    def scan_arbitrage(
        self,
        market_id: str,
        market_feed_map: list[tuple[str, str, float]],
        max_liquidity: float = 100.0,
    ) -> list[ArbitrageOpportunity]: ...
    # Market lifecycle management
    def set_market_expiry(self, market_id: str, expiry_ts: float) -> None: ...
    def set_lifecycle_lead_secs(self, secs: float) -> None: ...
    def check_lifecycle(self) -> list[str]: ...
    def market_expiries(self) -> dict[str, float]: ...
    def is_market_expired(self, market_id: str) -> bool: ...
    # L2 orderbook access
    def orderbook_snapshot(self, name: str) -> OrderbookSnapshot | None: ...
    def all_orderbook_snapshots(self) -> dict[str, OrderbookSnapshot]: ...
    # Historical tick storage
    def record_tick(self, feed_name: str, market_id: str) -> bool: ...
    def query_ticks(
        self,
        feed_name: str,
        start_ts: float,
        end_ts: float,
        limit: int = 10000,
    ) -> list[tuple[str, float, float, float, float, str, float]]: ...
    def tick_count(self, feed_name: str) -> int: ...
    def purge_old_ticks(self, max_age_secs: float) -> int: ...
    # Arbitrage execution
    # BookSim L2 book update
    def update_book(
        self,
        market_id: str,
        bids: list[tuple[float, float]],
        asks: list[tuple[float, float]],
        timestamp: float = 0.0,
        exchange: str | None = None,
    ) -> None: ...
    def execute_arbitrage(
        self,
        market_id: str,
        buy_exchange: str,
        sell_exchange: str,
        buy_price: float,
        sell_price: float,
        size: float,
        side: Side | None = None,
        token_id: str | None = None,
        neg_risk: bool = False,
    ) -> tuple[str, str]: ...

# Analytics (Rust)
class CalibrationResult:
    bins: list[tuple[float, float, int]]
    brier_score: float
    log_loss: float
    ece: float

class EdgeDecayResult:
    decay_curve: list[tuple[float, float]]
    half_life_hours: float

def calibration_curve(
    predictions: list[float],
    outcomes: list[float],
    n_bins: int = 10,
) -> CalibrationResult: ...

def log_loss(
    predictions: list[float],
    outcomes: list[float],
) -> float: ...

def edge_decay(
    entry_prices: list[float],
    outcomes: list[float],
    entry_ts: list[float],
    resolution_ts: list[float],
    n_buckets: int = 20,
) -> EdgeDecayResult: ...

# Data fetcher (Rust)
class HistoricalTrade:
    timestamp: float
    price: float
    size: float
    side: str
    market_id: str

class OHLCBar:
    timestamp: float
    open: float
    high: float
    low: float
    close: float
    volume: float

def fetch_polymarket_prices(
    token_id: str,
    start_ts: float,
    end_ts: float,
    fidelity: int = 60,
) -> list[OHLCBar]: ...

def fetch_polymarket_trades(
    token_id: str,
    limit: int = 1000,
) -> list[HistoricalTrade]: ...

def fetch_kalshi_book(ticker: str) -> OrderbookSnapshot: ...

# Markov regime detection (Rust HMM)
class MarkovRegimeModel:
    def __init__(self, n_states: int = 2) -> None: ...
    def fit(
        self,
        observations: list[float],
        max_iters: int = 100,
        tol: float = 1e-6,
    ) -> float: ...
    def decode(self, observations: list[float]) -> list[int]: ...
    def filter_step(self, observation: float) -> list[float]: ...
    def predict(self) -> list[float]: ...
    def smooth(self, observations: list[float]) -> list[list[float]]: ...
    def filtered_probs(self) -> list[float]: ...
    def reset_filter(self) -> None: ...
    def n_states(self) -> int: ...
    def transition_matrix(self) -> list[list[float]]: ...
    def emission_params(self) -> list[tuple[float, float]]: ...
    def current_regime(self) -> int: ...
    def is_trained(self) -> bool: ...

def prices_to_returns(prices: list[float]) -> list[float]: ...

# Quantitative analytics (Rust)

# Information theory
def shannon_entropy(p: float) -> float: ...
def joint_entropy(probs: list[float]) -> float: ...
def kl_divergence(p: list[float], q: list[float]) -> float: ...
def mutual_information(x: list[float], y: list[float], n_bins: int = 10) -> float: ...
def transfer_entropy(
    source: list[float], target: list[float], lag: int = 1, n_bins: int = 10
) -> float: ...

# Microstructure
def kyles_lambda(price_changes: list[float], signed_volumes: list[float]) -> float: ...
def amihud_ratio(returns: list[float], volumes: list[float]) -> float: ...
def roll_spread(returns: list[float]) -> float: ...
def effective_spread(fill_price: float, mid: float, is_buy: bool) -> float: ...
def realized_spread(fill_price: float, mid_after: float, is_buy: bool) -> float: ...
def lob_imbalance(
    bids: list[tuple[float, float]], asks: list[tuple[float, float]], levels: int = 5
) -> float: ...
def weighted_mid(
    bids: list[tuple[float, float]], asks: list[tuple[float, float]]
) -> float: ...

# Risk analytics
def cornish_fisher_var(returns: list[float], confidence: float = 0.95) -> float: ...
def cornish_fisher_cvar(returns: list[float], confidence: float = 0.95) -> float: ...

class PredictionGreeks:
    delta: float
    gamma: float
    theta: float
    vega: float

def prediction_greeks(
    price: float,
    size: float,
    is_yes: bool,
    t_hours: float = 24.0,
    vol: float = 0.2,
) -> PredictionGreeks: ...

# Signal analysis
def information_coefficient(
    predictions: list[float], outcomes: list[float]
) -> float: ...
def signal_half_life(values: list[float]) -> float: ...
def hurst_exponent(series: list[float]) -> float: ...
def variance_ratio(returns: list[float], period: int = 2) -> float: ...

# Statistical testing
def deflated_sharpe(
    sharpe: float, n_obs: int, n_trials: int, skew: float, kurt: float
) -> float: ...
def bonferroni_threshold(alpha: float, n_trials: int) -> float: ...
def benjamini_hochberg(p_values: list[float], alpha: float = 0.05) -> list[bool]: ...

# Streaming detectors
class VpinDetector:
    def __init__(self, bucket_volume: float = 1000.0, n_buckets: int = 50) -> None: ...
    def update(self, price: float, volume: float, is_buy: bool) -> float: ...
    def current_vpin(self) -> float: ...
    def reset(self) -> None: ...

class CusumDetector:
    def __init__(self, threshold: float = 5.0, drift: float = 0.0) -> None: ...
    def update(self, value: float) -> bool: ...
    def upper(self) -> float: ...
    def lower(self) -> float: ...
    def reset(self) -> None: ...

class OfiTracker:
    def __init__(self) -> None: ...
    def update(self, best_bid_qty: float, best_ask_qty: float) -> float: ...
    def cumulative(self) -> float: ...
    def reset(self) -> None: ...
