Download app.py from Miruzen/LSTM_API: direct link, hf CLI and curl.
- Browser
- Download file 3.43 kB
-
https://huggingface.co/spaces/Miruzen/LSTM_API/resolve/main/app.py
- Command line
-
hf download hf://spaces/Miruzen/LSTM_API/app.py
-
curl -L -o app.py https://huggingface.co/spaces/Miruzen/LSTM_API/resolve/main/app.py
3.43 kB
| from fastapi import FastAPI | |
| from pydantic import BaseModel | |
| import numpy as np | |
| import pandas as pd | |
| import tensorflow as tf | |
| from tensorflow.keras.models import load_model | |
| import json | |
| import os | |
| app = FastAPI( | |
| title="Forex LSTM Prediction API", | |
| description="Prediksi harga EUR/USD H+1 dengan LSTM menggunakan scaler harian", | |
| version="2.0" | |
| ) | |
| # ========================================================== | |
| # LOAD MODEL DAN KONFIGURASI | |
| # ========================================================== | |
| MODEL_PATH = "lstm_model.h5" | |
| PARAMS_PATH = "best_params.json" | |
| SCALER_FILE = "scaler_config.json" | |
| print("📥 Loading LSTM model...") | |
| model = load_model(MODEL_PATH, compile=False) | |
| print("📥 Loading best parameters...") | |
| with open(PARAMS_PATH, "r") as f: | |
| best_params = json.load(f) | |
| LOOKBACK = best_params.get("lookback", 7) | |
| FEATURE_ORDER = best_params.get("features", [ | |
| "mood_score", "t_pos", "t_neg", "c_pos", "c_neg", | |
| "norm_ema20", "norm_ema50", "norm_close" | |
| ]) | |
| # ========================================================== | |
| # LOAD SCALER CONFIG | |
| # ========================================================== | |
| def load_scaler_config(): | |
| if not os.path.exists(SCALER_FILE): | |
| print("⚠️ Scaler config not found, using default values.") | |
| return {"CLOSE_MIN": 1.05, "CLOSE_MAX": 1.15} | |
| with open(SCALER_FILE, "r") as f: | |
| return json.load(f) | |
| scaler_cfg = load_scaler_config() | |
| CLOSE_MIN = scaler_cfg["CLOSE_MIN"] | |
| CLOSE_MAX = scaler_cfg["CLOSE_MAX"] | |
| print(f"✅ Scaler range loaded: {CLOSE_MIN:.5f} - {CLOSE_MAX:.5f}") | |
| # ========================================================== | |
| # INPUT SCHEMA | |
| # ========================================================== | |
| class LSTMInput(BaseModel): | |
| data: list | |
| # ========================================================== | |
| # HELPER FUNCTIONS | |
| # ========================================================== | |
| def prepare_input(data): | |
| df = pd.DataFrame(data) | |
| missing_cols = [f for f in FEATURE_ORDER if f not in df.columns] | |
| if missing_cols: | |
| raise ValueError(f"Missing columns: {missing_cols}") | |
| X = df[FEATURE_ORDER].values[-LOOKBACK:] | |
| if X.shape[0] < LOOKBACK: | |
| raise ValueError(f"Need at least {LOOKBACK} timesteps, got {X.shape[0]}") | |
| X = np.expand_dims(X, axis=0) | |
| return X, df | |
| def inverse_scale(norm_value): | |
| """Denormalisasi nilai close dari [0,1] ke skala asli""" | |
| return (norm_value * (CLOSE_MAX - CLOSE_MIN)) + CLOSE_MIN | |
| # ========================================================== | |
| # ENDPOINT | |
| # ========================================================== | |
| def predict_price(input_data: LSTMInput): | |
| try: | |
| X, df = prepare_input(input_data.data) | |
| pred_norm = model.predict(X)[0][0] | |
| pred_close = inverse_scale(pred_norm) | |
| last_date = pd.to_datetime(df["date"].iloc[-1]) | |
| next_date = (last_date + pd.Timedelta(days=1)).strftime("%Y-%m-%d") | |
| result = { | |
| "next_date": next_date, | |
| "predicted_norm_close": float(pred_norm), | |
| "predicted_close": float(pred_close), | |
| "scaler_used": {"min": CLOSE_MIN, "max": CLOSE_MAX}, | |
| "features_used": FEATURE_ORDER | |
| } | |
| return {"status": "ok", "result": result} | |
| except Exception as e: | |
| return {"status": "error", "message": str(e)} | |
| def root(): | |
| return {"message": "Forex LSTM Prediction API is active!"} | |