Browse Source

Update bot version and enhance risk metrics reporting

- Incremented bot version to 2.4.255.
- Improved Sharpe ratio reporting in RiskCommands to handle cases with insufficient data, providing clearer user feedback.
- Refactored stats command to utilize a centralized formatter for better balance and performance statistics presentation.
Carles Sentis 3 days ago
parent
commit
719c150ea6
2 changed files with 15 additions and 69 deletions
  1. 4 1
      src/commands/info/risk.py
  2. 11 68
      src/commands/info/stats.py

+ 4 - 1
src/commands/info/risk.py

@@ -144,7 +144,10 @@ class RiskCommands(InfoCommandsBase):
 
 
                 # Sharpe Ratio
                 # Sharpe Ratio
                 sharpe_ratio = risk_metrics.get('sharpe_ratio')
                 sharpe_ratio = risk_metrics.get('sharpe_ratio')
-                message += f"• Sharpe Ratio: {sharpe_ratio:.2f}\n"
+                if sharpe_ratio is not None:
+                    message += f"• Sharpe Ratio: {sharpe_ratio:.2f}\n"
+                else:
+                    message += f"• Sharpe Ratio: N/A (Insufficient data)\n"
             
             
             await self._reply(update, message)
             await self._reply(update, message)
             
             

+ 11 - 68
src/commands/info/stats.py

@@ -88,79 +88,22 @@ class StatsCommands(InfoCommandsBase):
                 await self._reply(update, "❌ Trading stats not available.")
                 await self._reply(update, "❌ Trading stats not available.")
                 return
                 return
 
 
+            # If a token is provided, show detailed stats for that token
             if context.args and len(context.args) > 0:
             if context.args and len(context.args) > 0:
-                # Token-specific stats
                 token_name = context.args[0].upper()
                 token_name = context.args[0].upper()
-                token_stats = stats.get_token_stats(token_name)
-                if not token_stats:
-                    await self._reply(update, f"❌ No trading data found for {token_name}.")
-                    return
-                stats_message = await self._format_token_specific_stats_message(token_stats, token_name)
+                # Assuming get_token_detailed_stats is the correct method in TradingStats
+                # to get the data needed by format_token_stats_message.
+                stats_message = await stats.format_token_stats_message(token_name)
                 await self._reply(update, stats_message)
                 await self._reply(update, stats_message)
                 return
                 return
 
 
-            # Get current balance
-            current_balance = self.trading_engine.get_balance()
-            # Fix: If current_balance is a dict, extract the numeric value
-            if isinstance(current_balance, dict):
-                # Try common keys for USDC or total
-                if 'USDC' in current_balance and isinstance(current_balance['USDC'], dict):
-                    current_balance = current_balance['USDC'].get('total', 0)
-                elif 'total' in current_balance:
-                    current_balance = current_balance['total']
-                else:
-                    # Fallback: try to find a float value in the dict
-                    for v in current_balance.values():
-                        if isinstance(v, (float, int)):
-                            current_balance = v
-                            break
-                    else:
-                        current_balance = 0
-
-            # Get performance stats
-            perf = stats.get_performance_stats()
-            if not perf:
-                await self._reply(update, "❌ Could not get performance stats.")
-                return
-
-            # Format the message
-            formatter = get_formatter()
-            stats_text_parts = ["📊 <b>Trading Statistics</b>\n"]
-
-            # Account Overview
-            stats_text_parts.append("💰 <b>Account Overview:</b>")
-            stats_text_parts.append(f"• Current Balance: {await formatter.format_price_with_symbol(current_balance)}")
-            stats_text_parts.append(f"• Open Positions: {perf.get('open_positions', 0)}")
-            stats_text_parts.append(f"• Total P&L: {await formatter.format_price_with_symbol(perf.get('total_pnl', 0))}")
-
-            # Performance Metrics
-            stats_text_parts.append("\n🏆 <b>Performance Metrics:</b>")
-            stats_text_parts.append(f"• Total Trades: {perf.get('total_trades', 0)}")
-            stats_text_parts.append(f"• Win Rate: {perf.get('win_rate', 0.0):.1f}% ({perf.get('total_wins', 0)}/{perf.get('total_trades', 0)})")
-            stats_text_parts.append(f"• Trading Volume: {await formatter.format_price_with_symbol(perf.get('total_entry_volume', 0.0))}")
-            stats_text_parts.append(f"• Profit Factor: {perf.get('profit_factor', 0.0):.2f}")
-            stats_text_parts.append(f"• Expectancy: {await formatter.format_price_with_symbol(perf.get('expectancy', 0.0))}")
-
-            # Largest Trades
-            stats_text_parts.append("\n📈 <b>Largest Trades:</b>")
-            stats_text_parts.append(f"• Largest Win: {await formatter.format_price_with_symbol(perf.get('largest_win', 0.0))} ({perf.get('largest_win_pct', 0.0):+.2f}%) ({perf.get('largest_win_token', 'N/A')})")
-            stats_text_parts.append(f"• Largest Loss: {await formatter.format_price_with_symbol(perf.get('largest_loss', 0.0))} ({perf.get('largest_loss_pct', 0.0):+.2f}%) ({perf.get('largest_loss_token', 'N/A')})")
-
-            # Best/Worst Tokens
-            stats_text_parts.append("\n🏆 <b>Token Performance:</b>")
-            stats_text_parts.append(f"• Best Token: {perf.get('best_token', 'N/A')} {await formatter.format_price_with_symbol(perf.get('best_token_pnl', 0.0))} ({perf.get('best_token_pct', 0.0):+.2f}%)")
-            stats_text_parts.append(f"• Worst Token: {perf.get('worst_token', 'N/A')} {await formatter.format_price_with_symbol(perf.get('worst_token_pnl', 0.0))} ({perf.get('worst_token_pct', 0.0):+.2f}%)")
-
-            # Risk Metrics
-            stats_text_parts.append("\n⚠️ <b>Risk Metrics:</b>")
-            stats_text_parts.append(f"• Max Drawdown: {perf.get('max_drawdown_pct', 0.0):.2f}%")
-
-            # Session Info
-            stats_text_parts.append("\n⏰ <b>Session Info:</b>")
-            stats_text_parts.append(f"• Stats Last Updated: {datetime.now(timezone.utc).strftime('%Y-%m-%d %H:%M:%S UTC')}")
-
-            await self._reply(update, "\n".join(stats_text_parts))
+            # For the general /stats command, use the centralized formatter
+            balance_info = self.trading_engine.get_balance()
+            current_balance = balance_info.get('total', {}).get('USDC', 0.0)
+            
+            stats_message = await stats.format_stats_message(current_balance)
+            await self._reply(update, stats_message, disable_web_page_preview=True)
 
 
         except Exception as e:
         except Exception as e:
-            logger.error(f"Error in stats command: {e}")
+            logger.error(f"Error in stats command: {e}", exc_info=True)
             await self._reply(update, f"❌ Error getting statistics: {str(e)}")
             await self._reply(update, f"❌ Error getting statistics: {str(e)}")