from typing import List, Tuple, Optional, Dict, Any, Union, Callable

__version__: str

class IbkrBroker:
    def __init__(self, host: str, port: int, client_id: int) -> None: ...
    def connect(self) -> None: ...
    def disconnect(self) -> None: ...
    def positions(self) -> List[Dict[str, Any]]: ...
    def account(self) -> Dict[str, Any]: ...
    def submit_order(self, symbol: str, side: str, quantity: int, order_type: str = "market", limit_price_cents: Optional[int] = None) -> int: ...
    def order_status(self, order_id: int) -> Dict[str, Any]: ...
    def cancel_order(self, order_id: int) -> None: ...
    def quote(self, symbol: str) -> Dict[str, Any]: ...

class BinanceBroker:
    def __init__(self, api_key: str, secret_key: str, testnet: bool = False, quote_asset: str = "USDT") -> None: ...
    def connect(self) -> None: ...
    def disconnect(self) -> None: ...
    def positions(self) -> List[Dict[str, Any]]: ...
    def account(self) -> Dict[str, Any]: ...
    def submit_order(self, symbol: str, side: str, quantity: int, order_type: str = "market", limit_price_cents: Optional[int] = None) -> int: ...
    def order_status(self, order_id: int) -> Dict[str, Any]: ...
    def cancel_order(self, order_id: int) -> None: ...
    def quote(self, symbol: str) -> Dict[str, Any]: ...

class RiskEngine:
    def __init__(self, max_position_pct: float = 0.25, max_leverage: float = 1.5, max_drawdown_pct: float = 0.20, allow_short: bool = True, max_short_pct: float = 0.30, max_trade_usd: float = 100_000.0) -> None: ...
    def check_order(self, symbol: str, side: str, quantity: int, price_cents: int, equity_cents: int, positions: List[Tuple[str, int]]) -> List[Dict[str, Any]]: ...
    def check_batch(self, orders: List[Tuple[str, str, int, int]], equity_cents: int, positions: List[Tuple[str, int]], target_weights: List[Tuple[str, float]]) -> List[Dict[str, Any]]: ...

class Order:
    id: int
    side: str
    price: int
    original_quantity: int
    remaining_quantity: int
    filled_quantity: int
    status: str
    time_in_force: str
    timestamp: int

class Position:
    symbol: str
    quantity: int
    avg_entry_price: int
    total_cost: int
    realized_pnl: int
    def unrealized_pnl(self, price: int) -> int: ...

class Event:
    kind: str
    def __getstate__(self) -> str: ...
    def __setstate__(self, state: str) -> None: ...

class Trade:
    trade_id: int
    price: int
    quantity: int
    aggressor_side: str
    aggressor_order_id: int
    passive_order_id: int
    timestamp: int
    @property
    def price_float(self) -> float: ...

class LevelSnapshot:
    price: int
    quantity: int
    order_count: int
    @property
    def price_float(self) -> float: ...

class BookSnapshot:
    @property
    def bids(self) -> List[LevelSnapshot]: ...
    @property
    def asks(self) -> List[LevelSnapshot]: ...
    def imbalance(self) -> Optional[float]: ...
    def weighted_mid(self) -> Optional[float]: ...
    def mid_price(self) -> Optional[float]: ...
    def spread(self) -> Optional[int]: ...

class SubmitResult:
    order_id: int
    status: str
    filled_quantity: int
    resting_quantity: int
    cancelled_quantity: int
    @property
    def trades(self) -> List[Trade]: ...

class CancelResult:
    success: bool
    cancelled_quantity: int
    error: Optional[str]

class ModifyResult:
    success: bool
    old_order_id: int
    new_order_id: Optional[int]
    cancelled_quantity: int
    error: Optional[str]
    @property
    def trades(self) -> List[Trade]: ...

class StopSubmitResult:
    order_id: int
    status: str

class Metrics:
    total_return: float
    cagr: float
    volatility: float
    sharpe: float
    sortino: float
    max_drawdown: float
    calmar: float
    num_periods: int
    winning_periods: int
    losing_periods: int
    cvar_95: float
    win_rate: float
    profit_factor: float
    payoff_ratio: float
    kelly: float

class BacktestResult:
    portfolio: 'Portfolio'
    metrics: Optional[Metrics]

