QuantumLearner commited on
Commit
1fc84f0
·
verified ·
1 Parent(s): 025156d

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +342 -0
app.py ADDED
@@ -0,0 +1,342 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ import datetime
3
+ import requests
4
+ import pandas as pd
5
+ from streamlit_calendar import calendar
6
+
7
+ API_KEY = "b431ec171262073909ebf8c0c4afba71"
8
+
9
+ def parse_time_field(date_str, time_str):
10
+ """
11
+ Convert a date string plus partial time info into date-time strings.
12
+ Example: date='2023-08-17', time='pre market' -> '2023-08-17T07:00:00'
13
+ """
14
+ if time_str and ":" in time_str:
15
+ return f"{date_str}T{time_str}:00", f"{date_str}T{time_str}:00"
16
+ else:
17
+ time_map = {
18
+ "bmo": "06:00:00",
19
+ "amc": "18:00:00",
20
+ "pre market": "07:00:00",
21
+ "post market": "16:00:00",
22
+ "during market": "10:00:00",
23
+ }
24
+ chosen_time = time_map.get(time_str.lower(), "00:00:00")
25
+ return f"{date_str}T{chosen_time}", f"{date_str}T{chosen_time}"
26
+
27
+ def fetch_earnings(from_date, to_date, limit):
28
+ url = (
29
+ f"https://financialmodelingprep.com/api/v4/earning-calendar-confirmed"
30
+ f"?from={from_date}&to={to_date}&limit={limit}&apikey={API_KEY}"
31
+ )
32
+ resp = requests.get(url)
33
+ if resp.status_code == 200:
34
+ return resp.json()
35
+ return []
36
+
37
+ def fetch_dividends(from_date, to_date):
38
+ url = (
39
+ f"https://financialmodelingprep.com/api/v3/stock_dividend_calendar"
40
+ f"?from={from_date}&to={to_date}&apikey={API_KEY}"
41
+ )
42
+ resp = requests.get(url)
43
+ if resp.status_code == 200:
44
+ return resp.json()
45
+ return []
46
+
47
+ def fetch_splits(from_date, to_date):
48
+ url = (
49
+ f"https://financialmodelingprep.com/api/v3/stock_split_calendar"
50
+ f"?from={from_date}&to={to_date}&apikey={API_KEY}"
51
+ )
52
+ resp = requests.get(url)
53
+ if resp.status_code == 200:
54
+ return resp.json()
55
+ return []
56
+
57
+ def fetch_earnings_ticker(symbol, limit):
58
+ url = (
59
+ f"https://financialmodelingprep.com/api/v3/historical/earning_calendar/"
60
+ f"{symbol}?limit={limit}&apikey={API_KEY}"
61
+ )
62
+ resp = requests.get(url)
63
+ if resp.status_code == 200:
64
+ return resp.json()
65
+ return []
66
+
67
+ def fetch_dividends_ticker(symbol):
68
+ url = (
69
+ f"https://financialmodelingprep.com/api/v3/historical-price-full/stock_dividend/"
70
+ f"{symbol}?apikey={API_KEY}"
71
+ )
72
+ resp = requests.get(url)
73
+ if resp.status_code == 200:
74
+ return resp.json()
75
+ return {}
76
+
77
+ def fetch_splits_ticker(symbol):
78
+ url = (
79
+ f"https://financialmodelingprep.com/api/v3/historical-price-full/stock_split/"
80
+ f"{symbol}?apikey={API_KEY}"
81
+ )
82
+ resp = requests.get(url)
83
+ if resp.status_code == 200:
84
+ return resp.json()
85
+ return {}
86
+
87
+ def main():
88
+ # Updated title to reflect more events
89
+ st.set_page_config(page_title="Earnings, Dividends, and Splits Calendar", layout="wide")
90
+
91
+ # Initialize session state
92
+ if "general_data" not in st.session_state:
93
+ st.session_state["general_data"] = []
94
+ if "ticker_data" not in st.session_state:
95
+ st.session_state["ticker_data"] = []
96
+
97
+ st.title("Corporate Events Calendar")
98
+ st.write("This calendar shows earnings, dividends, and stock splits. "
99
+ "Use the selections on the sidebar to narrow results.")
100
+
101
+ st.sidebar.title("Input Parameters")
102
+
103
+ with st.sidebar.expander("How to Use", expanded=False):
104
+ st.write(
105
+ """
106
+ 1. Select "General Calendar" or "Ticker Calendar."
107
+ 2. Check which event types you want (earnings, dividends, splits).
108
+ 3. For the general view, choose a date range and limit.
109
+ 4. For the ticker view, choose a symbol and limit.
110
+ 5. Click the button to see results.
111
+ """
112
+ )
113
+ with st.sidebar.expander("", expanded=True):
114
+ page_choice = st.radio("Page", ["General Calendar", "Ticker Calendar"])
115
+
116
+ # Default date range
117
+ today = datetime.date.today()
118
+ one_month_later = today + datetime.timedelta(days=30)
119
+
120
+ if page_choice == "General Calendar":
121
+ with st.sidebar.expander("Event Type", expanded=True):
122
+ include_earnings = st.checkbox("Include Earnings", value=True, help="If checked, will fetch earnings within the date range.")
123
+ include_dividends = st.checkbox("Include Dividends", value=True, help="If checked, will fetch dividends within the date range.")
124
+ include_splits = st.checkbox("Include Stock Splits", value=True, help="If checked, will fetch stock splits within the date range.")
125
+
126
+ with st.sidebar.expander("Parameters", expanded=True):
127
+ from_date = st.date_input("From Date", value=today, help="Start date range")
128
+ to_date = st.date_input("To Date", value=one_month_later, help="End date range")
129
+ limit_val = st.number_input("Limit", value=200, help="Number of earnings records to retrieve")
130
+
131
+ if st.sidebar.button("Retrieve Calendar", key="fetch_general"):
132
+ # Collect everything in one list
133
+ all_events = []
134
+
135
+ if include_earnings:
136
+ earnings_data = fetch_earnings(from_date, to_date, limit_val)
137
+ for item in earnings_data:
138
+ date_str = item.get("date", "")
139
+ time_str = item.get("time", "")
140
+ start_dt, end_dt = parse_time_field(date_str, time_str)
141
+ sym = item.get("symbol", "")
142
+ event_title = f"[Earnings] {sym}"
143
+ # Store entire item plus fields for the calendar
144
+ event_entry = {
145
+ "start": start_dt,
146
+ "end": end_dt,
147
+ "title": event_title,
148
+ "color": "#3D9DF3",
149
+ "eventType": "Earnings"
150
+ }
151
+ # Merge item fields directly
152
+ event_entry.update(item)
153
+ all_events.append(event_entry)
154
+
155
+ if include_dividends:
156
+ div_data = fetch_dividends(from_date, to_date)
157
+ for item in div_data:
158
+ date_str = item.get("date", "")
159
+ start_dt = f"{date_str}T00:00:00"
160
+ end_dt = f"{date_str}T23:59:59"
161
+ sym = item.get("symbol", "")
162
+ event_title = f"[Dividend] {sym}"
163
+ event_entry = {
164
+ "start": start_dt,
165
+ "end": end_dt,
166
+ "title": event_title,
167
+ "color": "#80C080",
168
+ "eventType": "Dividend"
169
+ }
170
+ event_entry.update(item)
171
+ all_events.append(event_entry)
172
+
173
+ if include_splits:
174
+ split_data = fetch_splits(from_date, to_date)
175
+ for item in split_data:
176
+ date_str = item.get("date", "")
177
+ start_dt = f"{date_str}T00:00:00"
178
+ end_dt = f"{date_str}T23:59:59"
179
+ sym = item.get("symbol", "")
180
+ event_title = f"[Split] {sym}"
181
+ event_entry = {
182
+ "start": start_dt,
183
+ "end": end_dt,
184
+ "title": event_title,
185
+ "color": "#FFC870",
186
+ "eventType": "Split"
187
+ }
188
+ event_entry.update(item)
189
+ all_events.append(event_entry)
190
+
191
+ st.session_state["general_data"] = all_events
192
+
193
+ st.subheader("General Calendar Results")
194
+
195
+ data_general = st.session_state["general_data"]
196
+ if data_general:
197
+ # Prepare events for calendar
198
+ calendar_events = []
199
+ for ev in data_general:
200
+ event_for_cal = {
201
+ "title": ev["title"],
202
+ "start": ev["start"],
203
+ "end": ev["end"],
204
+ "color": ev["color"],
205
+ }
206
+ calendar_events.append(event_for_cal)
207
+
208
+ cal_options = {
209
+ "initialView": "dayGridMonth",
210
+ "headerToolbar": {
211
+ "left": "today prev,next",
212
+ "center": "title",
213
+ "right": "dayGridDay,dayGridWeek,dayGridMonth",
214
+ },
215
+ "navLinks": True,
216
+ }
217
+
218
+ # Show calendar
219
+ calendar(events=calendar_events, options=cal_options, key="general_cal")
220
+
221
+ # Show entire dataframe
222
+ st.write("Data Table")
223
+ df_g = pd.DataFrame(data_general)
224
+ st.dataframe(df_g, use_container_width=True)
225
+ else:
226
+ st.write("No data retrieved. Select event types and click the button.")
227
+
228
+ else:
229
+
230
+ with st.sidebar.expander("Event Type", expanded=True):
231
+ # Ticker Calendar
232
+ include_earnings_t = st.checkbox("Include Earnings", value=True, help="If checked, will fetch historical earnings data.")
233
+ include_dividends_t = st.checkbox("Include Dividends", value=True, help="If checked, will fetch historical dividends data.")
234
+ include_splits_t = st.checkbox("Include Splits", value=True, help="If checked, will fetch historical stock splits data.")
235
+
236
+ with st.sidebar.expander("Parameters", expanded=True):
237
+ symbol = st.text_input("Symbol", value="AAPL", help="Enter a stock ticker")
238
+ limit_val_ticker = st.number_input("Limit", value=50, help="Number of earnings records to retrieve")
239
+
240
+ if st.sidebar.button("Retrieve Ticker Calendar", key="fetch_ticker"):
241
+ ticker_events = []
242
+
243
+ if include_earnings_t:
244
+ data_earnings_t = fetch_earnings_ticker(symbol, limit_val_ticker)
245
+ for item in data_earnings_t:
246
+ date_str = item.get("date", "")
247
+ time_str = item.get("time", "")
248
+ start_dt, end_dt = parse_time_field(date_str, time_str)
249
+ event_title = f"[Earnings] {symbol}"
250
+ event_info = {
251
+ "start": start_dt,
252
+ "end": end_dt,
253
+ "title": event_title,
254
+ "color": "#3D9DF3",
255
+ "eventType": "Earnings"
256
+ }
257
+ event_info.update(item)
258
+ ticker_events.append(event_info)
259
+
260
+ if include_dividends_t:
261
+ data_div_t = fetch_dividends_ticker(symbol)
262
+ # The response is a dict with keys like "symbol" and "historical"
263
+ historical_divs = data_div_t.get("historical", [])
264
+ for item in historical_divs:
265
+ date_str = item.get("date", "")
266
+ start_dt = f"{date_str}T00:00:00"
267
+ end_dt = f"{date_str}T23:59:59"
268
+ event_title = f"[Dividend] {symbol}"
269
+ event_info = {
270
+ "start": start_dt,
271
+ "end": end_dt,
272
+ "title": event_title,
273
+ "color": "#80C080",
274
+ "eventType": "Dividend"
275
+ }
276
+ event_info.update(item)
277
+ ticker_events.append(event_info)
278
+
279
+ if include_splits_t:
280
+ data_split_t = fetch_splits_ticker(symbol)
281
+ # The response is a dict with keys like "symbol" and "historical"
282
+ historical_splits = data_split_t.get("historical", [])
283
+ for item in historical_splits:
284
+ date_str = item.get("date", "")
285
+ start_dt = f"{date_str}T00:00:00"
286
+ end_dt = f"{date_str}T23:59:59"
287
+ event_title = f"[Split] {symbol}"
288
+ event_info = {
289
+ "start": start_dt,
290
+ "end": end_dt,
291
+ "title": event_title,
292
+ "color": "#FFC870",
293
+ "eventType": "Split"
294
+ }
295
+ event_info.update(item)
296
+ ticker_events.append(event_info)
297
+
298
+ st.session_state["ticker_data"] = ticker_events
299
+
300
+ st.subheader("Ticker Calendar Results")
301
+
302
+ data_ticker = st.session_state["ticker_data"]
303
+ if data_ticker:
304
+ # Prepare events
305
+ calendar_events_t = []
306
+ for ev in data_ticker:
307
+ calendar_events_t.append({
308
+ "title": ev["title"],
309
+ "start": ev["start"],
310
+ "end": ev["end"],
311
+ "color": ev["color"]
312
+ })
313
+
314
+ cal_options_ticker = {
315
+ "initialView": "dayGridMonth",
316
+ "headerToolbar": {
317
+ "left": "today prev,next",
318
+ "center": "title",
319
+ "right": "dayGridDay,dayGridWeek,dayGridMonth",
320
+ },
321
+ "navLinks": True,
322
+ }
323
+
324
+ calendar(events=calendar_events_t, options=cal_options_ticker, key="ticker_cal")
325
+
326
+ st.write("Data Table")
327
+ df_t = pd.DataFrame(data_ticker)
328
+ st.dataframe(df_t, use_container_width=True)
329
+ else:
330
+ st.write("No data retrieved. Check your options and press the button.")
331
+
332
+ if __name__ == "__main__":
333
+ main()
334
+
335
+
336
+ hide_streamlit_style = """
337
+ <style>
338
+ #MainMenu {visibility: hidden;}
339
+ footer {visibility: hidden;}
340
+ </style>
341
+ """
342
+ st.markdown(hide_streamlit_style, unsafe_allow_html=True)