Lullooo commited on
Commit
d04cb0b
·
verified ·
1 Parent(s): 51f1e9c

Upload app.py

Browse files
Files changed (1) hide show
  1. app.py +187 -0
app.py ADDED
@@ -0,0 +1,187 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ################### PACKAGES
2
+ import pandas as pd
3
+ import numpy as np
4
+ from datetime import datetime, timedelta
5
+ import time
6
+ import requests
7
+ from pytrends.request import TrendReq
8
+ import joblib
9
+ import gradio as gr
10
+ from sklearn.preprocessing import StandardScaler
11
+
12
+
13
+ ################### MODEL LOADING
14
+ # Load XGBoost and NGBoost
15
+ xgb_artifact = joblib.load("xgb_volatility_model.joblib")
16
+ xgb_model = xgb_artifact["model"]
17
+ xgb_features = xgb_artifact["feature_names"]
18
+
19
+ ngb_artifact = joblib.load("ngb_volatility_model.joblib")
20
+ ngb_model = ngb_artifact["model"]
21
+ ngb_features = ngb_artifact["feature_names"]
22
+
23
+ forecast_ngb_artifact = joblib.load("Forecast_ngb_volatility_model.joblib")
24
+ forecast_ngb_model = forecast_ngb_artifact["model"]
25
+ forecast_ngb_features = forecast_ngb_artifact["feature_names"]
26
+
27
+ # Load KMeans + scaler
28
+ kmeans_artifact = joblib.load("kmeans_model.joblib")
29
+ kmeans_model = kmeans_artifact["model"]
30
+ cluster_scaler = kmeans_artifact["scaler"]
31
+ cluster_features_names = kmeans_artifact["feature_names"]
32
+
33
+
34
+ ################### FEATURE GATHERING
35
+ def fetch_ohlcv_last_6_days(symbol="BTC/USDT", date="2026-01-18"):
36
+ user_date = pd.to_datetime(date)
37
+ start_date = user_date - timedelta(days=6)
38
+
39
+ url = "https://api.coingecko.com/api/v3/coins/bitcoin/market_chart/range"
40
+ params = {
41
+ "vs_currency": "usd",
42
+ "from": int(start_date.timestamp()),
43
+ "to": int(user_date.timestamp())
44
+ }
45
+
46
+ r = requests.get(url, params=params, timeout=20)
47
+ r.raise_for_status()
48
+ data = r.json()
49
+
50
+ prices = pd.DataFrame(data["prices"], columns=["timestamp", "close"])
51
+ volumes = pd.DataFrame(data["total_volumes"], columns=["timestamp", "volume"])
52
+
53
+ df = prices.merge(volumes, on="timestamp")
54
+ df["timestamp"] = pd.to_datetime(df["timestamp"], unit="ms")
55
+ df.set_index("timestamp", inplace=True)
56
+
57
+ # CoinGecko does not give OHLC → reconstruct daily OHLC
58
+ df = df.resample("1D").agg(
59
+ open=("close", "first"),
60
+ high=("close", "max"),
61
+ low=("close", "min"),
62
+ close=("close", "last"),
63
+ volume=("volume", "sum")
64
+ )
65
+
66
+ df = df.dropna()
67
+ return df
68
+
69
+ def fetch_fg_last_6_days(df):
70
+ url = "https://api.alternative.me/fng/?limit=0&format=json"
71
+ response = requests.get(url)
72
+ fg_df = pd.DataFrame(response.json()["data"])
73
+ fg_df["timestamp"] = pd.to_datetime(fg_df["timestamp"], unit="s")
74
+ fg_df.set_index("timestamp", inplace=True)
75
+ fg_df = fg_df[["value"]].astype(float)
76
+ fg_df.rename(columns={"value":"fg_index"}, inplace=True)
77
+ fg_df = fg_df.reindex(df.index, method="ffill")
78
+ df["fg_index"] = fg_df["fg_index"].values
79
+ return df
80
+
81
+ def fetch_google_trend_for_date(keyword="Bitcoin", target_date="2024-01-15", window=7):
82
+ pytrends = TrendReq(hl="en-US", tz=360)
83
+ target_date = pd.to_datetime(target_date)
84
+ start_date = (target_date - timedelta(days=window)).strftime("%Y-%m-%d")
85
+ end_date = target_date.strftime("%Y-%m-%d")
86
+ timeframe = f"{start_date} {end_date}"
87
+ try:
88
+ pytrends.build_payload([keyword], timeframe=timeframe)
89
+ df = pytrends.interest_over_time()
90
+ if df.empty:
91
+ return 0
92
+ df = df.rename(columns={keyword: "trend"})
93
+ df = df.drop(columns=["isPartial"], errors="ignore")
94
+ df.index = pd.to_datetime(df.index)
95
+ if target_date in df.index:
96
+ return df.loc[target_date, "trend"]
97
+ else:
98
+ return 0
99
+ except:
100
+ return 0
101
+
102
+
103
+ ################### FEATURE ENGINEERING
104
+ def engineer_features(df):
105
+ df["log_return"] = np.log(df["close"] / df["close"].shift(1))
106
+ df["hl_spread"] = df["high"] - df["low"]
107
+ df["co_spread"] = df["close"] - df["open"]
108
+ df["momentum_3"] = df["close"] - df["close"].shift(3)
109
+ df["vol_change"] = df["volume"] - df["volume"].shift(1)
110
+ df["rolling_std_5"] = df["log_return"].rolling(5).std()
111
+ # Fill NaNs for first few rows
112
+ df = df.fillna(0)
113
+ return df
114
+
115
+ ################### ASSIGN CLUSTER
116
+ def assign_cluster(df):
117
+ cluster_features = df[cluster_features_names]
118
+ scaled = cluster_scaler.transform(cluster_features)
119
+ df["cluster"] = kmeans_model.predict(scaled)
120
+ return df
121
+
122
+
123
+ ################### PREDICTION FUNCTION
124
+ def predict_volatility(date):
125
+ # Fetch raw data
126
+ df = fetch_ohlcv_last_6_days(date=date)
127
+ df = fetch_fg_last_6_days(df)
128
+ trend_value = fetch_google_trend_for_date("Bitcoin", date)
129
+ df["trend"] = trend_value
130
+ df["trend"] = df["trend"].ffill().fillna(0)
131
+
132
+ # Feature engineering
133
+ df = engineer_features(df)
134
+
135
+ # Clustering
136
+ df = assign_cluster(df)
137
+
138
+ # ---------------- NOWCASTING ----------------
139
+ X_xgb = df.iloc[-1:][xgb_features]
140
+ X_ngb = df.iloc[-1:][ngb_features]
141
+
142
+ point = xgb_model.predict(X_xgb)[0]
143
+ dist = ngb_model.pred_dist(X_ngb)
144
+ low, high = dist.ppf([0.025, 0.975])[0]
145
+
146
+ # ---------------- FORECASTING (t+1) ----------------
147
+ X_ngb_fore = df.iloc[-1:][forecast_ngb_features]
148
+
149
+ for_point = forecast_ngb_model.predict(X_ngb_fore)[0]
150
+ for_dist = forecast_ngb_model.pred_dist(X_ngb_fore)
151
+ for_low, for_high = for_dist.ppf([0.025, 0.975])[0]
152
+
153
+ return point, low, high, for_point, for_low, for_high
154
+
155
+
156
+
157
+ ################### GRADIO INTERFACE
158
+ def gradio_predict(date):
159
+ try:
160
+ pd.to_datetime(date)
161
+ except:
162
+ return "❌ Invalid date format. Please use YYYY-MM-DD."
163
+
164
+ try:
165
+ point, low, high, for_point, for_low, for_high = predict_volatility(date)
166
+
167
+ return (
168
+ f"NOWCAST (t)\n"
169
+ f"Volatility: {point:.4f}\n"
170
+ f"95% CI: [{low:.4f}, {high:.4f}]\n\n"
171
+ f"FORECAST (t+1)\n"
172
+ f"Volatility: {for_point:.4f}\n"
173
+ f"95% CI: [{for_low:.4f}, {for_high:.4f}]"
174
+ )
175
+ except Exception as e:
176
+ return f"⚠️ Error while computing prediction:\n{str(e)}"
177
+
178
+ demo = gr.Interface(
179
+ fn=gradio_predict,
180
+ inputs=gr.Textbox(label="Date (YYYY-MM-DD)"),
181
+ outputs=gr.Textbox(label="Prediction"),
182
+ title="Crypto Volatility Predictor",
183
+ description="Enter a date to get predicted volatility and 95% confidence interval."
184
+ )
185
+
186
+ if __name__ == "__main__":
187
+ demo.launch()