Spaces:
Sleeping
Sleeping
Upload app.py
Browse files
app.py
ADDED
|
@@ -0,0 +1,108 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import streamlit as st # for overall GUI
|
| 2 |
+
from streamlit_calendar import calendar # to show calendar
|
| 3 |
+
from dateutil.relativedelta import relativedelta # for addition to dates
|
| 4 |
+
import datetime
|
| 5 |
+
import os # for extracting environment variable
|
| 6 |
+
from urllib.request import urlopen # for getting data from FMP API
|
| 7 |
+
import json # for parsing data from FMP API
|
| 8 |
+
|
| 9 |
+
def get_jsonparsed_data(url):
|
| 10 |
+
response = urlopen(url)
|
| 11 |
+
data = response.read().decode("utf-8")
|
| 12 |
+
return json.loads(data)
|
| 13 |
+
|
| 14 |
+
# Financialmodelingprep (FMP) api base url
|
| 15 |
+
base_url = "https://financialmodelingprep.com/api/v3/"
|
| 16 |
+
|
| 17 |
+
# Get FMP API stored as environment variable
|
| 18 |
+
apiKey = os.environ['FMP_API_KEY']
|
| 19 |
+
|
| 20 |
+
# Get today's date and add 3 months to it
|
| 21 |
+
# Convert both today's date and the 3 months later date to strings (for input into API endpoint URL later)
|
| 22 |
+
# This is the date range within which we want to get our earnings dates
|
| 23 |
+
today = datetime.datetime.today()
|
| 24 |
+
today_string = today.strftime('%Y-%m-%d')
|
| 25 |
+
future_string = (today + relativedelta(months=3)).strftime('%Y-%m-%d')
|
| 26 |
+
|
| 27 |
+
# This is the full API endpoint to get the earnings dates from today to 6 months after
|
| 28 |
+
url = f"{base_url}earning_calendar?from={today_string}&to={future_string}&apikey={apiKey}"
|
| 29 |
+
|
| 30 |
+
# This decorator ensures that the call to the FMP API will only run once at the start of this app
|
| 31 |
+
# The data will be cached after running
|
| 32 |
+
# Without this decorator, the API will be called each time
|
| 33 |
+
@st.experimental_singleton
|
| 34 |
+
def get_earnings_dates(url):
|
| 35 |
+
events = get_jsonparsed_data(url)
|
| 36 |
+
return events
|
| 37 |
+
|
| 38 |
+
events = get_earnings_dates(url)
|
| 39 |
+
|
| 40 |
+
|
| 41 |
+
with st.sidebar:
|
| 42 |
+
st.title("Stock Earnings 📆 App")
|
| 43 |
+
st.header("Choose Tickers of Interest")
|
| 44 |
+
#tickers = ['GOOG', 'META', 'TSLA', 'NET', 'V', 'MA', 'BA', 'C']
|
| 45 |
+
|
| 46 |
+
# For users to enter tickers of interest
|
| 47 |
+
tickers_string = st.text_area('Enter all stock tickers to be included in calendar, separated by commas \
|
| 48 |
+
e.g. "MA, META, V, AMZN, JPM, BA"',
|
| 49 |
+
value = 'GOOG, META, AAPL, MSFT, NVDA, NFLX, V, MA, AMZN, TSLA, JPM, BAC, BA, MMM, NET, C, CRM, PLTR, BABA').upper()
|
| 50 |
+
|
| 51 |
+
st.write('')
|
| 52 |
+
st.write('')
|
| 53 |
+
# Where the data came from
|
| 54 |
+
st.markdown("## [Financial Modeling Prep API](https://intelligence.financialmodelingprep.com/pricing-plans?couponCode=damianboh&utm_campaign=damianboh&utm_medium=blog&utm_source=medium)\
|
| 55 |
+
\n\nEarnings Dates for all tickers are obtained from the FinancialModelingPrep API, feel free to sign up\
|
| 56 |
+
[here](https://intelligence.financialmodelingprep.com/pricing-plans?couponCode=damianboh&utm_campaign=damianboh&utm_medium=blog&utm_source=medium)\
|
| 57 |
+
if you wish.")
|
| 58 |
+
|
| 59 |
+
# Parse user input into a list
|
| 60 |
+
tickers_string = tickers_string.replace(' ', '')
|
| 61 |
+
tickers = tickers_string.split(',')
|
| 62 |
+
|
| 63 |
+
# Converts the parsed json from FMP API into a list of events to be passed into streamlit_calendar
|
| 64 |
+
calendar_events = []
|
| 65 |
+
for event in events:
|
| 66 |
+
if event['symbol'] in tickers:
|
| 67 |
+
calendar_event = {}
|
| 68 |
+
calendar_event['title'] = event['symbol']
|
| 69 |
+
if event['time'] == 'bmo': # before market opens, add sunrise symbol
|
| 70 |
+
calendar_event['title'] = '☀ ' + calendar_event['title']
|
| 71 |
+
elif event['time'] == 'amc': # after market closes, add sunset symbol
|
| 72 |
+
calendar_event['title'] = '🌅 ' + calendar_event['title']
|
| 73 |
+
calendar_event['start'] = event['date']
|
| 74 |
+
calendar_events.append(calendar_event)
|
| 75 |
+
|
| 76 |
+
st.header("Stock Earnings Calendar 📆")
|
| 77 |
+
|
| 78 |
+
|
| 79 |
+
calendar_options = {
|
| 80 |
+
"editable": "true",
|
| 81 |
+
"navLinks": "true",
|
| 82 |
+
"headerToolbar": {
|
| 83 |
+
"left": "today prev,next",
|
| 84 |
+
"center": "title",
|
| 85 |
+
"right": "dayGridDay,dayGridWeek,dayGridMonth,listMonth",
|
| 86 |
+
},
|
| 87 |
+
#"initialDate": today.strftime('%Y-%m-%d'),
|
| 88 |
+
"initialView": "dayGridMonth"
|
| 89 |
+
}
|
| 90 |
+
|
| 91 |
+
|
| 92 |
+
custom_css="""
|
| 93 |
+
.fc-event-past {
|
| 94 |
+
opacity: 0.8;
|
| 95 |
+
}
|
| 96 |
+
.fc-event-time {
|
| 97 |
+
font-style: italic;
|
| 98 |
+
}
|
| 99 |
+
.fc-event-title {
|
| 100 |
+
font-weight: 700;
|
| 101 |
+
}
|
| 102 |
+
.fc-toolbar-title {
|
| 103 |
+
font-size: 2rem;
|
| 104 |
+
}
|
| 105 |
+
"""
|
| 106 |
+
|
| 107 |
+
|
| 108 |
+
calendar = calendar(events=calendar_events, options=calendar_options, custom_css=custom_css)
|