Spaces:
Build error
Build error
File size: 3,571 Bytes
c40c447 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 |
"""
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
}
|