from __future__ import annotations from functools import lru_cache from pydantic_settings import BaseSettings, SettingsConfigDict class Settings(BaseSettings): model_config = SettingsConfigDict( env_file=(".env", "../.env"), env_file_encoding="utf-8", extra="ignore", ) mode: str = "SIM" tz: str = "Asia/Shanghai" env_name: str = "test" # test / prod exchange: str = "okx" # okx | binance(币安占位) api_host: str = "0.0.0.0" api_port: int = 5155 # Web 登录(仅本机 .env,勿提交真密码) auth_username: str = "admin" auth_password: str = "admin123" auth_secret: str = "change-me-eth-hedge-sim-secret" auth_token_ttl_sec: int = 60 * 60 * 24 * 7 auth_token_version: int = 1 # 改密时递增,作废旧 token disable_api_docs: bool = True # 生产默认关闭 /docs login_max_attempts: int = 8 login_window_sec: int = 300 okx_api_key: str = "" okx_api_secret: str = "" okx_api_passphrase: str = "" okx_rest_base: str = "https://www.okx.com" okx_ws_public: str = "wss://ws.okx.com:8443/ws/v5/public" okx_http_proxy: str = "" # 币安私有交易密钥(LIVE 真下单:fapi 永续 + eapi 期权) binance_api_key: str = "" binance_api_secret: str = "" # 币安公共行情(SIM 只读) binance_fapi_base: str = "https://fapi.binance.com" binance_eapi_base: str = "https://eapi.binance.com" binance_futures_ws: str = "wss://fstream.binance.com/stream" # 欧式期权公共流(2025-12 起):/public/stream;旧 nbstream/eoptions 已 404 binance_options_ws: str = "wss://fstream.binance.com/public/stream" binance_http_proxy: str = "" perp_inst_id: str = "ETH-USDT-SWAP" option_inst_family: str = "ETH-USD_UM" index_inst_id: str = "ETH-USD" option_ct_mult_default: float = 0.01 fee_rate: float = 0.0005 initial_equity: float = 10_000.0 # SIM 模拟初始资金(USDT),设置页可改 max_rounds: int = 3 # 已不再强管控,仅兼容旧字段 open_hhmm: str = "16:00" # 已废弃开仓窗 stop_open_hhmm: str = "08:00" # 已废弃开仓窗 exit_move_points: float = 30.0 # 旧字段,已废弃 exit_move_pct: float = 2.0 # 旧字段,已废弃(改用净盈利出场) exit_mode: str = "fixed_usdt" # fixed_usdt | premium_multiple net_profit_target: float = 15.0 # fixed_usdt:净盈利 ≥ 该值(USDT) premium_exit_multiple: float = 1.0 # premium_multiple:净盈利 ≥ 权利金×倍数 rest_seconds: int = 300 live_order_interval_sec: float = 1.0 # LIVE 私有下单/查单最小间隔(秒) skip_weekends: bool = True # 上海时区周六日禁止新开仓(已有仓仍可平) # 每个到期只开一次(跨日):历史上已开过某 expiry_ymd 后不可再开同到期,只能盯下一档 one_expiry_per_day: bool = True leverage: float = 3.0 # 永续杠杆 # 永续保证金模式:cross=全仓(默认)| isolated=逐仓;期权仍固定 cash(OKX 逐仓/现金) perp_margin_mode: str = "cross" min_option_hours: float = 12.0 # 期权最小剩余小时 min_option_leverage: float = 100.0 # 现价/卖一权利金 下限 # 以损定仓权利金口径:actual=盘口卖一;selection=指数/选约杠杆(控节奏,默认) risk_leverage_basis: str = "selection" # 倍投:默认关;仅以损定仓+亏损幅度%且基础幅度≤3% 可开 martingale_enabled: bool = False martingale_start_after_loss_days: int = 2 # 连续亏损 N 天后开始翻倍 martingale_max_doubles: int = 3 # 最多翻倍次数(如 2→4→8→16 为 3 次) # 对冲模式:perp_option=永期(默认)| option_option=期期 hedge_mode: str = "perp_option" oo_amplitude_pct: float = 1.5 # 振幅最大 %(过滤开启时:超过则不开) oo_amplitude_hours: float = 12.0 # 振幅回看小时(选约高低点;过滤关也用) oo_amplitude_filter_enabled: bool = False # 振幅过滤开关(默认关) oo_min_option_hours: float = 24.0 # 期期:最短剩余到期小时 oo_min_leverage: float = 200.0 # 期期:单腿最低杠杆 oo_reward_ratio: float = 2.0 # 盈亏比:出场目标 = 预算 × 比 oo_budget_cushion: float = 0.92 # 定仓预留余地(用于权利金的预算比例) oo_strike_max_dev_pct: float = 1.0 # 虚值行权价相对振幅高低点最大偏离 % atm_open_offset_enabled: bool = False # 开仓 ATM 偏差限制开关(默认关) max_atm_open_offset: float = 3.0 # 开启后:|ATM行权价−标的| 上限(点) # 固定方向:关=现有 ATM/比价规则;开=指定永续多/空,期权 Put/Call 且须实值或平值 fixed_direction_enabled: bool = False fixed_perp_side: str = "long" # long|short;long→买Put,short→买Call # 半自动:系统设置开关;首页授权后盯开盯平,平完停 semi_auto_enabled: bool = False semi_armed: bool = False # 是否已授权本单(平完清零) semi_view_side: str = "long" # long=买Call+永续空;short=买Put+永续多 semi_option_move_points: float = 50.0 # 顺方向:标的波动点数 semi_perp_exit_unit: float = 5.0 # 净利出场基数(×k) semi_min_option_hours: float = 30.0 semi_min_option_leverage: float = 200.0 # 虚值默认 200(虚值门仍强制≥180) semi_moneyness: str = "otm" # itm|atm|otm semi_otm_max_offset: float = 25.0 # 虚值 |K−S| 上限(可配) semi_perp_unit: float = 1.0 # 半自动永续:期权 配比分子 semi_option_unit: float = 4.0 # 配比分母,默认 1:4 close_bid_mark_max_pct: float = 30.0 # 平仓:买一相对标记最大偏差% # 残留期权中途平:当前买一权利金 ≥ 初始权利金 × 该% 才尝试卖出 residual_min_premium_pct: float = 20.0 residual_close_check_sec: int = 300 # 残留巡检间隔(秒) perp_qty_eth: float = 1.0 option_qty_eth: float = 2.0 db_path: str = "" # empty -> backend/data/hedge.db # 企业微信群机器人 wecom_enabled: bool = False wecom_webhook_url: str = "" wecom_machine_name: str = "" @property def is_sim(self) -> bool: return self.mode.strip().upper() != "LIVE" # 切换交易所时的合约默认 EXCHANGE_MARKET_DEFAULTS: dict[str, dict[str, str | float]] = { "okx": { "perp_inst_id": "ETH-USDT-SWAP", "option_inst_family": "ETH-USD_UM", "index_inst_id": "ETH-USD", "option_ct_mult_default": 0.01, }, "binance": { "perp_inst_id": "ETHUSDT", "option_inst_family": "ETHUSDT", "index_inst_id": "ETHUSDT", "option_ct_mult_default": 1.0, }, } @lru_cache def get_settings() -> Settings: return Settings()