gaidasalsaa commited on
Commit
bad3546
·
1 Parent(s): ce0f10e

change app

Browse files
Files changed (1) hide show
  1. app.py +33 -50
app.py CHANGED
@@ -8,7 +8,6 @@ import numpy as np
8
  import os
9
  import requests
10
  import yfinance as yf
11
- import pandas as pd
12
 
13
  from huggingface_hub import hf_hub_download
14
  from model import LSTMModel
@@ -24,7 +23,8 @@ logging.basicConfig(level=logging.INFO)
24
  # CONFIG
25
  # ===========================
26
  HF_MODEL_REPO = "gaidasalsaa/lstm-exchange-rate-prediction-model"
27
- EXCHANGE_API_KEY = os.getenv("8b579e2eb898f797a652e3ef")
 
28
  EXCHANGE_API_URL = "https://v6.exchangerate-api.com/v6"
29
 
30
  MODEL_MAP = {
@@ -104,7 +104,7 @@ class PredictionResponse(BaseModel):
104
  data: Optional[dict] = None
105
 
106
  # ===========================
107
- # REAL-TIME EXCHANGE RATE
108
  # ===========================
109
  def get_realtime_rate(base, target):
110
  url = f"{EXCHANGE_API_URL}/{EXCHANGE_API_KEY}/pair/{base}/{target}"
@@ -112,11 +112,27 @@ def get_realtime_rate(base, target):
112
  data = r.json()
113
 
114
  if data.get("result") != "success":
115
- logger.error(f"ExchangeRate API error: {data}")
116
- raise ValueError("Failed to fetch real-time rate")
117
 
118
  return float(data["conversion_rate"])
119
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
120
 
121
  # ===========================
122
  # INFERENCE
@@ -131,16 +147,11 @@ def predict_forex(base, target, horizon):
131
  if model is None or scaler is None:
132
  return None, None
133
 
134
- # 1. Ambil harga real-time
135
- current_price = get_realtime_rate(base, target)
136
-
137
- # 2. Buat input sequence (LOOKBACK)
138
- # dummy historical values (stabil & aman)
139
- last_values = np.full((LOOKBACK - 1, 1), current_price)
140
- prices = np.vstack([last_values, [[current_price]]])
141
 
142
  scaled = scaler.transform(prices)
143
-
144
  X = create_input_sequence(scaled, LOOKBACK)
145
  X = torch.tensor(X, dtype=torch.float32)
146
 
@@ -148,24 +159,7 @@ def predict_forex(base, target, horizon):
148
  preds = model(X).numpy()
149
 
150
  preds = scaler.inverse_transform(preds.reshape(-1, 1)).flatten()
151
- return current_price, preds.tolist()
152
-
153
- # Mengambil 30 hari terakhir dari yfinance
154
- def fetch_last_30_days(base, target):
155
- symbol = f"{base}{target}=X"
156
-
157
- df = yf.download(
158
- symbol,
159
- period="60d", # ambil lebih untuk jaga-jaga
160
- interval="1d",
161
- progress=False
162
- )
163
-
164
- if df.empty or len(df) < 30:
165
- return None
166
-
167
- prices = df["Close"].dropna().tail(30).values.tolist()
168
- return prices
169
 
170
  # ===========================
171
  # ROUTE
@@ -173,36 +167,25 @@ def fetch_last_30_days(base, target):
173
  @app.post("/predict", response_model=PredictionResponse)
174
  def predict(req: PredictionRequest):
175
 
176
- prices = req.recent_prices
177
-
178
- # 🔥 Jika frontend tidak kirim data → backend ambil sendiri
179
- if not prices or len(prices) < LOOKBACK:
180
- logger.info("Fetching prices from Yahoo Finance...")
181
- prices = fetch_last_30_days(
182
- req.base_currency,
183
- req.target_currency
184
- )
185
 
186
- if prices is None:
187
  return PredictionResponse(
188
- message="Failed to fetch historical prices",
189
  data=None
190
  )
191
 
192
- preds = predict_forex(
193
- req.base_currency,
194
- req.target_currency,
195
- req.horizon,
196
- prices
197
- )
198
-
199
  return PredictionResponse(
200
  message="Prediction success",
201
  data={
202
  "base": req.base_currency,
203
  "target": req.target_currency,
204
  "horizon": req.horizon,
205
- "last_price": prices[-1],
206
  "predictions": preds
207
  }
208
  )
 
8
  import os
9
  import requests
10
  import yfinance as yf
 
11
 
12
  from huggingface_hub import hf_hub_download
13
  from model import LSTMModel
 
23
  # CONFIG
24
  # ===========================
25
  HF_MODEL_REPO = "gaidasalsaa/lstm-exchange-rate-prediction-model"
26
+
27
+ EXCHANGE_API_KEY = os.getenv("EXCHANGE_API_KEY")
28
  EXCHANGE_API_URL = "https://v6.exchangerate-api.com/v6"
29
 
30
  MODEL_MAP = {
 
104
  data: Optional[dict] = None
105
 
106
  # ===========================
107
+ # REAL-TIME RATE
108
  # ===========================
109
  def get_realtime_rate(base, target):
110
  url = f"{EXCHANGE_API_URL}/{EXCHANGE_API_KEY}/pair/{base}/{target}"
 
112
  data = r.json()
113
 
114
  if data.get("result") != "success":
115
+ raise ValueError("ExchangeRate API failed")
 
116
 
117
  return float(data["conversion_rate"])
118
 
119
+ # ===========================
120
+ # HISTORICAL DATA (YAHOO)
121
+ # ===========================
122
+ def fetch_last_30_days(base, target):
123
+ symbol = f"{base}{target}=X"
124
+
125
+ df = yf.download(
126
+ symbol,
127
+ period="60d",
128
+ interval="1d",
129
+ progress=False
130
+ )
131
+
132
+ if df.empty or len(df) < LOOKBACK:
133
+ return None
134
+
135
+ return df["Close"].dropna().tail(LOOKBACK).values.reshape(-1, 1)
136
 
137
  # ===========================
138
  # INFERENCE
 
147
  if model is None or scaler is None:
148
  return None, None
149
 
150
+ prices = fetch_last_30_days(base, target)
151
+ if prices is None:
152
+ return None, None
 
 
 
 
153
 
154
  scaled = scaler.transform(prices)
 
155
  X = create_input_sequence(scaled, LOOKBACK)
156
  X = torch.tensor(X, dtype=torch.float32)
157
 
 
159
  preds = model(X).numpy()
160
 
161
  preds = scaler.inverse_transform(preds.reshape(-1, 1)).flatten()
162
+ return prices[-1][0], preds.tolist()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
163
 
164
  # ===========================
165
  # ROUTE
 
167
  @app.post("/predict", response_model=PredictionResponse)
168
  def predict(req: PredictionRequest):
169
 
170
+ current_price, preds = predict_forex(
171
+ req.base_currency,
172
+ req.target_currency,
173
+ req.horizon
174
+ )
 
 
 
 
175
 
176
+ if preds is None:
177
  return PredictionResponse(
178
+ message="Prediction failed",
179
  data=None
180
  )
181
 
 
 
 
 
 
 
 
182
  return PredictionResponse(
183
  message="Prediction success",
184
  data={
185
  "base": req.base_currency,
186
  "target": req.target_currency,
187
  "horizon": req.horizon,
188
+ "current_price": current_price,
189
  "predictions": preds
190
  }
191
  )