From b9ea3f68ea77123bdfa2c39d9a519aa9db3015f3 Mon Sep 17 00:00:00 2001 From: tinkle-community Date: Wed, 29 Oct 2025 17:59:19 +0800 Subject: [PATCH] Fix: Correct Profit Factor calculation and display units in AI Learning Backend changes (logger/decision_logger.go): - Fixed Profit Factor to use standard formula (total profit / total loss) - Previously used average values which was incorrect when win/loss counts differ - Now saves total amounts before calculating averages for accurate ratio Frontend changes (web/src/components/AILearning.tsx): - Fixed display units: changed USDT amounts from "%" to "USDT" - Updated avg_win and avg_loss to show "USDT Average" instead of "%" - Updated best/worst performer displays to show "USDT" instead of "%" - Added "(USDT)" labels to table headers for clarity - Removed "%" from all table data cells showing monetary amounts This ensures accurate performance metrics and eliminates user confusion between percentage values and absolute USDT amounts. Co-Authored-By: tinkle-community --- logger/decision_logger.go | 10 ++++++++-- web/src/components/AILearning.tsx | 20 ++++++++++---------- 2 files changed, 18 insertions(+), 12 deletions(-) diff --git a/logger/decision_logger.go b/logger/decision_logger.go index ee5bb2af..4237c35c 100644 --- a/logger/decision_logger.go +++ b/logger/decision_logger.go @@ -429,6 +429,10 @@ func (l *DecisionLogger) AnalyzePerformance(lookbackCycles int) (*PerformanceAna if analysis.TotalTrades > 0 { analysis.WinRate = (float64(analysis.WinningTrades) / float64(analysis.TotalTrades)) * 100 + // 计算总盈利和总亏损 + totalWinAmount := analysis.AvgWin // 当前是累加的总和 + totalLossAmount := analysis.AvgLoss // 当前是累加的总和(负数) + if analysis.WinningTrades > 0 { analysis.AvgWin /= float64(analysis.WinningTrades) } @@ -436,8 +440,10 @@ func (l *DecisionLogger) AnalyzePerformance(lookbackCycles int) (*PerformanceAna analysis.AvgLoss /= float64(analysis.LosingTrades) } - if analysis.AvgLoss != 0 { - analysis.ProfitFactor = analysis.AvgWin / (-analysis.AvgLoss) + // Profit Factor = 总盈利 / 总亏损(绝对值) + // 注意:totalLossAmount 是负数,所以取负号得到绝对值 + if totalLossAmount != 0 { + analysis.ProfitFactor = totalWinAmount / (-totalLossAmount) } } diff --git a/web/src/components/AILearning.tsx b/web/src/components/AILearning.tsx index 47901fbb..e3806b36 100644 --- a/web/src/components/AILearning.tsx +++ b/web/src/components/AILearning.tsx @@ -190,9 +190,9 @@ export default function AILearning({ traderId }: AILearningProps) { {t('avgWin', language)}
- +{(performance.avg_win || 0).toFixed(2)}% + +{(performance.avg_win || 0).toFixed(2)}
-
📈 Average
+
📈 USDT Average
@@ -211,9 +211,9 @@ export default function AILearning({ traderId }: AILearningProps) { {t('avgLoss', language)}
- {(performance.avg_loss || 0).toFixed(2)}% + {(performance.avg_loss || 0).toFixed(2)}
-
📉 Average
+
📉 USDT Average
@@ -375,7 +375,7 @@ export default function AILearning({ traderId }: AILearningProps) { {symbolStats[performance.best_symbol] && (
{symbolStats[performance.best_symbol].total_pn_l > 0 ? '+' : ''} - {symbolStats[performance.best_symbol].total_pn_l.toFixed(2)}% {t('pnl', language)} + {symbolStats[performance.best_symbol].total_pn_l.toFixed(2)} USDT {t('pnl', language)}
)} @@ -397,7 +397,7 @@ export default function AILearning({ traderId }: AILearningProps) { {symbolStats[performance.worst_symbol] && (
{symbolStats[performance.worst_symbol].total_pn_l > 0 ? '+' : ''} - {symbolStats[performance.worst_symbol].total_pn_l.toFixed(2)}% {t('pnl', language)} + {symbolStats[performance.worst_symbol].total_pn_l.toFixed(2)} USDT {t('pnl', language)}
)} @@ -431,8 +431,8 @@ export default function AILearning({ traderId }: AILearningProps) { Symbol Trades Win Rate - Total P&L - Avg P&L + Total P&L (USDT) + Avg P&L (USDT) @@ -454,12 +454,12 @@ export default function AILearning({ traderId }: AILearningProps) { 0 ? '#10B981' : '#F87171' }}> - {(stat.total_pn_l || 0) > 0 ? '+' : ''}{(stat.total_pn_l || 0).toFixed(2)}% + {(stat.total_pn_l || 0) > 0 ? '+' : ''}{(stat.total_pn_l || 0).toFixed(2)} 0 ? '#10B981' : '#F87171' }}> - {(stat.avg_pn_l || 0) > 0 ? '+' : ''}{(stat.avg_pn_l || 0).toFixed(2)}% + {(stat.avg_pn_l || 0) > 0 ? '+' : ''}{(stat.avg_pn_l || 0).toFixed(2)} ))}