a
This commit is contained in:
parent
61af631e46
commit
6aca7f9f73
|
|
@ -210,15 +210,25 @@ async def get_trade_stats(
|
||||||
|
|
||||||
trades = Trade.get_all(start_timestamp, end_timestamp, symbol, None)
|
trades = Trade.get_all(start_timestamp, end_timestamp, symbol, None)
|
||||||
closed_trades = [t for t in trades if t['status'] == 'closed']
|
closed_trades = [t for t in trades if t['status'] == 'closed']
|
||||||
win_trades = [t for t in closed_trades if float(t['pnl']) > 0]
|
|
||||||
|
# 排除0盈亏的订单(abs(pnl) < 0.01 USDT视为0盈亏),这些订单不应该影响胜率统计
|
||||||
|
ZERO_PNL_THRESHOLD = 0.01 # 0.01 USDT的阈值,小于此值视为0盈亏
|
||||||
|
meaningful_trades = [t for t in closed_trades if abs(float(t['pnl'])) >= ZERO_PNL_THRESHOLD]
|
||||||
|
zero_pnl_trades = [t for t in closed_trades if abs(float(t['pnl'])) < ZERO_PNL_THRESHOLD]
|
||||||
|
|
||||||
|
# 只统计有意义的交易(排除0盈亏)的胜率
|
||||||
|
win_trades = [t for t in meaningful_trades if float(t['pnl']) > 0]
|
||||||
|
loss_trades = [t for t in meaningful_trades if float(t['pnl']) < 0]
|
||||||
|
|
||||||
stats = {
|
stats = {
|
||||||
"total_trades": len(trades),
|
"total_trades": len(trades),
|
||||||
"closed_trades": len(closed_trades),
|
"closed_trades": len(closed_trades),
|
||||||
"open_trades": len(trades) - len(closed_trades),
|
"open_trades": len(trades) - len(closed_trades),
|
||||||
|
"meaningful_trades": len(meaningful_trades), # 有意义的交易数(排除0盈亏)
|
||||||
|
"zero_pnl_trades": len(zero_pnl_trades), # 0盈亏交易数
|
||||||
"win_trades": len(win_trades),
|
"win_trades": len(win_trades),
|
||||||
"loss_trades": len(closed_trades) - len(win_trades),
|
"loss_trades": len(loss_trades),
|
||||||
"win_rate": len(win_trades) / len(closed_trades) * 100 if closed_trades else 0,
|
"win_rate": len(win_trades) / len(meaningful_trades) * 100 if meaningful_trades else 0, # 基于有意义的交易计算胜率
|
||||||
"total_pnl": sum(float(t['pnl']) for t in closed_trades),
|
"total_pnl": sum(float(t['pnl']) for t in closed_trades),
|
||||||
"avg_pnl": sum(float(t['pnl']) for t in closed_trades) / len(closed_trades) if closed_trades else 0,
|
"avg_pnl": sum(float(t['pnl']) for t in closed_trades) / len(closed_trades) if closed_trades else 0,
|
||||||
"filters": {
|
"filters": {
|
||||||
|
|
@ -231,7 +241,11 @@ async def get_trade_stats(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.info(f"交易统计: 总交易数={stats['total_trades']}, 已平仓={stats['closed_trades']}, 胜率={stats['win_rate']:.2f}%, 总盈亏={stats['total_pnl']:.2f} USDT")
|
logger.info(
|
||||||
|
f"交易统计: 总交易数={stats['total_trades']}, 已平仓={stats['closed_trades']}, "
|
||||||
|
f"有意义交易={stats['meaningful_trades']}, 0盈亏交易={stats['zero_pnl_trades']}, "
|
||||||
|
f"胜率={stats['win_rate']:.2f}%, 总盈亏={stats['total_pnl']:.2f} USDT"
|
||||||
|
)
|
||||||
|
|
||||||
return stats
|
return stats
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
|
|
||||||
|
|
@ -240,11 +240,19 @@ const TradeList = () => {
|
||||||
<div className="stat-card">
|
<div className="stat-card">
|
||||||
<div className="stat-label">总交易数</div>
|
<div className="stat-label">总交易数</div>
|
||||||
<div className="stat-value">{stats.total_trades}</div>
|
<div className="stat-value">{stats.total_trades}</div>
|
||||||
<div style={{ fontSize: '12px', color: '#999', marginTop: '4px' }}>(已平仓的完整交易)</div>
|
<div style={{ fontSize: '12px', color: '#999', marginTop: '4px' }}>
|
||||||
|
{stats.meaningful_trades !== undefined && (
|
||||||
|
<>(有意义: {stats.meaningful_trades},0盈亏: {stats.zero_pnl_trades || 0})</>
|
||||||
|
)}
|
||||||
|
{stats.meaningful_trades === undefined && <>(已平仓的完整交易)</>}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="stat-card">
|
<div className="stat-card">
|
||||||
<div className="stat-label">胜率</div>
|
<div className="stat-label">胜率</div>
|
||||||
<div className="stat-value">{stats.win_rate.toFixed(2)}%</div>
|
<div className="stat-value">{stats.win_rate.toFixed(2)}%</div>
|
||||||
|
<div style={{ fontSize: '12px', color: '#999', marginTop: '4px' }}>
|
||||||
|
{stats.meaningful_trades !== undefined && <>(已排除0盈亏订单)</>}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="stat-card">
|
<div className="stat-card">
|
||||||
<div className="stat-label">总盈亏</div>
|
<div className="stat-label">总盈亏</div>
|
||||||
|
|
|
||||||
|
|
@ -801,6 +801,16 @@ class BinanceClient:
|
||||||
f"最小要求: {min_margin_usdt:.2f} USDT (杠杆: {current_leverage}x)"
|
f"最小要求: {min_margin_usdt:.2f} USDT (杠杆: {current_leverage}x)"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# 最终检查:确保名义价值不小于0.2 USDT(避免无意义的小单子)
|
||||||
|
# 对于平仓操作(reduce_only=True),跳过此检查
|
||||||
|
# MIN_NOTIONAL_VALUE = 0.2 # 最小名义价值0.2 USDT
|
||||||
|
# if not reduce_only and notional_value < MIN_NOTIONAL_VALUE:
|
||||||
|
# logger.error(
|
||||||
|
# f"❌ {symbol} 订单名义价值 {notional_value:.4f} USDT < 最小要求 {MIN_NOTIONAL_VALUE:.2f} USDT,拒绝下单"
|
||||||
|
# )
|
||||||
|
# logger.error(f" 💡 此类小单子意义不大,拒绝开仓")
|
||||||
|
# return None
|
||||||
|
|
||||||
# 构建订单参数
|
# 构建订单参数
|
||||||
order_params = {
|
order_params = {
|
||||||
'symbol': symbol,
|
'symbol': symbol,
|
||||||
|
|
|
||||||
|
|
@ -114,6 +114,10 @@ class PositionManager:
|
||||||
logger.warning(f" 3. 总仓位超过限制")
|
logger.warning(f" 3. 总仓位超过限制")
|
||||||
logger.warning(f" 4. 无法获取价格数据")
|
logger.warning(f" 4. 无法获取价格数据")
|
||||||
logger.warning(f" 5. 保证金不足最小要求(MIN_MARGIN_USDT)")
|
logger.warning(f" 5. 保证金不足最小要求(MIN_MARGIN_USDT)")
|
||||||
|
<<<<<<< Current (Your changes)
|
||||||
|
=======
|
||||||
|
logger.warning(f" 6. 名义价值小于0.2 USDT(避免无意义的小单子)")
|
||||||
|
>>>>>>> Incoming (Background Agent changes)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
logger.info(f"✓ {symbol} 仓位计算成功: {quantity:.4f}")
|
logger.info(f"✓ {symbol} 仓位计算成功: {quantity:.4f}")
|
||||||
|
|
|
||||||
|
|
@ -354,6 +354,19 @@ class RiskManager:
|
||||||
|
|
||||||
# 检查是否通过风险控制
|
# 检查是否通过风险控制
|
||||||
logger.info(f" 检查仓位大小是否符合风险控制要求...")
|
logger.info(f" 检查仓位大小是否符合风险控制要求...")
|
||||||
|
|
||||||
|
# 计算最终的名义价值
|
||||||
|
final_notional_value = quantity * current_price
|
||||||
|
|
||||||
|
# 添加最小名义价值检查(0.2 USDT),避免下无意义的小单子
|
||||||
|
MIN_NOTIONAL_VALUE = 0.2 # 最小名义价值0.2 USDT
|
||||||
|
if final_notional_value < MIN_NOTIONAL_VALUE:
|
||||||
|
logger.warning(
|
||||||
|
f" ❌ {symbol} 名义价值 {final_notional_value:.4f} USDT < 最小要求 {MIN_NOTIONAL_VALUE:.2f} USDT"
|
||||||
|
)
|
||||||
|
logger.warning(f" 💡 此类小单子意义不大,拒绝开仓")
|
||||||
|
return None
|
||||||
|
|
||||||
if await self.check_position_size(symbol, quantity):
|
if await self.check_position_size(symbol, quantity):
|
||||||
final_margin = (quantity * current_price) / actual_leverage
|
final_margin = (quantity * current_price) / actual_leverage
|
||||||
logger.info(
|
logger.info(
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user