Spaces:
Running
Running
import gradio as gr | |
import pandas as pd | |
import numpy as np | |
from datetime import datetime, timedelta | |
import yfinance as yf | |
from sklearn.preprocessing import MinMaxScaler | |
from tensorflow.keras.models import Sequential | |
from tensorflow.keras.layers import LSTM, Dense | |
import plotly.graph_objects as go | |
def fetch_ethereum_data(): | |
""" | |
Fetch historical Ethereum price data using yfinance. | |
Returns DataFrame with datetime index and price information. | |
The data is sampled hourly for the past week. | |
""" | |
eth_ticker = yf.Ticker("ETH-USD") | |
# Get hourly data for the past week | |
hist_data = eth_ticker.history(period="7d", interval="1h") | |
# Keep the datetime index and Close price | |
return hist_data[['Close']] | |
def prepare_data(data, sequence_length=24): | |
""" | |
Prepare data for LSTM model by creating sequences and scaling. | |
Args: | |
data: DataFrame with price data and datetime index | |
sequence_length: Number of time steps to use for prediction (default: 24 hours) | |
""" | |
# Scale the data | |
scaler = MinMaxScaler() | |
scaled_data = scaler.fit_transform(data['Close'].values.reshape(-1, 1)) | |
# Create sequences for training | |
X, y = [], [] | |
for i in range(sequence_length, len(scaled_data)): | |
X.append(scaled_data[i-sequence_length:i, 0]) | |
y.append(scaled_data[i, 0]) | |
X = np.array(X) | |
y = np.array(y) | |
# Reshape X for LSTM input | |
X = X.reshape(X.shape[0], X.shape[1], 1) | |
return X, y, scaler | |
def create_model(sequence_length): | |
""" | |
Create and compile LSTM model for time series prediction. | |
Uses a two-layer LSTM architecture followed by dense layers. | |
""" | |
model = Sequential([ | |
LSTM(50, return_sequences=True, input_shape=(sequence_length, 1)), | |
LSTM(50, return_sequences=False), | |
Dense(25), | |
Dense(1) | |
]) | |
model.compile(optimizer='adam', loss='mse') | |
return model | |
def predict_future_prices(model, last_sequence, scaler, days=7): | |
""" | |
Predict future prices using the trained model. | |
Args: | |
model: Trained LSTM model | |
last_sequence: Last sequence of known prices | |
scaler: Fitted MinMaxScaler | |
days: Number of days to predict (default: 7) | |
""" | |
future_predictions = [] | |
current_sequence = last_sequence.copy() | |
# Convert days to hours since we're using hourly data | |
hours = days * 24 | |
for _ in range(hours): | |
# Predict next price | |
scaled_prediction = model.predict(current_sequence.reshape(1, -1, 1), verbose=0) | |
# Inverse transform to get actual price | |
prediction = scaler.inverse_transform(scaled_prediction)[0][0] | |
future_predictions.append(prediction) | |
# Update sequence for next prediction | |
current_sequence = np.roll(current_sequence, -1) | |
current_sequence[-1] = scaled_prediction | |
return future_predictions | |
def create_prediction_plot(historical_data, future_predictions, future_dates): | |
""" | |
Create an interactive plot showing the last week of historical prices | |
and week-ahead predictions with hourly granularity. | |
Args: | |
historical_data: DataFrame with historical price data and datetime index | |
future_predictions: List of predicted prices | |
future_dates: List of future datetime indices for predictions | |
""" | |
fig = go.Figure() | |
# Plot historical data using the datetime index | |
fig.add_trace(go.Scatter( | |
x=historical_data.index, | |
y=historical_data['Close'], | |
name='Historical Prices', | |
line=dict(color='blue') | |
)) | |
# Plot predictions | |
fig.add_trace(go.Scatter( | |
x=future_dates, | |
y=future_predictions, | |
name='Predictions', | |
line=dict(color='red', dash='dash') | |
)) | |
fig.update_layout( | |
title='Ethereum Price Prediction (Hourly)', | |
xaxis_title='Date', | |
yaxis_title='Price (USD)', | |
hovermode='x unified' | |
) | |
return fig | |
def predict_ethereum(): | |
""" | |
Main function for Gradio interface that orchestrates the prediction process. | |
Handles hourly data and generates predictions for the next week. | |
""" | |
# Fetch and prepare data | |
data = fetch_ethereum_data() | |
sequence_length = 24 # Use 24 hours of data for prediction | |
X, y, scaler = prepare_data(data, sequence_length) | |
# Create and train model | |
model = create_model(sequence_length) | |
model.fit(X, y, epochs=50, batch_size=32, verbose=0) | |
# Prepare last sequence for prediction | |
last_sequence = scaler.transform(data['Close'].values[-sequence_length:].reshape(-1, 1)) | |
# Generate future predictions | |
future_predictions = predict_future_prices(model, last_sequence, scaler) | |
# Create future dates (hourly intervals) | |
last_date = data.index[-1] | |
future_dates = [last_date + timedelta(hours=i+1) for i in range(len(future_predictions))] | |
# Create and return plot | |
fig = create_prediction_plot(data, future_predictions, future_dates) | |
return fig | |
# Create Gradio interface | |
iface = gr.Interface( | |
fn=predict_ethereum, | |
inputs=None, | |
outputs=gr.Plot(), | |
title="Ethereum Price Prediction", | |
description="Click to generate a 7-day price prediction for Ethereum based on hourly historical data.", | |
theme=gr.themes.Base() | |
) | |
if __name__ == "__main__": | |
iface.launch() |