From b95040a2823089b16e5e32bb4f16269db37f7e20 Mon Sep 17 00:00:00 2001 From: aaron <> Date: Mon, 23 Feb 2026 12:17:40 +0800 Subject: [PATCH] 1 --- backend/app/crypto_agent/crypto_agent.py | 6 +- .../app/crypto_agent/llm_signal_analyzer.py | 15 ++- backend/app/services/real_trading_service.py | 114 +++++++++++++++++- 3 files changed, 125 insertions(+), 10 deletions(-) diff --git a/backend/app/crypto_agent/crypto_agent.py b/backend/app/crypto_agent/crypto_agent.py index 44fcf81..8b24ec7 100644 --- a/backend/app/crypto_agent/crypto_agent.py +++ b/backend/app/crypto_agent/crypto_agent.py @@ -405,7 +405,11 @@ class CryptoAgent: return # 获取当前持仓信息(供 LLM 仓位决策) - position_info = self.paper_trading.get_position_info() + # 优先使用实盘持仓信息(如果实盘交易启用),否则使用模拟盘持仓 + if self.real_trading and self.real_trading.get_auto_trading_status(): + position_info = self.real_trading.get_position_info_for_llm() + else: + position_info = self.paper_trading.get_position_info() # 2. LLM 分析(包含新闻舆情和持仓信息) logger.info(f"\n🤖 【LLM 分析中...】") diff --git a/backend/app/crypto_agent/llm_signal_analyzer.py b/backend/app/crypto_agent/llm_signal_analyzer.py index 563e50e..9db8c64 100644 --- a/backend/app/crypto_agent/llm_signal_analyzer.py +++ b/backend/app/crypto_agent/llm_signal_analyzer.py @@ -172,15 +172,20 @@ class LLMSignalAnalyzer: - **C级**(40-59):有机会但量价不够理想 - **D级**(<40):量价背离或信号矛盾 -## 七、仓位管理(重要) +## 七、仓位管理(重要 - 全仓模式) 你需要根据信号质量和当前持仓情况,建议合适的仓位大小。 +### 全仓模式说明 +- **全仓模式**:所有持仓共享账户保证金,总杠杆 = 总持仓价值 / 账户余额 +- **杠杆限制**:总杠杆永远不得超过 20 倍(硬性限制) +- **风险集中**:所有仓位共享风险,需要更加谨慎 + ### 仓位等级 - **heavy**(重仓):机会极佳,建议使用较大仓位 - **medium**(中仓):机会不错,建议使用中等仓位 - **light**(轻仓):机会一般或风险较高,建议轻仓试探 -### 仓位决策规则 +### 仓位决策规则(必须参考持仓信息) 1. **A级信号**:可建议 heavy 或 medium 2. **B级信号**:建议 medium 或 light 3. **C级信号**:只能建议 light @@ -189,9 +194,11 @@ class LLMSignalAnalyzer: 6. **市场波动剧烈时**:仓位应保守 ### 安全底线(必须遵守) -- 总杠杆永远不得超过 20 倍 -- 单一交易对持仓不宜过大 +- **总杠杆永远不得超过 20 倍**(这是硬性限制) +- 如果当前杠杆已经接近 20 倍,即使有好机会也必须降低仓位或跳过 +- 单一交易对持仓不宜过大(建议不超过总资金的 30%) - 如果当前持仓已经较重,即使有好机会也要控制仓位 +- **必须参考当前持仓和挂单信息**:系统会提供账户余额、当前杠杆、可用杠杆空间等信息 ## 八、止损止盈策略(重要更新) diff --git a/backend/app/services/real_trading_service.py b/backend/app/services/real_trading_service.py index 15320c6..358db0c 100644 --- a/backend/app/services/real_trading_service.py +++ b/backend/app/services/real_trading_service.py @@ -148,6 +148,82 @@ class RealTradingService: finally: db.close() + def get_position_info_for_llm(self) -> Dict[str, Any]: + """ + 获取当前持仓信息供 LLM 分析参考 + + Returns: + 持仓信息字典,包含账户余额、持仓列表、当前杠杆等 + """ + try: + # 获取账户状态 + account = self.get_account_status() + balance = account.get('current_balance', 0) + total_position_value = account.get('total_position_value', 0) + used_margin = account.get('used_margin', 0) + available = account.get('available', 0) + + # 计算当前杠杆倍数(全仓模式) + current_leverage = (total_position_value / balance) if balance > 0 else 0 + + # 获取所有活跃持仓(本地记录) + positions = [] + for order in self.active_orders.values(): + if order.status in [OrderStatus.OPEN, OrderStatus.PENDING]: + positions.append({ + 'order_id': order.order_id, + 'symbol': order.symbol, + 'side': 'long' if order.side == OrderSide.LONG else 'short', + 'status': order.status.value, + 'entry_price': order.filled_price or order.entry_price, + 'quantity': order.quantity, + 'pnl_percent': order.pnl_percent or 0, + 'leverage': order.leverage + }) + + # 从交易所获取最新的持仓数据 + exchange_positions = [] + try: + if self.trading_api: + exchange_pos_list = self.trading_api.get_position() + for pos in exchange_pos_list: + contracts = float(pos.get('contracts', 0)) + if contracts != 0: + exchange_positions.append({ + 'symbol': pos.get('symbol'), + 'side': 'long' if pos.get('side') == 'long' else 'short', + 'contracts': contracts, + 'entryPrice': pos.get('entryPrice'), + 'markPrice': pos.get('markPrice'), + 'unrealizedPnl': pos.get('unrealizedPnl', 0), + 'leverage': pos.get('leverage', 1) + }) + except Exception as e: + logger.warning(f"获取交易所持仓失败: {e}") + + return { + 'account_balance': balance, + 'available': available, + 'total_position_value': total_position_value, + 'used_margin': used_margin, + 'current_leverage': current_leverage, + 'max_leverage': 20, # 全仓模式最大 20 倍杠杆 + 'positions': positions, + 'exchange_positions': exchange_positions + } + except Exception as e: + logger.error(f"获取持仓信息失败: {e}") + import traceback + logger.error(traceback.format_exc()) + return { + 'account_balance': 0, + 'total_position_value': 0, + 'current_leverage': 0, + 'max_leverage': 20, + 'positions': [], + 'exchange_positions': [] + } + def create_order_from_signal(self, signal: Dict[str, Any], current_price: float = None) -> Dict[str, Any]: """ 从信号创建实盘订单(集成 LLM 仓位管理) @@ -254,11 +330,23 @@ class RealTradingService: } # === 使用 LLM 建议的仓位大小计算仓位 === - # 实盘使用更保守的比例配置 + # 全仓模式:总杠杆不超过 20 倍 + # 检查当前杠杆,确保加仓后不超过 20 倍 + current_leverage = (total_position_value / balance) if balance > 0 else 0 + max_total_leverage = 20 # 全仓模式最大 20 倍 + available_leverage = max_total_leverage - current_leverage + + if available_leverage <= 0: + return { + 'success': False, + 'message': f'当前杠杆已达 {current_leverage:.1f}x,已超最大限制 {max_total_leverage}x,无法开仓' + } + + # 根据可用杠杆空间动态调整仓位比例 custom_ratios = { - 'heavy': 0.15, # 激进方案:heavy 15%(模拟盘是 30%) - 'medium': 0.08, # 激进方案:medium 8%(模拟盘是 15%) - 'light': 0.03 # 激进方案:light 3%(模拟盘是 5%) + 'heavy': 0.12, # heavy: 12% 可用杠杆空间 + 'medium': 0.06, # medium: 6% 可用杠杆空间 + 'light': 0.03 # light: 3% 可用杠杆空间 } # 计算仓位(使用统一的仓位管理器) @@ -268,7 +356,7 @@ class RealTradingService: total_position_value=total_position_value, position_size=position_size, symbol=symbol, - max_leverage=self.default_leverage, + max_leverage=int(available_leverage), # 使用可用杠杆空间 custom_ratios=custom_ratios ) @@ -278,6 +366,22 @@ class RealTradingService: 'message': '无法开仓:仓位计算失败或已达杠杆限制' } + # 再次验证:加仓后的总杠杆不超过 20 倍 + new_total_value = total_position_value + position_value + new_leverage = new_total_value / balance if balance > 0 else 0 + if new_leverage > max_total_leverage: + # 调整仓位大小到安全范围内 + safe_position_value = balance * max_total_leverage - total_position_value + if safe_position_value > 0: + position_value = safe_position_value + margin = position_value / self.default_leverage + logger.warning(f"仓位已调整,确保总杠杆不超过 {max_total_leverage}x") + else: + return { + 'success': False, + 'message': f'当前杠杆 {current_leverage:.1f}x,无法再加仓' + } + quantity = position_value # 订单数量(以 USDT 计价) # 最小仓位限制(100 美金测试,最小 5 USDT)