File size: 3,121 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
"""
DTOs para casos de uso de Forecasting.
"""

from dataclasses import dataclass
from typing import List, Optional, Dict


@dataclass
class ForecastInputDTO:
    """DTO de entrada para pron贸stico univariado."""
    
    values: List[float]
    prediction_length: int
    quantile_levels: List[float]
    timestamps: Optional[List[str]] = None
    series_id: str = "series_0"
    freq: str = "D"
    
    def validate(self) -> None:
        """Valida los datos de entrada."""
        if not self.values:
            raise ValueError("values no puede estar vac铆o")
        
        if self.prediction_length < 1:
            raise ValueError("prediction_length debe ser >= 1")
        
        if not all(0 <= q <= 1 for q in self.quantile_levels):
            raise ValueError("quantile_levels debe estar en [0, 1]")
        
        if self.timestamps and len(self.timestamps) != len(self.values):
            raise ValueError("timestamps y values deben tener la misma longitud")


@dataclass
class ForecastOutputDTO:
    """DTO de salida para pron贸stico univariado."""
    
    timestamps: List[str]
    median: List[float]
    quantiles: Dict[str, List[float]]
    series_id: str = "series_0"
    metadata: Optional[Dict] = None
    
    def to_dict(self) -> Dict:
        """Convierte a diccionario."""
        result = {
            "timestamps": self.timestamps,
            "median": self.median,
            "quantiles": self.quantiles,
            "series_id": self.series_id
        }
        
        if self.metadata:
            result["metadata"] = self.metadata
        
        return result


@dataclass
class SeriesInputDTO:
    """DTO para una serie individual en pron贸stico m煤ltiple."""
    
    series_id: str
    values: List[float]
    timestamps: Optional[List[str]] = None


@dataclass
class MultiForecastInputDTO:
    """DTO de entrada para pron贸stico m煤ltiple."""
    
    series_list: List[SeriesInputDTO]
    prediction_length: int
    quantile_levels: List[float]
    freq: str = "D"
    
    def validate(self) -> None:
        """Valida los datos de entrada."""
        if not self.series_list:
            raise ValueError("series_list no puede estar vac铆o")
        
        if self.prediction_length < 1:
            raise ValueError("prediction_length debe ser >= 1")
        
        if not all(0 <= q <= 1 for q in self.quantile_levels):
            raise ValueError("quantile_levels debe estar en [0, 1]")
        
        # Validar cada serie
        for series in self.series_list:
            if not series.values:
                raise ValueError(f"Serie {series.series_id} est谩 vac铆a")


@dataclass
class MultiForecastOutputDTO:
    """DTO de salida para pron贸stico m煤ltiple."""
    
    results: List[ForecastOutputDTO]
    total_series: int
    successful: int
    failed: int
    
    def to_dict(self) -> Dict:
        """Convierte a diccionario."""
        return {
            "results": [r.to_dict() for r in self.results],
            "total_series": self.total_series,
            "successful": self.successful,
            "failed": self.failed
        }