a
This commit is contained in:
parent
8c0cd85079
commit
bb795604a3
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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(() => {
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user