Miruzen commited on
Commit
fa6a7c9
Β·
verified Β·
1 Parent(s): 414edf4

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +35 -35
app.py CHANGED
@@ -1,61 +1,64 @@
1
- # app.py
2
  from fastapi import FastAPI
3
  from pydantic import BaseModel
4
  import numpy as np
5
  import pandas as pd
6
- import joblib
7
- import json
8
  import tensorflow as tf
9
  from tensorflow.keras.models import load_model
10
- from sklearn.preprocessing import MinMaxScaler
 
11
 
12
  app = FastAPI(
13
  title="Forex LSTM Prediction API",
14
- description="API untuk prediksi harga EUR/USD H+1 menggunakan model LSTM terbaik",
15
- version="1.0"
16
  )
17
 
18
  # ==========================================================
19
- # LOAD MODEL, PARAMETER, DAN SCALER
20
  # ==========================================================
21
  MODEL_PATH = "lstm_model.h5"
22
- SCALER_PATH = "scaler.pkl"
23
  PARAMS_PATH = "best_params.json"
 
24
 
25
  print("πŸ“₯ Loading LSTM model...")
26
- model = load_model(MODEL_PATH, compile = False)
27
-
28
- print("πŸ“₯ Loading scaler...")
29
- scaler = joblib.load(SCALER_PATH)
30
 
31
  print("πŸ“₯ Loading best parameters...")
32
  with open(PARAMS_PATH, "r") as f:
33
  best_params = json.load(f)
34
 
35
- LOOKBACK = best_params.get("lookback", 7) # default 7 jika tidak ada
36
  FEATURE_ORDER = best_params.get("features", [
37
  "mood_score", "t_pos", "t_neg", "c_pos", "c_neg",
38
  "norm_ema20", "norm_ema50", "norm_close"
39
  ])
40
 
41
- print(f"βœ… Model loaded. Lookback={LOOKBACK}, Features={FEATURE_ORDER}")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
42
 
43
  # ==========================================================
44
  # INPUT SCHEMA
45
  # ==========================================================
46
  class LSTMInput(BaseModel):
47
- data: list # list of daily records (latest LOOKBACK hari)
48
- # contoh format:
49
- # [
50
- # {"date": "2025-10-23", "mood_score": 0.5, "t_pos": 0.3, "t_neg": 0.2, ...},
51
- # ...
52
- # ]
53
 
54
  # ==========================================================
55
- # HELPER FUNCTION
56
  # ==========================================================
57
  def prepare_input(data):
58
- """Convert input list to numpy array sesuai urutan fitur dan lookback"""
59
  df = pd.DataFrame(data)
60
  missing_cols = [f for f in FEATURE_ORDER if f not in df.columns]
61
  if missing_cols:
@@ -64,10 +67,14 @@ def prepare_input(data):
64
  X = df[FEATURE_ORDER].values[-LOOKBACK:]
65
  if X.shape[0] < LOOKBACK:
66
  raise ValueError(f"Need at least {LOOKBACK} timesteps, got {X.shape[0]}")
67
-
68
  X = np.expand_dims(X, axis=0)
69
  return X, df
70
 
 
 
 
 
 
71
  # ==========================================================
72
  # ENDPOINT
73
  # ==========================================================
@@ -76,30 +83,23 @@ def predict_price(input_data: LSTMInput):
76
  try:
77
  X, df = prepare_input(input_data.data)
78
  pred_norm = model.predict(X)[0][0]
79
- pred_close = scaler.inverse_transform([[pred_norm]])[0][0]
80
 
81
  last_date = pd.to_datetime(df["date"].iloc[-1])
82
  next_date = (last_date + pd.Timedelta(days=1)).strftime("%Y-%m-%d")
83
 
84
- response = {
85
  "next_date": next_date,
86
  "predicted_norm_close": float(pred_norm),
87
  "predicted_close": float(pred_close),
88
- "model_info": {
89
- "lookback": LOOKBACK,
90
- "features_used": FEATURE_ORDER,
91
- "source_model": MODEL_PATH
92
- }
93
  }
94
-
95
- return {"status": "ok", "result": response}
96
 
97
  except Exception as e:
98
  return {"status": "error", "message": str(e)}
99
 
100
- # ==========================================================
101
- # ROOT TEST
102
- # ==========================================================
103
  @app.get("/")
104
  def root():
105
  return {"message": "Forex LSTM Prediction API is active!"}
 
 
