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