""" Backtesting Schemas. Pydantic schemas for validating and serializing backtesting API requests and responses. """ from typing import List, Optional, Dict, Any from pydantic import BaseModel, Field class BacktestingRequest(BaseModel): """Request schema for running backtesting.""" leagues: Optional[List[str]] = Field( None, description="List of leagues to filter by (e.g., ['Ligue 1', 'Premier League'])", example=["Ligue 1", "Premier League"] ) start_date: Optional[str] = Field( None, description="Start date for filtering matches (ISO 8601 format)", example="2025-01-01T00:00:00Z" ) end_date: Optional[str] = Field( None, description="End date for filtering matches (ISO 8601 format)", example="2025-12-31T23:59:59Z" ) export_format: Optional[str] = Field( None, description="Export format for results: 'json', 'csv', or 'html'", example="html" ) class Config: json_schema_extra = { "example": { "leagues": ["Ligue 1", "Premier League"], "start_date": "2025-01-01T00:00:00Z", "end_date": "2025-12-31T23:59:59Z", "export_format": "html" } } class MatchResultSchema(BaseModel): """Schema for single match backtesting result.""" match_id: int league: Optional[str] = None date: Optional[str] = None home_team: str away_team: str home_energy: float away_energy: float prediction: Dict[str, Any] actual_winner: str correct: bool class Config: from_attributes = True class LeagueMetricsSchema(BaseModel): """Schema for league-specific metrics.""" total: int correct: int accuracy: float class Config: from_attributes = True class ValidationThresholdsSchema(BaseModel): """Schema for validation thresholds.""" validated: float alert: float class Config: from_attributes = True class BacktestingData(BaseModel): """Schema for backtesting result data.""" total_matches: int correct_predictions: int incorrect_predictions: int accuracy: float status: str results: List[MatchResultSchema] metrics_by_league: Dict[str, LeagueMetricsSchema] timestamp: str validation_thresholds: ValidationThresholdsSchema export: Optional[Dict[str, Any]] = None class Config: from_attributes = True class BacktestingResponse(BaseModel): """Response schema for backtesting API.""" data: BacktestingData meta: Dict[str, Any] class Config: json_schema_extra = { "example": { "data": { "total_matches": 100, "correct_predictions": 65, "incorrect_predictions": 35, "accuracy": 65.0, "status": "VALIDATED", "results": [ { "match_id": 1, "league": "Ligue 1", "date": "2025-01-15T20:00:00Z", "home_team": "PSG", "away_team": "OM", "home_energy": 65.0, "away_energy": 45.0, "prediction": { "confidence": 40.0, "predicted_winner": "home", "home_energy": 65.0, "away_energy": 45.0 }, "actual_winner": "home", "correct": True } ], "metrics_by_league": { "Ligue 1": {"total": 50, "correct": 33, "accuracy": 66.0}, "Premier League": {"total": 50, "correct": 32, "accuracy": 64.0} }, "timestamp": "2026-01-17T10:30:00Z", "validation_thresholds": { "validated": 60.0, "alert": 55.0 } }, "meta": { "timestamp": "2026-01-17T10:30:00Z", "version": "v1" } } } class ErrorDetail(BaseModel): """Schema for error details.""" code: str message: str details: Optional[Dict[str, Any]] = None class BacktestingErrorResponse(BaseModel): """Response schema for backtesting API errors.""" error: ErrorDetail meta: Dict[str, Any] class Config: json_schema_extra = { "example": { "error": { "code": "NO_MATCHES_FOUND", "message": "No historical matches found matching the specified filters", "details": { "filters": { "leagues": ["Ligue 1"], "start_date": "2025-01-01T00:00:00Z", "end_date": "2025-12-31T23:59:59Z" } } }, "meta": { "timestamp": "2026-01-17T10:30:00Z", "request_id": "req-abc123" } } }