1
  from fastapi import FastAPI
2
  from pydantic import BaseModel
3
  import numpy as np
4
  import pandas as pd
 
 
5
  import tensorflow as tf
6
  from tensorflow.keras.models import load_model
7
+ import json
8
+ import os
9
 
10
  app = FastAPI(
11
  title="Forex LSTM Prediction API",
12
+ description="Prediksi harga EUR/USD H+1 dengan LSTM menggunakan scaler harian",
13
+ version="2.0"
14
  )
15
 
16
  # ==========================================================
17
+ # LOAD MODEL DAN KONFIGURASI
18
  # ==========================================================
19
  MODEL_PATH = "lstm_model.h5"
 
20
  PARAMS_PATH = "best_params.json"
21
+ SCALER_FILE = "scaler_config.json"
22
 
23
  print("πŸ“₯ Loading LSTM model...")
24
+ model = load_model(MODEL_PATH, compile=False)
 
 
 
25
 
26
  print("πŸ“₯ Loading best parameters...")
27
  with open(PARAMS_PATH, "r") as f:
28
  best_params = json.load(f)
29
 
30
+ LOOKBACK = best_params.get("lookback", 7)
31
  FEATURE_ORDER = best_params.get("features", [
32
  "mood_score", "t_pos", "t_neg", "c_pos", "c_neg",
33
  "norm_ema20", "norm_ema50", "norm_close"
34
  ])
35
 
36
+ # ==========================================================
37
+ # LOAD SCALER CONFIG
38
+ # ==========================================================
39
+ def load_scaler_config():
40
+ if not os.path.exists(SCALER_FILE):
41
+ print("⚠️ Scaler config not found, using default values.")
42
+ return {"CLOSE_MIN": 1.05, "CLOSE_MAX": 1.15}
43
+ with open(SCALER_FILE, "r") as f:
44
+ return json.load(f)
45
+
46
+ scaler_cfg = load_scaler_config()
47
+ CLOSE_MIN = scaler_cfg["CLOSE_MIN"]
48
+ CLOSE_MAX = scaler_cfg["CLOSE_MAX"]
49
+
50
+ print(f"βœ… Scaler range loaded: {CLOSE_MIN:.5f} - {CLOSE_MAX:.5f}")
51
 
52
  # ==========================================================
53
  # INPUT SCHEMA
54
  # ==========================================================
55
  class LSTMInput(BaseModel):
56
+ data: list
 
 
 
 
 
57
 
58
  # ==========================================================
59
+ # HELPER FUNCTIONS
60
  # ==========================================================
61
  def prepare_input(data):
 
62
  df = pd.DataFrame(data)
63
  missing_cols = [f for f in FEATURE_ORDER if f not in df.columns]
64
  if missing_cols:
 
67
  X = df[FEATURE_ORDER].values[-LOOKBACK:]
68
  if X.shape[0] < LOOKBACK:
69
  raise ValueError(f"Need at least {LOOKBACK} timesteps, got {X.shape[0]}")
 
70
  X = np.expand_dims(X, axis=0)
71
  return X, df
72
 
73
+
74
+ def inverse_scale(norm_value):
75
+ """Denormalisasi nilai close dari [0,1] ke skala asli"""
76
+ return (norm_value * (CLOSE_MAX - CLOSE_MIN)) + CLOSE_MIN
77
+
78
  # ==========================================================
79
  # ENDPOINT
80
  # ==========================================================
 
83
  try:
84
  X, df = prepare_input(input_data.data)
85
  pred_norm = model.predict(X)[0][0]
86
+ pred_close = inverse_scale(pred_norm)
87
 
88
  last_date = pd.to_datetime(df["date"].iloc[-1])
89
  next_date = (last_date + pd.Timedelta(days=1)).strftime("%Y-%m-%d")
90
 
91
+ result = {
92
  "next_date": next_date,
93
  "predicted_norm_close": float(pred_norm),
94
  "predicted_close": float(pred_close),
95
+ "scaler_used": {"min": CLOSE_MIN, "max": CLOSE_MAX},
96
+ "features_used": FEATURE_ORDER
 
 
 
97
  }
98
+ return {"status": "ok", "result": result}
 
99
 
100
  except Exception as e:
101
  return {"status": "error", "message": str(e)}
102
 
 
 
 
103
  @app.get("/")
104
  def root():
105
  return {"message": "Forex LSTM Prediction API is active!"}