|
@@ -896,17 +896,17 @@ class InfoCommands:
|
|
|
)
|
|
|
return
|
|
|
|
|
|
- # Sort tokens by total P&L (best to worst)
|
|
|
+ # Sort tokens by total P&L (best to worst) - token_performance is already a list of dicts
|
|
|
sorted_tokens = sorted(
|
|
|
- token_performance.items(),
|
|
|
- key=lambda x: x[1]['total_pnl'],
|
|
|
+ token_performance,
|
|
|
+ key=lambda x: x.get('total_realized_pnl', 0),
|
|
|
reverse=True
|
|
|
)
|
|
|
|
|
|
performance_text = "🏆 <b>Token Performance Ranking</b>\n\n"
|
|
|
|
|
|
# Add ranking with emojis
|
|
|
- for i, (token, stats_data) in enumerate(sorted_tokens, 1):
|
|
|
+ for i, stats_data in enumerate(sorted_tokens, 1):
|
|
|
# Ranking emoji
|
|
|
if i == 1:
|
|
|
rank_emoji = "🥇"
|
|
@@ -918,22 +918,31 @@ class InfoCommands:
|
|
|
rank_emoji = f"#{i}"
|
|
|
|
|
|
# P&L emoji
|
|
|
- pnl_emoji = "🟢" if stats_data['total_pnl'] >= 0 else "🔴"
|
|
|
+ total_pnl = stats_data.get('total_realized_pnl', 0)
|
|
|
+ pnl_emoji = "🟢" if total_pnl >= 0 else "🔴"
|
|
|
+
|
|
|
+ # Calculate PnL percentage from entry volume
|
|
|
+ entry_volume = stats_data.get('completed_entry_volume', 0)
|
|
|
+ pnl_percentage = (total_pnl / entry_volume * 100) if entry_volume > 0 else 0
|
|
|
+
|
|
|
+ token_name = stats_data.get('token', 'N/A')
|
|
|
+ completed_trades = stats_data.get('total_completed_cycles', 0)
|
|
|
|
|
|
# Format the line
|
|
|
- performance_text += f"{rank_emoji} <b>{token}</b>\n"
|
|
|
- performance_text += f" {pnl_emoji} P&L: ${stats_data['total_pnl']:,.2f} ({stats_data['pnl_percentage']:+.1f}%)\n"
|
|
|
- performance_text += f" 📊 Trades: {stats_data['completed_trades']}"
|
|
|
+ performance_text += f"{rank_emoji} <b>{token_name}</b>\n"
|
|
|
+ performance_text += f" {pnl_emoji} P&L: ${total_pnl:,.2f} ({pnl_percentage:+.1f}%)\n"
|
|
|
+ performance_text += f" 📊 Trades: {completed_trades}"
|
|
|
|
|
|
# Add win rate if there are completed trades
|
|
|
- if stats_data['completed_trades'] > 0:
|
|
|
- performance_text += f" | Win: {stats_data['win_rate']:.0f}%"
|
|
|
+ if completed_trades > 0:
|
|
|
+ win_rate = stats_data.get('win_rate', 0)
|
|
|
+ performance_text += f" | Win: {win_rate:.0f}%"
|
|
|
|
|
|
performance_text += "\n\n"
|
|
|
|
|
|
# Add summary
|
|
|
- total_pnl = sum(stats_data['total_pnl'] for stats_data in token_performance.values())
|
|
|
- total_trades = sum(stats_data['completed_trades'] for stats_data in token_performance.values())
|
|
|
+ total_pnl = sum(stats_data.get('total_realized_pnl', 0) for stats_data in token_performance)
|
|
|
+ total_trades = sum(stats_data.get('total_completed_cycles', 0) for stats_data in token_performance)
|
|
|
total_pnl_emoji = "🟢" if total_pnl >= 0 else "🔴"
|
|
|
|
|
|
performance_text += f"💼 <b>Portfolio Summary:</b>\n"
|
|
@@ -956,7 +965,7 @@ class InfoCommands:
|
|
|
formatter = get_formatter() # Get the formatter instance
|
|
|
|
|
|
# Check if token has any data
|
|
|
- if token_stats.get('total_trades', 0) == 0:
|
|
|
+ if token_stats.get('summary_total_trades', 0) == 0:
|
|
|
await context.bot.send_message(chat_id=chat_id, text=
|
|
|
f"📊 <b>{token} Performance</b>\n\n"
|
|
|
f"📭 No trading history found for {token}.\n\n"
|
|
@@ -969,13 +978,14 @@ class InfoCommands:
|
|
|
return
|
|
|
|
|
|
# Check if there's a message (no completed trades)
|
|
|
- if 'message' in token_stats and token_stats.get('completed_trades', 0) == 0:
|
|
|
+ perf_summary = token_stats.get('performance_summary', {})
|
|
|
+ if 'message' in token_stats and perf_summary.get('completed_trades', 0) == 0:
|
|
|
total_volume_str = formatter.format_price_with_symbol(token_stats.get('total_volume', 0), quote_asset=Config.QUOTE_CURRENCY) # Assuming total volume is in quote currency
|
|
|
await context.bot.send_message(chat_id=chat_id, text=
|
|
|
f"📊 <b>{token} Performance</b>\n\n"
|
|
|
f"{token_stats['message']}\n\n"
|
|
|
f"📈 <b>Current Activity:</b>\n"
|
|
|
- f"• Total Trades: {token_stats['total_trades']}\n"
|
|
|
+ f"• Total Trades: {token_stats.get('summary_total_trades', 0)}\n"
|
|
|
f"• Buy Orders: {token_stats.get('buy_trades', 0)}\n"
|
|
|
f"• Sell Orders: {token_stats.get('sell_trades', 0)}\n"
|
|
|
f"• Volume: {total_volume_str}\n\n"
|
|
@@ -985,36 +995,41 @@ class InfoCommands:
|
|
|
)
|
|
|
return
|
|
|
|
|
|
- # Detailed stats display
|
|
|
- pnl_emoji = "🟢" if token_stats['total_pnl'] >= 0 else "🔴"
|
|
|
+ # Detailed stats display - use performance_summary data
|
|
|
+ perf_summary = token_stats.get('performance_summary', {})
|
|
|
+ pnl_emoji = "🟢" if perf_summary.get('total_pnl', 0) >= 0 else "🔴"
|
|
|
+
|
|
|
+ total_pnl_str = formatter.format_price_with_symbol(perf_summary.get('total_pnl', 0))
|
|
|
+ completed_volume_str = formatter.format_price_with_symbol(perf_summary.get('completed_entry_volume', 0))
|
|
|
+ expectancy_str = formatter.format_price_with_symbol(perf_summary.get('expectancy', 0))
|
|
|
+ largest_win_str = formatter.format_price_with_symbol(perf_summary.get('largest_win', 0))
|
|
|
+ largest_loss_str = formatter.format_price_with_symbol(perf_summary.get('largest_loss', 0))
|
|
|
+ avg_win_str = formatter.format_price_with_symbol(perf_summary.get('avg_win', 0))
|
|
|
+ avg_loss_str = formatter.format_price_with_symbol(perf_summary.get('avg_loss', 0))
|
|
|
|
|
|
- total_pnl_str = formatter.format_price_with_symbol(token_stats['total_pnl'])
|
|
|
- completed_volume_str = formatter.format_price_with_symbol(token_stats['completed_volume'])
|
|
|
- expectancy_str = formatter.format_price_with_symbol(token_stats['expectancy'])
|
|
|
- largest_win_str = formatter.format_price_with_symbol(token_stats['largest_win'])
|
|
|
- largest_loss_str = formatter.format_price_with_symbol(token_stats['largest_loss']) # Assuming loss is positive number
|
|
|
- avg_win_str = formatter.format_price_with_symbol(token_stats['avg_win'])
|
|
|
- avg_loss_str = formatter.format_price_with_symbol(token_stats['avg_loss']) # Assuming loss is positive number
|
|
|
+ # Calculate PnL percentage
|
|
|
+ entry_vol = perf_summary.get('completed_entry_volume', 0)
|
|
|
+ pnl_pct = (perf_summary.get('total_pnl', 0) / entry_vol * 100) if entry_vol > 0 else 0
|
|
|
|
|
|
|
|
|
performance_text = f"""
|
|
|
📊 <b>{token} Detailed Performance</b>
|
|
|
|
|
|
🎯 <b>P&L Summary:</b>
|
|
|
-• {pnl_emoji} Total P&L: {total_pnl_str} ({token_stats['pnl_percentage']:+.2f}%)
|
|
|
+• {pnl_emoji} Total P&L: {total_pnl_str} ({pnl_pct:+.2f}%)
|
|
|
• 💵 Total Volume: {completed_volume_str}
|
|
|
• 📈 Expectancy: {expectancy_str}
|
|
|
|
|
|
📊 <b>Trading Activity:</b>
|
|
|
-• Total Trades: {token_stats['total_trades']}
|
|
|
-• Completed: {token_stats['completed_trades']}
|
|
|
-• Buy Orders: {token_stats['buy_trades']}
|
|
|
-• Sell Orders: {token_stats['sell_trades']}
|
|
|
+• Total Trades: {token_stats.get('summary_total_trades', 0)}
|
|
|
+• Completed: {perf_summary.get('completed_trades', 0)}
|
|
|
+• Buy Orders: {token_stats.get('buy_trades', 0)}
|
|
|
+• Sell Orders: {token_stats.get('sell_trades', 0)}
|
|
|
|
|
|
🏆 <b>Performance Metrics:</b>
|
|
|
-• Win Rate: {token_stats['win_rate']:.1f}%
|
|
|
-• Profit Factor: {token_stats['profit_factor']:.2f}
|
|
|
-• Wins: {token_stats['total_wins']} | Losses: {token_stats['total_losses']}
|
|
|
+• Win Rate: {perf_summary.get('win_rate', 0):.1f}%
|
|
|
+• Profit Factor: {perf_summary.get('profit_factor', 0):.2f}
|
|
|
+• Wins: {perf_summary.get('total_wins', 0)} | Losses: {perf_summary.get('total_losses', 0)}
|
|
|
|
|
|
💡 <b>Best/Worst:</b>
|
|
|
• Largest Win: {largest_win_str}
|