Harden strategy SoT: fail-closed funds gate, shared open pipeline, LIVE switch guards.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
dekun
2026-07-30 01:06:32 +08:00
parent 4c537e7520
commit 200702d066
14 changed files with 471 additions and 139 deletions
+50
View File
@@ -315,6 +315,32 @@ async def put_strategy_settings(
detail="有未平仓,无法切换永续保证金模式;请先平仓后再改",
)
# 持仓中禁止改动会影响本组成交/出场的参数(基线:运行中无人工开平仓,策略锁定本组成交)
if Matcher(db).has_open_position():
locked_keys = (
"net_profit_target",
"exit_mode",
"premium_exit_multiple",
"perp_qty_eth",
"option_qty_eth",
"leverage",
"sizing_mode",
"risk_perp_unit",
"risk_option_unit",
"risk_exit_unit",
"risk_loss_mode",
"risk_loss_pct",
"risk_loss_usdt",
"risk_capital_source",
"risk_manual_capital_usdt",
)
hit = [k for k in locked_keys if k in data]
if hit:
raise HTTPException(
status_code=409,
detail=f"有未平仓,禁止修改本组成交相关参数:{', '.join(hit)};请先平仓",
)
# 以损定仓 ↔ 手动仓位互斥;开启以损定仓时强制 fixed_usdt,并忽略手填名义/出场
sizing_mode = str(
data.get(
@@ -458,6 +484,12 @@ async def put_runtime_settings(
status_code=400,
detail="切换到 LIVE 须在 confirm_live_phrase 传入 LIVE",
)
secret = (s.auth_secret or "").strip()
if not secret or secret == "change-me-eth-hedge-sim-secret":
raise HTTPException(
status_code=400,
detail="切到 LIVE 前请在 .env 设置非默认 AUTH_SECRET",
)
updates: dict[str, str] = {}
if body.okx_api_key is not None and body.okx_api_key.strip():
@@ -495,6 +527,24 @@ async def put_runtime_settings(
detail="切到 LIVE 前请先配置完整币安 API Key/Secret",
)
# 热切 LIVE:强制暂停策略(对齐冷启动护栏;运行中禁止人工开平仓基线)
if new_mode == "LIVE" and cur_mode != "LIVE":
db.execute(
"UPDATE strategy_state SET running=0, phase=?, last_error=? WHERE id=1",
("paused", "已切换 LIVE,策略已强制暂停;确认就绪后再启动"),
)
try:
from ..strategy import get_engine
# 同步停循环标志(pause 为 async,此处只写状态)
get_engine()._set_state(
running=0,
phase="paused",
last_error="已切换 LIVE,策略已强制暂停;确认就绪后再启动",
)
except Exception:
pass
try:
from ..strategy import get_engine