Space50 / app.py
QuantumLearner's picture
Update app.py
8c7c777 verified
import streamlit as st
import requests
import pandas as pd
import os
import asyncio
import aiohttp
# Global API key and default parameters
API_KEY = os.getenv("FMP_API_KEY")
DEFAULT_COMPANY = "syros"
NUM_PAGES = 10 # Backend variable: number of pages to fetch
# Initialize session state run flags and inputs if not already set
if "run_mna_feed" not in st.session_state:
st.session_state.run_mna_feed = False
if "run_mna_search" not in st.session_state:
st.session_state.run_mna_search = False
if "search_company" not in st.session_state:
st.session_state.search_company = DEFAULT_COMPANY
if "feed_date" not in st.session_state:
st.session_state.feed_date = pd.to_datetime("2025-01-01").date()
##############################################
# ASYNCHRONOUS FUNCTIONS FOR M&A FEED
##############################################
async def fetch_mna_feed_page(session, page):
url = f"https://financialmodelingprep.com/api/v4/mergers-acquisitions-rss-feed?page={page}&apikey={API_KEY}"
try:
async with session.get(url) as response:
if response.status == 200:
data = await response.json()
return pd.DataFrame(data)
else:
return pd.DataFrame()
except Exception:
# Fail gracefully without exposing the data source
return pd.DataFrame()
async def fetch_all_mna_feed(num_pages=NUM_PAGES):
async with aiohttp.ClientSession() as session:
tasks = [fetch_mna_feed_page(session, page) for page in range(num_pages)]
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 / num_pages)
return results
def async_fetch_mna_feed(num_pages=NUM_PAGES) -> pd.DataFrame:
results = asyncio.run(fetch_all_mna_feed(num_pages))
if results:
df = pd.concat(results, ignore_index=True)
if "transactionDate" in df.columns:
df["transactionDate"] = pd.to_datetime(df["transactionDate"], errors="coerce")
return df
return pd.DataFrame()
##############################################
# CACHED FUNCTION FOR M&A SEARCH
##############################################
@st.cache_data(show_spinner=False)
def fetch_mna_search(company_name: str) -> pd.DataFrame:
"""
Fetch M&A news filtered by company name using the search endpoint.
"""
url = f"https://financialmodelingprep.com/api/v4/mergers-acquisitions/search?name={company_name}&apikey={API_KEY}"
try:
response = requests.get(url)
response.raise_for_status()
data = response.json()
except:
return pd.DataFrame()
if not data:
return pd.DataFrame()
return pd.DataFrame(data)
##############################################
# MAIN APP
##############################################
def main():
st.set_page_config(page_title="M&A Feed Dashboard", layout="wide")
st.title("M&A Transaction Analysis")
st.write(
"This dashboard provides a real-time stream of Mergers & Acquisitions news and announcements. "
"Use the side menu below to choose between viewing the full M&A live feed or searching for M&A news by company name."
)
# Sidebar (inside an expander) for navigation and options
with st.sidebar.expander("Navigation and Options", expanded=True):
page = st.radio(
"Select Page",
("M&A Feed", "M&A Search"),
help="Choose 'M&A Feed' to view the complete RSS feed or 'M&A Search' to search for news by company name."
)
if page == "M&A Feed":
feed_date = st.date_input(
"From Date",
value=pd.to_datetime("2025-01-01").date(),
help="Select a starting date. Only M&A transactions on or after this date will be shown."
)
st.session_state.feed_date = feed_date
if st.button("Run M&A Feed"):
st.session_state.run_mna_feed = True
else:
company = st.text_input(
"Company Name",
value=DEFAULT_COMPANY,
help="Enter the company name to search for M&A news (default is 'syros')."
)
st.session_state.search_company = company
if st.button("Run M&A Search"):
st.session_state.run_mna_search = True
# Display page content based on the selected page
if page == "M&A Feed":
st.header("M&A RSS Feed")
st.write(
"Below is the latest M&A live feed data filtered by transaction date. "
"Only M&A transactions on or after the selected date are shown. "
"The table displays details such as the acquiring company, target company, transaction date, and URL."
)
if st.session_state.run_mna_feed:
df_feed = async_fetch_mna_feed()
if df_feed.empty:
st.error("No data returned from the M&A feed.")
else:
if "transactionDate" in df_feed.columns:
filtered_df = df_feed[df_feed["transactionDate"].dt.date >= st.session_state.feed_date]
else:
filtered_df = df_feed
if filtered_df.empty:
st.error("No M&A transactions found on or after the selected date.")
else:
st.dataframe(filtered_df, use_container_width=True)
else:
st.info("Click 'Run M&A Feed' in the sidebar to fetch data.")
else:
st.header("M&A Search")
st.write(
"Search for M&A news by company name. "
"The table below displays the matching announcements, including details such as the acquiring company, "
"target company, transaction date, and announcement URL."
)
if st.session_state.run_mna_search:
df_search = fetch_mna_search(st.session_state.search_company)
if df_search.empty:
st.error("No M&A news found for the specified company name.")
else:
st.dataframe(df_search, use_container_width=True)
else:
st.info("Enter a company name in the sidebar and click 'Run M&A Search' to fetch data.")
if __name__ == "__main__":
main()
hide_streamlit_style = """
<style>
#MainMenu {visibility: hidden;}
footer {visibility: hidden;}
</style>
"""
st.markdown(hide_streamlit_style, unsafe_allow_html=True)