kapr commited on
Commit
2a14d16
·
verified ·
1 Parent(s): 2ec9ea1

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +71 -20
app.py CHANGED
@@ -3,6 +3,7 @@ import pandas as pd
3
  import requests
4
  from prophet import Prophet
5
  import logging
 
6
 
7
  logging.basicConfig(level=logging.INFO)
8
 
@@ -18,7 +19,7 @@ TIMEFRAME_MAPPING = {
18
  "5m": "5m",
19
  "15m": "15m",
20
  "30m": "30m",
21
- "1h": "1H", # OKX expects '1H'
22
  "2h": "2H",
23
  "4h": "4H",
24
  "6h": "6H",
@@ -58,7 +59,7 @@ 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...")
@@ -130,7 +131,7 @@ def prepare_data_for_prophet(df):
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.")
@@ -157,10 +158,60 @@ def prophet_wrapper(df_prophet, forecast_steps, freq):
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
  ########################################
165
  # Main Gradio logic
166
  ########################################
@@ -169,17 +220,13 @@ def predict(symbol, timeframe, forecast_steps):
169
  """
170
  Orchestrate candle fetch + prophet forecast.
171
  """
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:
185
  return pd.DataFrame(), err2
@@ -187,14 +234,13 @@ def predict(symbol, timeframe, forecast_steps):
187
  return future_df, ""
188
 
189
  def display_forecast(symbol, timeframe, forecast_steps):
190
- """
191
- For the Gradio UI, returns forecast or error message.
192
- """
193
  logging.info(f"User requested: symbol={symbol}, timeframe={timeframe}, steps={forecast_steps}")
194
  forecast_df, error = predict(symbol, timeframe, forecast_steps)
195
  if error:
196
- return f"Error: {error}"
197
- return forecast_df
 
 
198
 
199
  def main():
200
  # Fetch OKX symbols
@@ -205,8 +251,8 @@ def main():
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(
@@ -227,22 +273,27 @@ def main():
227
  )
228
  forecast_btn = gr.Button("Generate Forecast")
229
 
230
- output_df = gr.Dataframe(
231
- label="Future Forecast Only",
 
 
 
 
232
  headers=["ds", "yhat", "yhat_lower", "yhat_upper"]
233
  )
234
 
 
235
  forecast_btn.click(
236
  fn=display_forecast,
237
  inputs=[symbol_dd, timeframe_dd, steps_slider],
238
- outputs=output_df
239
  )
240
 
241
  gr.Markdown(
242
- "Need more tools? Check out this "
243
- "[crypto trading bot](https://www.gunbot.com)."
244
  )
245
 
 
246
  return demo
247
 
248
  if __name__ == "__main__":
 
3
  import requests
4
  from prophet import Prophet
5
  import logging
6
+ import plotly.graph_objs as go
7
 
8
  logging.basicConfig(level=logging.INFO)
9
 
 
19
  "5m": "5m",
20
  "15m": "15m",
21
  "30m": "30m",
22
+ "1h": "1H",
23
  "2h": "2H",
24
  "4h": "4H",
25
  "6h": "6H",
 
59
  """
60
  Fetch historical candle data for a symbol from OKX.
61
 
62
+ Data columns (9):
63
  [ts, o, h, l, c, vol, volCcy, volCcyQuote, confirm]
64
  """
65
  logging.info(f"Fetching {limit} candles for {symbol} @ {timeframe} from OKX...")
 
131
  def prophet_forecast(df_prophet, periods=10, freq="h"):
132
  """
133
  Train a Prophet model and forecast.
134
+ Using 'h' or 'd' for freq to avoid future deprecation warnings in pandas.
135
  """
136
  if df_prophet.empty:
137
  logging.warning("Prophet input is empty, no forecast can be generated.")
 
158
  if err:
159
  return pd.DataFrame(), err
160
 
161
+ # Only future portion
162
  future_only = full_forecast.loc[len(df_prophet):, ["ds", "yhat", "yhat_lower", "yhat_upper"]]
163
  return future_only, ""
164
 
165
+ ########################################
166
+ # Plot helper
167
+ ########################################
168
+
169
+ def create_line_plot(forecast_df):
170
+ """
171
+ Create a Plotly line chart with the future forecast (ds vs yhat).
172
+ We'll shade the region between yhat_lower and yhat_upper.
173
+ """
174
+ if forecast_df.empty:
175
+ return go.Figure() # empty figure if no data
176
+
177
+ fig = go.Figure()
178
+ # Main forecast
179
+ fig.add_trace(go.Scatter(
180
+ x=forecast_df["ds"],
181
+ y=forecast_df["yhat"],
182
+ mode="lines",
183
+ name="Forecast",
184
+ line=dict(color="blue")
185
+ ))
186
+
187
+ # Lower bound
188
+ fig.add_trace(go.Scatter(
189
+ x=forecast_df["ds"],
190
+ y=forecast_df["yhat_lower"],
191
+ fill=None,
192
+ mode="lines",
193
+ line=dict(width=0, color="lightblue"),
194
+ name="Lower"
195
+ ))
196
+
197
+ # Upper bound
198
+ fig.add_trace(go.Scatter(
199
+ x=forecast_df["ds"],
200
+ y=forecast_df["yhat_upper"],
201
+ fill="tonexty", # fill area between upper & lower
202
+ mode="lines",
203
+ line=dict(width=0, color="lightblue"),
204
+ name="Upper"
205
+ ))
206
+
207
+ fig.update_layout(
208
+ title="Forecasted Prices",
209
+ xaxis_title="Timestamp",
210
+ yaxis_title="Price",
211
+ hovermode="x"
212
+ )
213
+ return fig
214
+
215
  ########################################
216
  # Main Gradio logic
217
  ########################################
 
220
  """
221
  Orchestrate candle fetch + prophet forecast.
222
  """
 
223
  okx_bar = TIMEFRAME_MAPPING.get(timeframe, "1H")
 
224
  df_raw, err = fetch_okx_candles(symbol, timeframe=okx_bar, limit=500)
225
  if err:
226
  return pd.DataFrame(), err
227
 
228
  df_prophet = prepare_data_for_prophet(df_raw)
 
229
  freq = "h" if "h" in timeframe.lower() else "d"
 
230
  future_df, err2 = prophet_wrapper(df_prophet, forecast_steps, freq)
231
  if err2:
232
  return pd.DataFrame(), err2
 
234
  return future_df, ""
235
 
236
  def display_forecast(symbol, timeframe, forecast_steps):
 
 
 
237
  logging.info(f"User requested: symbol={symbol}, timeframe={timeframe}, steps={forecast_steps}")
238
  forecast_df, error = predict(symbol, timeframe, forecast_steps)
239
  if error:
240
+ return None, f"Error: {error}"
241
+
242
+ fig = create_line_plot(forecast_df)
243
+ return fig, forecast_df
244
 
245
  def main():
246
  # Fetch OKX symbols
 
251
  with gr.Blocks() as demo:
252
  gr.Markdown("# OKX Price Forecasting with Prophet")
253
  gr.Markdown(
254
+ "This app gathers recent candles from OKX's spot market and makes short-term predictions using Prophet. "
255
+ "You can pick any available symbol and timeframe, then see a future forecast (no historical lines) in a line chart and table."
256
  )
257
 
258
  symbol_dd = gr.Dropdown(
 
273
  )
274
  forecast_btn = gr.Button("Generate Forecast")
275
 
276
+ # First output: the line chart
277
+ chart_output = gr.Plot(label="Forecast Chart")
278
+
279
+ # Second output: the forecast dataframe
280
+ df_output = gr.Dataframe(
281
+ label="Forecast (Future Only)",
282
  headers=["ds", "yhat", "yhat_lower", "yhat_upper"]
283
  )
284
 
285
+ # We return two items from display_forecast: (chart, df)
286
  forecast_btn.click(
287
  fn=display_forecast,
288
  inputs=[symbol_dd, timeframe_dd, steps_slider],
289
+ outputs=[chart_output, df_output]
290
  )
291
 
292
  gr.Markdown(
293
+ "For automated trading tools, consider Gunbot as your next [crypto trading bot](https://www.gunbot.com)."
 
294
  )
295
 
296
+
297
  return demo
298
 
299
  if __name__ == "__main__":