fix: hot-reload trade direction/whitelist on env save without forced restart.

EOF

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
dekun
2026-07-17 19:24:10 +08:00
parent b7966fd935
commit 4d381e9104
12 changed files with 111 additions and 15 deletions
+33
View File
@@ -93,6 +93,24 @@ HOT_RELOAD_EXACT = frozenset({
"HEDGE_PLAN_PARTIAL_AUTO_CLOSE_OPTION",
})
TRADE_POLICY_ENV_KEYS = frozenset({
"TRADE_DIRECTION_RESTRICT_ENABLED",
"TRADE_DIRECTION",
"TRADE_SYMBOL_RESTRICT_ENABLED",
"TRADE_SYMBOL_WHITELIST",
})
def normalize_trade_direction(raw: str) -> str:
s = (raw or "").strip().lower().replace("-", "_").replace(" ", "")
if s in ("long_only", "long", "longonly", "", "只多", "仅多", "做多"):
return "long_only"
if s in ("short_only", "short", "shortonly", "", "只空", "仅空", "做空"):
return "short_only"
if s in ("both", "双向", "多空", "all"):
return "both"
return (raw or "").strip()
SENSITIVE_EXACT = frozenset({
"APP_PASSWORD",
"FLASK_SECRET_KEY",
@@ -315,6 +333,14 @@ def validate_env_updates(groups: list[dict], updates: dict[str, str]) -> tuple[d
if val not in ("risk", "full_margin"):
errors.append("计仓模式须为 risk(以损定仓)或 full_margin(全仓杠杆)")
continue
if key == "TRADE_DIRECTION":
val = normalize_trade_direction(val)
if val not in ("long_only", "short_only", "both"):
errors.append("允许方向须为 long_only / short_only / both")
continue
if key == "TRADE_SYMBOL_RESTRICT_ENABLED":
# 开启白名单但名单为空时,后面统一补默认
pass
if ftype == "bool":
low = val.lower()
if low not in ("true", "false", "1", "0", "yes", "no", "on", "off"):
@@ -334,6 +360,13 @@ def validate_env_updates(groups: list[dict], updates: dict[str, str]) -> tuple[d
errors.append(f"{key} 须为整数")
continue
clean[key] = val
# 开启币种白名单且名单为空时,补默认 BTC,ETH,避免「开了等于没开」
if clean.get("TRADE_SYMBOL_RESTRICT_ENABLED") == "true":
wl = (clean.get("TRADE_SYMBOL_WHITELIST") or "").strip()
if not wl:
# 若本次没提交白名单,仍允许用已有 env;这里只在明确提交空串时补默认
if "TRADE_SYMBOL_WHITELIST" in (updates or {}):
clean["TRADE_SYMBOL_WHITELIST"] = "BTC,ETH"
return clean, errors