2026-02-01 09:31:38 +01:00

192 lines
5.3 KiB
Python

"""
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"
}
}
}