|
@@ -449,6 +449,15 @@ class TradingStats:
|
|
|
sum_winning_pnl = token_agg_stats.get('sum_of_winning_pnl', 0.0)
|
|
|
sum_losing_pnl = token_agg_stats.get('sum_of_losing_pnl', 0.0)
|
|
|
|
|
|
+ # Calculate percentages for largest trades
|
|
|
+ largest_win_pnl = token_agg_stats.get('largest_winning_cycle_pnl', 0.0)
|
|
|
+ largest_loss_pnl = token_agg_stats.get('largest_losing_cycle_pnl', 0.0)
|
|
|
+ largest_win_entry_volume = token_agg_stats.get('largest_winning_cycle_entry_volume', 0.0)
|
|
|
+ largest_loss_entry_volume = token_agg_stats.get('largest_losing_cycle_entry_volume', 0.0)
|
|
|
+
|
|
|
+ largest_win_percentage = (largest_win_pnl / largest_win_entry_volume * 100) if largest_win_entry_volume > 0 else 0.0
|
|
|
+ largest_loss_percentage = (largest_loss_pnl / largest_loss_entry_volume * 100) if largest_loss_entry_volume > 0 else 0.0
|
|
|
+
|
|
|
perf_stats.update({
|
|
|
'completed_trades': total_cycles,
|
|
|
'total_pnl': token_agg_stats.get('total_realized_pnl', 0.0),
|
|
@@ -456,8 +465,10 @@ class TradingStats:
|
|
|
'profit_factor': (sum_winning_pnl / sum_losing_pnl) if sum_losing_pnl > 0 else float('inf') if sum_winning_pnl > 0 else 0.0,
|
|
|
'avg_win': (sum_winning_pnl / winning_cycles) if winning_cycles > 0 else 0.0,
|
|
|
'avg_loss': (sum_losing_pnl / losing_cycles) if losing_cycles > 0 else 0.0,
|
|
|
- 'largest_win': token_agg_stats.get('largest_winning_cycle_pnl', 0.0),
|
|
|
- 'largest_loss': token_agg_stats.get('largest_losing_cycle_pnl', 0.0),
|
|
|
+ 'largest_win': largest_win_pnl,
|
|
|
+ 'largest_loss': largest_loss_pnl,
|
|
|
+ 'largest_win_percentage': largest_win_percentage,
|
|
|
+ 'largest_loss_percentage': largest_loss_percentage,
|
|
|
'total_wins': winning_cycles,
|
|
|
'total_losses': losing_cycles,
|
|
|
'completed_entry_volume': token_agg_stats.get('total_entry_volume', 0.0),
|
|
@@ -579,13 +590,17 @@ class TradingStats:
|
|
|
stats_text_parts.append(f"• Profit Factor: {perf['profit_factor']:.2f}")
|
|
|
stats_text_parts.append(f"• Expectancy: {formatter.format_price_with_symbol(perf['expectancy'])}")
|
|
|
|
|
|
- stats_text_parts.append(f"• Largest Winning Trade: {formatter.format_price_with_symbol(perf['largest_win'])}")
|
|
|
- stats_text_parts.append(f"• Largest Losing Trade: {formatter.format_price_with_symbol(-perf['largest_loss'])}")
|
|
|
+ largest_win_pct_str = f" ({perf.get('largest_winning_percentage', 0):+.2f}%)" if perf.get('largest_winning_percentage', 0) != 0 else ""
|
|
|
+ largest_loss_pct_str = f" ({perf.get('largest_losing_percentage', 0):+.2f}%)" if perf.get('largest_losing_percentage', 0) != 0 else ""
|
|
|
+
|
|
|
+ stats_text_parts.append(f"• Largest Winning Trade: {formatter.format_price_with_symbol(perf['largest_win'])}{largest_win_pct_str}")
|
|
|
+ stats_text_parts.append(f"• Largest Losing Trade: {formatter.format_price_with_symbol(-perf['largest_loss'])}{largest_loss_pct_str}")
|
|
|
|
|
|
- best_token_stats = perf.get('best_performing_token', {'name': 'N/A', 'pnl_percentage': 0.0})
|
|
|
- worst_token_stats = perf.get('worst_performing_token', {'name': 'N/A', 'pnl_percentage': 0.0})
|
|
|
- stats_text_parts.append(f"• Best Performing Token: {best_token_stats['name']} ({best_token_stats['pnl_percentage']:+.2f}%)")
|
|
|
- stats_text_parts.append(f"• Worst Performing Token: {worst_token_stats['name']} ({worst_token_stats['pnl_percentage']:+.2f}%)")
|
|
|
+ best_token_stats = perf.get('best_performing_token', {'name': 'N/A', 'pnl_percentage': 0.0, 'volume': 0.0, 'pnl_value': 0.0})
|
|
|
+ worst_token_stats = perf.get('worst_performing_token', {'name': 'N/A', 'pnl_percentage': 0.0, 'volume': 0.0, 'pnl_value': 0.0})
|
|
|
+
|
|
|
+ stats_text_parts.append(f"• Best Token: {best_token_stats['name']} {formatter.format_price_with_symbol(best_token_stats['pnl_value'])} ({best_token_stats['pnl_percentage']:+.2f}%)")
|
|
|
+ stats_text_parts.append(f"• Worst Token: {worst_token_stats['name']} {formatter.format_price_with_symbol(worst_token_stats['pnl_value'])} ({worst_token_stats['pnl_percentage']:+.2f}%)")
|
|
|
|
|
|
stats_text_parts.append(f"• Average Trade Duration: {perf.get('avg_trade_duration', 'N/A')}")
|
|
|
stats_text_parts.append(f"• Portfolio Max Drawdown: {risk.get('max_drawdown_live_percentage', 0.0):.2f}% <i>(Live)</i>")
|
|
@@ -637,7 +652,12 @@ class TradingStats:
|
|
|
parts.append(f"• Profit Factor: {perf_summary.get('profit_factor', 0.0):.2f}")
|
|
|
parts.append(f"• Expectancy: {formatter.format_price_with_symbol(perf_summary.get('expectancy', 0.0))}")
|
|
|
parts.append(f"• Avg Win: {formatter.format_price_with_symbol(perf_summary.get('avg_win', 0.0))} | Avg Loss: {formatter.format_price_with_symbol(perf_summary.get('avg_loss', 0.0))}")
|
|
|
- parts.append(f"• Largest Win: {formatter.format_price_with_symbol(perf_summary.get('largest_win', 0.0))} | Largest Loss: {formatter.format_price_with_symbol(perf_summary.get('largest_loss', 0.0))}")
|
|
|
+
|
|
|
+ # Format largest trades with percentages
|
|
|
+ largest_win_pct_str = f" ({perf_summary.get('largest_win_percentage', 0):+.2f}%)" if perf_summary.get('largest_win_percentage', 0) != 0 else ""
|
|
|
+ largest_loss_pct_str = f" ({perf_summary.get('largest_loss_percentage', 0):+.2f}%)" if perf_summary.get('largest_loss_percentage', 0) != 0 else ""
|
|
|
+
|
|
|
+ parts.append(f"• Largest Win: {formatter.format_price_with_symbol(perf_summary.get('largest_win', 0.0))}{largest_win_pct_str} | Largest Loss: {formatter.format_price_with_symbol(perf_summary.get('largest_loss', 0.0))}{largest_loss_pct_str}")
|
|
|
parts.append(f"• Entry Volume: {formatter.format_price_with_symbol(perf_summary.get('completed_entry_volume', 0.0))}")
|
|
|
parts.append(f"• Exit Volume: {formatter.format_price_with_symbol(perf_summary.get('completed_exit_volume', 0.0))}")
|
|
|
parts.append(f"• Average Trade Duration: {perf_summary.get('avg_trade_duration', 'N/A')}")
|