daily.py 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
  1. import logging
  2. from telegram import Update
  3. from telegram.ext import ContextTypes
  4. from .base import InfoCommandsBase
  5. from src.utils.token_display_formatter import get_formatter
  6. logger = logging.getLogger(__name__)
  7. class DailyCommands(InfoCommandsBase):
  8. """Handles all daily performance-related commands."""
  9. async def daily_command(self, update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
  10. """Handle the /daily command to show daily performance stats."""
  11. if not self._is_authorized(update):
  12. return
  13. try:
  14. stats = self.trading_engine.get_stats()
  15. if not stats:
  16. await self._reply(update, "❌ Could not load trading statistics")
  17. return
  18. daily_stats_list = stats.get_daily_stats(10) # Last 10 days
  19. formatter = get_formatter()
  20. if not daily_stats_list:
  21. await self._reply(update, "📅 <b>Daily Performance</b>\n📭 No daily performance data available yet.\n💡 Daily stats are calculated from completed trades. Start trading to see them!")
  22. return
  23. daily_text_parts = [f"📅 <b>Daily Performance (Last 10 Days)</b>"]
  24. total_pnl_all_days = 0
  25. total_trades_all_days = 0
  26. total_roe_all_days = 0
  27. trading_days_count = 0
  28. period_lines = []
  29. for day_stats_item in daily_stats_list:
  30. if day_stats_item.get('has_trades'):
  31. pnl_emoji = "🟢" if day_stats_item.get('pnl', 0) >= 0 else "🔴"
  32. pnl_str = formatter.format_price_with_symbol(day_stats_item.get('pnl', 0))
  33. roe = day_stats_item.get('roe', 0.0) # Get ROE from stats
  34. roe_str = f"ROE: {roe:+.1f}%" if roe != 0 else ""
  35. day_str = day_stats_item.get('date_formatted', 'Unknown')
  36. period_lines.append(f"📅 <b>{day_str}</b>: {pnl_emoji} {pnl_str} ({day_stats_item.get('pnl_pct', 0):+.1f}%) {roe_str} | Trades: {day_stats_item.get('trades', 0)}")
  37. total_pnl_all_days += day_stats_item.get('pnl', 0)
  38. total_trades_all_days += day_stats_item.get('trades', 0)
  39. total_roe_all_days += roe
  40. trading_days_count += 1
  41. else:
  42. day_str = day_stats_item.get('date_formatted', 'Unknown')
  43. period_lines.append(f"📅 <b>{day_str}</b>: 📭 No trading activity")
  44. if period_lines:
  45. daily_text_parts.append("\n".join(period_lines))
  46. if trading_days_count > 0:
  47. avg_daily_pnl = total_pnl_all_days / trading_days_count
  48. avg_daily_roe = total_roe_all_days / trading_days_count
  49. avg_pnl_emoji = "🟢" if avg_daily_pnl >= 0 else "🔴"
  50. total_pnl_all_days_str = formatter.format_price_with_symbol(total_pnl_all_days)
  51. avg_daily_pnl_str = formatter.format_price_with_symbol(avg_daily_pnl)
  52. daily_text_parts.append(f"\n\n📈 <b>Period Summary:</b>")
  53. daily_text_parts.append(f" Total P&L: {avg_pnl_emoji} {total_pnl_all_days_str} | Avg Daily: {avg_daily_pnl_str}")
  54. daily_text_parts.append(f" Total ROE: {total_roe_all_days:+.1f}% | Avg Daily ROE: {avg_daily_roe:+.1f}%")
  55. daily_text_parts.append(f" Trading Days: {trading_days_count}/10 | Total Trades: {total_trades_all_days}")
  56. else:
  57. if not period_lines:
  58. daily_text_parts = [daily_text_parts[0]]
  59. daily_text_parts.append("\n\n📉 No trading activity in the last 10 days.")
  60. await self._reply(update, "\n".join(daily_text_parts).strip())
  61. except Exception as e:
  62. error_message = f"❌ Error processing daily command: {str(e)}"
  63. await self._reply(update, error_message)
  64. logger.error(f"Error in daily command: {e}")