This commit is contained in:
薇薇安 2026-01-15 15:23:30 +08:00
parent 8c0cd85079
commit bb795604a3
4 changed files with 35 additions and 14 deletions

View File

@ -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)

View File

@ -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(() => {

View File

@ -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:

View File

@ -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: