import streamlit as st # for overall GUI from streamlit_calendar import calendar # to show calendar from dateutil.relativedelta import relativedelta # for addition to dates import datetime import os # for extracting environment variable from urllib.request import urlopen # for getting data from FMP API import json # for parsing data from FMP API # For parsing data from API from JSON to a Python Dictionary def get_jsonparsed_data(url): response = urlopen(url) data = response.read().decode("utf-8") return json.loads(data) # Get FMP API stored as environment variable apiKey = os.environ['FMP_API_KEY'] # Financialmodelingprep (FMP) api base url base_url = "https://financialmodelingprep.com/api/v3/" # Get today's date and add 3 months to it # Convert both today's date and the 3 months later date to strings (for input into API endpoint URL later) # This is the date range within which we want to get our earnings dates today = datetime.datetime.today() today_string = today.strftime('%Y-%m-%d') future_string = (today + relativedelta(months=3)).strftime('%Y-%m-%d') # This is the full API endpoint to get the earnings dates from today to 6 months after url = f"{base_url}earning_calendar?from={today_string}&to={future_string}&apikey={apiKey}" # This decorator ensures that the call to the FMP API will only run once at the start of this app # The data returned will be cached after the function runs # Without this decorator, the API will be called each time you click something in the streamlit app @st.cache_resource def get_earnings_dates(url): events = get_jsonparsed_data(url) return events events = get_earnings_dates(url) with st.sidebar: st.title("Stock Earnings 📆 App") st.header("Choose Tickers of Interest") #tickers = ['GOOG', 'META', 'TSLA', 'NET', 'V', 'MA', 'BA', 'C'] # For users to enter tickers of interest tickers_string = st.text_area('Enter all stock tickers to be included in calendar, separated by commas \ e.g. "MA, META, V, AMZN, JPM, BA"', value = 'GOOG, META, AAPL, MSFT, NVDA, NFLX, V, MA, AMZN, TSLA, JPM, BAC, BA, MMM, NET, C, CRM, PLTR, BABA').upper() st.write("Note: Earnings dates are shown for the next 3 months") st.write('') st.markdown("## [Explanatory Article](https://medium.datadriveninvestor.com/build-a-stock-earnings-calendar-of-your-favorite-stocks-in-python-36bba1950a61)") st.write('') # Where the data came from st.markdown("## [Financial Modeling Prep API](https://intelligence.financialmodelingprep.com/pricing-plans?couponCode=damianboh&utm_campaign=damianboh&utm_medium=blog&utm_source=medium)\ \n\nEarnings Dates for all tickers are obtained from the FinancialModelingPrep API, feel free to sign up\ [here](https://intelligence.financialmodelingprep.com/pricing-plans?couponCode=damianboh&utm_campaign=damianboh&utm_medium=blog&utm_source=medium)\ if you wish.") # Parse user input into a list tickers_string = tickers_string.replace(' ', '') tickers = tickers_string.split(',') # Converts the parsed json from FMP API into a list of events to be passed into streamlit_calendar calendar_events = [] for event in events: if event['symbol'] in tickers: calendar_event = {} calendar_event['title'] = event['symbol'] if event['time'] == 'bmo': # before market opens, add sunrise symbol calendar_event['title'] = '☀ ' + calendar_event['title'] elif event['time'] == 'amc': # after market closes, add sunset symbol calendar_event['title'] = '🌅 ' + calendar_event['title'] calendar_event['start'] = event['date'] calendar_events.append(calendar_event) st.header("Stock Earnings Calendar 📆") calendar_options = { "editable": "true", "navLinks": "true", "headerToolbar": { "left": "today prev,next", "center": "title", "right": "dayGridDay,dayGridWeek,dayGridMonth,listMonth", }, #"initialDate": today.strftime('%Y-%m-%d'), "initialView": "dayGridMonth" } custom_css=""" .fc-event-past { opacity: 0.8; } .fc-event-time { font-style: italic; } .fc-event-title { font-weight: 700; } .fc-toolbar-title { font-size: 2rem; } """ calendar = calendar(events=calendar_events, options=calendar_options, custom_css=custom_css)