import streamlit as st from datetime import date import yfinance as yf import pandas as pd # Importing pandas to avoid NameError from prophet import Prophet from prophet.plot import plot_plotly from plotly import graph_objs as go # Constants for date range START = "2015-01-01" TODAY = date.today().strftime("%Y-%m-%d") # Streamlit app title st.title('Stock & Cryptocurrency Forecast App') # Stock and cryptocurrency selection assets = ('GOOG', 'AAPL', 'MSFT', 'GME', 'BTC-USD', 'ETH-USD') # Added BTC and ETH selected_asset = st.selectbox('Select dataset for prediction', assets) # Years of prediction slider n_years = st.slider('Years of prediction:', 1, 4) period = n_years * 365 @st.cache_data def load_data(ticker): """Load stock or cryptocurrency data from Yahoo Finance.""" data = yf.download(ticker, START, TODAY) data.reset_index(inplace=True) return data # Load data and show loading state data_load_state = st.text('Loading data...') data = load_data(selected_asset) data_load_state.text('Loading data... done!') # Display raw data for debugging purposes st.subheader('Raw Data') st.write(data.tail()) # Check if 'Close' column exists before converting if 'Close' in data.columns: # Check data types of the DataFrame st.write("Data Types:") st.write(data.dtypes) # Display unique values in the 'Close' column for debugging st.write("Unique values in 'Close' column:") st.write(data['Close'].unique()) # Ensure 'Close' prices are numeric and handle any missing values try: # Convert to numeric with coercion for invalid parsing data['Close'] = pd.to_numeric(data['Close'], errors='coerce') # Drop rows with NaN values in 'Close' data.dropna(subset=['Close'], inplace=True) except Exception as e: st.error(f"Error converting 'Close' prices to numeric: {e}") else: st.error("The 'Close' column is missing from the data. Please check the selected asset.") # Check if there is valid data after processing if not data.empty and 'Close' in data.columns: # Plot raw data function def plot_raw_data(): fig = go.Figure() fig.add_trace(go.Scatter(x=data['Date'], y=data['Open'], name="Open Price", line=dict(color='blue'))) fig.add_trace(go.Scatter(x=data['Date'], y=data['Close'], name="Close Price", line=dict(color='orange'))) fig.layout.update(title_text='Time Series Data with Rangeslider', xaxis_rangeslider_visible=True) st.plotly_chart(fig) # Call the plotting function if there's enough data plot_raw_data() # Prepare data for Prophet model df_train = data[['Date', 'Close']] df_train = df_train.rename(columns={"Date": "ds", "Close": "y"}) # Create and fit the Prophet model m = Prophet() try: m.fit(df_train) # Create future dataframe and make predictions future = m.make_future_dataframe(periods=period) forecast = m.predict(future) # Show forecast data and plot forecast st.subheader('Forecast Data') st.write(forecast[['ds', 'yhat', 'yhat_lower', 'yhat_upper']].tail()) st.write(f'Forecast plot for the next {n_years} years') fig1 = plot_plotly(m, forecast) st.plotly_chart(fig1) # Show forecast components st.subheader("Forecast Components") fig2 = m.plot_components(forecast) st.plotly_chart(fig2) # Additional Insights: Displaying key metrics st.subheader("Key Metrics") latest_data = forecast.iloc[-1] st.write(f"Predicted Price: ${latest_data['yhat']:.2f}") st.write(f"Lower Bound: ${latest_data['yhat_lower']:.2f}") st.write(f"Upper Bound: ${latest_data['yhat_upper']:.2f}") except Exception as e: st.error(f"Error fitting model: {e}") else: st.error("No valid data available to make predictions.") # User Guidance Section st.sidebar.header("User Guidance") st.sidebar.write(""" This application allows you to predict stock prices or cryptocurrency values based on historical data. - Select a stock or cryptocurrency from the dropdown menu. - Use the slider to choose how many years into the future you want to predict. - View the forecasted prices along with confidence intervals. """)