from __future__ import annotations import os from dataclasses import dataclass from typing import Literal, cast TradingMode = Literal["schwab_live", "alpaca_paper", "tradier_live", "tradier_sandbox"] @dataclass(frozen=True) class TradingModeSettings: execution_mode: TradingMode = "alpaca_paper" @classmethod def from_env(cls, env: dict[str, str] | None = None) -> "TradingModeSettings": values = dict(os.environ) if env is not None: values.update(env) # BROKER=tradier swaps the execution client, so the default mode label # must follow it — else the Tradier stack reports "alpaca_paper". if values.get("BROKER", "alpaca").strip().lower() == "tradier": sandbox = values.get("TRADIER_ENV", "sandbox").strip().lower() != "live" default = "tradier_sandbox" if sandbox else "tradier_live" else: default = "alpaca_paper" mode = values.get("TRADING_EXECUTION_MODE", default) if mode not in {"schwab_live", "alpaca_paper", "tradier_live", "tradier_sandbox"}: mode = default return cls(execution_mode=cast(TradingMode, mode))