|
@@ -855,74 +855,145 @@ Please try again in a moment. If the issue persists, contact support.
|
|
stats['pnl_pct'] = 0.0
|
|
stats['pnl_pct'] = 0.0
|
|
|
|
|
|
def get_daily_stats(self, limit: int = 10) -> List[Dict[str, Any]]:
|
|
def get_daily_stats(self, limit: int = 10) -> List[Dict[str, Any]]:
|
|
- """Get daily performance stats for the last N days."""
|
|
|
|
|
|
+ """Get daily performance stats for the last N days (including days with no trades)."""
|
|
# Ensure period stats are up to date
|
|
# Ensure period stats are up to date
|
|
self._update_period_stats()
|
|
self._update_period_stats()
|
|
|
|
|
|
- # Get sorted daily stats (most recent first)
|
|
|
|
|
|
+ # Generate the last N calendar days
|
|
daily_stats = []
|
|
daily_stats = []
|
|
- for date_str, stats in sorted(self.data['daily_stats'].items(), reverse=True):
|
|
|
|
- try:
|
|
|
|
- date_obj = datetime.strptime(date_str, '%Y-%m-%d')
|
|
|
|
|
|
+ today = datetime.now().date()
|
|
|
|
+
|
|
|
|
+ for i in range(limit):
|
|
|
|
+ # Calculate the date (going backwards from today)
|
|
|
|
+ target_date = today - timedelta(days=i)
|
|
|
|
+ date_str = target_date.strftime('%Y-%m-%d')
|
|
|
|
+ date_formatted = target_date.strftime('%m/%d')
|
|
|
|
+
|
|
|
|
+ # Check if we have stats for this date
|
|
|
|
+ if date_str in self.data['daily_stats']:
|
|
|
|
+ stats = self.data['daily_stats'][date_str]
|
|
daily_stats.append({
|
|
daily_stats.append({
|
|
'date': date_str,
|
|
'date': date_str,
|
|
- 'date_formatted': date_obj.strftime('%m/%d'),
|
|
|
|
|
|
+ 'date_formatted': date_formatted,
|
|
'trades': stats['trades'],
|
|
'trades': stats['trades'],
|
|
'pnl': stats['pnl'],
|
|
'pnl': stats['pnl'],
|
|
'pnl_pct': stats['pnl_pct'],
|
|
'pnl_pct': stats['pnl_pct'],
|
|
- 'volume': stats['volume']
|
|
|
|
|
|
+ 'volume': stats['volume'],
|
|
|
|
+ 'has_trades': True
|
|
|
|
+ })
|
|
|
|
+ else:
|
|
|
|
+ # No trades on this date
|
|
|
|
+ daily_stats.append({
|
|
|
|
+ 'date': date_str,
|
|
|
|
+ 'date_formatted': date_formatted,
|
|
|
|
+ 'trades': 0,
|
|
|
|
+ 'pnl': 0.0,
|
|
|
|
+ 'pnl_pct': 0.0,
|
|
|
|
+ 'volume': 0.0,
|
|
|
|
+ 'has_trades': False
|
|
})
|
|
})
|
|
- except ValueError:
|
|
|
|
- continue
|
|
|
|
|
|
|
|
- return daily_stats[:limit]
|
|
|
|
|
|
+ return daily_stats
|
|
|
|
|
|
def get_weekly_stats(self, limit: int = 10) -> List[Dict[str, Any]]:
|
|
def get_weekly_stats(self, limit: int = 10) -> List[Dict[str, Any]]:
|
|
- """Get weekly performance stats for the last N weeks."""
|
|
|
|
|
|
+ """Get weekly performance stats for the last N weeks (including weeks with no trades)."""
|
|
# Ensure period stats are up to date
|
|
# Ensure period stats are up to date
|
|
self._update_period_stats()
|
|
self._update_period_stats()
|
|
|
|
|
|
- # Get sorted weekly stats (most recent first)
|
|
|
|
|
|
+ # Generate the last N calendar weeks
|
|
weekly_stats = []
|
|
weekly_stats = []
|
|
- for week_str, stats in sorted(self.data['weekly_stats'].items(), reverse=True):
|
|
|
|
- try:
|
|
|
|
- # Parse week format YYYY-WXX
|
|
|
|
- year, week_num = week_str.split('-W')
|
|
|
|
- week_start = datetime.strptime(f"{year}-W{week_num.zfill(2)}-1", "%Y-W%U-%w")
|
|
|
|
- week_end = week_start + timedelta(days=6)
|
|
|
|
-
|
|
|
|
|
|
+ today = datetime.now().date()
|
|
|
|
+
|
|
|
|
+ for i in range(limit):
|
|
|
|
+ # Calculate the start of the week (going backwards from today)
|
|
|
|
+ # Find the Monday of the target week
|
|
|
|
+ days_since_monday = today.weekday()
|
|
|
|
+ current_monday = today - timedelta(days=days_since_monday)
|
|
|
|
+ target_monday = current_monday - timedelta(weeks=i)
|
|
|
|
+ target_sunday = target_monday + timedelta(days=6)
|
|
|
|
+
|
|
|
|
+ # Generate week string (YYYY-WXX format)
|
|
|
|
+ week_str = target_monday.strftime('%Y-W%U')
|
|
|
|
+ week_formatted = f"{target_monday.strftime('%m/%d')}-{target_sunday.strftime('%m/%d')}"
|
|
|
|
+
|
|
|
|
+ # Check if we have stats for this week
|
|
|
|
+ if week_str in self.data['weekly_stats']:
|
|
|
|
+ stats = self.data['weekly_stats'][week_str]
|
|
weekly_stats.append({
|
|
weekly_stats.append({
|
|
'week': week_str,
|
|
'week': week_str,
|
|
- 'week_formatted': f"{week_start.strftime('%m/%d')}-{week_end.strftime('%m/%d')}",
|
|
|
|
|
|
+ 'week_formatted': week_formatted,
|
|
'trades': stats['trades'],
|
|
'trades': stats['trades'],
|
|
'pnl': stats['pnl'],
|
|
'pnl': stats['pnl'],
|
|
'pnl_pct': stats['pnl_pct'],
|
|
'pnl_pct': stats['pnl_pct'],
|
|
- 'volume': stats['volume']
|
|
|
|
|
|
+ 'volume': stats['volume'],
|
|
|
|
+ 'has_trades': True
|
|
|
|
+ })
|
|
|
|
+ else:
|
|
|
|
+ # No trades in this week
|
|
|
|
+ weekly_stats.append({
|
|
|
|
+ 'week': week_str,
|
|
|
|
+ 'week_formatted': week_formatted,
|
|
|
|
+ 'trades': 0,
|
|
|
|
+ 'pnl': 0.0,
|
|
|
|
+ 'pnl_pct': 0.0,
|
|
|
|
+ 'volume': 0.0,
|
|
|
|
+ 'has_trades': False
|
|
})
|
|
})
|
|
- except (ValueError, IndexError):
|
|
|
|
- continue
|
|
|
|
|
|
|
|
- return weekly_stats[:limit]
|
|
|
|
|
|
+ return weekly_stats
|
|
|
|
|
|
def get_monthly_stats(self, limit: int = 10) -> List[Dict[str, Any]]:
|
|
def get_monthly_stats(self, limit: int = 10) -> List[Dict[str, Any]]:
|
|
- """Get monthly performance stats for the last N months."""
|
|
|
|
|
|
+ """Get monthly performance stats for the last N months (including months with no trades)."""
|
|
# Ensure period stats are up to date
|
|
# Ensure period stats are up to date
|
|
self._update_period_stats()
|
|
self._update_period_stats()
|
|
|
|
|
|
- # Get sorted monthly stats (most recent first)
|
|
|
|
|
|
+ # Generate the last N calendar months
|
|
monthly_stats = []
|
|
monthly_stats = []
|
|
- for month_str, stats in sorted(self.data['monthly_stats'].items(), reverse=True):
|
|
|
|
- try:
|
|
|
|
- month_obj = datetime.strptime(month_str, '%Y-%m')
|
|
|
|
|
|
+ today = datetime.now().date()
|
|
|
|
+ current_month = today.replace(day=1) # First day of current month
|
|
|
|
+
|
|
|
|
+ for i in range(limit):
|
|
|
|
+ # Calculate the target month (going backwards from current month)
|
|
|
|
+ if i == 0:
|
|
|
|
+ target_month = current_month
|
|
|
|
+ else:
|
|
|
|
+ # Go back i months
|
|
|
|
+ year = current_month.year
|
|
|
|
+ month = current_month.month - i
|
|
|
|
+
|
|
|
|
+ # Handle year rollover
|
|
|
|
+ while month <= 0:
|
|
|
|
+ month += 12
|
|
|
|
+ year -= 1
|
|
|
|
+
|
|
|
|
+ target_month = datetime(year, month, 1).date()
|
|
|
|
+
|
|
|
|
+ # Generate month string (YYYY-MM format)
|
|
|
|
+ month_str = target_month.strftime('%Y-%m')
|
|
|
|
+ month_formatted = target_month.strftime('%b %Y')
|
|
|
|
+
|
|
|
|
+ # Check if we have stats for this month
|
|
|
|
+ if month_str in self.data['monthly_stats']:
|
|
|
|
+ stats = self.data['monthly_stats'][month_str]
|
|
monthly_stats.append({
|
|
monthly_stats.append({
|
|
'month': month_str,
|
|
'month': month_str,
|
|
- 'month_formatted': month_obj.strftime('%b %Y'),
|
|
|
|
|
|
+ 'month_formatted': month_formatted,
|
|
'trades': stats['trades'],
|
|
'trades': stats['trades'],
|
|
'pnl': stats['pnl'],
|
|
'pnl': stats['pnl'],
|
|
'pnl_pct': stats['pnl_pct'],
|
|
'pnl_pct': stats['pnl_pct'],
|
|
- 'volume': stats['volume']
|
|
|
|
|
|
+ 'volume': stats['volume'],
|
|
|
|
+ 'has_trades': True
|
|
|
|
+ })
|
|
|
|
+ else:
|
|
|
|
+ # No trades in this month
|
|
|
|
+ monthly_stats.append({
|
|
|
|
+ 'month': month_str,
|
|
|
|
+ 'month_formatted': month_formatted,
|
|
|
|
+ 'trades': 0,
|
|
|
|
+ 'pnl': 0.0,
|
|
|
|
+ 'pnl_pct': 0.0,
|
|
|
|
+ 'volume': 0.0,
|
|
|
|
+ 'has_trades': False
|
|
})
|
|
})
|
|
- except ValueError:
|
|
|
|
- continue
|
|
|
|
|
|
|
|
- return monthly_stats[:limit]
|
|
|
|
|
|
+ return monthly_stats
|