class CostModel:
    def __init__(self, commission_bps: int = 0, slippage_bps: int = 0, min_trade_fee: int = 0) -> None: ...
    @staticmethod
    def zero() -> 'CostModel': ...
    def compute_cost(self, notional: int) -> int: ...

class Portfolio:
    def __init__(self, initial_cash: int, cost_model: CostModel) -> None: ...
    @property
    def cash(self) -> int: ...
    def position(self, symbol: str) -> Optional[Position]: ...
    def positions(self) -> Dict[str, Position]: ...
    def total_equity(self, prices: List[Tuple[str, int]]) -> int: ...
    def current_weights(self, prices: List[Tuple[str, int]]) -> List[Tuple[str, float]]: ...
    def returns(self) -> List[float]: ...
    def equity_curve(self) -> List[int]: ...
    def rebalance_simple(self, targets: List[Tuple[str, float]], prices: List[Tuple[str, int]]) -> None: ...
    def rebalance_lob(self, targets: List[Tuple[str, float]], exchanges: 'MultiExchange') -> None: ...
    def record_return(self, prices: List[Tuple[str, int]]) -> None: ...
    def snapshot(self, prices: List[Tuple[str, int]]) -> Dict[str, Any]: ...
    def compute_metrics(self, periods_per_year: float, risk_free: float) -> Optional[Metrics]: ...
    def save_json(self, path: str) -> None: ...
    @staticmethod
    def load_json(path: str) -> 'Portfolio': ...

class Exchange:
    def __init__(self) -> None: ...
    @staticmethod
    def replay(events: List[Event]) -> 'Exchange': ...
    def submit_limit(self, side: str, price: int, quantity: int, tif: str = "gtc") -> SubmitResult: ...
    def submit_market(self, side: str, quantity: int) -> SubmitResult: ...
    def cancel(self, order_id: int) -> CancelResult: ...
    def modify(self, order_id: int, new_price: int, new_quantity: int) -> ModifyResult: ...
    def submit_stop_market(self, side: str, stop_price: int, quantity: int) -> StopSubmitResult: ...
    def submit_stop_limit(self, side: str, stop_price: int, limit_price: int, quantity: int, tif: str = "gtc") -> StopSubmitResult: ...
    def submit_trailing_stop_market(self, side: str, initial_stop_price: int, quantity: int, trail_type: str, trail_value: float, atr_period: Optional[int] = None) -> StopSubmitResult: ...
    def submit_trailing_stop_limit(self, side: str, initial_stop_price: int, limit_price: int, quantity: int, trail_type: str, trail_value: float, tif: str = "gtc", atr_period: Optional[int] = None) -> StopSubmitResult: ...
    def get_order(self, order_id: int) -> Optional[Order]: ...
    def get_stop_order(self, order_id: int) -> Optional[Dict[str, Any]]: ...
    def best_bid_ask(self) -> Tuple[Optional[int], Optional[int]]: ...
    def best_bid(self) -> Optional[int]: ...
    def best_ask(self) -> Optional[int]: ...
    def spread(self) -> Optional[int]: ...
    def last_trade_price(self) -> Optional[int]: ...
    def trades(self) -> List[Trade]: ...
    def events(self) -> List[Event]: ...
    def depth(self, levels: int = 10) -> BookSnapshot: ...
    def full_book(self) -> BookSnapshot: ...
    def pending_stop_count(self) -> int: ...
    def clear_trades(self) -> None: ...
    def clear_order_history(self) -> int: ...
    def compact(self) -> None: ...

class MultiExchange:
    def __init__(self) -> None: ...
    def get_or_create(self, symbol: str) -> Exchange: ...
    def symbols(self) -> List[str]: ...
    def best_prices(self) -> List[Tuple[str, Optional[int], Optional[int]]]: ...
    def submit_limit(self, symbol: str, side: str, price: int, quantity: int, tif: str = "gtc") -> SubmitResult: ...
    def submit_market(self, symbol: str, side: str, quantity: int) -> SubmitResult: ...
    def cancel(self, symbol: str, order_id: int) -> CancelResult: ...
    def modify(self, symbol: str, order_id: int, new_price: int, new_quantity: int) -> ModifyResult: ...
    def len(self) -> int: ...

