Harden env save against empty numerics; default coin margin and hedge off.
Reject blank float/int/select on save and parse env with safe helpers so options config edits cannot crash into 502; default OKX_TRADE_MODE=options and OKX_OPTIONS_MARGIN_MODE=coin. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Vendored
+54
@@ -378,6 +378,32 @@ def validate_env_updates(groups: list[dict], updates: dict[str, str]) -> tuple[d
|
||||
allowed[field["key"]] = field
|
||||
clean: dict[str, str] = {}
|
||||
errors: list[str] = []
|
||||
|
||||
def _looks_numeric_key(k: str) -> bool:
|
||||
u = (k or "").upper()
|
||||
return any(
|
||||
s in u
|
||||
for s in (
|
||||
"_BUFFER",
|
||||
"_RATIO",
|
||||
"_PERCENT",
|
||||
"_SECONDS",
|
||||
"_HOURS",
|
||||
"_MINUTES",
|
||||
"_LIMIT",
|
||||
"_AMOUNT",
|
||||
"_BUDGET",
|
||||
"_CAP_",
|
||||
"_MAX_",
|
||||
"_MIN_",
|
||||
"LEVERAGE",
|
||||
"_DTE_",
|
||||
"_USDT",
|
||||
"_USDC",
|
||||
"RISK_PERCENT",
|
||||
)
|
||||
)
|
||||
|
||||
for key, value in (updates or {}).items():
|
||||
if key not in allowed:
|
||||
errors.append(f"未知配置项: {key}")
|
||||
@@ -392,6 +418,17 @@ def validate_env_updates(groups: list[dict], updates: dict[str, str]) -> tuple[d
|
||||
errors.append(f"{key} 长度异常,疑似自动填充;留空则不修改已有密钥")
|
||||
continue
|
||||
ftype = allowed[key].get("type")
|
||||
if val == "":
|
||||
# 空值写入会导致 float('') / int('') 启动崩溃(曾出现 502)
|
||||
if ftype in ("float", "int") or _looks_numeric_key(key):
|
||||
errors.append(f"{key} 不能为空,请填写数字")
|
||||
continue
|
||||
if ftype == "select" or key in SELECT_OPTIONS:
|
||||
errors.append(f"{key} 不能为空,请从下拉选择")
|
||||
continue
|
||||
if ftype == "bool":
|
||||
errors.append(f"{key} 不能为空,请选择 true/false")
|
||||
continue
|
||||
if ftype == "bool":
|
||||
low = val.lower()
|
||||
if low not in ("true", "false", "1", "0", "yes", "no", "on", "off"):
|
||||
@@ -412,6 +449,23 @@ def validate_env_updates(groups: list[dict], updates: dict[str, str]) -> tuple[d
|
||||
errors.append(f"{key} 须为: {labels}")
|
||||
continue
|
||||
val = norm
|
||||
elif ftype == "float" or (ftype != "int" and _looks_numeric_key(key) and "." in val):
|
||||
try:
|
||||
float(val)
|
||||
except ValueError:
|
||||
errors.append(f"{key} 须为数字")
|
||||
continue
|
||||
ftype = "float"
|
||||
elif ftype == "int" or _looks_numeric_key(key):
|
||||
try:
|
||||
# 允许 0.98 类缓冲写成 float 键名但值是 int 也可
|
||||
if "." in val:
|
||||
float(val)
|
||||
else:
|
||||
int(val)
|
||||
except ValueError:
|
||||
errors.append(f"{key} 须为数字")
|
||||
continue
|
||||
clean[key] = val
|
||||
return clean, errors
|
||||
|
||||
|
||||
Vendored
+4
-2
@@ -251,14 +251,16 @@ _RUNTIME_ENV_DEFAULTS: dict[str, str] = {
|
||||
"AUTO_TRANSFER_FROM": "funding",
|
||||
"AUTO_TRANSFER_TO": "swap",
|
||||
"TRANSFER_CCY": "USDT",
|
||||
"HEDGE_PLAN_SHOW_PERP_OPTIONS": "true",
|
||||
"HEDGE_PLAN_SHOW_OPTIONS_OPTIONS": "true",
|
||||
"HEDGE_PLAN_SHOW_PERP_OPTIONS": "false",
|
||||
"HEDGE_PLAN_SHOW_OPTIONS_OPTIONS": "false",
|
||||
"OKX_SHOW_PERP_FUNDS": "false",
|
||||
"OKX_OPTIONS_CHAIN_ASK_LIQ_FILTER_ENABLED": "true",
|
||||
"OKX_OPTIONS_CHAIN_MAX_DTE_DAYS": "14",
|
||||
"OKX_OPTIONS_MAX_DTE_DAYS": "2",
|
||||
"OKX_OPTIONS_MAX_ACTIVE_POSITIONS": "0",
|
||||
"OKX_OPTIONS_MARGIN_MODE": "coin",
|
||||
"OKX_TRADE_MODE": "options",
|
||||
"HEDGE_PLAN_ENABLED": "false",
|
||||
"MAX_ACTIVE_HEDGE_PLANS": "1",
|
||||
"HEDGE_PLAN_OO_CLOSE_MODE_ENABLED": "true",
|
||||
"HEDGE_PLAN_OO_BIAS_SPLIT_BY": "budget",
|
||||
|
||||
@@ -48,19 +48,10 @@ def normalize_okx_trade_mode(raw: Optional[str]) -> str:
|
||||
|
||||
|
||||
def legacy_infer_okx_trade_mode() -> str:
|
||||
"""未配置 OKX_TRADE_MODE 时,按旧开关推断,避免已有部署行为突变."""
|
||||
if not _env_bool("HEDGE_PLAN_ENABLED", False):
|
||||
return MODE_OPTIONS
|
||||
show_po = _env_bool("HEDGE_PLAN_SHOW_PERP_OPTIONS", True)
|
||||
show_oo = _env_bool("HEDGE_PLAN_SHOW_OPTIONS_OPTIONS", True)
|
||||
if show_po and not show_oo:
|
||||
return MODE_PERP
|
||||
if show_oo and not show_po:
|
||||
return MODE_OO
|
||||
if show_po:
|
||||
return MODE_PERP
|
||||
if show_oo:
|
||||
return MODE_OO
|
||||
"""未配置 OKX_TRADE_MODE 时默认单独期权(对冲关闭).
|
||||
|
||||
旧 HEDGE_PLAN_* 开关不再自动打开对冲,避免误开;需显式设 OKX_TRADE_MODE=options_options.
|
||||
"""
|
||||
return MODE_OPTIONS
|
||||
|
||||
|
||||
|
||||
@@ -34,9 +34,9 @@ def _env_bool(key: str, default: bool = False) -> bool:
|
||||
|
||||
def _env_float(key: str, default: float) -> float:
|
||||
try:
|
||||
return float(os.getenv(key, str(default)))
|
||||
return float(os.getenv(key) or default)
|
||||
except (TypeError, ValueError):
|
||||
return default
|
||||
return float(default)
|
||||
|
||||
|
||||
def attach_options_templates(app: Flask, repo_root: str) -> None:
|
||||
|
||||
Reference in New Issue
Block a user