QuantumLearner commited on
Commit
1d1952a
·
verified ·
1 Parent(s): 4389005

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +61 -43
app.py CHANGED
@@ -14,7 +14,6 @@ API_KEY = os.getenv("FMP_API_KEY")
14
 
15
  # ---- SIDEBAR INPUTS ----
16
  st.sidebar.title("User Inputs")
17
-
18
  with st.sidebar.expander("Configuration", expanded=True):
19
  ticker = st.text_input("Ticker:", "ASML", help="Insert the stock ticker.")
20
 
@@ -34,6 +33,9 @@ with st.sidebar.expander("Configuration", expanded=True):
34
  xaxis_title = "Year"
35
  tickformat = "%Y"
36
  dtick = "M12"
 
 
 
37
  else:
38
  period_api = "quarter"
39
  period_count = st.number_input(
@@ -47,9 +49,18 @@ with st.sidebar.expander("Configuration", expanded=True):
47
  xaxis_title = "Quarter"
48
  tickformat = "%Y-%m"
49
  dtick = "M3"
 
 
 
50
 
51
  run_button = st.sidebar.button("Run Analysis")
52
 
 
 
 
 
 
 
53
  # ---- HELPER FUNCTION: VALUE FORMATTING ----
54
  def format_value(x):
55
  if abs(x) >= 1e9:
@@ -61,43 +72,53 @@ def format_value(x):
61
  else:
62
  return f"{x:.1f}"
63
 
 
 
 
 
 
 
 
64
  # ---- MAIN APP START ----
65
  def main():
66
  st.title("Analyst Forecasts & Estimates")
67
- st.write("This tool fetches historical financial data and analyst forecasts. "
68
- "It helps you see past trends and future estimates over your selected period.")
69
-
70
- if not run_button:
71
- st.info("Set your inputs in the sidebar, then click **Run Analysis**.")
72
- return
73
-
74
- if not ticker.strip():
75
- st.error("Please enter a valid ticker.")
76
- return
77
-
78
- # ---- FETCH AND PREPARE DATA ----
79
- hist_url = (
80
- f"https://financialmodelingprep.com/api/v3/income-statement/{ticker}"
81
- f"?period={period_api}&limit={period_count}&apikey={API_KEY}"
82
  )
83
- forecast_url = (
84
- f"https://financialmodelingprep.com/api/v3/analyst-estimates/{ticker}"
85
- f"?period={period_api}&apikey={API_KEY}"
86
- )
87
- try:
88
- hist_data = requests.get(hist_url, timeout=10).json()
89
- forecast_data = requests.get(forecast_url, timeout=10).json()
90
- except Exception:
91
- st.error("Could not retrieve data at this time.")
92
- return
93
 
94
- historical_df = pd.DataFrame(hist_data)
95
- forecast_df = pd.DataFrame(forecast_data)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
96
 
97
- if historical_df.empty and forecast_df.empty:
98
- st.warning("No data found for the specified ticker.")
 
99
  return
100
 
 
 
 
 
101
  if not historical_df.empty and "date" in historical_df.columns:
102
  historical_df["date"] = pd.to_datetime(historical_df["date"])
103
  historical_df.sort_values("date", inplace=True)
@@ -223,7 +244,6 @@ def main():
223
  legend=dict(),
224
  margin=dict(l=40, r=40, t=80, b=80)
225
  )
226
-
227
  return fig
228
 
229
  # ---- DISPLAY RESULTS BY METRIC ----
@@ -238,22 +258,19 @@ def main():
238
  st.plotly_chart(fig, use_container_width=True)
239
 
240
  with st.expander(f"View {metric} Data", expanded=False):
241
- relevant_cols = []
242
  hc = mapping["historical"]
243
- if hc in historical_df.columns:
244
- relevant_cols.append(hc)
245
- for fc in mapping["forecast"].values():
246
- if fc in forecast_df.columns:
247
- relevant_cols.append(fc)
248
-
249
  hist_disp = historical_df[["date", hc]].copy() if hc in historical_df.columns else pd.DataFrame()
250
  if not hist_disp.empty:
251
  hist_disp.rename(columns={hc: f"{metric}_Historical"}, inplace=True)
252
 
253
- forecast_disp = forecast_df[["date"] + list(mapping["forecast"].values())].copy() if not forecast_df.empty else pd.DataFrame()
254
- for fc_key, fc_val in mapping["forecast"].items():
255
- if fc_val in forecast_disp.columns:
256
- forecast_disp.rename(columns={fc_val: f"{metric}_Forecast_{fc_key}"}, inplace=True)
 
 
 
 
257
 
258
  if not hist_disp.empty and not forecast_disp.empty:
259
  merged_df = pd.merge(hist_disp, forecast_disp, on="date", how="outer")
@@ -274,6 +291,7 @@ def main():
274
  if __name__ == "__main__":
275
  main()
276
 
 
277
  st.markdown(
278
  """
279
  <style>
@@ -282,4 +300,4 @@ st.markdown(
282
  </style>
283
  """,
284
  unsafe_allow_html=True
285
- )
 
14
 
15
  # ---- SIDEBAR INPUTS ----
16
  st.sidebar.title("User Inputs")
 
17
  with st.sidebar.expander("Configuration", expanded=True):
18
  ticker = st.text_input("Ticker:", "ASML", help="Insert the stock ticker.")
