QuantumLearner commited on
Commit
f6764ad
·
verified ·
1 Parent(s): ee8fa3c

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +257 -0
app.py ADDED
@@ -0,0 +1,257 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ import pandas as pd
3
+ import requests
4
+ import plotly.express as px
5
+ from datetime import datetime, timedelta
6
+ import textwrap
7
+ import os
8
+
9
+ API_KEY = os.getenv("FMP_API_KEY")
10
+
11
+ # Set wide page layout
12
+ st.set_page_config(page_title="Analyst Recommendations", layout="wide")
13
+
14
+ # Sidebar: Global ticker and page navigation
15
+ st.sidebar.header("Inputs")
16
+ with st.sidebar.expander("Ticker and Page Settings", expanded=True):
17
+ ticker = st.text_input(
18
+ "Enter Ticker Symbol",
19
+ value="AAPL",
20
+ help="Input the stock ticker symbol (e.g., AAPL, MSFT)."
21
+ )
22
+ page = st.radio(
23
+ "Select Page",
24
+ ["Historical Ratings", "Recommendations"],
25
+ help="Choose which analysis page to view."
26
+ )
27
+
28
+ # Reset stored results if ticker changes
29
+ if "ticker" not in st.session_state or st.session_state.ticker != ticker:
30
+ st.session_state.ticker = ticker
31
+ st.session_state.historical_data = None
32
+ st.session_state.analyst_data = None
33
+ st.session_state.run_pressed_hist = False
34
+ st.session_state.run_pressed_analyst = False
35
+
36
+ # Cached function for historical data
37
+ @st.cache_data(show_spinner=False)
38
+ def load_historical_data(ticker):
39
+ try:
40
+ API_KEY = API_KEY
41
+ url = f"https://financialmodelingprep.com/api/v3/historical-rating/{ticker}?apikey={API_KEY}"
42
+ response = requests.get(url)
43
+ if response.status_code != 200:
44
+ st.error("Error retrieving historical data.")
45
+ return None
46
+ data = response.json()
47
+ df = pd.DataFrame(data)
48
+ # Define required columns.
49
+ req_cols = [
50
+ 'date', 'rating', 'ratingScore', 'ratingRecommendation', 'ratingDetailsDCFScore',
51
+ 'ratingDetailsROEScore', 'ratingDetailsROERecommendation',
52
+ 'ratingDetailsROAScore', 'ratingDetailsROARecommendation',
53
+ 'ratingDetailsDEScore', 'ratingDetailsDERecommendation',
54
+ 'ratingDetailsPEScore', 'ratingDetailsPERecommendation',
55
+ 'ratingDetailsPBScore', 'ratingDetailsPBRecommendation'
56
+ ]
57
+ # Use alternative column if available.
58
+ if 'ratingDetailsROCFRecommendation' in df.columns:
59
+ req_cols.insert(4, 'ratingDetailsROCFRecommendation')
60
+ else:
61
+ req_cols.insert(4, 'ratingDetailsDCFRecommendation')
62
+ df = df[req_cols]
63
+ df['date'] = pd.to_datetime(df['date'])
64
+ df = df.sort_values('date')
65
+ return df
66
+ except Exception:
67
+ st.error("An error occurred while loading historical data.")
68
+ return None
69
+
70
+ # Cached function for analyst recommendations data
71
+ @st.cache_data(show_spinner=False)
72
+ def load_analyst_data(ticker):
73
+ try:
74
+ API_KEY = API_KEY
75
+ url = f"https://financialmodelingprep.com/api/v3/analyst-stock-recommendations/{ticker}?apikey={API_KEY}"
76
+ response = requests.get(url)
77
+ if response.status_code != 200:
78
+ st.error("Error retrieving analyst data.")
79
+ return None
80
+ data = response.json()
81
+ if isinstance(data, dict):
82
+ data = [data]
83
+ df = pd.DataFrame(data)
84
+ df['date'] = pd.to_datetime(df['date'])
85
+ df = df.sort_values('date')
86
+ return df
87
+ except Exception:
88
+ st.error("An error occurred while loading analyst data.")
89
+ return None
90
+
91
+ # Main area explanation
92
+ #st.title("Analysts Recommendations")
93
+ #st.write("This app displays historical rating scores and analyst recommendations for the specified ticker.")
94
+
95
+
96
+ # PAGE: Historical Ratings
97
+ if page == "Historical Ratings":
98
+ st.header("Historical Ratings")
99
+ # Sidebar inputs for this page
100
+ st.write("Below are a series of bar charts that show historical trends in key financial metrics.")
101
+ with st.expander("Category Description", expanded=False):
102
+ description = textwrap.dedent("""
103
+ - **Overall Rating Score**: Reflects the general analyst rating, summarizing overall performance.
104
+ - **DCF Score**: Represents the discounted cash flow valuation, which estimates a stock's intrinsic value.
105
+ - **ROE Score**: Measures return on equity to assess how efficiently a company uses shareholder funds.
106
+ - **ROA Score**: Indicates return on assets to gauge the effectiveness of asset use in generating profits.
107
+ - **DE Score**: Shows the debt-to-equity ratio, highlighting the financial leverage of the company.
108
+ - **PE Score**: Provides the price-to-earnings ratio, indicating market valuation relative to earnings.
109
+ - **PB Score**: Measures the price-to-book ratio to assess if the stock is undervalued compared to its book value.
110
+ Each chart displays the numerical score with a text recommendation. Colors denote recommendations like "Strong Buy", "Buy", "Neutral", "Sell", and "Strong Sell".
111
+ """)
112
+ st.markdown(description)
113
+ default_date = datetime.today() - timedelta(days=365)
114
+ with st.sidebar.expander("Date Settings", expanded=True):
115
+ start_date = st.date_input(
116
+ "Start Date",
117
+ value=default_date,
118
+ help="Select a start date for filtering historical data."
119
+ )
120
+ # Place run button below the start date input
121
+ if st.sidebar.button("Run Analysis", key="hist_run_button"):
122
+ st.session_state.run_pressed_hist = True
123
+
124
+ if st.session_state.run_pressed_hist:
125
+ # Load data if not already loaded
126
+ if st.session_state.historical_data is None:
127
+ st.session_state.historical_data = load_historical_data(ticker)
128
+ df_hist = st.session_state.historical_data
129
+ if df_hist is not None:
130
+ # Filter data based on start date.
131
+ df_filtered = df_hist[df_hist['date'] >= pd.to_datetime(start_date)]
132
+ #st.subheader(f"Historical Ratings for {ticker}")
133
+ #st.write("Bar charts below show various score metrics over time.")
134
+ recommendation_colors = {
135
+ "Strong Buy": "green",
136
+ "Buy": "lightgreen",
137
+ "Neutral": "orange",
138
+ "Sell": "lightcoral",
139
+ "Strong Sell": "red"
140
+ }
141
+ categories = [
142
+ 'ratingScore', 'ratingDetailsDCFScore', 'ratingDetailsROEScore',
143
+ 'ratingDetailsROAScore', 'ratingDetailsDEScore', 'ratingDetailsPEScore',
144
+ 'ratingDetailsPBScore'
145
+ ]
146
+ titles = [
147
+ 'Overall Rating Score', 'DCF Score', 'ROE Score',
148
+ 'ROA Score', 'DE Score', 'PE Score', 'PB Score'
149
+ ]
150
+ for category, title in zip(categories, titles):
151
+ recommendation_col = category.replace("Score", "Recommendation")
152
+ st.markdown(f"**{title} Chart**")
153
+ #st.write("This chart shows the score over time with its associated recommendation.")
154
+ try:
155
+ fig = px.bar(
156
+ df_filtered,
157
+ x='date',
158
+ y=category,
159
+ text=category,
160
+ labels={'date': 'Date', category: 'Score'},
161
+ title=title,
162
+ color=recommendation_col,
163
+ color_discrete_map=recommendation_colors,
164
+ custom_data=['rating', recommendation_col]
165
+ )
166
+ fig.update_traces(
167
+ texttemplate="%{text}<br>%{customdata[0]} (%{customdata[1]})",
168
+ textposition='outside',
169
+ hovertemplate="<b>Date</b>: %{x}<br><b>Score</b>: %{y}<br><b>Rating</b>: %{customdata[0]}<br><b>Recommendation</b>: %{customdata[1]}<extra></extra>"
170
+ )
171
+ st.plotly_chart(fig, use_container_width=True)
172
+ except Exception:
173
+ st.error("Error displaying the chart. Please check the data and inputs.")
174
+ with st.expander("Show Detailed Historical Data"):
175
+ st.dataframe(df_filtered)
176
+ else:
177
+ st.info("Press 'Run Analysis' in the sidebar to load historical ratings data.")
178
+
179
+ # PAGE: Analyst Recommendations
180
+ elif page == "Recommendations":
181
+ st.header("Analyst Recommendations")
182
+ st.write("This section presents the monthly analyst recommendations for the selected ticker. The stacked bar chart aggregates various recommendation types over time.")
183
+ with st.expander("Category Description", expanded=False):
184
+ description = textwrap.dedent("""
185
+ - **Strong Buy**: Indicates that analysts are very confident the stock will perform strongly.
186
+ - **Buy**: Reflects a positive outlook from analysts regarding future performance.
187
+ - **Hold**: Suggests that analysts expect the stock to maintain its current performance.
188
+ - **Sell**: Signals a negative outlook, indicating the stock may underperform.
189
+ - **Strong Sell**: Represents a very bearish sentiment, with analysts expecting significant underperformance.
190
+ The chart lets you observe shifts in market sentiment over time and compare the prevalence of each recommendation type.
191
+ """)
192
+ st.markdown(description)
193
+ # No additional page-specific inputs; thus, no expander is shown.
194
+ if st.sidebar.button("Run Analysis", key="analyst_run_button"):
195
+ st.session_state.run_pressed_analyst = True
196
+
197
+ if st.session_state.run_pressed_analyst:
198
+ if st.session_state.analyst_data is None:
199
+ st.session_state.analyst_data = load_analyst_data(ticker)
200
+ df_analyst = st.session_state.analyst_data
201
+ if df_analyst is not None:
202
+ st.subheader(f"Analyst Recommendations for {ticker}")
203
+ st.write("The stacked bar chart below shows monthly analyst recommendations.")
204
+ rating_cols = [
205
+ "analystRatingsStrongBuy",
206
+ "analystRatingsbuy",
207
+ "analystRatingsHold",
208
+ "analystRatingsSell",
209
+ "analystRatingsStrongSell"
210
+ ]
211
+ df_melted = pd.melt(
212
+ df_analyst,
213
+ id_vars=["date"],
214
+ value_vars=rating_cols,
215
+ var_name="RatingType",
216
+ value_name="Count"
217
+ )
218
+ color_map = {
219
+ "analystRatingsStrongBuy": "green",
220
+ "analystRatingsbuy": "lightgreen",
221
+ "analystRatingsHold": "orange",
222
+ "analystRatingsSell": "lightcoral",
223
+ "analystRatingsStrongSell": "red"
224
+ }
225
+ rating_order = [
226
+ "analystRatingsStrongBuy",
227
+ "analystRatingsbuy",
228
+ "analystRatingsHold",
229
+ "analystRatingsSell",
230
+ "analystRatingsStrongSell"
231
+ ]
232
+ try:
233
+ fig2 = px.bar(
234
+ df_melted,
235
+ x="date",
236
+ y="Count",
237
+ color="RatingType",
238
+ text="Count",
239
+ title=f"Monthly Analyst Recommendations for {ticker.upper()}",
240
+ color_discrete_map=color_map,
241
+ category_orders={"RatingType": rating_order},
242
+ custom_data=["RatingType"],
243
+ labels={"date": "Date", "Count": "Number of Recommendations", "RatingType": "Recommendation Type"}
244
+ )
245
+ fig2.update_layout(barmode="stack")
246
+ fig2.update_traces(
247
+ texttemplate="%{text}",
248
+ textposition="inside",
249
+ hovertemplate="<b>Date</b>: %{x}<br><b>Count</b>: %{y}<br><b>Rating Type</b>: %{customdata[0]}<extra></extra>"
250
+ )
251
+ st.plotly_chart(fig2, use_container_width=True)
252
+ except Exception:
253
+ st.error("Error displaying the chart. Please check the data and inputs.")
254
+ with st.expander("Show Detailed Analyst Data"):
255
+ st.dataframe(df_analyst)
256
+ else:
257
+ st.info("Press 'Run Analysis' in the sidebar to load analyst recommendations data.")