ttzzs's picture
Deploy Chronos2 Forecasting API v3.0.0 with new SOLID architecture
c40c447 verified
"""
Modelo de dominio para configuraci贸n de forecasting.
Este m贸dulo define la entidad ForecastConfig, cumpliendo con SRP.
"""
from dataclasses import dataclass, field
from typing import List
@dataclass
class ForecastConfig:
"""
Configuraci贸n para operaciones de forecasting.
Define los par谩metros necesarios para realizar un pron贸stico,
incluyendo horizonte de predicci贸n, cuantiles y frecuencia.
Attributes:
prediction_length: N煤mero de per铆odos a pronosticar
quantile_levels: Cuantiles a calcular (ej: [0.1, 0.5, 0.9])
freq: Frecuencia temporal (D, H, M, etc.)
Example:
>>> config = ForecastConfig(
... prediction_length=7,
... quantile_levels=[0.1, 0.5, 0.9],
... freq="D"
... )
>>> config.has_median
True
"""
prediction_length: int
quantile_levels: List[float] = field(default_factory=lambda: [0.1, 0.5, 0.9])
freq: str = "D"
def __post_init__(self):
"""Validaci贸n y normalizaci贸n autom谩tica"""
self.validate()
self._ensure_median()
self._sort_quantiles()
@property
def has_median(self) -> bool:
"""Verifica si el cuantil 0.5 (mediana) est谩 incluido"""
return 0.5 in self.quantile_levels
def validate(self) -> bool:
"""
Valida la configuraci贸n.
Returns:
bool: True si es v谩lida
Raises:
ValueError: Si la configuraci贸n es inv谩lida
"""
# Validar prediction_length
if self.prediction_length < 1:
raise ValueError(
f"prediction_length debe ser >= 1, recibido: {self.prediction_length}"
)
# Validar quantile_levels
if not self.quantile_levels:
raise ValueError("quantile_levels no puede estar vac铆o")
# Verificar que los cuantiles est茅n en [0, 1]
for q in self.quantile_levels:
if not 0 <= q <= 1:
raise ValueError(
f"Todos los cuantiles deben estar en [0, 1], encontrado: {q}"
)
# Validar freq
valid_freqs = {"D", "H", "M", "W", "Y", "Q", "S", "T", "min"}
if self.freq not in valid_freqs:
raise ValueError(
f"Frecuencia '{self.freq}' no reconocida. "
f"V谩lidas: {valid_freqs}"
)
return True
def _ensure_median(self):
"""Asegura que la mediana (0.5) est茅 incluida"""
if not self.has_median:
self.quantile_levels.append(0.5)
def _sort_quantiles(self):
"""Ordena los cuantiles de menor a mayor"""
self.quantile_levels = sorted(set(self.quantile_levels))
@classmethod
def default(cls) -> "ForecastConfig":
"""
Crea una configuraci贸n con valores por defecto.
Returns:
ForecastConfig: Configuraci贸n por defecto
- prediction_length: 7
- quantile_levels: [0.1, 0.5, 0.9]
- freq: "D"
"""
return cls(
prediction_length=7,
quantile_levels=[0.1, 0.5, 0.9],
freq="D"
)
def to_dict(self) -> dict:
"""Serializa la configuraci贸n a diccionario"""
return {
"prediction_length": self.prediction_length,
"quantile_levels": self.quantile_levels,
"freq": self.freq
}