19
 
 
33
  xaxis_title = "Year"
34
  tickformat = "%Y"
35
  dtick = "M12"
36
+ # We'll use these session state keys
37
+ HIST_KEY = "historical_df_annual"
38
+ FORECAST_KEY = "forecast_df_annual"
39
  else:
40
  period_api = "quarter"
41
  period_count = st.number_input(
 
49
  xaxis_title = "Quarter"
50
  tickformat = "%Y-%m"
51
  dtick = "M3"
52
+ # We'll use these session state keys
53
+ HIST_KEY = "historical_df_quarter"
54
+ FORECAST_KEY = "forecast_df_quarter"
55
 
56
  run_button = st.sidebar.button("Run Analysis")
57
 
58
+ # Initialize session state if not present
59
+ if HIST_KEY not in st.session_state:
60
+ st.session_state[HIST_KEY] = pd.DataFrame()
61
+ if FORECAST_KEY not in st.session_state:
62
+ st.session_state[FORECAST_KEY] = pd.DataFrame()
63
+
64
  # ---- HELPER FUNCTION: VALUE FORMATTING ----
65
  def format_value(x):
66
  if abs(x) >= 1e9:
 
72
  else:
73
  return f"{x:.1f}"
74
 
75
+ # Use st.cache_data for caching the fetch operation.
76
+ @st.cache_data
77
+ def fetch_data(hist_url, forecast_url):
78
+ hist_data = requests.get(hist_url, timeout=10).json()
79
+ forecast_data = requests.get(forecast_url, timeout=10).json()
80
+ return hist_data, forecast_data
81
+
82
  # ---- MAIN APP START ----
83
  def main():
84
  st.title("Analyst Forecasts & Estimates")
85
+ st.write(
86
+ "This tool fetches historical financial data and analyst forecasts. "
87
+ "It helps you see past trends and future estimates over your selected period."
 
 
 
 
 
 
 
 
 
 
 
 
88
  )
 
 
 
 
 
 
 
 
 
 
89
 
90
+ # If the user pressed the button, fetch data and store under the chosen keys
91
+ if run_button:
92
+ if not ticker.strip():
93
+ st.error("Please enter a valid ticker.")
94
+ return
95
+
96
+ hist_url = (
97
+ f"https://financialmodelingprep.com/api/v3/income-statement/{ticker}"
98
+ f"?period={period_api}&limit={period_count}&apikey={API_KEY}"
99
+ )
100
+ forecast_url = (
101
+ f"https://financialmodelingprep.com/api/v3/analyst-estimates/{ticker}"
102
+ f"?period={period_api}&apikey={API_KEY}"
103
+ )
104
+ try:
105
+ hist_data, forecast_data = fetch_data(hist_url, forecast_url)
106
+ except Exception:
107
+ st.error("Could not retrieve data at this time.")
108
+ return
109
+
110
+ st.session_state[HIST_KEY] = pd.DataFrame(hist_data)
111
+ st.session_state[FORECAST_KEY] = pd.DataFrame(forecast_data)
112
 
113
+ # If we have no stored data for this period, prompt user to run
114
+ if st.session_state[HIST_KEY].empty and st.session_state[FORECAST_KEY].empty:
115
+ st.info("Set your inputs in the sidebar, then click **Run Analysis**.")
116
  return
117
 
118
+ # Otherwise, use the data from session state
119
+ historical_df = st.session_state[HIST_KEY]
120
+ forecast_df = st.session_state[FORECAST_KEY]
121
+
122
  if not historical_df.empty and "date" in historical_df.columns:
123
  historical_df["date"] = pd.to_datetime(historical_df["date"])
124
  historical_df.sort_values("date", inplace=True)
 
244
  legend=dict(),
245
  margin=dict(l=40, r=40, t=80, b=80)
246
  )
 
247
  return fig
248
 
249
  # ---- DISPLAY RESULTS BY METRIC ----
 
258
  st.plotly_chart(fig, use_container_width=True)
259
 
260
  with st.expander(f"View {metric} Data", expanded=False):
 
261
  hc = mapping["historical"]
 
 
 
 
 
 
262
  hist_disp = historical_df[["date", hc]].copy() if hc in historical_df.columns else pd.DataFrame()
263
  if not hist_disp.empty:
264
  hist_disp.rename(columns={hc: f"{metric}_Historical"}, inplace=True)
265
 
266
+ forecast_disp = pd.DataFrame()
267
+ if not forecast_df.empty:
268
+ wanted_cols = ["date"] + list(mapping["forecast"].values())
269
+ existing_cols = [c for c in wanted_cols if c in forecast_df.columns]
270
+ forecast_disp = forecast_df[existing_cols].copy()
271
+ for fc_key, fc_val in mapping["forecast"].items():
272
+ if fc_val in forecast_disp.columns:
273
+ forecast_disp.rename(columns={fc_val: f"{metric}_Forecast_{fc_key}"}, inplace=True)
274
 
275
  if not hist_disp.empty and not forecast_disp.empty:
276
  merged_df = pd.merge(hist_disp, forecast_disp, on="date", how="outer")
 
291
  if __name__ == "__main__":
292
  main()
293
 
294
+ # Hide Streamlit elements
295
  st.markdown(
296
  """
297
  <style>
 
300
  </style>
301
  """,
302
  unsafe_allow_html=True
303
+ )