Space56 / app.py
QuantumLearner's picture
Update app.py
67169c8 verified
import streamlit as st
import requests
import pandas as pd
from datetime import date
import asyncio
import aiohttp
import os
st.set_page_config(layout="wide")
API_KEY = os.getenv("FMP_API_KEY")
########################################
# SYNCHRONOUS FUNCTION FOR LIVE FEED
########################################
@st.cache_data(show_spinner=False)
def get_live_feed_data(limit, filing_type, from_date, to_date, is_done):
params = {
"apikey": API_KEY,
"limit": limit,
"from": from_date,
"to": to_date,
"isDone": str(is_done).lower()
}
if filing_type != "All":
params["type"] = filing_type
url = "https://financialmodelingprep.com/api/v4/rss_feed"
response = requests.get(url, params=params)
if response.status_code == 200:
return pd.DataFrame(response.json())
else:
st.error(f"Error fetching data (Status Code {response.status_code}).")
return pd.DataFrame()
########################################
# ASYNCHRONOUS FUNCTIONS FOR 8-K FILINGS
########################################
async def fetch_8k_page(session, page, from_date, to_date, has_financial):
params = {
"apikey": API_KEY,
"page": page,
"from": from_date,
"to": to_date,
"hasFinancial": str(has_financial).lower()
}
url = "https://financialmodelingprep.com/api/v4/rss_feed_8k"
async with session.get(url, params=params) as resp:
if resp.status == 200:
data = await resp.json()
return pd.DataFrame(data)
else:
return pd.DataFrame()
async def fetch_all_8k(pages_to_fetch, from_date, to_date, has_financial):
async with aiohttp.ClientSession() as session:
tasks = [fetch_8k_page(session, p, from_date, to_date, has_financial)
for p in range(pages_to_fetch)]
results = []
progress_bar = st.progress(0)
completed = 0
for task in asyncio.as_completed(tasks):
result = await task
results.append(result)
completed += 1
progress_bar.progress(completed / pages_to_fetch)
return results
########################################
# ASYNCHRONOUS FUNCTIONS FOR COMPANY FILINGS
########################################
async def fetch_company_page(session, symbol, filing_type, page):
params = {
"apikey": API_KEY,
"page": page,
"type": filing_type
}
url = f"https://financialmodelingprep.com/api/v3/sec_filings/{symbol}"
async with session.get(url, params=params) as resp:
if resp.status == 200:
data = await resp.json()
return pd.DataFrame(data)
else:
return pd.DataFrame()
async def fetch_all_company(symbol, filing_type, pages_to_fetch):
async with aiohttp.ClientSession() as session:
tasks = [fetch_company_page(session, symbol, filing_type, p)
for p in range(pages_to_fetch)]
results = []
progress_bar = st.progress(0)
completed = 0
for task in asyncio.as_completed(tasks):
result = await task
results.append(result)
completed += 1
progress_bar.progress(completed / pages_to_fetch)
return results
########################################
# PAGE FUNCTIONS
########################################
def live_feed_page():
st.title("Live SEC Filings Feed")
st.write(
"""
This page displays a list of recent SEC filings by public companies.
Filings include annual reports (10-K), quarterly reports (10-Q), and other important updates.
Use the filters to narrow down the list by filing type, date range, and whether the filing is complete.
"""
)
# Initialize session state if not set.
if "live_feed_results" not in st.session_state:
st.session_state.live_feed_results = None
with st.sidebar:
with st.expander("Live Feed Filter Parameters", expanded=True):
filing_type = st.selectbox(
"Filing Type",
options=["All", "10-K", "10-Q", "8-K", "6-K"],
help="Choose a specific filing type or 'All' for no filtering."
)
from_date = st.date_input(
"From Date",
value=date(2025, 1, 1),
help="Start date for the filings."
)
to_date = st.date_input(
"To Date",
value=date.today(),
help="End date for the filings."
)
is_done = st.checkbox(
"Completed Filings Only",
value=True,
help="Check to show only filings marked as completed."
)
run_live = st.button("Run Live Feed Query")
limit = 500
if run_live:
st.session_state.live_feed_results = get_live_feed_data(
limit, filing_type, from_date.isoformat(), to_date.isoformat(), is_done
)
if st.session_state.live_feed_results is not None:
st.write("### Live SEC Filings Data")
st.dataframe(st.session_state.live_feed_results, use_container_width=True)
def eight_k_page():
st.title("8-K Filings Specialized")
st.write(
"""
This page displays 8-K filings from public companies.
8-K filings are reports companies file when major events occur.
Use the filter below to show only filings that include financial information.
"""
)
if "eight_k_results" not in st.session_state:
st.session_state.eight_k_results = None
with st.sidebar:
with st.expander("8-K Filter Parameters", expanded=True):
from_date = st.date_input(
"From Date (8-K)",
value=date(2025, 1, 1),
help="Start date for 8-K filings."
)
to_date = st.date_input(
"To Date (8-K)",
value=date.today(),
help="End date for 8-K filings."
)
has_financial_option = st.selectbox(
"Only Filings with Financial Data",
options=["True", "False"],
help="Select 'True' to display only filings that include financial statements."
)
has_financial = has_financial_option.lower() == "true"
run_8k = st.button("Run 8-K Query")
pages_to_fetch = 15
if run_8k:
results = asyncio.run(
fetch_all_8k(pages_to_fetch, from_date.isoformat(), to_date.isoformat(), has_financial)
)
dfs = [df for df in results if not df.empty]
if dfs:
df_all = pd.concat(dfs, ignore_index=True)
st.session_state.eight_k_results = df_all
else:
st.session_state.eight_k_results = None
st.warning("No data returned for the given parameters.")
if st.session_state.eight_k_results is not None:
st.write("### 8-K Filings Data")
st.dataframe(st.session_state.eight_k_results, use_container_width=True)
def company_specific_page():
st.title("Company Specific SEC Filings")
st.write(
"""
This page displays filings for a specific company.
Enter a company ticker (e.g., AAPL) and select a filing type (like 10-K or 10-Q) to view the reports.
"""
)
if "company_results" not in st.session_state:
st.session_state.company_results = None
if "company_symbol" not in st.session_state:
st.session_state.company_symbol = None
with st.sidebar:
with st.expander("Company Filings Parameters", expanded=True):
symbol = st.text_input(
"Company Ticker",
value="AAPL",
help="Enter the ticker symbol of the company (e.g., AAPL)."
)
filing_type = st.selectbox(
"Filing Type",
options=["10-K", "10-Q", "8-K", "6-K"],
help="Select the type of filing to retrieve."
)
run_company = st.button("Run Company Query")
pages_to_fetch = 10
if run_company:
if symbol.strip():
results = asyncio.run(
fetch_all_company(symbol.upper(), filing_type, pages_to_fetch)
)
dfs = [df for df in results if not df.empty]
if dfs:
df_all = pd.concat(dfs, ignore_index=True)
st.session_state.company_results = df_all
st.session_state.company_symbol = symbol.upper()
else:
st.session_state.company_results = None
st.warning("No filings found for the given parameters.")
else:
st.warning("Please enter a valid company ticker.")
if st.session_state.company_results is not None:
st.write(f"### SEC Filings for {st.session_state.company_symbol}")
st.dataframe(st.session_state.company_results, use_container_width=True)
########################################
# MAIN APPLICATION
########################################
def main():
st.sidebar.title("Input Parameters")
page_selection = st.sidebar.radio(
"Select a Page",
("Live Feed", "8-K Specialized", "Company Specific"),
help="Navigate to the desired SEC filings page."
)
if page_selection == "Live Feed":
live_feed_page()
elif page_selection == "8-K Specialized":
eight_k_page()
elif page_selection == "Company Specific":
company_specific_page()
if __name__ == "__main__":
main()
hide_streamlit_style = """
<style>
#MainMenu {visibility: hidden;}
footer {visibility: hidden;}
</style>
"""
st.markdown(hide_streamlit_style, unsafe_allow_html=True)