File size: 2,390 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
"""
Backtesting API endpoints.

Responsabilidad: Manejar requests de backtesting (evaluaci贸n de modelos).
"""

from fastapi import APIRouter, Depends, HTTPException, status

from app.api.dependencies import get_backtest_use_case
from app.application.use_cases.backtest_use_case import BacktestUseCase
from app.application.dtos.backtest_dtos import (
    BacktestRequestDTO,
    BacktestResponseDTO
)
from app.utils.logger import setup_logger

logger = setup_logger(__name__)

router = APIRouter(prefix="/backtest", tags=["Backtesting"])


@router.post(
    "/simple",
    response_model=BacktestResponseDTO,
    status_code=status.HTTP_200_OK,
    summary="Backtesting simple",
    description="Eval煤a pron贸stico comparando con valores reales"
)
async def backtest_simple(
    request: BacktestRequestDTO,
    use_case: BacktestUseCase = Depends(get_backtest_use_case)
):
    """
    Backtesting simple (hold-out).
    
    Divide la serie en train/test, genera pron贸stico con train,
    y compara con test para calcular m茅tricas de error.
    
    Args:
        request: Serie completa y par谩metros de backtesting
        use_case: Caso de uso inyectado
        
    Returns:
        M茅tricas de error (MAE, MAPE, RMSE) y comparaci贸n forecast vs actual
        
    Example:
        ```json
        {
            "full_series": [100, 102, 105, 103, 108, 112, 115, 118],
            "test_size": 3,
            "freq": "D",
            "quantile_levels": [0.1, 0.5, 0.9]
        }
        ```
    """
    try:
        logger.info(
            f"Backtest request: {len(request.full_series)} values, "
            f"test_size={request.test_size}"
        )
        
        # Ejecutar use case
        response = use_case.execute(request)
        
        logger.info(
            f"Backtest completed: MAE={response.metrics.mae:.2f}, "
            f"MAPE={response.metrics.mape:.2f}%"
        )
        
        return response
        
    except ValueError as e:
        logger.error(f"Validation error: {e}")
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail=str(e)
        )
    except Exception as e:
        logger.error(f"Unexpected error in backtest: {e}", exc_info=True)
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="Error interno en backtesting"
        )