From 9fceadcb2730a80028091de62de6787f60835ea7 Mon Sep 17 00:00:00 2001 From: aaron <> Date: Fri, 13 Mar 2026 23:47:44 +0800 Subject: [PATCH] update --- backend/app/config.py | 3 +- backend/app/services/paper_trading_service.py | 54 +++++++++++++++++-- frontend/trading.html | 20 ++++++- 3 files changed, 72 insertions(+), 5 deletions(-) diff --git a/backend/app/config.py b/backend/app/config.py index 3ca5c9a..4dca54f 100644 --- a/backend/app/config.py +++ b/backend/app/config.py @@ -130,7 +130,8 @@ class Settings(BaseSettings): # 模拟交易配置 paper_trading_enabled: bool = True # 是否启用模拟交易 paper_trading_initial_balance: float = 10000 # 初始本金 (USDT) - paper_trading_leverage: int = 20 # 杠杆倍数(全仓模式下的最大杠杆) + paper_trading_leverage: int = 20 # 单笔订单杠杆倍数 + paper_trading_max_total_leverage: float = 10 # 总杠杆上限(持仓+挂单,倍数) paper_trading_margin_per_order: float = 1000 # 每单保证金 (USDT) paper_trading_max_orders: int = 10 # 最大持仓+挂单总数 paper_trading_auto_close_opposite: bool = False # 是否自动平掉反向持仓(智能策略) diff --git a/backend/app/services/paper_trading_service.py b/backend/app/services/paper_trading_service.py index 0d29fa5..8549628 100644 --- a/backend/app/services/paper_trading_service.py +++ b/backend/app/services/paper_trading_service.py @@ -27,6 +27,7 @@ class PaperTradingService: self.max_orders = self.settings.paper_trading_max_orders # 最大订单数 self.auto_close_opposite = self.settings.paper_trading_auto_close_opposite # 是否自动平掉反向持仓 self.breakeven_threshold = self.settings.paper_trading_breakeven_threshold # 保本止损触发阈值 + self.max_total_leverage = self.settings.paper_trading_max_total_leverage # 总杠杆上限 # 移动止损配置 self.trailing_stop_enabled = self.settings.paper_trading_trailing_stop_enabled @@ -48,7 +49,8 @@ class PaperTradingService: # 加载活跃订单到内存 self._load_active_orders() - logger.info(f"交易服务初始化完成(自动平反向持仓: {'启用' if self.auto_close_opposite else '禁用'}," + logger.info(f"交易服务初始化完成(单笔杠杆: {self.leverage}x,总杠杆上限: {self.max_total_leverage}x," + f"自动平反向持仓: {'启用' if self.auto_close_opposite else '禁用'}," f"保本止损阈值: {self.breakeven_threshold}%," f"移动止损: {'启用' if self.trailing_stop_enabled else '禁用'}," f"触发倍数: {self.trailing_stop_threshold_multiplier}x," @@ -265,6 +267,46 @@ class PaperTradingService: result['message'] = msg return result + # === 检查总杠杆是否超限 === + # 计算当前已用保证金(持仓+挂单) + current_used_margin = len(self.active_orders) * self.margin_per_order + # 新订单增加的保证金 + new_margin = margin + # 新订单的总持仓价值 = 保证金 × 杠杆 + new_position_value = new_margin * self.leverage + # 新增后的总持仓价值 + new_total_position_value = (current_used_margin * self.leverage) + new_position_value + + # 获取当前账户余额 + db = db_service.get_session() + try: + closed_orders = db.query(PaperOrder).filter( + PaperOrder.status.in_([ + OrderStatus.CLOSED_TP, + OrderStatus.CLOSED_SL, + OrderStatus.CLOSED_BE, + OrderStatus.CLOSED_TS, + OrderStatus.CLOSED_MANUAL + ]) + ).all() + realized_pnl = sum(o.pnl_amount for o in closed_orders) + finally: + db.close() + + current_balance = self.initial_balance + realized_pnl + + # 计算新订单后的总杠杆 + new_total_leverage = new_total_position_value / current_balance if current_balance > 0 else 0 + + if new_total_leverage > self.max_total_leverage: + msg = f"总杠杆超限!当前 {new_total_leverage:.1f}x,上限 {self.max_total_leverage}x" + logger.info(f"{msg}: {symbol} | 当前持仓价值: ${current_used_margin * self.leverage:,.0f} | " + f"新订单持仓价值: ${new_position_value:,.0f} | 总持仓价值: ${new_total_position_value:,.0f} | " + f"账户余额: ${current_balance:,.0f}") + result['message'] = msg + return result + + logger.debug(f"总杠杆检查通过: {new_total_leverage:.1f}x / {self.max_total_leverage}x") quantity = round(position_value, 2) # 确保持仓价值保留2位小数 # 确定入场类型 @@ -1769,6 +1811,10 @@ class PaperTradingService: # 计算当前余额 current_balance = self.initial_balance + realized_pnl + # 计算当前总杠杆(持仓价值 / 账户余额) + total_position_value = used_margin * self.leverage + current_total_leverage = total_position_value / current_balance if current_balance > 0 else 0 + # 计算可用保证金 available_margin = current_balance - used_margin @@ -1782,12 +1828,14 @@ class PaperTradingService: 'used_margin': round(used_margin, 2), 'available': round(available_margin, 2), # 添加 available 字段,兼容性 'available_margin': round(available_margin, 2), - 'leverage': self.leverage, + 'leverage': self.leverage, # 单笔订单杠杆 + 'max_total_leverage': self.max_total_leverage, # 总杠杆上限 + 'current_total_leverage': round(current_total_leverage, 2), # 当前总杠杆 'margin_per_order': self.margin_per_order, 'active_orders': active_count, 'max_orders': self.max_orders, 'available_orders': available_orders, - 'total_position_value': round(used_margin * self.leverage, 2), + 'total_position_value': round(total_position_value, 2), 'margin_ratio': round((used_margin / current_balance * 100), 2) if current_balance > 0 else 0, 'max_drawdown': round(account_max_drawdown, 2), # 账户最大回撤百分比 'max_drawdown_amount': round(account_max_drawdown * self.initial_balance / 100, 2) if account_max_drawdown != 0 else 0, # 账户最大回撤金额 diff --git a/frontend/trading.html b/frontend/trading.html index 091a203..f3ae002 100644 --- a/frontend/trading.html +++ b/frontend/trading.html @@ -135,6 +135,10 @@ color: #ef4444; } + .stat-value.warning { + color: #f59e0b; /* 橙色警告 */ + } + /* 统计卡片内的正值/负值样式 */ .grade-card-stats .positive { color: var(--accent); @@ -1200,6 +1204,18 @@ ${{ account.current_balance?.toFixed(2) || '0.00' }} +
+
总仓位价值
+
+ ${{ account.total_position_value?.toFixed(2) || '0.00' }} +
+
+
+
总杠杆率
+
+ {{ account.current_total_leverage?.toFixed(1) || '0.0' }}x / {{ account.max_total_leverage }}x +
+
收益率
@@ -1701,7 +1717,9 @@ available_orders: 10, total_position_value: 0, margin_ratio: 0, - realized_pnl: 0 + realized_pnl: 0, + current_total_leverage: 0, // 当前总杠杆率 + max_total_leverage: 10 // 总杠杆上限 }, monitorRunning: false, latestPrices: {},