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 <tinklefund@gmail.com>
This commit is contained in:
tinkle-community
2025-10-29 17:59:19 +08:00
parent 3e5a701859
commit b9ea3f68ea
2 changed files with 18 additions and 12 deletions

View File

@@ -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)
}
}

View File

@@ -190,9 +190,9 @@ export default function AILearning({ traderId }: AILearningProps) {
{t('avgWin', language)}
</div>
<div className="text-4xl font-bold mono mb-1" style={{ color: '#10B981' }}>
+{(performance.avg_win || 0).toFixed(2)}%
+{(performance.avg_win || 0).toFixed(2)}
</div>
<div className="text-xs" style={{ color: '#6EE7B7' }}>📈 Average</div>
<div className="text-xs" style={{ color: '#6EE7B7' }}>📈 USDT Average</div>
</div>
</div>
@@ -211,9 +211,9 @@ export default function AILearning({ traderId }: AILearningProps) {
{t('avgLoss', language)}
</div>
<div className="text-4xl font-bold mono mb-1" style={{ color: '#F87171' }}>
{(performance.avg_loss || 0).toFixed(2)}%
{(performance.avg_loss || 0).toFixed(2)}
</div>
<div className="text-xs" style={{ color: '#FCA5A5' }}>📉 Average</div>
<div className="text-xs" style={{ color: '#FCA5A5' }}>📉 USDT Average</div>
</div>
</div>
</div>
@@ -375,7 +375,7 @@ export default function AILearning({ traderId }: AILearningProps) {
{symbolStats[performance.best_symbol] && (
<div className="text-lg font-semibold" style={{ color: '#6EE7B7' }}>
{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)}
</div>
)}
</div>
@@ -397,7 +397,7 @@ export default function AILearning({ traderId }: AILearningProps) {
{symbolStats[performance.worst_symbol] && (
<div className="text-lg font-semibold" style={{ color: '#FCA5A5' }}>
{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)}
</div>
)}
</div>
@@ -431,8 +431,8 @@ export default function AILearning({ traderId }: AILearningProps) {
<th className="text-left px-4 py-3 text-xs font-semibold" style={{ color: '#94A3B8' }}>Symbol</th>
<th className="text-right px-4 py-3 text-xs font-semibold" style={{ color: '#94A3B8' }}>Trades</th>
<th className="text-right px-4 py-3 text-xs font-semibold" style={{ color: '#94A3B8' }}>Win Rate</th>
<th className="text-right px-4 py-3 text-xs font-semibold" style={{ color: '#94A3B8' }}>Total P&L</th>
<th className="text-right px-4 py-3 text-xs font-semibold" style={{ color: '#94A3B8' }}>Avg P&L</th>
<th className="text-right px-4 py-3 text-xs font-semibold" style={{ color: '#94A3B8' }}>Total P&L (USDT)</th>
<th className="text-right px-4 py-3 text-xs font-semibold" style={{ color: '#94A3B8' }}>Avg P&L (USDT)</th>
</tr>
</thead>
<tbody>
@@ -454,12 +454,12 @@ export default function AILearning({ traderId }: AILearningProps) {
<td className="px-4 py-3 text-right mono text-sm font-bold" style={{
color: (stat.total_pn_l || 0) > 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)}
</td>
<td className="px-4 py-3 text-right mono text-sm" style={{
color: (stat.avg_pn_l || 0) > 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)}
</td>
</tr>
))}