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

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +55 -26
app.py CHANGED
@@ -10,14 +10,10 @@ logging.basicConfig(level=logging.INFO)
10
  # OKX endpoints & utility
11
  ########################################
12
 
13
- # 1) GET symbols (spot tickers)
14
  OKX_TICKERS_ENDPOINT = "https://www.okx.com/api/v5/market/tickers?instType=SPOT"
15
-
16
- # 2) GET historical candles for a symbol
17
- # e.g. https://www.okx.com/api/v5/market/candles?instId=BTC-USDT&bar=1H&limit=100
18
  OKX_CANDLE_ENDPOINT = "https://www.okx.com/api/v5/market/candles"
19
 
20
- # You can extend or modify this to match more of OKX's `bar` intervals
21
  TIMEFRAME_MAPPING = {
22
  "1m": "1m",
23
  "5m": "5m",
@@ -29,7 +25,7 @@ TIMEFRAME_MAPPING = {
29
  "6h": "6H",
30
  "12h": "12H",
31
  "1d": "1D",
32
- "1w": "1W", # OKX supports 1W, etc.
33
  }
34
 
35
  def fetch_okx_symbols():
@@ -63,8 +59,22 @@ def fetch_okx_symbols():
63
  def fetch_okx_candles(symbol, timeframe="1H", limit=100):
64
  """
65
  Fetch historical candle data for a symbol from OKX.
66
- timeframe must match OKX's `bar` (e.g. "1H", "4H", "1D").
67
- Returns (DataFrame, error_message) or (DataFrame, "").
 
 
 
 
 
 
 
 
 
 
 
 
 
 
68
  """
69
  logging.info(f"Fetching {limit} candles for {symbol} @ {timeframe} from OKX...")
70
  params = {
@@ -83,28 +93,47 @@ def fetch_okx_candles(symbol, timeframe="1H", limit=100):
83
  logging.error(msg)
84
  return pd.DataFrame(), msg
85
 
86
- # Data looks like: ["1673684400000", "20923.7", "20952.5", "20881.3", "20945.8", "927.879", "19412314.5671"]
87
- # Let's parse columns: [0] ts, [1] open, [2] high, [3] low, [4] close, [5] volume, [6] ??? quoteVol
88
  items = json_data.get("data", [])
89
  if not items:
90
  warning_msg = f"No candle data returned for {symbol}."
91
  logging.warning(warning_msg)
92
  return pd.DataFrame(), warning_msg
93
 
94
- # items is a list of lists, each is a candle. Reverse if needed to go old->new:
95
- # OKX returns the most recent data first, so we invert it for chronological order
96
  items.reverse()
97
 
98
- df = pd.DataFrame(items, columns=[
99
- "timestamp", "open", "high", "low", "close", "volume", "quoteVolume"
100
- ])
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
101
  df["timestamp"] = pd.to_datetime(df["timestamp"], unit="ms")
102
- df[["open", "high", "low", "close", "volume", "quoteVolume"]] = df[
103
- ["open", "high", "low", "close", "volume", "quoteVolume"]
104
- ].astype(float)
105
 
106
  logging.info(f"Fetched {len(df)} rows for {symbol}.")
107
  return df, ""
 
108
  except Exception as e:
109
  err_msg = f"Error fetching candles for {symbol}: {e}"
110
  logging.error(err_msg)
@@ -154,7 +183,7 @@ def prophet_wrapper(df_prophet, forecast_steps, freq):
154
  if err:
155
  return pd.DataFrame(), err
156
 
157
- # Only keep the newly generated future portion
158
  future_only = full_forecast.iloc[len(df_prophet):, ["ds", "yhat", "yhat_lower", "yhat_upper"]]
159
  return future_only, ""
160
 
@@ -169,15 +198,15 @@ def predict(symbol, timeframe, forecast_steps):
169
  # Convert user timeframe to OKX bar param
170
  okx_bar = TIMEFRAME_MAPPING.get(timeframe, "1H")
171
 
172
- # Lets fetch 500 candles
173
  df_raw, err = fetch_okx_candles(symbol, timeframe=okx_bar, limit=500)
174
  if err:
175
  return pd.DataFrame(), err
176
 
177
  df_prophet = prepare_data_for_prophet(df_raw)
178
- # We guess frequency from timeframe. If timeframe is "1h", we'll do freq="H" in Prophet, etc.
179
- # We'll do a simple mapping here:
180
- freq = "H" if "h" in timeframe.lower() else "D" # e.g. "1h" -> "H", "1d" -> "D"
181
 
182
  future_df, err2 = prophet_wrapper(df_prophet, forecast_steps, freq)
183
  if err2:
@@ -205,8 +234,8 @@ def main():
205
  gr.Markdown("# OKX Price Forecasting with Prophet")
206
  gr.Markdown(
207
  "This app uses OKX's spot market candles to predict future price movements. "
208
- "Select a symbol and timeframe, specify forecast steps, then click 'Generate Forecast'. "
209
- "No proxies or special access required."
210
  )
211
 
212
  symbol_dd = gr.Dropdown(
@@ -239,7 +268,7 @@ def main():
239
  )
240
 
241
  gr.Markdown(
242
- "Looking for more automation? Check out this "
243
  "[crypto trading bot](https://www.gunbot.com)."
244
  )
245
 
 
10
  # OKX endpoints & utility
11
  ########################################
12
 
 
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",
 
25
  "6h": "6H",
26
  "12h": "12H",
27
  "1d": "1D",
28
+ "1w": "1W",
29
  }
30
 
31
  def fetch_okx_symbols():
 
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 = {
 
93
  logging.error(msg)
94
  return pd.DataFrame(), msg
95
 
 
 
96
  items = json_data.get("data", [])
97
  if not items:
98
  warning_msg = f"No candle data returned for {symbol}."
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",
123
+ "h": "high",
124
+ "l": "low",
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)
 
133
 
134
  logging.info(f"Fetched {len(df)} rows for {symbol}.")
135
  return df, ""
136
+
137
  except Exception as e:
138
  err_msg = f"Error fetching candles for {symbol}: {e}"
139
  logging.error(err_msg)
 
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
 
 
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:
 
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(
 
268
  )
269
 
270
  gr.Markdown(
271
+ "Need more tools? Check out this "
272
  "[crypto trading bot](https://www.gunbot.com)."
273
  )
274