From 5abd1c340c735159b8a30d1791a7fb513e0da660 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=96=87=E8=96=87=E5=AE=89?= Date: Mon, 19 Jan 2026 22:49:24 +0800 Subject: [PATCH] a --- backend/api/routes/account.py | 48 ++++++++++++++++++++++++++++++++++- 1 file changed, 47 insertions(+), 1 deletion(-) diff --git a/backend/api/routes/account.py b/backend/api/routes/account.py index ad81a68..ba4818b 100644 --- a/backend/api/routes/account.py +++ b/backend/api/routes/account.py @@ -83,7 +83,13 @@ async def _ensure_exchange_sltp_for_symbol(symbol: str): open_trades = Trade.get_by_symbol(symbol, status='open') or [] if not open_trades: raise HTTPException(status_code=400, detail=f"{symbol} 数据库无 open 交易记录,无法确定止损止盈价") + # 尽量取最新一条 open trade(避免同一symbol多条 open 时取到旧记录) + try: + open_trades.sort(key=lambda x: int(x.get("id", 0) or 0), reverse=True) + except Exception: + pass trade = open_trades[0] + sl = trade.get("stop_loss_price") tp = trade.get("take_profit_2") or trade.get("take_profit_price") or trade.get("take_profit_1") try: @@ -94,8 +100,48 @@ async def _ensure_exchange_sltp_for_symbol(symbol: str): tp = float(tp) if tp is not None else None except Exception: tp = None + + # 兼容旧数据库:如果 trades 表还没迁移 stop_loss_price / take_profit_price 字段, + # 则回退用 entry_price/quantity/leverage + 配置的 STOP_LOSS_PERCENT/TAKE_PROFIT_PERCENT 计算。 if not sl or not tp: - raise HTTPException(status_code=400, detail=f"{symbol} 数据库缺少止损/止盈价,无法补挂") + try: + entry_price = float(trade.get("entry_price") or 0) + qty = float(trade.get("quantity") or 0) + lv = float(trade.get("leverage") or 0) or float(p0.get("leverage") or 0) or 10.0 + if entry_price <= 0 or qty <= 0 or lv <= 0: + raise ValueError("entry_price/quantity/leverage invalid") + + def _ratio(v, default): + try: + x = float(v) + # 兼容:若误存成 5(表示5%),则转为 0.05 + if x > 1: + x = x / 100.0 + if x < 0: + x = default + return x + except Exception: + return default + + sl_pct = _ratio(TradingConfig.get_value("STOP_LOSS_PERCENT", 0.05), 0.05) + tp_pct = _ratio(TradingConfig.get_value("TAKE_PROFIT_PERCENT", 0.15), 0.15) + + notional = entry_price * qty + margin = notional / lv + sl_amount = margin * sl_pct + tp_amount = margin * tp_pct + + if side == "BUY": + sl = entry_price - (sl_amount / qty) + tp = entry_price + (tp_amount / qty) + else: + sl = entry_price + (sl_amount / qty) + tp = entry_price - (tp_amount / qty) + + if not sl or not tp or sl <= 0 or tp <= 0: + raise ValueError("computed sl/tp invalid") + except Exception: + raise HTTPException(status_code=400, detail=f"{symbol} 数据库缺少止损/止盈价,且无法回退计算,无法补挂") # 5) 取消旧的保护单,避免重复 try: