shaheerawan3 commited on
Commit
673e0a8
ยท
verified ยท
1 Parent(s): 037b8cf

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +202 -111
app.py CHANGED
@@ -1,125 +1,216 @@
1
  import streamlit as st
2
- from datetime import date
3
  import yfinance as yf
4
  import pandas as pd
 
5
  from prophet import Prophet
6
  from prophet.plot import plot_plotly
7
  import plotly.graph_objects as go
8
  from sklearn.metrics import mean_absolute_error, mean_squared_error
 
9
 
10
- # Constants for date range
 
 
 
 
 
 
 
11
  START = "2015-01-01"
12
  TODAY = date.today().strftime("%Y-%m-%d")
13
 
14
- # Streamlit app title
15
- st.title('Advanced Stock & Cryptocurrency Forecast App')
16
-
17
- # Stock and cryptocurrency selection
18
- assets = ('GOOG', 'AAPL', 'MSFT', 'GME', 'BTC-USD', 'ETH-USD')
19
- selected_asset = st.selectbox('Select dataset for prediction', assets)
20
-
21
- # Years of prediction slider
22
- n_years = st.slider('Years of prediction:', 1, 4)
23
- period = n_years * 365
24
-
25
- @st.cache_data
26
- def load_data(ticker):
27
- """Load stock or cryptocurrency data from Yahoo Finance."""
28
- data = yf.download(ticker, START, TODAY)
29
- data.reset_index(inplace=True)
30
- return data
31
-
32
- # Load data and show loading state
33
- data_load_state = st.text('Loading data...')
34
- data = load_data(selected_asset)
35
- data_load_state.text('Loading data... done!')
36
-
37
- # Display raw data for debugging purposes
38
- st.subheader('Raw Data')
39
- st.write(data.tail())
40
-
41
- # Check if 'Close' column exists before converting
42
- if 'Close' in data.columns:
43
- # Ensure 'Close' prices are numeric and handle any missing values
44
- try:
45
- data['Close'] = pd.to_numeric(data['Close'], errors='coerce')
46
- data.dropna(subset=['Close'], inplace=True)
47
-
48
- # Check for any infinite values after conversion
49
- if not pd.isnull(data['Close']).any() and not (data['Close'].isinf()).any():
50
- st.success("Data is clean and ready for modeling.")
51
- else:
52
- st.error("Data contains NaN or infinite values after conversion.")
53
- st.stop() # Stop execution if data is not valid
54
-
55
- except Exception as e:
56
- st.error(f"Error converting 'Close' prices to numeric: {e}")
57
-
58
- # Plot raw data using candlestick chart for better visualization
59
- fig_candlestick = go.Figure(data=[go.Candlestick(x=data['Date'],
60
- open=data['Open'],
61
- high=data['High'],
62
- low=data['Low'],
63
- close=data['Close'])])
64
- fig_candlestick.update_layout(title=f'{selected_asset} Price Data',
65
- xaxis_title='Date',
66
- yaxis_title='Price (USD)',
67
- xaxis_rangeslider_visible=True)
68
- st.plotly_chart(fig_candlestick)
69
-
70
- # Prepare data for Prophet model
71
- df_train = data[['Date', 'Close']]
72
- df_train = df_train.rename(columns={"Date": "ds", "Close": "y"})
73
-
74
- # Create and fit the Prophet model
75
- m = Prophet()
76
-
77
- try:
78
- m.fit(df_train)
79
-
80
- # Create future dataframe and make predictions
81
- future = m.make_future_dataframe(periods=period)
82
- forecast = m.predict(future)
83
-
84
- # Calculate performance metrics on historical predictions (if available)
85
- if len(df_train) > 30: # Ensure we have enough historical data to evaluate
86
- historical_forecast = m.predict(df_train)
87
- mae = mean_absolute_error(df_train['y'], historical_forecast['yhat'])
88
- rmse = mean_squared_error(df_train['y'], historical_forecast['yhat'], squared=False)
89
- st.write(f"Mean Absolute Error (MAE): {mae:.2f}")
90
- st.write(f"Root Mean Squared Error (RMSE): {rmse:.2f}")
91
-
92
- # Show forecast data and plot forecast
93
- st.subheader('Forecast Data')
94
- st.write(forecast[['ds', 'yhat', 'yhat_lower', 'yhat_upper']].tail())
95
 
96
- # Plot forecast with confidence intervals
97
- fig_forecast = plot_plotly(m, forecast)
98
- st.plotly_chart(fig_forecast)
99
-
100
- # Show forecast components
101
- st.subheader("Forecast Components")
102
- fig_components = m.plot_components(forecast)
103
- st.plotly_chart(fig_components)
104
-
105
- # Additional Insights: Displaying key metrics
106
- st.subheader("Key Metrics")
107
- latest_data = forecast.iloc[-1]
108
- st.write(f"Predicted Price: ${latest_data['yhat']:.2f}")
109
- st.write(f"Lower Bound: ${latest_data['yhat_lower']:.2f}")
110
- st.write(f"Upper Bound: ${latest_data['yhat_upper']:.2f}")
111
-
112
- except Exception as e:
113
- st.error(f"Error fitting model: {e}")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
114
 
115
- else:
116
- st.error("No valid data available to make predictions.")
 
 
117
 
118
- # User Guidance Section
119
- st.sidebar.header("User Guidance")
120
- st.sidebar.write("""
121
- This application allows you to predict stock prices or cryptocurrency values based on historical data.
122
- - Select a stock or cryptocurrency from the dropdown menu.
123
- - Use the slider to choose how many years into the future you want to predict.
124
- - View the forecasted prices along with confidence intervals.
125
- """)
 
1
  import streamlit as st
2
+ from datetime import date, datetime
3
  import yfinance as yf
4
  import pandas as pd
5
+ import numpy as np
6
  from prophet import Prophet
7
  from prophet.plot import plot_plotly
8
  import plotly.graph_objects as go
9
  from sklearn.metrics import mean_absolute_error, mean_squared_error
10
+ import plotly.express as px
11
 
12
+ # Configure Streamlit page settings
13
+ st.set_page_config(
14
+ page_title="Stock & Crypto Forecast",
15
+ page_icon="๐Ÿ“ˆ",
16
+ layout="wide"
17
+ )
18
+
19
+ # Constants and configurations
20
  START = "2015-01-01"
21
  TODAY = date.today().strftime("%Y-%m-%d")
22
 
23
+ # Custom CSS for better styling
24
+ st.markdown("""
25
+ <style>
26
+ .stButton>button {
27
+ width: 100%;
28
+ }
29
+ .reportview-container {
30
+ background: #f0f2f6
31
+ }
32
+ </style>
33
+ """, unsafe_allow_html=True)
34
+
35
+ class AssetPredictor:
36
+ def __init__(self):
37
+ self.assets = {
38
+ 'Stocks': ['GOOG', 'AAPL', 'MSFT', 'GME'],
39
+ 'Cryptocurrencies': ['BTC-USD', 'ETH-USD', 'DOGE-USD', 'ADA-USD']
40
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
41
 
42
+ @st.cache_data(ttl=3600) # Cache data for 1 hour
43
+ def load_data(self, ticker):
44
+ """Load and validate financial data."""
45
+ try:
46
+ data = yf.download(ticker, START, TODAY)
47
+ if data.empty:
48
+ raise ValueError(f"No data found for {ticker}")
49
+
50
+ data.reset_index(inplace=True)
51
+ # Ensure all required columns exist and are numeric
52
+ required_columns = ['Date', 'Open', 'High', 'Low', 'Close', 'Volume']
53
+ for col in required_columns:
54
+ if col not in data.columns:
55
+ raise ValueError(f"Missing required column: {col}")
56
+ if col != 'Date':
57
+ data[col] = pd.to_numeric(data[col], errors='coerce')
58
+
59
+ data.dropna(inplace=True)
60
+ return data
61
+ except Exception as e:
62
+ st.error(f"Error loading data: {str(e)}")
63
+ return None
64
+
65
+ def prepare_prophet_data(self, data):
66
+ """Prepare data for Prophet model."""
67
+ df_prophet = data[['Date', 'Close']].copy()
68
+ df_prophet.columns = ['ds', 'y']
69
+ return df_prophet
70
+
71
+ def train_prophet_model(self, data, period):
72
+ """Train and return Prophet model with customized parameters."""
73
+ model = Prophet(
74
+ yearly_seasonality=True,
75
+ weekly_seasonality=True,
76
+ daily_seasonality=True,
77
+ changepoint_prior_scale=0.05,
78
+ seasonality_prior_scale=10.0,
79
+ changepoint_range=0.9
80
+ )
81
+
82
+ # Add custom seasonalities
83
+ model.add_seasonality(
84
+ name='monthly',
85
+ period=30.5,
86
+ fourier_order=5
87
+ )
88
+
89
+ model.fit(data)
90
+ future = model.make_future_dataframe(periods=period)
91
+ return model, future
92
+
93
+ def main():
94
+ predictor = AssetPredictor()
95
+
96
+ # Sidebar for user inputs
97
+ st.sidebar.title("โš™๏ธ Configuration")
98
+ asset_type = st.sidebar.radio("Select Asset Type", list(predictor.assets.keys()))
99
+ selected_asset = st.sidebar.selectbox(
100
+ 'Select Asset',
101
+ predictor.assets[asset_type]
102
+ )
103
+
104
+ # Main content
105
+ st.title('๐Ÿ“ˆ Advanced Stock & Cryptocurrency Forecast')
106
+
107
+ # Time range selection
108
+ col1, col2 = st.columns(2)
109
+ with col1:
110
+ n_years = st.slider('Forecast Period (Years):', 1, 4)
111
+ with col2:
112
+ confidence_level = st.slider('Confidence Level:', 0.8, 0.99, 0.95)
113
+
114
+ period = n_years * 365
115
+
116
+ # Load and process data
117
+ with st.spinner('Loading data...'):
118
+ data = predictor.load_data(selected_asset)
119
+
120
+ if data is not None:
121
+ # Display technical indicators
122
+ st.subheader('๐Ÿ“Š Technical Analysis')
123
+
124
+ # Calculate technical indicators
125
+ data['SMA_20'] = data['Close'].rolling(window=20).mean()
126
+ data['SMA_50'] = data['Close'].rolling(window=50).mean()
127
+ data['RSI'] = calculate_rsi(data['Close'])
128
+
129
+ # Create technical analysis plot
130
+ fig_technical = go.Figure()
131
+ fig_technical.add_trace(go.Candlestick(
132
+ x=data['Date'],
133
+ open=data['Open'],
134
+ high=data['High'],
135
+ low=data['Low'],
136
+ close=data['Close'],
137
+ name='Price'
138
+ ))
139
+ fig_technical.add_trace(go.Scatter(
140
+ x=data['Date'],
141
+ y=data['SMA_20'],
142
+ name='SMA 20',
143
+ line=dict(color='orange')
144
+ ))
145
+ fig_technical.add_trace(go.Scatter(
146
+ x=data['Date'],
147
+ y=data['SMA_50'],
148
+ name='SMA 50',
149
+ line=dict(color='blue')
150
+ ))
151
+
152
+ fig_technical.update_layout(
153
+ title=f'{selected_asset} Technical Analysis',
154
+ yaxis_title='Price',
155
+ template='plotly_dark'
156
+ )
157
+ st.plotly_chart(fig_technical, use_container_width=True)
158
+
159
+ # Prepare and train Prophet model
160
+ df_prophet = predictor.prepare_prophet_data(data)
161
+
162
+ try:
163
+ model, future = predictor.train_prophet_model(df_prophet, period)
164
+ forecast = model.predict(future)
165
+
166
+ # Calculate performance metrics
167
+ historical_predictions = forecast[forecast['ds'].isin(df_prophet['ds'])]
168
+ mae = mean_absolute_error(df_prophet['y'], historical_predictions['yhat'])
169
+ rmse = np.sqrt(mean_squared_error(df_prophet['y'], historical_predictions['yhat']))
170
+ mape = np.mean(np.abs((df_prophet['y'] - historical_predictions['yhat']) / df_prophet['y'])) * 100
171
+
172
+ # Display metrics in columns
173
+ st.subheader('๐Ÿ“‰ Model Performance Metrics')
174
+ col1, col2, col3 = st.columns(3)
175
+ col1.metric("MAE", f"${mae:.2f}")
176
+ col2.metric("RMSE", f"${rmse:.2f}")
177
+ col3.metric("MAPE", f"{mape:.2f}%")
178
+
179
+ # Forecast visualization
180
+ st.subheader('๐Ÿ”ฎ Price Forecast')
181
+ fig_forecast = plot_plotly(model, forecast)
182
+ fig_forecast.update_layout(template='plotly_dark')
183
+ st.plotly_chart(fig_forecast, use_container_width=True)
184
+
185
+ # Show forecast components
186
+ st.subheader("๐Ÿ“Š Forecast Components")
187
+ fig_components = model.plot_components(forecast)
188
+ st.plotly_chart(fig_components, use_container_width=True)
189
+
190
+ # Download forecast data
191
+ csv = convert_df_to_csv(forecast)
192
+ st.download_button(
193
+ label="Download Forecast Data",
194
+ data=csv,
195
+ file_name=f'{selected_asset}_forecast.csv',
196
+ mime='text/csv'
197
+ )
198
+
199
+ except Exception as e:
200
+ st.error(f"Error in prediction: {str(e)}")
201
+
202
+ def calculate_rsi(prices, period=14):
203
+ """Calculate Relative Strength Index."""
204
+ delta = prices.diff()
205
+ gain = (delta.where(delta > 0, 0)).rolling(window=period).mean()
206
+ loss = (-delta.where(delta < 0, 0)).rolling(window=period).mean()
207
+ rs = gain / loss
208
+ return 100 - (100 / (1 + rs))
209
 
210
+ @st.cache_data
211
+ def convert_df_to_csv(df):
212
+ """Convert dataframe to CSV for download."""
213
+ return df.to_csv(index=False).encode('utf-8')
214
 
215
+ if __name__ == "__main__":
216
+ main()