marrtinagg commited on
Commit
9aac6c4
·
1 Parent(s): 1696aa3

Añadir modelo BBVA y endpoint de predicción

Browse files
app.py CHANGED
@@ -1,7 +1,129 @@
 
 
 
 
1
  from fastapi import FastAPI
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2
 
3
- app = FastAPI()
 
 
4
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5
  @app.get("/")
6
  def home():
7
- return {"message": "✅ Hola Martina, el backend está funcionando correctamente!"}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # ============================================================
2
+ # 📈 app.py — Backend FastAPI para predicciones BBVA
3
+ # ============================================================
4
+
5
  from fastapi import FastAPI
6
+ from pydantic import BaseModel
7
+ from fastapi.middleware.cors import CORSMiddleware
8
+ import torch
9
+ from torch import nn
10
+ import joblib
11
+ import numpy as np
12
+ import pandas as pd
13
+
14
+ # ============================================================
15
+ # 1️⃣ Configuración base de FastAPI
16
+ # ============================================================
17
+ app = FastAPI(title="Predicción BBVA API")
18
+
19
+ # Permitir acceso desde cualquier dominio (para GitHub Pages luego)
20
+ app.add_middleware(
21
+ CORSMiddleware,
22
+ allow_origins=["*"],
23
+ allow_credentials=True,
24
+ allow_methods=["*"],
25
+ allow_headers=["*"],
26
+ )
27
+
28
+ # ============================================================
29
+ # 2️⃣ Definición del modelo LSTM (idéntico al entrenamiento)
30
+ # ============================================================
31
+ class LSTMModel(nn.Module):
32
+ def __init__(self, n_features, hidden_size=64):
33
+ super().__init__()
34
+ self.lstm = nn.LSTM(input_size=n_features, hidden_size=hidden_size, batch_first=True)
35
+ self.fc = nn.Linear(hidden_size, 1)
36
+ def forward(self, x):
37
+ out, _ = self.lstm(x)
38
+ out = out[:, -1, :]
39
+ out = self.fc(out)
40
+ return out.squeeze()
41
+
42
+ # ============================================================
43
+ # 3️⃣ Cargar el modelo y los scalers
44
+ # ============================================================
45
+ MODEL_PATH = "models_bbva/bbva_lstm_model.pth"
46
+ SCALER_FULL_PATH = "models_bbva/scaler_features_full.pkl"
47
+ SCALER_TARGET_PATH = "models_bbva/scaler_target.pkl"
48
 
49
+ n_features = 5
50
+ hidden_size = 64
51
+ device = torch.device("cpu")
52
 
53
+ # Cargar modelo y scalers
54
+ model = LSTMModel(n_features, hidden_size)
55
+ model.load_state_dict(torch.load(MODEL_PATH, map_location=device))
56
+ model.to(device)
57
+ model.eval()
58
+
59
+ scaler_features = joblib.load(SCALER_FULL_PATH)
60
+ scaler_target = joblib.load(SCALER_TARGET_PATH)
61
+
62
+ # ============================================================
63
+ # 4️⃣ Modelo de entrada (JSON)
64
+ # ============================================================
65
+ class PredictRequest(BaseModel):
66
+ n_future: int = 3
67
+
68
+ # ============================================================
69
+ # 5️⃣ Endpoint raíz de prueba
70
+ # ============================================================
71
  @app.get("/")
72
  def home():
73
+ return {"message": "✅ Backend BBVA activo y listo para predecir"}
74
+
75
+ # ============================================================
76
+ # 6️⃣ Endpoint de predicción
77
+ # ============================================================
78
+ @app.post("/predict/bbva")
79
+ def predict_bbva(req: PredictRequest):
80
+ # === Cargar dataset base ===
81
+ PATH_BBVA = "data/bbva_pred.csv" # opcional, puedes cambiarlo
82
+ try:
83
+ bbva = pd.read_csv(PATH_BBVA)
84
+ except Exception:
85
+ return {"error": "No se encontró el archivo de datos base (data/bbva_pred.csv)"}
86
+
87
+ bbva["Date"] = pd.to_datetime(bbva["Date"])
88
+ bbva = bbva.set_index("Date")
89
+ start_date = "2021-01-01"
90
+ end_date = "2025-10-31"
91
+ bbva = bbva.loc[(bbva.index >= start_date) & (bbva.index <= end_date)].copy()
92
+
93
+ # === Columnas del modelo ===
94
+ cols_to_scale = [
95
+ 'Open', 'High', 'Low', 'Close', 'Adj Close',
96
+ 'ma_5', 'close_lag1', 'close_lag2', 'close_lag3',
97
+ 'Volume', 'ibex_momentum_5d'
98
+ ]
99
+ features = ['Open', 'High', 'Low', 'return_1d', 'return_3d']
100
+ window_size = 3
101
+ n_future = req.n_future
102
+
103
+ # === Escalar ===
104
+ bbva_scaled = bbva.copy()
105
+ bbva_scaled[cols_to_scale] = scaler_features.transform(bbva[cols_to_scale])
106
+
107
+ # === Última ventana ===
108
+ last_window = bbva_scaled[features].iloc[-window_size:].values
109
+
110
+ # === Predicción iterativa ===
111
+ preds_scaled = []
112
+ window = last_window.copy()
113
+ for _ in range(n_future):
114
+ X_input = torch.tensor(window, dtype=torch.float32).unsqueeze(0).to(device)
115
+ with torch.no_grad():
116
+ pred_scaled = model(X_input).cpu().numpy().flatten()[0]
117
+ preds_scaled.append(pred_scaled)
118
+ next_day = window[-1].copy()
119
+ window = np.vstack([window[1:], next_day])
120
+
121
+ # === Desescalar ===
122
+ preds_real = scaler_target.inverse_transform(np.array(preds_scaled).reshape(-1, 1)).flatten().tolist()
123
+
124
+ # === Fechas futuras ===
125
+ last_date = bbva.index[-1]
126
+ future_dates = pd.date_range(last_date + pd.Timedelta(days=1), periods=n_future, freq="B")
127
+ fechas = [str(d.date()) for d in future_dates]
128
+
129
+ return {"fechas": fechas, "predicciones": preds_real}
data/bbva_pred.csv ADDED
The diff for this file is too large to render. See raw diff
 
models_bbva/bbva_lstm_model.pth ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:c83ee225e37688bc90d9c19d3a43d9fcf6dc6da245fe43c56f4cb9960792075c
3
+ size 75497
models_bbva/scaler_features_full.pkl ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:362d0ed626b992c46b7abfb343876c908065350f9645d8b6b3c07176b23f5f5e
3
+ size 1487
models_bbva/scaler_features_train.pkl ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:b3738f565788faf7031bb48aae5e9569bbb1c13b9c04ced86265b08d20395e73
3
+ size 1487
models_bbva/scaler_target.pkl ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:88a0fa16db10ebc2c1959eb96de8397e2c091febad0006f83aa10abcaaf81b2c
3
+ size 975