diff --git a/backend/api/routes/account.py b/backend/api/routes/account.py index 2c4cfbe..d6a1b2d 100644 --- a/backend/api/routes/account.py +++ b/backend/api/routes/account.py @@ -311,7 +311,9 @@ async def get_realtime_positions(): async def close_position(symbol: str): """手动平仓指定交易对的持仓""" try: + logger.info(f"=" * 60) logger.info(f"收到平仓请求: {symbol}") + logger.info(f"=" * 60) # 从数据库读取API密钥 api_key = TradingConfig.get_value('BINANCE_API_KEY') @@ -328,27 +330,36 @@ async def close_position(symbol: str): from binance_client import BinanceClient from risk_manager import RiskManager from position_manager import PositionManager - except ImportError: + logger.info("✓ 成功导入交易系统模块") + except ImportError as import_error: + logger.warning(f"首次导入失败: {import_error},尝试从trading_system路径导入") trading_system_path = project_root / 'trading_system' sys.path.insert(0, str(trading_system_path)) from binance_client import BinanceClient from risk_manager import RiskManager from position_manager import PositionManager + logger.info("✓ 从trading_system路径导入成功") # 创建客户端和仓位管理器 + logger.info(f"创建BinanceClient (testnet={use_testnet})...") client = BinanceClient( api_key=api_key, api_secret=api_secret, testnet=use_testnet ) + logger.info("连接币安API...") await client.connect() + logger.info("✓ 币安API连接成功") try: + logger.info("初始化RiskManager和PositionManager...") risk_manager = RiskManager(client) position_manager = PositionManager(client, risk_manager) + logger.info("✓ 管理器初始化成功") # 执行平仓(reason='manual' 表示手动平仓) + logger.info(f"开始执行平仓操作: {symbol}...") success = await position_manager.close_position(symbol, reason='manual') if success: @@ -366,11 +377,16 @@ async def close_position(symbol: str): "status": "failed" } finally: + logger.info("断开币安API连接...") await client.disconnect() + logger.info("✓ 已断开连接") except HTTPException: raise except Exception as e: error_msg = f"平仓失败: {str(e)}" - logger.error(error_msg, exc_info=True) + logger.error("=" * 60) + logger.error(f"平仓操作异常: {error_msg}") + logger.error(f"错误类型: {type(e).__name__}") + logger.error("=" * 60, exc_info=True) raise HTTPException(status_code=500, detail=error_msg) diff --git a/frontend/src/components/StatsDashboard.jsx b/frontend/src/components/StatsDashboard.jsx index bab0221..11c765c 100644 --- a/frontend/src/components/StatsDashboard.jsx +++ b/frontend/src/components/StatsDashboard.jsx @@ -35,7 +35,9 @@ const StatsDashboard = () => { setMessage('') try { + console.log(`开始平仓 ${symbol}...`) const result = await api.closePosition(symbol) + console.log('平仓结果:', result) setMessage(result.message || `${symbol} 平仓成功`) // 立即刷新数据 @@ -46,8 +48,9 @@ const StatsDashboard = () => { setMessage('') }, 3000) } catch (error) { - setMessage(`平仓失败: ${error.message}`) console.error('Close position error:', error) + const errorMessage = error.message || error.toString() || '平仓失败,请检查网络连接或后端服务' + setMessage(`平仓失败: ${errorMessage}`) // 错误消息5秒后清除 setTimeout(() => { diff --git a/trading_system/position_manager.py b/trading_system/position_manager.py index 6e82a86..9d810aa 100644 --- a/trading_system/position_manager.py +++ b/trading_system/position_manager.py @@ -90,10 +90,10 @@ class PositionManager: # 设置杠杆 await self.client.set_leverage(symbol, leverage) - # 计算仓位大小 + # 计算仓位大小(传入实际使用的杠杆) logger.info(f"开始为 {symbol} 计算仓位大小...") quantity = await self.risk_manager.calculate_position_size( - symbol, change_percent + symbol, change_percent, leverage=leverage ) if quantity is None: diff --git a/trading_system/risk_manager.py b/trading_system/risk_manager.py index 55dc773..8add938 100644 --- a/trading_system/risk_manager.py +++ b/trading_system/risk_manager.py @@ -205,7 +205,8 @@ class RiskManager: async def calculate_position_size( self, symbol: str, - change_percent: float + change_percent: float, + leverage: Optional[int] = None ) -> Optional[float]: """ 根据涨跌幅和风险参数计算合适的仓位大小 @@ -303,21 +304,22 @@ class RiskManager: # 检查最小保证金要求(避免手续费侵蚀收益) min_margin_usdt = self.config.get('MIN_MARGIN_USDT', 0.5) # 默认0.5 USDT - leverage = self.config.get('LEVERAGE', 10) + # 使用传入的实际杠杆,如果没有传入则使用配置的基础杠杆 + actual_leverage = leverage if leverage is not None else self.config.get('LEVERAGE', 10) # 计算实际需要的保证金 = 仓位价值 / 杠杆 - required_margin = position_value / leverage - logger.info(f" 计算保证金: {required_margin:.4f} USDT (仓位价值: {position_value:.2f} USDT / 杠杆: {leverage}x)") + required_margin = position_value / actual_leverage + logger.info(f" 计算保证金: {required_margin:.4f} USDT (仓位价值: {position_value:.2f} USDT / 杠杆: {actual_leverage}x)") if required_margin < min_margin_usdt: # 保证金不足,需要增加仓位价值 - required_position_value = min_margin_usdt * leverage + required_position_value = min_margin_usdt * actual_leverage logger.warning( f" ⚠ 保证金 {required_margin:.4f} USDT < 最小保证金要求 {min_margin_usdt:.2f} USDT" ) logger.info( f" 需要的最小仓位价值: {required_position_value:.2f} USDT " - f"(最小保证金 {min_margin_usdt:.2f} USDT × 杠杆 {leverage}x)" + f"(最小保证金 {min_margin_usdt:.2f} USDT × 杠杆 {actual_leverage}x)" ) # 检查是否可以使用更大的仓位价值(但不超过最大仓位限制) @@ -332,7 +334,7 @@ class RiskManager: ) else: # 即使使用最大仓位也无法满足最小保证金要求 - max_margin = max_position_value / leverage + max_margin = max_position_value / actual_leverage logger.warning( f" ❌ 无法满足最小保证金要求: " f"需要 {min_margin_usdt:.2f} USDT 保证金 (仓位价值 {required_position_value:.2f} USDT)," @@ -348,12 +350,12 @@ class RiskManager: # 检查是否通过风险控制 logger.info(f" 检查仓位大小是否符合风险控制要求...") if await self.check_position_size(symbol, quantity): - final_margin = (quantity * current_price) / leverage + final_margin = (quantity * current_price) / actual_leverage logger.info( f"✓ {symbol} 仓位计算成功: {quantity:.4f} " f"(仓位价值: {position_value:.2f} USDT, " f"名义价值: {quantity * current_price:.2f} USDT, " - f"保证金: {final_margin:.4f} USDT)" + f"保证金: {final_margin:.4f} USDT, 杠杆: {actual_leverage}x)" ) return quantity else: