Spaces:
Sleeping
Sleeping
Upload 3 files
Browse files- app.py +8 -515
- pages/π_Stock_Analysis.py +516 -0
- pages/π_Stock_Comparison.py +63 -0
app.py
CHANGED
@@ -1,518 +1,11 @@
|
|
1 |
-
|
2 |
-
import pandas as pd
|
3 |
-
import numpy as np
|
4 |
-
import matplotlib.pyplot as plt
|
5 |
-
import pandas_datareader.data as web
|
6 |
-
import datetime as dt
|
7 |
-
import yfinance as yf
|
8 |
-
from sklearn.preprocessing import MinMaxScaler
|
9 |
-
from keras.models import load_model
|
10 |
import streamlit as st
|
11 |
-
import streamlit as st
|
12 |
-
import plotly.graph_objects as go
|
13 |
-
import base64
|
14 |
-
import plotly.express as px
|
15 |
-
from datetime import datetime
|
16 |
-
|
17 |
-
|
18 |
-
## ............................................... ##
|
19 |
-
# Set page configuration (Call this once and make changes as needed)
|
20 |
-
st.set_page_config(page_title='Regression Stocks Prediction', layout='wide', page_icon=':rocket:')
|
21 |
-
|
22 |
-
## ............................................... ##
|
23 |
-
# Add a dictonary of stock tickers and their company names and make a drop down menu to select the stock to predict
|
24 |
-
stock_tickers = {
|
25 |
-
"MAPI":"MAPI.JK","MAP Aktif": "MAPA.JK","MAP Boga": "MAPB.JK",
|
26 |
-
"Tesla": "TSLA", "Apple": "AAPL", "Microsoft": "MSFT", "Google": "GOOGL",
|
27 |
-
"Meta": "META", "Amazon": "AMZN", "Netflix": "NFLX", "Alphabet": "GOOG",
|
28 |
-
"Nvidia": "NVDA", "Paypal": "PYPL", "Adobe": "ADBE", "Intel": "INTC",
|
29 |
-
"Cisco": "CSCO", "Comcast": "CMCSA", "Pepsi": "PEP", "Costco": "COST",
|
30 |
-
"Starbucks": "SBUX", "Walmart": "WMT", "Disney": "DIS", "Visa": "V",
|
31 |
-
"Mastercard": "MA", "Boeing": "BA", "IBM": "IBM", "McDonalds": "MCD",
|
32 |
-
"Nike": "NKE", "Exxon": "XOM", "Chevron": "CVX", "Verizon": "VZ",
|
33 |
-
"AT&T": "T", "Home Depot": "HD", "Salesforce": "CRM", "Oracle": "ORCL",
|
34 |
-
"Qualcomm": "QCOM", "AMD": "AMD"
|
35 |
-
}
|
36 |
-
|
37 |
-
st.sidebar.title("Stock Option")
|
38 |
-
# Custom CSS to change the sidebar color
|
39 |
-
sidebar_css = """
|
40 |
-
<style>
|
41 |
-
div[data-testid="stSidebar"] > div:first-child {
|
42 |
-
width: 350px; # Adjust the width as needed
|
43 |
-
background-color: #FF6969;
|
44 |
-
}
|
45 |
-
</style>
|
46 |
-
"""
|
47 |
-
|
48 |
-
# User Input
|
49 |
-
#default_index = stock_tickers.keys().index("MAPI.JK") if "MAPI.JK" in stock_tickers.keys() else 0
|
50 |
-
#st.markdown(sidebar_css, unsafe_allow_html=True)
|
51 |
-
#user_input = st.sidebar.selectbox("Select a Stock", list(stock_tickers.keys()), index=default_index , key="main_selectbox")
|
52 |
-
#stock_name = user_input
|
53 |
-
#user_input = stock_tickers[user_input]
|
54 |
-
|
55 |
-
user_input = st.sidebar.text_input("Select a Stock", "MAPI.JK")
|
56 |
-
|
57 |
-
# User input for start and end dates using calendar widget
|
58 |
-
start_date = st.sidebar.date_input("Select start date:", datetime(2023, 1, 1))
|
59 |
-
end_date = st.sidebar.date_input("Select end date:", datetime(2023, 12, 1))
|
60 |
-
|
61 |
-
|
62 |
-
st.sidebar.markdown("----")
|
63 |
-
st.sidebar.markdown("Β© 2023 Stocks Prediction App")
|
64 |
-
st.sidebar.markdown("----")
|
65 |
-
st.sidebar.markdown("Example Stock Tickers")
|
66 |
-
st.sidebar.markdown(stock_tickers)
|
67 |
-
|
68 |
-
## ............................................... ##
|
69 |
-
# Page Title and Description
|
70 |
-
st.title("Stock Price Analysis and Prediction")
|
71 |
-
st.write("Created by Bayhaqy")
|
72 |
-
st.write("Using Dataset MAPI to Train and Test the Model")
|
73 |
-
|
74 |
-
## ............................................... ##
|
75 |
-
|
76 |
-
# Try to fetch information from Yahoo Finance
|
77 |
-
try:
|
78 |
-
stock_info = yf.Ticker(user_input).info
|
79 |
-
|
80 |
-
# Check if the 'longName' key exists in stock_info
|
81 |
-
if 'longName' in stock_info:
|
82 |
-
stock_name = stock_info['longName']
|
83 |
-
else:
|
84 |
-
stock_name = user_input
|
85 |
-
|
86 |
-
# Fetch the latest news using yfinance
|
87 |
-
news_data = yf.Ticker(user_input).news
|
88 |
-
|
89 |
-
# Create a Streamlit app
|
90 |
-
title = f"<h1 style='color: red; font-size: 25px; text-align: center; '>{stock_name}'s Stock Fundamental Analysis</h1>"
|
91 |
-
st.markdown(title, unsafe_allow_html=True)
|
92 |
-
|
93 |
-
with st.expander("See Details"):
|
94 |
-
## ............................................... ##
|
95 |
-
# Display the retrieved stock information
|
96 |
-
if 'longName' in stock_info:
|
97 |
-
company_name = stock_info['longName']
|
98 |
-
st.write(f"Company Name: {company_name}")
|
99 |
-
else:
|
100 |
-
st.write("Company name information not available for this stock.")
|
101 |
-
|
102 |
-
if 'industry' in stock_info:
|
103 |
-
Industry = stock_info['industry']
|
104 |
-
st.write(f"Industry: {Industry}")
|
105 |
-
else:
|
106 |
-
st.write("Industry information not available for this stock.")
|
107 |
-
|
108 |
-
if 'sector' in stock_info:
|
109 |
-
Sector = stock_info['sector']
|
110 |
-
st.write(f"Sector: {Sector}")
|
111 |
-
else:
|
112 |
-
st.write("Sector information not available for this stock.")
|
113 |
-
|
114 |
-
if 'website' in stock_info:
|
115 |
-
Website = stock_info['website']
|
116 |
-
st.write(f"Sector: {Website}")
|
117 |
-
else:
|
118 |
-
st.write("Website information not available for this stock.")
|
119 |
-
|
120 |
-
if 'marketCap' in stock_info:
|
121 |
-
MarketCap = stock_info['marketCap']
|
122 |
-
st.write(f"Market Cap: {MarketCap}")
|
123 |
-
else:
|
124 |
-
st.write("Market Cap information not available for this stock.")
|
125 |
-
|
126 |
-
if 'previousClose' in stock_info:
|
127 |
-
PreviousClose = stock_info['previousClose']
|
128 |
-
st.write(f"Previous Close: {PreviousClose}")
|
129 |
-
else:
|
130 |
-
st.write("Previous Close information not available for this stock.")
|
131 |
-
|
132 |
-
if 'dividendYield' in stock_info:
|
133 |
-
dividend_yield = stock_info['dividendYield'] * 100 # Convert to percentage
|
134 |
-
st.write(f"Dividend Yield: {dividend_yield:.2f}%")
|
135 |
-
else:
|
136 |
-
st.write("Dividend Yield information not available for this stock.")
|
137 |
-
|
138 |
-
## ............................................... ##
|
139 |
-
# Display financial metrics
|
140 |
-
st.subheader('Financial Metrics')
|
141 |
-
if 'trailingEps' in stock_info:
|
142 |
-
trailing_eps = stock_info['trailingEps']
|
143 |
-
st.write(f"Earnings Per Share (EPS): {trailing_eps:.2f}")
|
144 |
-
else:
|
145 |
-
st.write("Earnings Per Share (EPS) information not available for this stock.")
|
146 |
-
|
147 |
-
if 'trailingPE' in stock_info:
|
148 |
-
trailing_pe = stock_info['trailingPE']
|
149 |
-
st.write(f"Price-to-Earnings (P/E) Ratio: {trailing_pe:.2f}")
|
150 |
-
else:
|
151 |
-
st.write("Price-to-Earnings (P/E) Ratio information not available for this stock.")
|
152 |
-
|
153 |
-
if 'priceToSalesTrailing12Months' in stock_info:
|
154 |
-
priceToSalesTrailing_12Months = stock_info['priceToSalesTrailing12Months']
|
155 |
-
st.write(f"Price-to-Sales (P/S) Ratio: {priceToSalesTrailing_12Months:.2f}")
|
156 |
-
else:
|
157 |
-
st.write("Price-to-Sales (P/S) Ratio information not available for this stock.")
|
158 |
-
|
159 |
-
if 'priceToBook' in stock_info:
|
160 |
-
price_ToBook = stock_info['priceToBook']
|
161 |
-
st.write(f"Price-to-Book (P/B) Ratio: {price_ToBook:.2f}")
|
162 |
-
else:
|
163 |
-
st.write("Price-to-Book (P/B) Ratio information not available for this stock.")
|
164 |
-
|
165 |
-
## ............................................... ##
|
166 |
-
# Display more detailed information
|
167 |
-
st.subheader('Company Summary')
|
168 |
-
if 'longBusinessSummary' in stock_info:
|
169 |
-
LongBusinessSummary = stock_info['longBusinessSummary']
|
170 |
-
st.write(f"Company Summary: {LongBusinessSummary}")
|
171 |
-
else:
|
172 |
-
st.write("Company Summary information not available for this stock.")
|
173 |
-
|
174 |
-
## ............................................... ##
|
175 |
-
# Display information about company officers
|
176 |
-
st.subheader('Company Officers')
|
177 |
-
if 'fullTimeEmployees' in stock_info:
|
178 |
-
FullTimeEmployees = stock_info['fullTimeEmployees']
|
179 |
-
st.write(f"Full Time Employees: {FullTimeEmployees}")
|
180 |
-
else:
|
181 |
-
st.write("Full Time Employees information not available for this stock.")
|
182 |
-
|
183 |
-
if 'companyOfficers' in stock_info:
|
184 |
-
officers = stock_info['companyOfficers']
|
185 |
-
officer_data = []
|
186 |
-
|
187 |
-
# Create a DataFrame
|
188 |
-
df = pd.DataFrame(columns=["Name", "Title", "Age"])
|
189 |
-
|
190 |
-
# Populate the DataFrame with officer information
|
191 |
-
#for officer in officers:
|
192 |
-
# officer_data.append([officer['name'], officer['title'], officer['age']])
|
193 |
-
|
194 |
-
for officer in officers:
|
195 |
-
name = officer.get('name', 'N/A')
|
196 |
-
title = officer.get('title', 'N/A')
|
197 |
-
age = officer.get('age', 'N/A')
|
198 |
-
officer_data.append([name, title, age])
|
199 |
-
|
200 |
-
|
201 |
-
df = pd.concat([df, pd.DataFrame(officer_data, columns=["Name", "Title", "Age"])], ignore_index=True)
|
202 |
-
|
203 |
-
# Display the DataFrame using Markdown without the index column
|
204 |
-
st.markdown(df.to_markdown(index=False))
|
205 |
-
|
206 |
-
else:
|
207 |
-
st.write("Company Officers information not available for this stock.")
|
208 |
-
|
209 |
-
## ............................................... ##
|
210 |
-
# Display the latest news
|
211 |
-
st.subheader('Latest News')
|
212 |
-
|
213 |
-
# Prepare the data for the DataFrame
|
214 |
-
news_data_for_dataframe = []
|
215 |
-
for news_item in news_data:
|
216 |
-
news_title = news_item['title']
|
217 |
-
news_link = f"[Link]({news_item['link']})"
|
218 |
-
news_publisher = news_item['publisher']
|
219 |
-
news_provider_publish_time = pd.to_datetime(news_item['providerPublishTime'], unit='s')
|
220 |
-
news_type = news_item['type']
|
221 |
-
news_data_for_dataframe.append([news_title, news_link, news_publisher, news_provider_publish_time, news_type])
|
222 |
-
|
223 |
-
# Create a Pandas DataFrame
|
224 |
-
df = pd.DataFrame(news_data_for_dataframe, columns=["Title", "Link", "Publisher", "Provider Publish Time", "Type"])
|
225 |
-
|
226 |
-
# Display the DataFrame using Markdown without the index column
|
227 |
-
st.markdown(df.to_markdown(index=False), unsafe_allow_html=True)
|
228 |
-
|
229 |
-
## ............................................... ##
|
230 |
-
# Enhanced title with larger font size and a different color
|
231 |
-
title = f"<h1 style='color: red; font-size: 25px; text-align: center; '>{stock_name}'s Stock Technical Analysis</h1>"
|
232 |
-
st.markdown(title, unsafe_allow_html=True)
|
233 |
-
|
234 |
-
with st.expander("See Details"):
|
235 |
-
# Describing the data
|
236 |
-
st.subheader(f'Data from {start_date} - {end_date}')
|
237 |
-
data = yf.download(user_input, start_date, end_date)
|
238 |
-
|
239 |
-
if data.empty:
|
240 |
-
# Display a message to the user when no data is available
|
241 |
-
st.warning(f"No data available for stock symbol {stock_name} in the specified date range.")
|
242 |
-
else:
|
243 |
-
# Reset the index to add the date column
|
244 |
-
data = data.reset_index()
|
245 |
-
|
246 |
-
# Display data in a Plotly table
|
247 |
-
fig = go.Figure(data=[go.Table(
|
248 |
-
header=dict(values=list(data.columns),
|
249 |
-
font=dict(size=12, color='white'),
|
250 |
-
fill_color='#264653',
|
251 |
-
line_color='rgba(255,255,255,0.2)',
|
252 |
-
align=['left', 'center'],
|
253 |
-
height=20),
|
254 |
-
cells=dict(values=[data[k].tolist() for k in data.columns],
|
255 |
-
font=dict(size=12),
|
256 |
-
align=['left', 'center'],
|
257 |
-
line_color='rgba(255,255,255,0.2)',
|
258 |
-
height=20))])
|
259 |
-
|
260 |
-
fig.update_layout(title_text=f"Data for {stock_name}", title_font_color='#264653', title_x=0, margin=dict(l=0, r=10, b=10, t=30))
|
261 |
-
|
262 |
-
st.plotly_chart(fig, use_container_width=True)
|
263 |
-
|
264 |
-
|
265 |
-
st.markdown(f"<h2 style='text-align: center; color: #264653;'>Data Overview for {stock_name}</h2>", unsafe_allow_html=True)
|
266 |
-
# Get the description of the data
|
267 |
-
description = data.describe()
|
268 |
-
|
269 |
-
# Dictionary of columns and rows to highlight
|
270 |
-
highlight_dict = {
|
271 |
-
"Open": ["mean", "min", "max", "std"],
|
272 |
-
"High": ["mean", "min", "max", "std"],
|
273 |
-
"Low": ["mean", "min", "max", "std"],
|
274 |
-
"Close": ["mean", "min", "max", "std"],
|
275 |
-
"Adj Close": ["mean", "min", "max", "std"]
|
276 |
-
}
|
277 |
-
|
278 |
-
# Colors for specific rows
|
279 |
-
color_dict = {
|
280 |
-
"mean": "lightgreen",
|
281 |
-
"min": "salmon",
|
282 |
-
"max": "lightblue",
|
283 |
-
"std": "lightyellow"
|
284 |
-
}
|
285 |
-
|
286 |
-
# Function to highlight specific columns and rows based on the dictionaries
|
287 |
-
def highlight_specific_cells(val, col_name, row_name):
|
288 |
-
if col_name in highlight_dict and row_name in highlight_dict[col_name]:
|
289 |
-
return f'background-color: {color_dict[row_name]}'
|
290 |
-
return ''
|
291 |
-
|
292 |
-
styled_description = description.style.apply(lambda row: [highlight_specific_cells(val, col, row.name) for col, val in row.items()], axis=1)
|
293 |
-
|
294 |
-
# Display the styled table in Streamlit
|
295 |
-
st.table(styled_description)
|
296 |
-
|
297 |
-
### ............................................... ##
|
298 |
-
# Stock Price Over Time
|
299 |
-
g1, g2, g3 = st.columns((1.2,1.2,1))
|
300 |
-
|
301 |
-
fig1 = px.line(data, x='Date', y='Close', template='seaborn')
|
302 |
-
fig1.update_traces(line_color='#264653')
|
303 |
-
fig1.update_layout(title_text="Stock Price Over Time", title_x=0, margin=dict(l=20, r=20, b=20, t=30), yaxis_title=None, xaxis_title=None, height=400, width=700)
|
304 |
-
g1.plotly_chart(fig1, use_container_width=True)
|
305 |
-
|
306 |
-
# Volume of Stocks Traded Over Time
|
307 |
-
fig2 = px.bar(data, x='Date', y='Volume', template='seaborn')
|
308 |
-
fig2.update_traces(marker_color='#7A9E9F')
|
309 |
-
fig2.update_layout(title_text="Volume of Stocks Traded Over Time", title_x=0, margin=dict(l=20, r=20, b=20, t=30), yaxis_title=None, xaxis_title=None, height=400, width=700)
|
310 |
-
g2.plotly_chart(fig2, use_container_width=True)
|
311 |
-
|
312 |
-
# Moving Averages
|
313 |
-
short_window = 40
|
314 |
-
long_window = 100
|
315 |
-
data['Short_MA'] = data['Close'].rolling(window=short_window).mean()
|
316 |
-
data['Long_MA'] = data['Close'].rolling(window=long_window).mean()
|
317 |
-
fig3 = px.line(data, x='Date', y='Close', template='seaborn')
|
318 |
-
fig3.add_scatter(x=data['Date'], y=data['Short_MA'], mode='lines', line=dict(color="red"), name=f'Short {short_window}D MA')
|
319 |
-
fig3.add_scatter(x=data['Date'], y=data['Long_MA'], mode='lines', line=dict(color="blue"), name=f'Long {long_window}D MA')
|
320 |
-
fig3.update_layout(title_text="Stock Price with Moving Averages", title_x=0, margin=dict(l=20, r=20, b=20, t=30), yaxis_title=None, xaxis_title=None, legend=dict(orientation="h", yanchor="bottom", y=0.9, xanchor="right", x=0.99), height=400, width=700)
|
321 |
-
g3.plotly_chart(fig3, use_container_width=True)
|
322 |
-
|
323 |
-
## ............................................... ##
|
324 |
-
# Daily Returns
|
325 |
-
g4, g5, g6 = st.columns((1,1,1))
|
326 |
-
data['Daily_Returns'] = data['Close'].pct_change()
|
327 |
-
fig4 = px.line(data, x='Date', y='Daily_Returns', template='seaborn')
|
328 |
-
fig4.update_traces(line_color='#E76F51')
|
329 |
-
fig4.update_layout(title_text="Daily Returns", title_x=0, margin=dict(l=0, r=10, b=10, t=30), yaxis_title=None, xaxis_title=None)
|
330 |
-
g4.plotly_chart(fig4, use_container_width=True)
|
331 |
-
|
332 |
-
# Cumulative Returns
|
333 |
-
data['Cumulative_Returns'] = (1 + data['Daily_Returns']).cumprod()
|
334 |
-
fig5 = px.line(data, x='Date', y='Cumulative_Returns', template='seaborn')
|
335 |
-
fig5.update_traces(line_color='#2A9D8F')
|
336 |
-
fig5.update_layout(title_text="Cumulative Returns", title_x=0, margin=dict(l=0, r=10, b=10, t=30), yaxis_title=None, xaxis_title=None)
|
337 |
-
g5.plotly_chart(fig5, use_container_width=True)
|
338 |
-
# Stock Price Distribution
|
339 |
-
fig6 = px.histogram(data, x='Close', template='seaborn', nbins=50)
|
340 |
-
fig6.update_traces(marker_color='#F4A261')
|
341 |
-
fig6.update_layout(title_text="Stock Price Distribution", title_x=0, margin=dict(l=0, r=10, b=10, t=30), yaxis_title=None, xaxis_title=None)
|
342 |
-
g6.plotly_chart(fig6, use_container_width=True)
|
343 |
-
|
344 |
-
## ............................................... ##
|
345 |
-
|
346 |
-
# Bollinger Bands
|
347 |
-
g7, g8, g9 = st.columns((1,1,1))
|
348 |
-
rolling_mean = data['Close'].rolling(window=20).mean()
|
349 |
-
rolling_std = data['Close'].rolling(window=20).std()
|
350 |
-
data['Bollinger_Upper'] = rolling_mean + (rolling_std * 2)
|
351 |
-
data['Bollinger_Lower'] = rolling_mean - (rolling_std * 2)
|
352 |
-
fig7 = px.line(data, x='Date', y='Close', template='seaborn')
|
353 |
-
fig7.add_scatter(x=data['Date'], y=data['Bollinger_Upper'], mode='lines', line=dict(color="green"), name='Upper Bollinger Band')
|
354 |
-
fig7.add_scatter(x=data['Date'], y=data['Bollinger_Lower'], mode='lines', line=dict(color="red"), name='Lower Bollinger Band')
|
355 |
-
fig7.update_layout(title_text="Bollinger Bands", title_x=0, margin=dict(l=0, r=10, b=10, t=30), yaxis_title=None, xaxis_title=None)
|
356 |
-
g7.plotly_chart(fig7, use_container_width=True)
|
357 |
-
|
358 |
-
# Stock Price vs. Volume
|
359 |
-
fig8 = px.line(data, x='Date', y='Close', template='seaborn')
|
360 |
-
fig8.add_bar(x=data['Date'], y=data['Volume'], name='Volume')
|
361 |
-
fig8.update_layout(title_text="Stock Price vs. Volume", title_x=0, margin=dict(l=0, r=10, b=10, t=30), yaxis_title=None, xaxis_title=None)
|
362 |
-
g8.plotly_chart(fig8, use_container_width=True)
|
363 |
-
|
364 |
-
# MACD
|
365 |
-
data['12D_EMA'] = data['Close'].ewm(span=12, adjust=False).mean()
|
366 |
-
data['26D_EMA'] = data['Close'].ewm(span=26, adjust=False).mean()
|
367 |
-
data['MACD'] = data['12D_EMA'] - data['26D_EMA']
|
368 |
-
data['Signal_Line'] = data['MACD'].ewm(span=9, adjust=False).mean()
|
369 |
-
fig9 = px.line(data, x='Date', y='MACD', template='seaborn', title="MACD")
|
370 |
-
fig9.add_scatter(x=data['Date'], y=data['Signal_Line'], mode='lines', line=dict(color="orange"), name='Signal Line')
|
371 |
-
fig9.update_layout(title_text="MACD", title_x=0, margin=dict(l=0, r=10, b=10, t=30), yaxis_title=None, xaxis_title=None)
|
372 |
-
g9.plotly_chart(fig9, use_container_width=True)
|
373 |
-
|
374 |
-
### ............................................... ##
|
375 |
-
|
376 |
-
# Relative Strength Index (RSI)
|
377 |
-
g10, g11, g12 = st.columns((1,1,1))
|
378 |
-
delta = data['Close'].diff()
|
379 |
-
gain = (delta.where(delta > 0, 0)).fillna(0)
|
380 |
-
loss = (-delta.where(delta < 0, 0)).fillna(0)
|
381 |
-
avg_gain = gain.rolling(window=14).mean()
|
382 |
-
avg_loss = loss.rolling(window=14).mean()
|
383 |
-
rs = avg_gain / avg_loss
|
384 |
-
data['RSI'] = 100 - (100 / (1 + rs))
|
385 |
-
fig10 = px.line(data, x='Date', y='RSI', template='seaborn')
|
386 |
-
fig10.update_layout(title_text="Relative Strength Index (RSI)", title_x=0, margin=dict(l=0, r=10, b=10, t=30), yaxis_title=None, xaxis_title=None)
|
387 |
-
g10.plotly_chart(fig10, use_container_width=True)
|
388 |
-
|
389 |
-
# Candlestick Chart
|
390 |
-
fig11 = go.Figure(data=[go.Candlestick(x=data['Date'],
|
391 |
-
open=data['Open'],
|
392 |
-
high=data['High'],
|
393 |
-
low=data['Low'],
|
394 |
-
close=data['Close'])])
|
395 |
-
fig11.update_layout(title_text="Candlestick Chart", title_x=0, margin=dict(l=0, r=10, b=10, t=30))
|
396 |
-
g11.plotly_chart(fig11, use_container_width=True)
|
397 |
-
|
398 |
-
# Correlation Matrix
|
399 |
-
corr_matrix = data[['Open', 'High', 'Low', 'Close', 'Volume']].corr()
|
400 |
-
fig12 = px.imshow(corr_matrix, template='seaborn')
|
401 |
-
fig12.update_layout(title_text="Correlation Matrix", title_x=0, margin=dict(l=0, r=10, b=10, t=30))
|
402 |
-
g12.plotly_chart(fig12, use_container_width=True)
|
403 |
-
|
404 |
-
### ............................................... ##
|
405 |
-
# Price Rate of Change (ROC)
|
406 |
-
g13, g14, g15 = st.columns((1,1,1))
|
407 |
-
n = 12
|
408 |
-
data['ROC'] = ((data['Close'] - data['Close'].shift(n)) / data['Close'].shift(n)) * 100
|
409 |
-
fig13 = px.line(data, x='Date', y='ROC', template='seaborn')
|
410 |
-
fig13.update_layout(title_text="Price Rate of Change (ROC)", title_x=0, margin=dict(l=0, r=10, b=10, t=30), yaxis_title=None, xaxis_title=None)
|
411 |
-
g13.plotly_chart(fig13, use_container_width=True)
|
412 |
-
|
413 |
-
# Stochastic Oscillator
|
414 |
-
low_min = data['Low'].rolling(window=14).min()
|
415 |
-
high_max = data['High'].rolling(window=14).max()
|
416 |
-
data['%K'] = (100 * (data['Close'] - low_min) / (high_max - low_min))
|
417 |
-
data['%D'] = data['%K'].rolling(window=3).mean()
|
418 |
-
fig14 = px.line(data, x='Date', y='%K', template='seaborn')
|
419 |
-
fig14.add_scatter(x=data['Date'], y=data['%D'], mode='lines', line=dict(color="orange"), name='%D (3-day SMA of %K)')
|
420 |
-
fig14.update_layout(title_text="Stochastic Oscillator", title_x=0, margin=dict(l=0, r=10, b=10, t=30), yaxis_title=None, xaxis_title=None)
|
421 |
-
g14.plotly_chart(fig14, use_container_width=True)
|
422 |
-
|
423 |
-
# Historical Volatility
|
424 |
-
data['Log_Return'] = np.log(data['Close'] / data['Close'].shift(1))
|
425 |
-
data['Historical_Volatility'] = data['Log_Return'].rolling(window=252).std() * np.sqrt(252)
|
426 |
-
fig15 = px.line(data, x='Date', y='Historical_Volatility', template='seaborn')
|
427 |
-
fig15.update_layout(title_text="Historical Volatility (252-day)", title_x=0, margin=dict(l=0, r=10, b=10, t=30), yaxis_title=None, xaxis_title=None)
|
428 |
-
g15.plotly_chart(fig15, use_container_width=True)
|
429 |
-
|
430 |
-
### ............................................... ##
|
431 |
-
|
432 |
-
# Visualizing the data and want to get the data when hovering over the graph
|
433 |
-
st.subheader('Closing Price vs Time Chart')
|
434 |
-
fig1 = go.Figure()
|
435 |
-
fig1.add_trace(go.Scatter(x=data.index, y=data['Close'], mode='lines', name='Close'))
|
436 |
-
fig1.layout.update(hovermode='x')
|
437 |
-
# Display the figure in Streamlit
|
438 |
-
st.plotly_chart(fig1,use_container_width=True)
|
439 |
-
|
440 |
-
st.subheader('Closing Price vs Time Chart with 100MA')
|
441 |
-
ma100 = data['Close'].rolling(100).mean()
|
442 |
-
fig2 = go.Figure()
|
443 |
-
# Add traces for 100MA and Closing Price
|
444 |
-
fig2.add_trace(go.Scatter(x=data.index, y=ma100, mode='lines', name='100MA'))
|
445 |
-
fig2.add_trace(go.Scatter(x=data.index, y=data['Close'], mode='lines', name='Closing Price'))
|
446 |
-
fig2.layout.update(hovermode='x')
|
447 |
-
# Display the figure in Streamlit
|
448 |
-
st.plotly_chart(fig2,use_container_width=True)
|
449 |
-
|
450 |
-
st.subheader('Closing Price vs Time Chart with 100MA and 200MA')
|
451 |
-
ma100 = data['Close'].rolling(100).mean()
|
452 |
-
ma200 = data['Close'].rolling(200).mean()
|
453 |
-
fig3 = go.Figure()
|
454 |
-
# Add traces for 100MA and Closing Price
|
455 |
-
fig3.add_trace(go.Scatter(x=data.index, y=ma100, mode='lines', name='100MA'))
|
456 |
-
fig3.add_trace(go.Scatter(x=data.index, y=ma200, mode='lines', name='200MA'))
|
457 |
-
fig3.add_trace(go.Scatter(x=data.index, y=data['Close'], mode='lines', name='Closing Price'))
|
458 |
-
fig3.layout.update(hovermode='x')
|
459 |
-
|
460 |
-
# Display the figure in Streamlit
|
461 |
-
st.plotly_chart(fig3,use_container_width=True)
|
462 |
-
|
463 |
-
## ............................................... ##
|
464 |
-
# Enhanced title with larger font size and a different color
|
465 |
-
title = f"<h1 style='color: red; font-size: 25px; text-align: center; '>{stock_name}'s Stock Prediction</h1>"
|
466 |
-
st.markdown(title, unsafe_allow_html=True)
|
467 |
-
|
468 |
-
with st.expander("See Details"):
|
469 |
-
# Define the minimum number of days required for predictions
|
470 |
-
minimum_days_for_predictions = 100
|
471 |
-
|
472 |
-
# Check if the available data is less than the minimum required days
|
473 |
-
if len(data) < minimum_days_for_predictions:
|
474 |
-
st.warning(f"The available data for {stock_name} is less than {minimum_days_for_predictions} days, which is insufficient for predictions.")
|
475 |
-
else:
|
476 |
-
# Splitting the data into training and testing data
|
477 |
-
data_training = pd.DataFrame(data['Close'][0:int(len(data)*0.70)])
|
478 |
-
data_testing = pd.DataFrame(data['Close'][int(len(data)*0.70): int(len(data))])
|
479 |
-
|
480 |
-
# Scaling the data
|
481 |
-
scaler = MinMaxScaler(feature_range=(0,1))
|
482 |
-
data_training_array = scaler.fit_transform(data_training)
|
483 |
-
|
484 |
-
# load the model
|
485 |
-
model = load_model('best_model_MAPI.h5')
|
486 |
-
|
487 |
-
# Testing the model
|
488 |
-
past_100_days = data_training.tail(100)
|
489 |
-
final_df = pd.concat([past_100_days,data_testing], ignore_index=True)
|
490 |
-
input_data = scaler.fit_transform(final_df)
|
491 |
-
|
492 |
-
x_test = []
|
493 |
-
y_test = []
|
494 |
-
for i in range(100, input_data.shape[0]):
|
495 |
-
x_test.append(input_data[i-100:i])
|
496 |
-
y_test.append(input_data[i,0])
|
497 |
-
|
498 |
-
x_test, y_test = np.array(x_test), np.array(y_test)
|
499 |
-
|
500 |
-
y_predicted = model.predict(x_test)
|
501 |
-
|
502 |
-
scaler = scaler.scale_
|
503 |
-
scale_factor = 1/scaler[0]
|
504 |
-
y_predicted = y_predicted * scale_factor
|
505 |
-
y_test = y_test * scale_factor
|
506 |
|
507 |
-
# Visualizing the results
|
508 |
-
st.subheader('Predictions vs Actual')
|
509 |
-
fig4 = go.Figure()
|
510 |
-
# Add traces for Actual and Predicted Price
|
511 |
-
fig4.add_trace(go.Scatter(x=data.index[-len(y_test):], y=y_test, mode='lines', name='Actual Price'))
|
512 |
-
fig4.add_trace(go.Scatter(x=data.index[-len(y_predicted):], y=y_predicted[:,0], mode='lines', name='Predicted Price'))
|
513 |
-
fig4.layout.update(hovermode='x')
|
514 |
-
# Display the figure in Streamlit
|
515 |
-
st.plotly_chart(fig4,use_container_width=True)
|
516 |
|
517 |
-
|
518 |
-
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from pathlib import Path
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2 |
import streamlit as st
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
3 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
4 |
|
5 |
+
st.set_page_config(page_title='Regression Stocks Prediction', layout='wide', page_icon='π')
|
6 |
+
st.title("π Stock Analysis and Prediction")
|
7 |
+
st.write(
|
8 |
+
"""
|
9 |
+
Welcome to the **π Stock Analysis and Prediction**!
|
10 |
+
"""
|
11 |
+
)
|
pages/π_Stock_Analysis.py
ADDED
@@ -0,0 +1,516 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import pandas as pd
|
2 |
+
import numpy as np
|
3 |
+
import matplotlib.pyplot as plt
|
4 |
+
import pandas_datareader.data as web
|
5 |
+
import datetime as dt
|
6 |
+
import yfinance as yf
|
7 |
+
from sklearn.preprocessing import MinMaxScaler
|
8 |
+
from keras.models import load_model
|
9 |
+
import streamlit as st
|
10 |
+
import plotly.graph_objects as go
|
11 |
+
import base64
|
12 |
+
import plotly.express as px
|
13 |
+
from datetime import datetime
|
14 |
+
|
15 |
+
|
16 |
+
## ............................................... ##
|
17 |
+
# Set page configuration (Call this once and make changes as needed)
|
18 |
+
st.set_page_config(page_title='Regression Stocks Prediction', layout='wide', page_icon=':rocket:')
|
19 |
+
|
20 |
+
## ............................................... ##
|
21 |
+
# Add a dictonary of stock tickers and their company names and make a drop down menu to select the stock to predict
|
22 |
+
stock_tickers = {
|
23 |
+
"MAPI":"MAPI.JK","MAP Aktif": "MAPA.JK","MAP Boga": "MAPB.JK",
|
24 |
+
"Tesla": "TSLA", "Apple": "AAPL", "Microsoft": "MSFT", "Google": "GOOGL",
|
25 |
+
"Meta": "META", "Amazon": "AMZN", "Netflix": "NFLX", "Alphabet": "GOOG",
|
26 |
+
"Nvidia": "NVDA", "Paypal": "PYPL", "Adobe": "ADBE", "Intel": "INTC",
|
27 |
+
"Cisco": "CSCO", "Comcast": "CMCSA", "Pepsi": "PEP", "Costco": "COST",
|
28 |
+
"Starbucks": "SBUX", "Walmart": "WMT", "Disney": "DIS", "Visa": "V",
|
29 |
+
"Mastercard": "MA", "Boeing": "BA", "IBM": "IBM", "McDonalds": "MCD",
|
30 |
+
"Nike": "NKE", "Exxon": "XOM", "Chevron": "CVX", "Verizon": "VZ",
|
31 |
+
"AT&T": "T", "Home Depot": "HD", "Salesforce": "CRM", "Oracle": "ORCL",
|
32 |
+
"Qualcomm": "QCOM", "AMD": "AMD"
|
33 |
+
}
|
34 |
+
|
35 |
+
st.sidebar.title("Stock Option")
|
36 |
+
# Custom CSS to change the sidebar color
|
37 |
+
sidebar_css = """
|
38 |
+
<style>
|
39 |
+
div[data-testid="stSidebar"] > div:first-child {
|
40 |
+
width: 350px; # Adjust the width as needed
|
41 |
+
background-color: #FF6969;
|
42 |
+
}
|
43 |
+
</style>
|
44 |
+
"""
|
45 |
+
|
46 |
+
# User Input
|
47 |
+
#default_index = stock_tickers.keys().index("MAPI.JK") if "MAPI.JK" in stock_tickers.keys() else 0
|
48 |
+
#st.markdown(sidebar_css, unsafe_allow_html=True)
|
49 |
+
#user_input = st.sidebar.selectbox("Select a Stock", list(stock_tickers.keys()), index=default_index , key="main_selectbox")
|
50 |
+
#stock_name = user_input
|
51 |
+
#user_input = stock_tickers[user_input]
|
52 |
+
|
53 |
+
user_input = st.sidebar.text_input("Select a Stock", "MAPI.JK")
|
54 |
+
|
55 |
+
# User input for start and end dates using calendar widget
|
56 |
+
start_date = st.sidebar.date_input("Select start date:", datetime(2023, 1, 1))
|
57 |
+
end_date = st.sidebar.date_input("Select end date:", datetime(2023, 12, 1))
|
58 |
+
|
59 |
+
|
60 |
+
st.sidebar.markdown("----")
|
61 |
+
st.sidebar.markdown("Β© 2023 Stocks Prediction App")
|
62 |
+
st.sidebar.markdown("----")
|
63 |
+
st.sidebar.markdown("Example Stock Tickers")
|
64 |
+
st.sidebar.markdown(stock_tickers)
|
65 |
+
|
66 |
+
## ............................................... ##
|
67 |
+
# Page Title and Description
|
68 |
+
st.title("Stock Price Analysis and Prediction")
|
69 |
+
st.write("Created by Bayhaqy")
|
70 |
+
st.write("Using Dataset MAPI to Train and Test the Model")
|
71 |
+
|
72 |
+
## ............................................... ##
|
73 |
+
|
74 |
+
# Try to fetch information from Yahoo Finance
|
75 |
+
try:
|
76 |
+
stock_info = yf.Ticker(user_input).info
|
77 |
+
|
78 |
+
# Check if the 'longName' key exists in stock_info
|
79 |
+
if 'longName' in stock_info:
|
80 |
+
stock_name = stock_info['longName']
|
81 |
+
else:
|
82 |
+
stock_name = user_input
|
83 |
+
|
84 |
+
# Fetch the latest news using yfinance
|
85 |
+
news_data = yf.Ticker(user_input).news
|
86 |
+
|
87 |
+
# Create a Streamlit app
|
88 |
+
title = f"<h1 style='color: red; font-size: 25px; text-align: center; '>{stock_name}'s Stock Fundamental Analysis</h1>"
|
89 |
+
st.markdown(title, unsafe_allow_html=True)
|
90 |
+
|
91 |
+
with st.expander("See Details"):
|
92 |
+
## ............................................... ##
|
93 |
+
# Display the retrieved stock information
|
94 |
+
if 'longName' in stock_info:
|
95 |
+
company_name = stock_info['longName']
|
96 |
+
st.write(f"Company Name: {company_name}")
|
97 |
+
else:
|
98 |
+
st.write("Company name information not available for this stock.")
|
99 |
+
|
100 |
+
if 'industry' in stock_info:
|
101 |
+
Industry = stock_info['industry']
|
102 |
+
st.write(f"Industry: {Industry}")
|
103 |
+
else:
|
104 |
+
st.write("Industry information not available for this stock.")
|
105 |
+
|
106 |
+
if 'sector' in stock_info:
|
107 |
+
Sector = stock_info['sector']
|
108 |
+
st.write(f"Sector: {Sector}")
|
109 |
+
else:
|
110 |
+
st.write("Sector information not available for this stock.")
|
111 |
+
|
112 |
+
if 'website' in stock_info:
|
113 |
+
Website = stock_info['website']
|
114 |
+
st.write(f"Sector: {Website}")
|
115 |
+
else:
|
116 |
+
st.write("Website information not available for this stock.")
|
117 |
+
|
118 |
+
if 'marketCap' in stock_info:
|
119 |
+
MarketCap = stock_info['marketCap']
|
120 |
+
st.write(f"Market Cap: {MarketCap}")
|
121 |
+
else:
|
122 |
+
st.write("Market Cap information not available for this stock.")
|
123 |
+
|
124 |
+
if 'previousClose' in stock_info:
|
125 |
+
PreviousClose = stock_info['previousClose']
|
126 |
+
st.write(f"Previous Close: {PreviousClose}")
|
127 |
+
else:
|
128 |
+
st.write("Previous Close information not available for this stock.")
|
129 |
+
|
130 |
+
if 'dividendYield' in stock_info:
|
131 |
+
dividend_yield = stock_info['dividendYield'] * 100 # Convert to percentage
|
132 |
+
st.write(f"Dividend Yield: {dividend_yield:.2f}%")
|
133 |
+
else:
|
134 |
+
st.write("Dividend Yield information not available for this stock.")
|
135 |
+
|
136 |
+
## ............................................... ##
|
137 |
+
# Display financial metrics
|
138 |
+
st.subheader('Financial Metrics')
|
139 |
+
if 'trailingEps' in stock_info:
|
140 |
+
trailing_eps = stock_info['trailingEps']
|
141 |
+
st.write(f"Earnings Per Share (EPS): {trailing_eps:.2f}")
|
142 |
+
else:
|
143 |
+
st.write("Earnings Per Share (EPS) information not available for this stock.")
|
144 |
+
|
145 |
+
if 'trailingPE' in stock_info:
|
146 |
+
trailing_pe = stock_info['trailingPE']
|
147 |
+
st.write(f"Price-to-Earnings (P/E) Ratio: {trailing_pe:.2f}")
|
148 |
+
else:
|
149 |
+
st.write("Price-to-Earnings (P/E) Ratio information not available for this stock.")
|
150 |
+
|
151 |
+
if 'priceToSalesTrailing12Months' in stock_info:
|
152 |
+
priceToSalesTrailing_12Months = stock_info['priceToSalesTrailing12Months']
|
153 |
+
st.write(f"Price-to-Sales (P/S) Ratio: {priceToSalesTrailing_12Months:.2f}")
|
154 |
+
else:
|
155 |
+
st.write("Price-to-Sales (P/S) Ratio information not available for this stock.")
|
156 |
+
|
157 |
+
if 'priceToBook' in stock_info:
|
158 |
+
price_ToBook = stock_info['priceToBook']
|
159 |
+
st.write(f"Price-to-Book (P/B) Ratio: {price_ToBook:.2f}")
|
160 |
+
else:
|
161 |
+
st.write("Price-to-Book (P/B) Ratio information not available for this stock.")
|
162 |
+
|
163 |
+
## ............................................... ##
|
164 |
+
# Display more detailed information
|
165 |
+
st.subheader('Company Summary')
|
166 |
+
if 'longBusinessSummary' in stock_info:
|
167 |
+
LongBusinessSummary = stock_info['longBusinessSummary']
|
168 |
+
st.write(f"Company Summary: {LongBusinessSummary}")
|
169 |
+
else:
|
170 |
+
st.write("Company Summary information not available for this stock.")
|
171 |
+
|
172 |
+
## ............................................... ##
|
173 |
+
# Display information about company officers
|
174 |
+
st.subheader('Company Officers')
|
175 |
+
if 'fullTimeEmployees' in stock_info:
|
176 |
+
FullTimeEmployees = stock_info['fullTimeEmployees']
|
177 |
+
st.write(f"Full Time Employees: {FullTimeEmployees}")
|
178 |
+
else:
|
179 |
+
st.write("Full Time Employees information not available for this stock.")
|
180 |
+
|
181 |
+
if 'companyOfficers' in stock_info:
|
182 |
+
officers = stock_info['companyOfficers']
|
183 |
+
officer_data = []
|
184 |
+
|
185 |
+
# Create a DataFrame
|
186 |
+
df = pd.DataFrame(columns=["Name", "Title", "Age"])
|
187 |
+
|
188 |
+
# Populate the DataFrame with officer information
|
189 |
+
#for officer in officers:
|
190 |
+
# officer_data.append([officer['name'], officer['title'], officer['age']])
|
191 |
+
|
192 |
+
for officer in officers:
|
193 |
+
name = officer.get('name', 'N/A')
|
194 |
+
title = officer.get('title', 'N/A')
|
195 |
+
age = officer.get('age', 'N/A')
|
196 |
+
officer_data.append([name, title, age])
|
197 |
+
|
198 |
+
|
199 |
+
df = pd.concat([df, pd.DataFrame(officer_data, columns=["Name", "Title", "Age"])], ignore_index=True)
|
200 |
+
|
201 |
+
# Display the DataFrame using Markdown without the index column
|
202 |
+
st.markdown(df.to_markdown(index=False))
|
203 |
+
|
204 |
+
else:
|
205 |
+
st.write("Company Officers information not available for this stock.")
|
206 |
+
|
207 |
+
## ............................................... ##
|
208 |
+
# Display the latest news
|
209 |
+
st.subheader('Latest News')
|
210 |
+
|
211 |
+
# Prepare the data for the DataFrame
|
212 |
+
news_data_for_dataframe = []
|
213 |
+
for news_item in news_data:
|
214 |
+
news_title = news_item['title']
|
215 |
+
news_link = f"[Link]({news_item['link']})"
|
216 |
+
news_publisher = news_item['publisher']
|
217 |
+
news_provider_publish_time = pd.to_datetime(news_item['providerPublishTime'], unit='s')
|
218 |
+
news_type = news_item['type']
|
219 |
+
news_data_for_dataframe.append([news_title, news_link, news_publisher, news_provider_publish_time, news_type])
|
220 |
+
|
221 |
+
# Create a Pandas DataFrame
|
222 |
+
df = pd.DataFrame(news_data_for_dataframe, columns=["Title", "Link", "Publisher", "Provider Publish Time", "Type"])
|
223 |
+
|
224 |
+
# Display the DataFrame using Markdown without the index column
|
225 |
+
st.markdown(df.to_markdown(index=False), unsafe_allow_html=True)
|
226 |
+
|
227 |
+
## ............................................... ##
|
228 |
+
# Enhanced title with larger font size and a different color
|
229 |
+
title = f"<h1 style='color: red; font-size: 25px; text-align: center; '>{stock_name}'s Stock Technical Analysis</h1>"
|
230 |
+
st.markdown(title, unsafe_allow_html=True)
|
231 |
+
|
232 |
+
with st.expander("See Details"):
|
233 |
+
# Describing the data
|
234 |
+
st.subheader(f'Data from {start_date} - {end_date}')
|
235 |
+
data = yf.download(user_input, start_date, end_date)
|
236 |
+
|
237 |
+
if data.empty:
|
238 |
+
# Display a message to the user when no data is available
|
239 |
+
st.warning(f"No data available for stock symbol {stock_name} in the specified date range.")
|
240 |
+
else:
|
241 |
+
# Reset the index to add the date column
|
242 |
+
data = data.reset_index()
|
243 |
+
|
244 |
+
# Display data in a Plotly table
|
245 |
+
fig = go.Figure(data=[go.Table(
|
246 |
+
header=dict(values=list(data.columns),
|
247 |
+
font=dict(size=12, color='white'),
|
248 |
+
fill_color='#264653',
|
249 |
+
line_color='rgba(255,255,255,0.2)',
|
250 |
+
align=['left', 'center'],
|
251 |
+
height=20),
|
252 |
+
cells=dict(values=[data[k].tolist() for k in data.columns],
|
253 |
+
font=dict(size=12),
|
254 |
+
align=['left', 'center'],
|
255 |
+
line_color='rgba(255,255,255,0.2)',
|
256 |
+
height=20))])
|
257 |
+
|
258 |
+
fig.update_layout(title_text=f"Data for {stock_name}", title_font_color='#264653', title_x=0, margin=dict(l=0, r=10, b=10, t=30))
|
259 |
+
|
260 |
+
st.plotly_chart(fig, use_container_width=True)
|
261 |
+
|
262 |
+
|
263 |
+
st.markdown(f"<h2 style='text-align: center; color: #264653;'>Data Overview for {stock_name}</h2>", unsafe_allow_html=True)
|
264 |
+
# Get the description of the data
|
265 |
+
description = data.describe()
|
266 |
+
|
267 |
+
# Dictionary of columns and rows to highlight
|
268 |
+
highlight_dict = {
|
269 |
+
"Open": ["mean", "min", "max", "std"],
|
270 |
+
"High": ["mean", "min", "max", "std"],
|
271 |
+
"Low": ["mean", "min", "max", "std"],
|
272 |
+
"Close": ["mean", "min", "max", "std"],
|
273 |
+
"Adj Close": ["mean", "min", "max", "std"]
|
274 |
+
}
|
275 |
+
|
276 |
+
# Colors for specific rows
|
277 |
+
color_dict = {
|
278 |
+
"mean": "lightgreen",
|
279 |
+
"min": "salmon",
|
280 |
+
"max": "lightblue",
|
281 |
+
"std": "lightyellow"
|
282 |
+
}
|
283 |
+
|
284 |
+
# Function to highlight specific columns and rows based on the dictionaries
|
285 |
+
def highlight_specific_cells(val, col_name, row_name):
|
286 |
+
if col_name in highlight_dict and row_name in highlight_dict[col_name]:
|
287 |
+
return f'background-color: {color_dict[row_name]}'
|
288 |
+
return ''
|
289 |
+
|
290 |
+
styled_description = description.style.apply(lambda row: [highlight_specific_cells(val, col, row.name) for col, val in row.items()], axis=1)
|
291 |
+
|
292 |
+
# Display the styled table in Streamlit
|
293 |
+
st.table(styled_description)
|
294 |
+
|
295 |
+
### ............................................... ##
|
296 |
+
# Stock Price Over Time
|
297 |
+
g1, g2, g3 = st.columns((1.2,1.2,1))
|
298 |
+
|
299 |
+
fig1 = px.line(data, x='Date', y='Close', template='seaborn')
|
300 |
+
fig1.update_traces(line_color='#264653')
|
301 |
+
fig1.update_layout(title_text="Stock Price Over Time", title_x=0, margin=dict(l=20, r=20, b=20, t=30), yaxis_title=None, xaxis_title=None, height=400, width=700)
|
302 |
+
g1.plotly_chart(fig1, use_container_width=True)
|
303 |
+
|
304 |
+
# Volume of Stocks Traded Over Time
|
305 |
+
fig2 = px.bar(data, x='Date', y='Volume', template='seaborn')
|
306 |
+
fig2.update_traces(marker_color='#7A9E9F')
|
307 |
+
fig2.update_layout(title_text="Volume of Stocks Traded Over Time", title_x=0, margin=dict(l=20, r=20, b=20, t=30), yaxis_title=None, xaxis_title=None, height=400, width=700)
|
308 |
+
g2.plotly_chart(fig2, use_container_width=True)
|
309 |
+
|
310 |
+
# Moving Averages
|
311 |
+
short_window = 40
|
312 |
+
long_window = 100
|
313 |
+
data['Short_MA'] = data['Close'].rolling(window=short_window).mean()
|
314 |
+
data['Long_MA'] = data['Close'].rolling(window=long_window).mean()
|
315 |
+
fig3 = px.line(data, x='Date', y='Close', template='seaborn')
|
316 |
+
fig3.add_scatter(x=data['Date'], y=data['Short_MA'], mode='lines', line=dict(color="red"), name=f'Short {short_window}D MA')
|
317 |
+
fig3.add_scatter(x=data['Date'], y=data['Long_MA'], mode='lines', line=dict(color="blue"), name=f'Long {long_window}D MA')
|
318 |
+
fig3.update_layout(title_text="Stock Price with Moving Averages", title_x=0, margin=dict(l=20, r=20, b=20, t=30), yaxis_title=None, xaxis_title=None, legend=dict(orientation="h", yanchor="bottom", y=0.9, xanchor="right", x=0.99), height=400, width=700)
|
319 |
+
g3.plotly_chart(fig3, use_container_width=True)
|
320 |
+
|
321 |
+
## ............................................... ##
|
322 |
+
# Daily Returns
|
323 |
+
g4, g5, g6 = st.columns((1,1,1))
|
324 |
+
data['Daily_Returns'] = data['Close'].pct_change()
|
325 |
+
fig4 = px.line(data, x='Date', y='Daily_Returns', template='seaborn')
|
326 |
+
fig4.update_traces(line_color='#E76F51')
|
327 |
+
fig4.update_layout(title_text="Daily Returns", title_x=0, margin=dict(l=0, r=10, b=10, t=30), yaxis_title=None, xaxis_title=None)
|
328 |
+
g4.plotly_chart(fig4, use_container_width=True)
|
329 |
+
|
330 |
+
# Cumulative Returns
|
331 |
+
data['Cumulative_Returns'] = (1 + data['Daily_Returns']).cumprod()
|
332 |
+
fig5 = px.line(data, x='Date', y='Cumulative_Returns', template='seaborn')
|
333 |
+
fig5.update_traces(line_color='#2A9D8F')
|
334 |
+
fig5.update_layout(title_text="Cumulative Returns", title_x=0, margin=dict(l=0, r=10, b=10, t=30), yaxis_title=None, xaxis_title=None)
|
335 |
+
g5.plotly_chart(fig5, use_container_width=True)
|
336 |
+
# Stock Price Distribution
|
337 |
+
fig6 = px.histogram(data, x='Close', template='seaborn', nbins=50)
|
338 |
+
fig6.update_traces(marker_color='#F4A261')
|
339 |
+
fig6.update_layout(title_text="Stock Price Distribution", title_x=0, margin=dict(l=0, r=10, b=10, t=30), yaxis_title=None, xaxis_title=None)
|
340 |
+
g6.plotly_chart(fig6, use_container_width=True)
|
341 |
+
|
342 |
+
## ............................................... ##
|
343 |
+
|
344 |
+
# Bollinger Bands
|
345 |
+
g7, g8, g9 = st.columns((1,1,1))
|
346 |
+
rolling_mean = data['Close'].rolling(window=20).mean()
|
347 |
+
rolling_std = data['Close'].rolling(window=20).std()
|
348 |
+
data['Bollinger_Upper'] = rolling_mean + (rolling_std * 2)
|
349 |
+
data['Bollinger_Lower'] = rolling_mean - (rolling_std * 2)
|
350 |
+
fig7 = px.line(data, x='Date', y='Close', template='seaborn')
|
351 |
+
fig7.add_scatter(x=data['Date'], y=data['Bollinger_Upper'], mode='lines', line=dict(color="green"), name='Upper Bollinger Band')
|
352 |
+
fig7.add_scatter(x=data['Date'], y=data['Bollinger_Lower'], mode='lines', line=dict(color="red"), name='Lower Bollinger Band')
|
353 |
+
fig7.update_layout(title_text="Bollinger Bands", title_x=0, margin=dict(l=0, r=10, b=10, t=30), yaxis_title=None, xaxis_title=None)
|
354 |
+
g7.plotly_chart(fig7, use_container_width=True)
|
355 |
+
|
356 |
+
# Stock Price vs. Volume
|
357 |
+
fig8 = px.line(data, x='Date', y='Close', template='seaborn')
|
358 |
+
fig8.add_bar(x=data['Date'], y=data['Volume'], name='Volume')
|
359 |
+
fig8.update_layout(title_text="Stock Price vs. Volume", title_x=0, margin=dict(l=0, r=10, b=10, t=30), yaxis_title=None, xaxis_title=None)
|
360 |
+
g8.plotly_chart(fig8, use_container_width=True)
|
361 |
+
|
362 |
+
# MACD
|
363 |
+
data['12D_EMA'] = data['Close'].ewm(span=12, adjust=False).mean()
|
364 |
+
data['26D_EMA'] = data['Close'].ewm(span=26, adjust=False).mean()
|
365 |
+
data['MACD'] = data['12D_EMA'] - data['26D_EMA']
|
366 |
+
data['Signal_Line'] = data['MACD'].ewm(span=9, adjust=False).mean()
|
367 |
+
fig9 = px.line(data, x='Date', y='MACD', template='seaborn', title="MACD")
|
368 |
+
fig9.add_scatter(x=data['Date'], y=data['Signal_Line'], mode='lines', line=dict(color="orange"), name='Signal Line')
|
369 |
+
fig9.update_layout(title_text="MACD", title_x=0, margin=dict(l=0, r=10, b=10, t=30), yaxis_title=None, xaxis_title=None)
|
370 |
+
g9.plotly_chart(fig9, use_container_width=True)
|
371 |
+
|
372 |
+
### ............................................... ##
|
373 |
+
|
374 |
+
# Relative Strength Index (RSI)
|
375 |
+
g10, g11, g12 = st.columns((1,1,1))
|
376 |
+
delta = data['Close'].diff()
|
377 |
+
gain = (delta.where(delta > 0, 0)).fillna(0)
|
378 |
+
loss = (-delta.where(delta < 0, 0)).fillna(0)
|
379 |
+
avg_gain = gain.rolling(window=14).mean()
|
380 |
+
avg_loss = loss.rolling(window=14).mean()
|
381 |
+
rs = avg_gain / avg_loss
|
382 |
+
data['RSI'] = 100 - (100 / (1 + rs))
|
383 |
+
fig10 = px.line(data, x='Date', y='RSI', template='seaborn')
|
384 |
+
fig10.update_layout(title_text="Relative Strength Index (RSI)", title_x=0, margin=dict(l=0, r=10, b=10, t=30), yaxis_title=None, xaxis_title=None)
|
385 |
+
g10.plotly_chart(fig10, use_container_width=True)
|
386 |
+
|
387 |
+
# Candlestick Chart
|
388 |
+
fig11 = go.Figure(data=[go.Candlestick(x=data['Date'],
|
389 |
+
open=data['Open'],
|
390 |
+
high=data['High'],
|
391 |
+
low=data['Low'],
|
392 |
+
close=data['Close'])])
|
393 |
+
fig11.update_layout(title_text="Candlestick Chart", title_x=0, margin=dict(l=0, r=10, b=10, t=30))
|
394 |
+
g11.plotly_chart(fig11, use_container_width=True)
|
395 |
+
|
396 |
+
# Correlation Matrix
|
397 |
+
corr_matrix = data[['Open', 'High', 'Low', 'Close', 'Volume']].corr()
|
398 |
+
fig12 = px.imshow(corr_matrix, template='seaborn')
|
399 |
+
fig12.update_layout(title_text="Correlation Matrix", title_x=0, margin=dict(l=0, r=10, b=10, t=30))
|
400 |
+
g12.plotly_chart(fig12, use_container_width=True)
|
401 |
+
|
402 |
+
### ............................................... ##
|
403 |
+
# Price Rate of Change (ROC)
|
404 |
+
g13, g14, g15 = st.columns((1,1,1))
|
405 |
+
n = 12
|
406 |
+
data['ROC'] = ((data['Close'] - data['Close'].shift(n)) / data['Close'].shift(n)) * 100
|
407 |
+
fig13 = px.line(data, x='Date', y='ROC', template='seaborn')
|
408 |
+
fig13.update_layout(title_text="Price Rate of Change (ROC)", title_x=0, margin=dict(l=0, r=10, b=10, t=30), yaxis_title=None, xaxis_title=None)
|
409 |
+
g13.plotly_chart(fig13, use_container_width=True)
|
410 |
+
|
411 |
+
# Stochastic Oscillator
|
412 |
+
low_min = data['Low'].rolling(window=14).min()
|
413 |
+
high_max = data['High'].rolling(window=14).max()
|
414 |
+
data['%K'] = (100 * (data['Close'] - low_min) / (high_max - low_min))
|
415 |
+
data['%D'] = data['%K'].rolling(window=3).mean()
|
416 |
+
fig14 = px.line(data, x='Date', y='%K', template='seaborn')
|
417 |
+
fig14.add_scatter(x=data['Date'], y=data['%D'], mode='lines', line=dict(color="orange"), name='%D (3-day SMA of %K)')
|
418 |
+
fig14.update_layout(title_text="Stochastic Oscillator", title_x=0, margin=dict(l=0, r=10, b=10, t=30), yaxis_title=None, xaxis_title=None)
|
419 |
+
g14.plotly_chart(fig14, use_container_width=True)
|
420 |
+
|
421 |
+
# Historical Volatility
|
422 |
+
data['Log_Return'] = np.log(data['Close'] / data['Close'].shift(1))
|
423 |
+
data['Historical_Volatility'] = data['Log_Return'].rolling(window=252).std() * np.sqrt(252)
|
424 |
+
fig15 = px.line(data, x='Date', y='Historical_Volatility', template='seaborn')
|
425 |
+
fig15.update_layout(title_text="Historical Volatility (252-day)", title_x=0, margin=dict(l=0, r=10, b=10, t=30), yaxis_title=None, xaxis_title=None)
|
426 |
+
g15.plotly_chart(fig15, use_container_width=True)
|
427 |
+
|
428 |
+
### ............................................... ##
|
429 |
+
|
430 |
+
# Visualizing the data and want to get the data when hovering over the graph
|
431 |
+
st.subheader('Closing Price vs Time Chart')
|
432 |
+
fig1 = go.Figure()
|
433 |
+
fig1.add_trace(go.Scatter(x=data.index, y=data['Close'], mode='lines', name='Close'))
|
434 |
+
fig1.layout.update(hovermode='x')
|
435 |
+
# Display the figure in Streamlit
|
436 |
+
st.plotly_chart(fig1,use_container_width=True)
|
437 |
+
|
438 |
+
st.subheader('Closing Price vs Time Chart with 100MA')
|
439 |
+
ma100 = data['Close'].rolling(100).mean()
|
440 |
+
fig2 = go.Figure()
|
441 |
+
# Add traces for 100MA and Closing Price
|
442 |
+
fig2.add_trace(go.Scatter(x=data.index, y=ma100, mode='lines', name='100MA'))
|
443 |
+
fig2.add_trace(go.Scatter(x=data.index, y=data['Close'], mode='lines', name='Closing Price'))
|
444 |
+
fig2.layout.update(hovermode='x')
|
445 |
+
# Display the figure in Streamlit
|
446 |
+
st.plotly_chart(fig2,use_container_width=True)
|
447 |
+
|
448 |
+
st.subheader('Closing Price vs Time Chart with 100MA and 200MA')
|
449 |
+
ma100 = data['Close'].rolling(100).mean()
|
450 |
+
ma200 = data['Close'].rolling(200).mean()
|
451 |
+
fig3 = go.Figure()
|
452 |
+
# Add traces for 100MA and Closing Price
|
453 |
+
fig3.add_trace(go.Scatter(x=data.index, y=ma100, mode='lines', name='100MA'))
|
454 |
+
fig3.add_trace(go.Scatter(x=data.index, y=ma200, mode='lines', name='200MA'))
|
455 |
+
fig3.add_trace(go.Scatter(x=data.index, y=data['Close'], mode='lines', name='Closing Price'))
|
456 |
+
fig3.layout.update(hovermode='x')
|
457 |
+
|
458 |
+
# Display the figure in Streamlit
|
459 |
+
st.plotly_chart(fig3,use_container_width=True)
|
460 |
+
|
461 |
+
## ............................................... ##
|
462 |
+
# Enhanced title with larger font size and a different color
|
463 |
+
title = f"<h1 style='color: red; font-size: 25px; text-align: center; '>{stock_name}'s Stock Prediction</h1>"
|
464 |
+
st.markdown(title, unsafe_allow_html=True)
|
465 |
+
|
466 |
+
with st.expander("See Details"):
|
467 |
+
# Define the minimum number of days required for predictions
|
468 |
+
minimum_days_for_predictions = 100
|
469 |
+
|
470 |
+
# Check if the available data is less than the minimum required days
|
471 |
+
if len(data) < minimum_days_for_predictions:
|
472 |
+
st.warning(f"The available data for {stock_name} is less than {minimum_days_for_predictions} days, which is insufficient for predictions.")
|
473 |
+
else:
|
474 |
+
# Splitting the data into training and testing data
|
475 |
+
data_training = pd.DataFrame(data['Close'][0:int(len(data)*0.70)])
|
476 |
+
data_testing = pd.DataFrame(data['Close'][int(len(data)*0.70): int(len(data))])
|
477 |
+
|
478 |
+
# Scaling the data
|
479 |
+
scaler = MinMaxScaler(feature_range=(0,1))
|
480 |
+
data_training_array = scaler.fit_transform(data_training)
|
481 |
+
|
482 |
+
# load the model
|
483 |
+
model = load_model('best_model_MAPI.h5')
|
484 |
+
|
485 |
+
# Testing the model
|
486 |
+
past_100_days = data_training.tail(100)
|
487 |
+
final_df = pd.concat([past_100_days,data_testing], ignore_index=True)
|
488 |
+
input_data = scaler.fit_transform(final_df)
|
489 |
+
|
490 |
+
x_test = []
|
491 |
+
y_test = []
|
492 |
+
for i in range(100, input_data.shape[0]):
|
493 |
+
x_test.append(input_data[i-100:i])
|
494 |
+
y_test.append(input_data[i,0])
|
495 |
+
|
496 |
+
x_test, y_test = np.array(x_test), np.array(y_test)
|
497 |
+
|
498 |
+
y_predicted = model.predict(x_test)
|
499 |
+
|
500 |
+
scaler = scaler.scale_
|
501 |
+
scale_factor = 1/scaler[0]
|
502 |
+
y_predicted = y_predicted * scale_factor
|
503 |
+
y_test = y_test * scale_factor
|
504 |
+
|
505 |
+
# Visualizing the results
|
506 |
+
st.subheader('Predictions vs Actual')
|
507 |
+
fig4 = go.Figure()
|
508 |
+
# Add traces for Actual and Predicted Price
|
509 |
+
fig4.add_trace(go.Scatter(x=data.index[-len(y_test):], y=y_test, mode='lines', name='Actual Price'))
|
510 |
+
fig4.add_trace(go.Scatter(x=data.index[-len(y_predicted):], y=y_predicted[:,0], mode='lines', name='Predicted Price'))
|
511 |
+
fig4.layout.update(hovermode='x')
|
512 |
+
# Display the figure in Streamlit
|
513 |
+
st.plotly_chart(fig4,use_container_width=True)
|
514 |
+
|
515 |
+
except Exception as e:
|
516 |
+
st.error(f"An error fetching stock information: {str(e)}")
|
pages/π_Stock_Comparison.py
ADDED
@@ -0,0 +1,63 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import pandas as pd
|
2 |
+
import numpy as np
|
3 |
+
import matplotlib.pyplot as plt
|
4 |
+
import pandas_datareader.data as web
|
5 |
+
import datetime as dt
|
6 |
+
import yfinance as yf
|
7 |
+
from sklearn.preprocessing import MinMaxScaler
|
8 |
+
from keras.models import load_model
|
9 |
+
import streamlit as st
|
10 |
+
import plotly.graph_objects as go
|
11 |
+
import base64
|
12 |
+
import plotly.express as px
|
13 |
+
from datetime import datetime
|
14 |
+
|
15 |
+
st.set_page_config(page_title='Stock Comparison', layout='wide', page_icon='π')
|
16 |
+
|
17 |
+
stock_tickers = {
|
18 |
+
"MAPI":"MAPI.JK","MAP Aktif": "MAPA.JK","MAP Boga": "MAPB.JK",
|
19 |
+
"Tesla": "TSLA", "Apple": "AAPL", "Microsoft": "MSFT", "Google": "GOOGL",
|
20 |
+
"Facebook": "FB", "Amazon": "AMZN", "Netflix": "NFLX", "Alphabet": "GOOG",
|
21 |
+
"Nvidia": "NVDA", "Paypal": "PYPL", "Adobe": "ADBE", "Intel": "INTC",
|
22 |
+
"Cisco": "CSCO", "Comcast": "CMCSA", "Pepsi": "PEP", "Costco": "COST",
|
23 |
+
"Starbucks": "SBUX", "Walmart": "WMT", "Disney": "DIS", "Visa": "V",
|
24 |
+
"Mastercard": "MA", "Boeing": "BA", "IBM": "IBM", "McDonalds": "MCD",
|
25 |
+
"Nike": "NKE", "Exxon": "XOM", "Chevron": "CVX", "Verizon": "VZ",
|
26 |
+
"AT&T": "T", "Home Depot": "HD", "Salesforce": "CRM", "Oracle": "ORCL",
|
27 |
+
"Qualcomm": "QCOM", "AMD": "AMD"
|
28 |
+
}
|
29 |
+
|
30 |
+
st.title("Stock Comparison and Analysis")
|
31 |
+
|
32 |
+
# Sidebar for stock selection and date range specification
|
33 |
+
st.sidebar.header("Select Stocks and Date Ranges")
|
34 |
+
|
35 |
+
#stock1 = st.sidebar.selectbox("Select Stock 1", list(stock_tickers.keys()), key="stock1_selectbox")
|
36 |
+
#stock2 = st.sidebar.selectbox("Select Stock 2", list(stock_tickers.keys()), key="stock2_selectbox")
|
37 |
+
|
38 |
+
stock1 = st.sidebar.text_input("Select a Stock", "MAPI.JK")
|
39 |
+
stock2 = st.sidebar.text_input("Select a Stock", "MAPA.JK")
|
40 |
+
|
41 |
+
start_date_stock1 = st.sidebar.date_input(f"Start date for {stock1}", datetime(2018, 1, 1), key=f"start_date_{stock1}")
|
42 |
+
end_date_stock1 = st.sidebar.date_input(f"End date for {stock1}", datetime(2023, 12, 1), key=f"end_date_{stock1}")
|
43 |
+
start_date_stock2 = st.sidebar.date_input(f"Start date for {stock2}", datetime(2018, 1, 1), key=f"start_date_{stock2}")
|
44 |
+
end_date_stock2 = st.sidebar.date_input(f"End date for {stock2}", datetime(2023, 12, 1), key=f"end_date_{stock2}")
|
45 |
+
|
46 |
+
# Button to trigger the comparison
|
47 |
+
if st.sidebar.button("Compare"):
|
48 |
+
# Load data for both stocks
|
49 |
+
data_stock1 = yf.download(stock1, start=start_date_stock1, end=end_date_stock1)
|
50 |
+
data_stock2 = yf.download(stock2, start=start_date_stock2, end=end_date_stock2)
|
51 |
+
|
52 |
+
# Plotting the data
|
53 |
+
fig = go.Figure()
|
54 |
+
|
55 |
+
fig.add_trace(go.Scatter(x=data_stock1.index, y=data_stock1['Close'], mode='lines', name=f'{stock1}'))
|
56 |
+
fig.add_trace(go.Scatter(x=data_stock2.index, y=data_stock2['Close'], mode='lines', name=f'{stock2}'))
|
57 |
+
|
58 |
+
fig.update_layout(title=f"Comparison of {stock1} and {stock2}", xaxis_title="Date", yaxis_title="Closing Price")
|
59 |
+
|
60 |
+
st.plotly_chart(fig)
|
61 |
+
|
62 |
+
st.sidebar.markdown("----")
|
63 |
+
st.sidebar.markdown("Β© 2023 Stock Comparison and Analysis")
|