Lullooo commited on
Commit
125bf4c
·
verified ·
1 Parent(s): 6e211cf
Files changed (1) hide show
  1. app.py +138 -0
app.py ADDED
@@ -0,0 +1,138 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ################### PACKAGES
2
+ import ccxt
3
+ import pandas as pd
4
+ import numpy as np
5
+ from datetime import datetime, timedelta
6
+ import time
7
+ import requests
8
+ from pytrends.request import TrendReq
9
+ import joblib
10
+ import gradio as gr
11
+ from sklearn.preprocessing import StandardScaler
12
+
13
+
14
+ ################### MODEL LOADING
15
+ # Load XGBoost and NGBoost
16
+ xgb_artifact = joblib.load("xgb_volatility_model.joblib")
17
+ xgb_model = xgb_artifact["model"]
18
+ xgb_features = xgb_artifact["feature_names"]
19
+
20
+ ngb_artifact = joblib.load("ngb_volatility_model.joblib")
21
+ ngb_model = ngb_artifact["model"]
22
+ ngb_features = ngb_artifact["feature_names"]
23
+
24
+ # Load KMeans + scaler
25
+ kmeans_artifact = joblib.load("kmeans_model.joblib")
26
+ kmeans_model = kmeans_artifact["model"]
27
+ cluster_scaler = kmeans_artifact["scaler"]
28
+ cluster_features_names = kmeans_artifact["feature_names"]
29
+
30
+
31
+ ################### FEATURE GATHERING
32
+ def fetch_ohlcv_last_6_days(symbol="BTC/USDT", date="2026-01-18", timeframe="1d"):
33
+ binance = ccxt.binance()
34
+ user_date = pd.to_datetime(date)
35
+ start_date = user_date - timedelta(days=5) # 5 days before
36
+ since = binance.parse8601(start_date.strftime("%Y-%m-%dT00:00:00Z"))
37
+ data = binance.fetch_ohlcv(symbol, timeframe=timeframe, since=since, limit=6)
38
+ df = pd.DataFrame(data, columns=["timestamp","open","high","low","close","volume"])
39
+ df["timestamp"] = pd.to_datetime(df["timestamp"], unit="ms")
40
+ df.set_index("timestamp", inplace=True)
41
+ return df
42
+
43
+ def fetch_fg_last_6_days(df):
44
+ url = "https://api.alternative.me/fng/?limit=0&format=json"
45
+ response = requests.get(url)
46
+ fg_df = pd.DataFrame(response.json()["data"])
47
+ fg_df["timestamp"] = pd.to_datetime(fg_df["timestamp"], unit="s")
48
+ fg_df.set_index("timestamp", inplace=True)
49
+ fg_df = fg_df[["value"]].astype(float)
50
+ fg_df.rename(columns={"value":"fg_index"}, inplace=True)
51
+ fg_df = fg_df.reindex(df.index, method="ffill")
52
+ df["fg_index"] = fg_df["fg_index"].values
53
+ return df
54
+
55
+ def fetch_google_trend_for_date(keyword="Bitcoin", target_date="2024-01-15", window=7):
56
+ pytrends = TrendReq(hl="en-US", tz=360)
57
+ target_date = pd.to_datetime(target_date)
58
+ start_date = (target_date - timedelta(days=window)).strftime("%Y-%m-%d")
59
+ end_date = target_date.strftime("%Y-%m-%d")
60
+ timeframe = f"{start_date} {end_date}"
61
+ try:
62
+ pytrends.build_payload([keyword], timeframe=timeframe)
63
+ df = pytrends.interest_over_time()
64
+ if df.empty:
65
+ return 0
66
+ df = df.rename(columns={keyword: "trend"})
67
+ df = df.drop(columns=["isPartial"], errors="ignore")
68
+ df.index = pd.to_datetime(df.index)
69
+ if target_date in df.index:
70
+ return df.loc[target_date, "trend"]
71
+ else:
72
+ return 0
73
+ except:
74
+ return 0
75
+
76
+
77
+ ################### FEATURE ENGINEERING
78
+ def engineer_features(df):
79
+ df["log_return"] = np.log(df["close"] / df["close"].shift(1))
80
+ df["hl_spread"] = df["high"] - df["low"]
81
+ df["co_spread"] = df["close"] - df["open"]
82
+ df["momentum_3"] = df["close"] - df["close"].shift(3)
83
+ df["vol_change"] = df["volume"] - df["volume"].shift(1)
84
+ df["rolling_std_5"] = df["log_return"].rolling(5).std()
85
+ # Fill NaNs for first few rows
86
+ df = df.fillna(0)
87
+ return df
88
+
89
+ ################### ASSIGN CLUSTER
90
+ def assign_cluster(df):
91
+ cluster_features = df[cluster_features_names]
92
+ scaled = cluster_scaler.transform(cluster_features)
93
+ df["cluster"] = kmeans_model.predict(scaled)
94
+ return df
95
+
96
+
97
+ ################### PREDICTION FUNCTION
98
+ def predict_volatility(date):
99
+ #Fetch raw data
100
+ df = fetch_ohlcv_last_6_days(date=date)
101
+ df = fetch_fg_last_6_days(df)
102
+ trend_value = fetch_google_trend_for_date("Bitcoin", date)
103
+ df["trend"] = trend_value
104
+ df["trend"] = df["trend"].fillna(method="ffill").fillna(0)
105
+
106
+ #Feature engineering
107
+ df = engineer_features(df)
108
+
109
+ #Clustering
110
+ df = assign_cluster(df)
111
+
112
+ #Select features for models (last row only)
113
+ X_xgb = df.iloc[-1:][xgb_features]
114
+ X_ngb = df.iloc[-1:][ngb_features]
115
+
116
+ #Predict
117
+ point = xgb_model.predict(X_xgb)[0]
118
+ dist = ngb_model.pred_dist(X_ngb)
119
+ low, high = dist.ppf([0.025, 0.975])[0]
120
+
121
+ return point, low, high
122
+
123
+
124
+ ################### GRADIO INTERFACE
125
+ def gradio_predict(date):
126
+ point, low, high = predict_volatility(date)
127
+ return f"Point volatility: {point:.4f}\n95% CI: [{low:.4f}, {high:.4f}]"
128
+
129
+ demo = gr.Interface(
130
+ fn=gradio_predict,
131
+ inputs=gr.Textbox(label="Date (YYYY-MM-DD)"),
132
+ outputs=gr.Textbox(label="Prediction"),
133
+ title="Crypto Volatility Predictor",
134
+ description="Enter a date to get predicted volatility and 95% confidence interval."
135
+ )
136
+
137
+ if __name__ == "__main__":
138
+ demo.launch()