kapr commited on
Commit
f1bfa96
·
verified ·
1 Parent(s): 0ff9cc9

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +15 -44
app.py CHANGED
@@ -13,13 +13,12 @@ logging.basicConfig(level=logging.INFO)
13
  OKX_TICKERS_ENDPOINT = "https://www.okx.com/api/v5/market/tickers?instType=SPOT"
14
  OKX_CANDLE_ENDPOINT = "https://www.okx.com/api/v5/market/candles"
15
 
16
- # For demonstration, only these mappings
17
  TIMEFRAME_MAPPING = {
18
  "1m": "1m",
19
  "5m": "5m",
20
  "15m": "15m",
21
  "30m": "30m",
22
- "1h": "1H",
23
  "2h": "2H",
24
  "4h": "4H",
25
  "6h": "6H",
@@ -43,7 +42,6 @@ def fetch_okx_symbols():
43
  return ["Error: Could not fetch OKX symbols"]
44
 
45
  data = json_data.get("data", [])
46
- # Example item in data: { "instId": "ETH-USDT", "instType": "SPOT", ... }
47
  symbols = [item["instId"] for item in data if item.get("instType") == "SPOT"]
48
  if not symbols:
49
  logging.warning("No spot symbols found.")
@@ -56,25 +54,12 @@ def fetch_okx_symbols():
56
  logging.error(f"Error fetching OKX symbols: {e}")
57
  return [f"Error: {str(e)}"]
58
 
59
- def fetch_okx_candles(symbol, timeframe="1H", limit=100):
60
  """
61
  Fetch historical candle data for a symbol from OKX.
62
 
63
  OKX data columns:
64
  [ts, o, h, l, c, vol, volCcy, volCcyQuote, confirm]
65
-
66
- Example:
67
- [
68
- "1597026383085", # ts
69
- "3.721", # o
70
- "3.743", # h
71
- "3.677", # l
72
- "3.708", # c
73
- "8422410", # vol
74
- "22698348.04828491", # volCcy
75
- "12698348.04828491", # volCcyQuote
76
- "0" # confirm
77
- ]
78
  """
79
  logging.info(f"Fetching {limit} candles for {symbol} @ {timeframe} from OKX...")
80
  params = {
@@ -99,24 +84,14 @@ def fetch_okx_candles(symbol, timeframe="1H", limit=100):
99
  logging.warning(warning_msg)
100
  return pd.DataFrame(), warning_msg
101
 
102
- # OKX returns newest data first, so reverse to chronological
103
  items.reverse()
104
 
105
- # Expecting 9 columns per the docs
106
  columns = [
107
- "ts", # timestamp
108
- "o", # open
109
- "h", # high
110
- "l", # low
111
- "c", # close
112
- "vol", # volume (base currency)
113
- "volCcy", # volume in quote currency (for SPOT)
114
- "volCcyQuote",
115
- "confirm"
116
  ]
117
  df = pd.DataFrame(items, columns=columns)
118
-
119
- # Rename columns to be more descriptive or consistent
120
  df.rename(columns={
121
  "ts": "timestamp",
122
  "o": "open",
@@ -125,8 +100,6 @@ def fetch_okx_candles(symbol, timeframe="1H", limit=100):
125
  "c": "close"
126
  }, inplace=True)
127
 
128
- # Convert numeric columns
129
- # 'confirm' often is "0" or "1" string, which you can parse as float or int if you want
130
  df["timestamp"] = pd.to_datetime(df["timestamp"], unit="ms")
131
  numeric_cols = ["open", "high", "low", "close", "vol", "volCcy", "volCcyQuote", "confirm"]
132
  df[numeric_cols] = df[numeric_cols].astype(float)
@@ -154,9 +127,10 @@ def prepare_data_for_prophet(df):
154
  df_prophet = df.rename(columns={"timestamp": "ds", "close": "y"})
155
  return df_prophet[["ds", "y"]]
156
 
157
- def prophet_forecast(df_prophet, periods=10, freq="H"):
158
  """
159
  Train a Prophet model and forecast.
 
160
  """
161
  if df_prophet.empty:
162
  logging.warning("Prophet input is empty, no forecast can be generated.")
@@ -174,7 +148,7 @@ def prophet_forecast(df_prophet, periods=10, freq="H"):
174
 
175
  def prophet_wrapper(df_prophet, forecast_steps, freq):
176
  """
177
- Do the forecast, then slice out the new/future rows.
178
  """
179
  if len(df_prophet) < 10:
180
  return pd.DataFrame(), "Not enough data for forecasting (need >=10 rows)."
@@ -183,8 +157,8 @@ def prophet_wrapper(df_prophet, forecast_steps, freq):
183
  if err:
184
  return pd.DataFrame(), err
185
 
186
- # Only keep newly generated portion
187
- future_only = full_forecast.iloc[len(df_prophet):, ["ds", "yhat", "yhat_lower", "yhat_upper"]]
188
  return future_only, ""
189
 
190
  ########################################
@@ -198,15 +172,13 @@ def predict(symbol, timeframe, forecast_steps):
198
  # Convert user timeframe to OKX bar param
199
  okx_bar = TIMEFRAME_MAPPING.get(timeframe, "1H")
200
 
201
- # Let's fetch 500 candles
202
  df_raw, err = fetch_okx_candles(symbol, timeframe=okx_bar, limit=500)
203
  if err:
204
  return pd.DataFrame(), err
205
 
206
  df_prophet = prepare_data_for_prophet(df_raw)
207
-
208
- # We'll guess the freq for Prophet: if timeframe has 'h', let's use 'H', else 'D'
209
- freq = "H" if "h" in timeframe.lower() else "D"
210
 
211
  future_df, err2 = prophet_wrapper(df_prophet, forecast_steps, freq)
212
  if err2:
@@ -233,9 +205,8 @@ def main():
233
  with gr.Blocks() as demo:
234
  gr.Markdown("# OKX Price Forecasting with Prophet")
235
  gr.Markdown(
236
- "This app uses OKX's spot market candles to predict future price movements. "
237
- "It requests up to 500 candles (1,440 max on OKX side). If you get errors, "
238
- "please try a different symbol or timeframe."
239
  )
240
 
241
  symbol_dd = gr.Dropdown(
@@ -249,7 +220,7 @@ def main():
249
  value="1h"
250
  )
251
  steps_slider = gr.Slider(
252
- label="Forecast Steps (hours/days depending on timeframe)",
253
  minimum=1,
254
  maximum=100,
255
  value=10
 
13
  OKX_TICKERS_ENDPOINT = "https://www.okx.com/api/v5/market/tickers?instType=SPOT"
14
  OKX_CANDLE_ENDPOINT = "https://www.okx.com/api/v5/market/candles"
15
 
 
16
  TIMEFRAME_MAPPING = {
17
  "1m": "1m",
18
  "5m": "5m",
19
  "15m": "15m",
20
  "30m": "30m",
21
+ "1h": "1H", # OKX expects '1H'
22
  "2h": "2H",
23
  "4h": "4H",
24
  "6h": "6H",
 
42
  return ["Error: Could not fetch OKX symbols"]
43
 
44
  data = json_data.get("data", [])
 
45
  symbols = [item["instId"] for item in data if item.get("instType") == "SPOT"]
46
  if not symbols:
47
  logging.warning("No spot symbols found.")
 
54
  logging.error(f"Error fetching OKX symbols: {e}")
55
  return [f"Error: {str(e)}"]
56
 
57
+ def fetch_okx_candles(symbol, timeframe="1H", limit=500):
58
  """
59
  Fetch historical candle data for a symbol from OKX.
60
 
61
  OKX data columns:
62
  [ts, o, h, l, c, vol, volCcy, volCcyQuote, confirm]
 
 
 
 
 
 
 
 
 
 
 
 
 
63
  """
64
  logging.info(f"Fetching {limit} candles for {symbol} @ {timeframe} from OKX...")
65
  params = {
 
84
  logging.warning(warning_msg)
85
  return pd.DataFrame(), warning_msg
86
 
87
+ # Reverse to chronological (OKX returns newest first)
88
  items.reverse()
89
 
 
90
  columns = [
91
+ "ts", "o", "h", "l", "c", "vol",
92
+ "volCcy", "volCcyQuote", "confirm"
 
 
 
 
 
 
 
93
  ]
94
  df = pd.DataFrame(items, columns=columns)
 
 
95
  df.rename(columns={
96
  "ts": "timestamp",
97
  "o": "open",
 
100
  "c": "close"
101
  }, inplace=True)
102
 
 
 
103
  df["timestamp"] = pd.to_datetime(df["timestamp"], unit="ms")
104
  numeric_cols = ["open", "high", "low", "close", "vol", "volCcy", "volCcyQuote", "confirm"]
105
  df[numeric_cols] = df[numeric_cols].astype(float)
 
127
  df_prophet = df.rename(columns={"timestamp": "ds", "close": "y"})
128
  return df_prophet[["ds", "y"]]
129
 
130
+ def prophet_forecast(df_prophet, periods=10, freq="h"):
131
  """
132
  Train a Prophet model and forecast.
133
+ Using 'h' or 'd' to avoid the future deprecation warning in pandas.
134
  """
135
  if df_prophet.empty:
136
  logging.warning("Prophet input is empty, no forecast can be generated.")
 
148
 
149
  def prophet_wrapper(df_prophet, forecast_steps, freq):
150
  """
151
+ Forecast, then slice out only the new/future rows using .loc.
152
  """
153
  if len(df_prophet) < 10:
154
  return pd.DataFrame(), "Not enough data for forecasting (need >=10 rows)."
 
157
  if err:
158
  return pd.DataFrame(), err
159
 
160
+ # Slice from len(df_prophet) onward, for columns ds, yhat, yhat_lower, yhat_upper
161
+ future_only = full_forecast.loc[len(df_prophet):, ["ds", "yhat", "yhat_lower", "yhat_upper"]]
162
  return future_only, ""
163
 
164
  ########################################
 
172
  # Convert user timeframe to OKX bar param
173
  okx_bar = TIMEFRAME_MAPPING.get(timeframe, "1H")
174
 
 
175
  df_raw, err = fetch_okx_candles(symbol, timeframe=okx_bar, limit=500)
176
  if err:
177
  return pd.DataFrame(), err
178
 
179
  df_prophet = prepare_data_for_prophet(df_raw)
180
+ # If timeframe string has 'h', use 'h' for freq. Else use 'd'
181
+ freq = "h" if "h" in timeframe.lower() else "d"
 
182
 
183
  future_df, err2 = prophet_wrapper(df_prophet, forecast_steps, freq)
184
  if err2:
 
205
  with gr.Blocks() as demo:
206
  gr.Markdown("# OKX Price Forecasting with Prophet")
207
  gr.Markdown(
208
+ "This app pulls spot-market candles from OKX, trains a simple Prophet model, "
209
+ "and displays only future predictions. If you see errors or no data, try another symbol/timeframe."
 
210
  )
211
 
212
  symbol_dd = gr.Dropdown(
 
220
  value="1h"
221
  )
222
  steps_slider = gr.Slider(
223
+ label="Forecast Steps",
224
  minimum=1,
225
  maximum=100,
226
  value=10