diff --git a/backend/api/routes/trades.py b/backend/api/routes/trades.py
index 3ab1d6e..e28d269 100644
--- a/backend/api/routes/trades.py
+++ b/backend/api/routes/trades.py
@@ -210,15 +210,25 @@ async def get_trade_stats(
trades = Trade.get_all(start_timestamp, end_timestamp, symbol, None)
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 = {
"total_trades": len(trades),
"closed_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),
- "loss_trades": len(closed_trades) - len(win_trades),
- "win_rate": len(win_trades) / len(closed_trades) * 100 if closed_trades else 0,
+ "loss_trades": len(loss_trades),
+ "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),
"avg_pnl": sum(float(t['pnl']) for t in closed_trades) / len(closed_trades) if closed_trades else 0,
"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
except Exception as e:
diff --git a/frontend/src/components/TradeList.jsx b/frontend/src/components/TradeList.jsx
index fcad521..d9a2f83 100644
--- a/frontend/src/components/TradeList.jsx
+++ b/frontend/src/components/TradeList.jsx
@@ -240,11 +240,19 @@ const TradeList = () => {
总交易数
{stats.total_trades}
-
(已平仓的完整交易)
+
+ {stats.meaningful_trades !== undefined && (
+ <>(有意义: {stats.meaningful_trades},0盈亏: {stats.zero_pnl_trades || 0})>
+ )}
+ {stats.meaningful_trades === undefined && <>(已平仓的完整交易)>}
+
胜率
{stats.win_rate.toFixed(2)}%
+
+ {stats.meaningful_trades !== undefined && <>(已排除0盈亏订单)>}
+
总盈亏
diff --git a/trading_system/binance_client.py b/trading_system/binance_client.py
index e524f75..50c261d 100644
--- a/trading_system/binance_client.py
+++ b/trading_system/binance_client.py
@@ -801,6 +801,16 @@ class BinanceClient:
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 = {
'symbol': symbol,
diff --git a/trading_system/position_manager.py b/trading_system/position_manager.py
index f2dc6df..eeea8b6 100644
--- a/trading_system/position_manager.py
+++ b/trading_system/position_manager.py
@@ -114,6 +114,10 @@ class PositionManager:
logger.warning(f" 3. 总仓位超过限制")
logger.warning(f" 4. 无法获取价格数据")
logger.warning(f" 5. 保证金不足最小要求(MIN_MARGIN_USDT)")
+<<<<<<< Current (Your changes)
+=======
+ logger.warning(f" 6. 名义价值小于0.2 USDT(避免无意义的小单子)")
+>>>>>>> Incoming (Background Agent changes)
return None
logger.info(f"✓ {symbol} 仓位计算成功: {quantity:.4f}")
diff --git a/trading_system/risk_manager.py b/trading_system/risk_manager.py
index 3d24550..72f79a4 100644
--- a/trading_system/risk_manager.py
+++ b/trading_system/risk_manager.py
@@ -354,6 +354,19 @@ class RiskManager:
# 检查是否通过风险控制
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):
final_margin = (quantity * current_price) / actual_leverage
logger.info(