0f552eb50e
Enable in settings (default off): after N consecutive loss days, double the effective risk_loss_pct up to a configurable max; blocked when base pct > 3%. Co-authored-by: Cursor <cursoragent@cursor.com>
126 lines
5.2 KiB
Python
126 lines
5.2 KiB
Python
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 次)
|
||
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
|
||
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()
|