def compute_metrics(returns: List[float], periods_per_year: float = 252.0, risk_free: float = 0.0) -> Optional[Metrics]: ...
def sweep_equal_weight(price_series: List[List[Tuple[str, int]]], initial_cash: int, cost_model: CostModel, periods_per_year: float = 252.0, risk_free: float = 0.0) -> BacktestResult: ...
def run_backtest(strategy: Callable[[int, Dict[str, int], Portfolio], List[Tuple[str, float]]], price_series: List[Dict[str, int]], initial_cash: int, cost_model: CostModel, periods_per_year: float = 252.0, risk_free: float = 0.0) -> BacktestResult: ...
def parse_itch(path: str) -> List[Tuple[str, Event]]: ...
def py_backtest_weights(weight_schedule: List[List[Tuple[str, float]]], price_schedule: List[List[Tuple[str, int]]], initial_cash: int, cost_bps: int, periods_per_year: float = 252.0, risk_free: float = 0.0, stop_cfg: Optional[Dict[str, Any]] = None) -> Dict[str, Any]: ...

# v0.8 — Technical indicators (ta-lib replacements)
def py_rsi(close: List[float], period: int) -> List[float]: ...
def py_macd(close: List[float], fast_period: int, slow_period: int, signal_period: int) -> Tuple[List[float], List[float], List[float]]: ...
def py_bbands(close: List[float], period: int, num_std_up: float, num_std_dn: float) -> Tuple[List[float], List[float], List[float]]: ...
def py_atr(high: List[float], low: List[float], close: List[float], period: int) -> List[float]: ...

# v0.8 — Statistics (scipy replacements)
def py_spearman(x: List[float], y: List[float]) -> Tuple[float, float]: ...
def py_quintile_spread(scores: List[float], returns: List[float], n_quantiles: int) -> float: ...

# v0.8 — Cross-validation (sklearn replacement)
def py_time_series_split(n_samples: int, n_splits: int) -> List[Tuple[List[int], List[int]]]: ...

# v0.8 — Rolling metrics (quantstats replacements)
def py_rolling_sharpe(returns: List[float], window: int, periods_per_year: int = 252) -> List[float]: ...
def py_rolling_volatility(returns: List[float], window: int, periods_per_year: int = 252) -> List[float]: ...

# v0.9 — Capability probing and advanced compute APIs
def py_capabilities() -> List[str]: ...
def py_garch_forecast(returns: List[float], p: int = 1, q: int = 1, mean: str = "zero") -> float: ...
def py_optimize_min_variance(returns_matrix: List[List[float]], symbols: List[str]) -> Dict[str, float]: ...
def py_optimize_max_sharpe(returns_matrix: List[List[float]], symbols: List[str], risk_free: float = 0.0) -> Dict[str, float]: ...
def py_optimize_risk_parity(returns_matrix: List[List[float]], symbols: List[str]) -> Dict[str, float]: ...
def py_optimize_cvar(returns_matrix: List[List[float]], symbols: List[str], alpha: float = 0.95) -> Dict[str, float]: ...
def py_optimize_cdar(returns_matrix: List[List[float]], symbols: List[str], alpha: float = 0.95) -> Dict[str, float]: ...

# v0.9 — Clean aliases (preferred for new callers)
def capabilities() -> List[str]: ...
def backtest_weights(weight_schedule: List[List[Tuple[str, float]]], price_schedule: List[List[Tuple[str, int]]], initial_cash: int, cost_bps: int, periods_per_year: float = 252.0, risk_free: float = 0.0, stop_cfg: Optional[Dict[str, Any]] = None) -> Dict[str, Any]: ...
def garch_forecast(returns: List[float], p: int = 1, q: int = 1, mean: str = "zero") -> float: ...
def optimize_min_variance(returns_matrix: List[List[float]], symbols: List[str]) -> Dict[str, float]: ...
def optimize_max_sharpe(returns_matrix: List[List[float]], symbols: List[str], risk_free: float = 0.0) -> Dict[str, float]: ...
def optimize_risk_parity(returns_matrix: List[List[float]], symbols: List[str]) -> Dict[str, float]: ...
def optimize_cvar(returns_matrix: List[List[float]], symbols: List[str], alpha: float = 0.95) -> Dict[str, float]: ...
def optimize_cdar(returns_matrix: List[List[float]], symbols: List[str], alpha: float = 0.95) -> Dict[str, float]: ...
