Spaces:
Sleeping
Sleeping
| 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 | |
| ######################################## | |
| 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) | |