Sigrid De los Santos commited on
Commit
33a4549
Β·
1 Parent(s): f2e1cf5
app.py CHANGED
@@ -1,109 +1,118 @@
1
  import os
2
  import sys
 
3
  import time
4
  import itertools
5
  import streamlit as st
6
  import pandas as pd
7
- from io import StringIO
 
8
 
9
  # Add 'src' to Python path so we can import main.py
10
  sys.path.append(os.path.join(os.path.dirname(__file__), 'src'))
11
- from main import run_pipeline # We will update this to return report, articles_df, insights_df
12
 
13
- # --- Page Config ---
14
  st.set_page_config(page_title="πŸ“° AI News Analyzer", layout="wide")
15
  st.title("🧠 AI-Powered Investing News Analyzer")
16
 
17
- # --- API Key Inputs ---
18
  st.subheader("πŸ” API Keys")
19
  openai_api_key = st.text_input("OpenAI API Key", type="password").strip()
20
  tavily_api_key = st.text_input("Tavily API Key", type="password").strip()
21
 
22
- # --- Topics ---
23
  st.subheader("πŸ“ˆ Topics of Interest")
24
  topics_data = []
25
-
26
  with st.form("topics_form"):
27
  topic_count = st.number_input("How many topics?", min_value=1, max_value=10, value=1, step=1)
 
28
  for i in range(topic_count):
29
  col1, col2 = st.columns(2)
30
  with col1:
31
  topic = st.text_input(f"Topic {i+1}", key=f"topic_{i}")
32
  with col2:
33
- timespan = st.number_input(f"Timespan (days) for Topic {i+1}", min_value=1, max_value=30, value=7, step=1, key=f"timespan_{i}")
34
- topics_data.append((topic, timespan))
35
- run_button = st.form_submit_button("πŸš€ Run Analysis")
36
 
37
- # --- Placeholder for logs ---
38
- log_placeholder = st.empty()
39
 
40
- # --- Results Tabs ---
41
- tabs = st.tabs(["πŸ“ Report", "πŸ“‹ Articles", "πŸ“Š Insights"])
 
 
 
42
 
43
- if run_button:
44
- if not openai_api_key or not tavily_api_key:
45
- st.error("Please provide both OpenAI and Tavily API keys.")
46
- else:
47
- run_button = False # Disable button
48
- log_placeholder.info("πŸ” Starting analysis...")
49
-
50
- # Rotating status messages
51
- status_placeholder = st.empty()
52
- steps = ["Running Tavily search...", "Analyzing with FinBERT & FinGPT...", "Generating LLM summary..."]
53
- cycle = itertools.cycle(steps)
54
-
55
- # Display rotating messages while running pipeline
56
- with st.spinner("Working..."):
57
- for _ in range(3):
58
- status_placeholder.text(next(cycle))
59
- time.sleep(0.8)
60
-
61
- # Run the pipeline
62
- try:
63
- report_md, articles_df, insights_df = run_pipeline(
64
- topics=topics_data,
65
- openai_api_key=openai_api_key,
66
- tavily_api_key=tavily_api_key
67
- )
68
- log_placeholder.success("βœ… Analysis completed.")
69
- except Exception as e:
70
- log_placeholder.error(f"❌ Error: {e}")
71
- st.stop()
72
-
73
- # --- Report Tab ---
74
- with tabs[0]:
75
- st.subheader("πŸ“ AI-Generated Report")
76
- st.markdown(report_md, unsafe_allow_html=True)
77
-
78
- # --- Articles Tab ---
79
- with tabs[1]:
80
- st.subheader("πŸ“‹ Articles & Priorities")
81
- if not articles_df.empty:
82
- # Color code priority
83
- articles_df['Priority'] = articles_df['Priority'].map(
84
- lambda x: "πŸ”΄ High" if str(x).lower() == "haute" or str(x).lower() == "high" else "🟒 Low"
85
- )
86
-
87
- st.dataframe(articles_df, use_container_width=True)
88
-
89
- # CSV download
90
- csv = articles_df.to_csv(index=False)
91
- st.download_button("⬇️ Download Articles CSV", data=csv, file_name="articles.csv", mime="text/csv")
92
- else:
93
- st.warning("No articles found.")
94
-
95
- # --- Insights Tab ---
96
- with tabs[2]:
97
- st.subheader("πŸ“Š Company Insights (FinGPT + FinBERT)")
98
- if insights_df is not None and not insights_df.empty:
99
- st.dataframe(insights_df, use_container_width=True)
100
- csv = insights_df.to_csv(index=False)
101
- st.download_button("⬇️ Download Insights CSV", data=csv, file_name="insights.csv", mime="text/csv")
102
- else:
103
- st.info("No company insights generated yet.")
104
 
 
 
 
 
105
 
106
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
107
  # import os
108
  # import sys
109
  # import tempfile
 
1
  import os
2
  import sys
3
+ import tempfile
4
  import time
5
  import itertools
6
  import streamlit as st
7
  import pandas as pd
8
+ from io import BytesIO
9
+ from xhtml2pdf import pisa
10
 
11
  # Add 'src' to Python path so we can import main.py
12
  sys.path.append(os.path.join(os.path.dirname(__file__), 'src'))
13
+ from main import run_pipeline
14
 
 
15
  st.set_page_config(page_title="πŸ“° AI News Analyzer", layout="wide")
16
  st.title("🧠 AI-Powered Investing News Analyzer")
17
 
18
+ # === API Key Input ===
19
  st.subheader("πŸ” API Keys")
20
  openai_api_key = st.text_input("OpenAI API Key", type="password").strip()
21
  tavily_api_key = st.text_input("Tavily API Key", type="password").strip()
22
 
23
+ # === Topic Input ===
24
  st.subheader("πŸ“ˆ Topics of Interest")
25
  topics_data = []
 
26
  with st.form("topics_form"):
27
  topic_count = st.number_input("How many topics?", min_value=1, max_value=10, value=1, step=1)
28
+
29
  for i in range(topic_count):
30
  col1, col2 = st.columns(2)
31
  with col1:
32
  topic = st.text_input(f"Topic {i+1}", key=f"topic_{i}")
33
  with col2:
34
+ days = st.number_input(f"Timespan (days)", min_value=1, max_value=30, value=7, key=f"days_{i}")
35
+ topics_data.append({"topic": topic, "timespan_days": days})
 
36
 
37
+ submitted = st.form_submit_button("Run Analysis")
 
38
 
39
+ # === Tabs Setup ===
40
+ tab_report, tab_articles, tab_insights = st.tabs(["πŸ“ Report", "πŸ“‹ Articles", "πŸ“Š Insights"])
41
+ articles_df = pd.DataFrame()
42
+ insights_df = pd.DataFrame()
43
+ html_paths = []
44
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
45
 
46
+ def convert_html_to_pdf(source_html):
47
+ output = BytesIO()
48
+ pisa.CreatePDF(source_html, dest=output)
49
+ return output.getvalue()
50
 
51
 
52
+ # === Submission logic ===
53
+ if submitted:
54
+ if not openai_api_key or not tavily_api_key or not all([td['topic'] for td in topics_data]):
55
+ st.warning("Please fill in all fields.")
56
+ else:
57
+ os.environ["OPENAI_API_KEY"] = openai_api_key
58
+ os.environ["TAVILY_API_KEY"] = tavily_api_key
59
+
60
+ df = pd.DataFrame(topics_data)
61
+ with tempfile.NamedTemporaryFile(delete=False, suffix=".csv") as tmp_csv:
62
+ df.to_csv(tmp_csv.name, index=False)
63
+ csv_path = tmp_csv.name
64
+
65
+ spinner_box = st.empty()
66
+ log_box = st.empty()
67
+ logs = []
68
+
69
+ def log(msg):
70
+ logs.append(msg)
71
+ log_box.code("\n".join(logs))
72
+
73
+ try:
74
+ spinner_box.markdown("⏳ Running analysis pipeline...")
75
+
76
+ # Run the full pipeline
77
+ html_paths, articles_df, insights_df = run_pipeline(csv_path, tavily_api_key, progress_callback=log)
78
+
79
+ spinner_box.success("βœ… Analysis complete!")
80
+
81
+ # --- Report Tab ---
82
+ with tab_report:
83
+ if html_paths:
84
+ for path in html_paths:
85
+ with open(path, 'r', encoding='utf-8') as f:
86
+ html_content = f.read()
87
+ st.components.v1.html(html_content, height=600, scrolling=True)
88
+ pdf_data = convert_html_to_pdf(html_content)
89
+ st.download_button(
90
+ label="⬇️ Download Report as PDF",
91
+ data=pdf_data,
92
+ file_name=os.path.basename(path).replace(".html", ".pdf"),
93
+ mime="application/pdf"
94
+ )
95
+ else:
96
+ st.error("❌ No reports were generated.")
97
+
98
+ # --- Articles Tab ---
99
+ with tab_articles:
100
+ if not articles_df.empty:
101
+ st.dataframe(articles_df, use_container_width=True)
102
+ else:
103
+ st.info("No articles available.")
104
+
105
+ # --- Insights Tab ---
106
+ with tab_insights:
107
+ if not insights_df.empty:
108
+ st.dataframe(insights_df, use_container_width=True)
109
+ else:
110
+ st.info("No insights available.")
111
+
112
+ except Exception as e:
113
+ spinner_box.error("❌ Failed.")
114
+ log_box.error(f"❌ Error: {e}")
115
+
116
  # import os
117
  # import sys
118
  # import tempfile
data/rejuvenation_2025-07-26.md ADDED
@@ -0,0 +1,105 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ > Topic: `Rejuvenation`
3
+ > Articles Collected: `297`
4
+ > Generated: `2025-07-26 15:26`
5
+ >
6
+ # Rejuvenation Sector – Value Investor Memo (Week of July 22, 2025)
7
+
8
+ ---
9
+
10
+ ## πŸ“Œ Executive Summary
11
+
12
+ - **Sentiment:** The rejuvenation and longevity space is heating up, driven by new research, partnerships, and acquisitions, but is mostly in β€œwatch” territory for public equity investors, with most innovation found in early-stage private startups.
13
+ - **Risks:** Many advances remain years from commercialization; the sector is hype-prone, and most investable stocks lack strong traditional value metrics (P/E, P/B, ROE).
14
+ - **Catalysts:** Partnerships (e.g., Novo Nordisk in China), growing M&A activity (ZimVie, OSR Holdings), significant fundraising, and emerging AI-driven biomedical platform technologies are worth monitoring.
15
+ - **Smart money:** VCs are backing AI/biotech hybrids and noninvasive monitoring startups, while large strategics remain cautious but active in select buyouts.
16
+
17
+ ---
18
+
19
+ ## πŸ“Š Signals and Analysis
20
+
21
+ ### 1. **AI & Brain Aging Therapeutics**
22
+
23
+ - **What:** New research uses machine learning to pinpoint brain cell rejuvenation compounds, with aging clock tech as a key enabler.
24
+ - **Why it matters:** Early-stage, but suggests future pipelines for biotech firms targeting Alzheimer’s and neurodegeneration. No direct investable company is named, suggesting to watch academic/AI-bio platform spinouts.
25
+ - **Source:** [Aging Clock Unveils Compounds That Rejuvenate Brain Cells - Neuroscience News](https://neurosciencenews.com/aging-clock-neurogenesis-29510/)
26
+
27
+ ### 2. **M&A & Undervalued Opportunities**
28
+
29
+ - **What:** **ZimVie** (ZIMV), a post-spinout dental device company, is being acquired for $730M after a series of divestitures.
30
+ - **Why it matters:** Potential undervaluation after dramatic slimming and focus; its P/B and FCF should be monitored if still publicly listed pre-acquisition. Indicates smart money (private equity) snapping up legacy assets with strong cash flows.
31
+ - **Source:** [ZimVie to sell to investment firm for about $730M - MedTech Dive](https://www.medtechdive.com/news/zimvie--sell-archimed-730m/753691/)
32
+
33
+ ### 3. **AI x Health Management Partnerships in China**
34
+
35
+ - **What:** Fangzhou partners with **Novo Nordisk** to transform chronic disease management using AI.
36
+ - **Why it matters:** Global pharma tapping local AI, possibly opening up new data-driven health ecosystems in massive markets. Worth watching for new, scalable models if Fangzhou IPOs or if Novo’s deal delivers material financial impact.
37
+ - **Sources:**
38
+ - [Fangzhou and Novo Nordisk Partner to Transform Chronic Disease Management with AI in China - HIT Consultant](https://hitconsultant.net/2025/07/21/fangzhou-and-novo-nordisk-china-partnership/)
39
+ - [Fangzhou and Novo Nordisk Signed Collaboration Memorandum to Establish a New Ecosystem for Health Management - BioSpace](https://www.biospace.com/press-releases/fangzhou-and-novo-nordisk-signed-collaboration-memorandum-to-establish-a-new-ecosystem-for-health-management)
40
+
41
+ ### 4. **Acquisition in Noninvasive Monitoring**
42
+
43
+ - **What:** **OSR Holdings** to acquire Woori IO, a pioneer in noninvasive glucose tech.
44
+ - **Why it matters:** As noninvasive monitoring is a potential β€œplatform moat” for chronic conditions management, this type of tech could underpin future rejuvenation or wellness ecosystem companies. Acquisition signals strategic value; watch for Woori IO’s technology adoption curve.
45
+ - **Source:** [OSR Holdings Enters into Term Sheet to Acquire Woori IO, a Pioneer in Noninvasive Glucose Monitoring Technology - BioSpace](https://www.biospace.com/press-releases/osr-holdings-enters-into-term-sheet-to-acquire-woori-io-a-pioneer-in-noninvasive-glucose-monitoring-technology)
46
+
47
+ ### 5. **Startups and Funding in Rejuvenation**
48
+
49
+ - **What:** Slingshot AI (mental healthcare chatbot) raised $50M; Makersite (manufacturing decisioning) raised €60M; 6 biotechs in the longevity space (undisclosed) highlighted.
50
+ - **Why it matters:** Rapid fundraising for health AI startups suggests a robust VC pipeline, but public market access is limited; premium on getting in at pre-IPO stages or via crossover funds.
51
+ - **Source:** [xAI's raise, Nudge's noninvasive brain implant, and Stripe's buy - Axios](https://www.axios.com/pro/all-deals/2025/07/22/pro-rata-premium-first-look)
52
+
53
+ ### 6. **Fundamental Value Screen**
54
+
55
+ - Very few listed companies in the β€˜rejuvenation’/longevity/biotech AI fields have both value investor-friendly metrics and growth optionality. ZimVie possibly fits the bill short-term; **Novo Nordisk** is strong on fundamentals but is a large, fairly valued pharma stock.
56
+ - Sectors with cash generative characteristics (e.g., dental/divested medtech, as with ZimVie) present special situations for patient investors.
57
+ ---
58
+
59
+ ## πŸ“ˆ Stocks or Startups to Watch
60
+
61
+ - **ZimVie (ZIMV)**
62
+ - [ZimVie to sell to investment firm for about $730M](https://www.medtechdive.com/news/zimvie--sell-archimed-730m/753691/)
63
+ - *Special situation: acquisition at premium post-business focus, but no longer a long-term pure rejuvenation play if going private soon.*
64
+ - **Novo Nordisk (NVO)**
65
+ - [Fangzhou & Novo Nordisk partnership](https://www.biospace.com/press-releases/fangzhou-and-novo-nordisk-signed-collaboration-memorandum-to-establish-a-new-ecosystem-for-health-management)
66
+ - *Classic big pharma, but aggressively pursuing chronic disease management with AI. Strong FCF yield, moat, and attractive ROE.*
67
+ - **OSR Holdings** and **Woori IO** (private)
68
+ - [OSR Holdings Acquires Woori IO](https://www.biospace.com/press-releases/osr-holdings-enters-into-term-sheet-to-acquire-woori-io-a-pioneer-in-noninvasive-glucose-monitoring-technology)
69
+ - *Pure play in noninvasive diagnostics. If/when OSR lists or expands, worth screening for value metrics.*
70
+
71
+ ---
72
+
73
+ ## 🧠 Investment Thesis
74
+
75
+ **Current view:**
76
+ This week’s rejuvenation news is most actionable for early-stage venture investors, with public equity players in β€œwatch and wait” mode except for special situations in medtech (ZimVie) and established innovative pharma (Novo Nordisk).
77
+
78
+ **Risk/Reward:**
79
+ - **Risks:** Most developments are pre-commercial, limited liquidity and financial visibility in small caps, and hype-driven valuation risk in AI/biotech.
80
+ - **Rewards:** Secular tailwind from aging demographics, structural innovation in personalized/AI-driven health, and M&A tailwinds for asset-rich legacy firms.
81
+ - **Themes to Watch:**
82
+ - Partnerships between global pharma and AI/diagnostics startups (could drive reratings if partnerships scale).
83
+ - M&A among β€œorphaned” divested medtech assets with robust FCF.
84
+ - Emergence of platform technologies (aging clocks, noninvasive monitors) as moats.
85
+
86
+ **Macro:**
87
+ - The value thesis remains challenging in the near term for public stocks; rising capital flowing into AI + longevity startups signals future wave of IPOs or M&A.
88
+ - Watch regulatory ramp-up in diagnostics and digital health (esp. in China and US); successful early adoption could leverage global scale.
89
+
90
+ ---
91
+
92
+ ## πŸ”— References
93
+
94
+ - [Aging Clock Unveils Compounds That Rejuvenate Brain Cells - Neuroscience News](https://neurosciencenews.com/aging-clock-neurogenesis-29510/)
95
+ - [ZimVie to sell to investment firm for about $730M - MedTech Dive](https://www.medtechdive.com/news/zimvie--sell-archimed-730m/753691/)
96
+ - [Fangzhou and Novo Nordisk Partner to Transform Chronic Disease Management with AI in China - HIT Consultant](https://hitconsultant.net/2025/07/21/fangzhou-and-novo-nordisk-china-partnership/)
97
+ - [Fangzhou and Novo Nordisk Signed Collaboration Memorandum - BioSpace](https://www.biospace.com/press-releases/fangzhou-and-novo-nordisk-signed-collaboration-memorandum-to-establish-a-new-ecosystem-for-health-management)
98
+ - [OSR Holdings Acquires Woori IO - BioSpace](https://www.biospace.com/press-releases/osr-holdings-enters-into-term-sheet-to-acquire-woori-io-a-pioneer-in-noninvasive-glucose-monitoring-technology)
99
+ - [xAI's raise, Nudge's noninvasive brain implant, and Stripe's buy - Axios](https://www.axios.com/pro/all-deals/2025/07/22/pro-rata-premium-first-look)
100
+
101
+ ---
102
+
103
+ # **Conclusion: Watch for Turnkey Partnerships, Asset Sales, and AI Moat Formation**
104
+
105
+ For deep value or moat strategies, eyes should remain on the strategic M&A trend and on emerging partnerships between established pharma and new tech platforms. Near-term plays are special situation value (ZimVie, possibly OSR Holdings if public), while longer-term exposure may require hybrid VC or holding company vehicles as the sector matures and lists more investable companies with traditional value metrics.
html/rejuvenation_2025-07-26.html ADDED
@@ -0,0 +1,201 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ <!DOCTYPE html>
3
+ <html lang="en">
4
+ <head>
5
+ <meta charset="UTF-8">
6
+ <title>rejuvenation_2025-07-26</title>
7
+ <style>
8
+ body {
9
+ font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
10
+ margin: 0;
11
+ background-color: #f8f9fa;
12
+ color: #212529;
13
+ line-height: 1.6;
14
+ }
15
+ header {
16
+ background-color: #ffffff;
17
+ text-align: center;
18
+ padding: 1em;
19
+ border-bottom: 2px solid #dee2e6;
20
+ }
21
+ header img {
22
+ width: 100%;
23
+ height: auto;
24
+ max-height: 50vh;
25
+ object-fit: cover;
26
+ }
27
+ .credit {
28
+ font-size: 0.85em;
29
+ color: #6c757d;
30
+ margin-top: 0.5em;
31
+ }
32
+ .container {
33
+ display: flex;
34
+ flex-direction: row;
35
+ max-width: 1200px;
36
+ margin: 2em auto;
37
+ padding: 0 1em;
38
+ gap: 2em;
39
+ }
40
+ main {
41
+ flex: 3;
42
+ }
43
+ aside {
44
+ flex: 1;
45
+ background-color: #ffffff;
46
+ border: 1px solid #dee2e6;
47
+ border-radius: 8px;
48
+ padding: 1em;
49
+ box-shadow: 0 2px 6px rgba(0,0,0,0.05);
50
+ height: fit-content;
51
+ }
52
+ main img {
53
+ max-width: 100%;
54
+ height: auto;
55
+ display: block;
56
+ margin: 1.5em auto;
57
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
58
+ }
59
+ h1, h2, h3 {
60
+ color: #0d6efd;
61
+ }
62
+ a {
63
+ color: #0d6efd;
64
+ text-decoration: none;
65
+ }
66
+ a:hover {
67
+ text-decoration: underline;
68
+ }
69
+ code {
70
+ background: #e9ecef;
71
+ padding: 0.2em 0.4em;
72
+ border-radius: 4px;
73
+ font-family: monospace;
74
+ }
75
+ pre {
76
+ background: #e9ecef;
77
+ padding: 1em;
78
+ overflow-x: auto;
79
+ border-radius: 6px;
80
+ }
81
+ blockquote {
82
+ border-left: 4px solid #0d6efd;
83
+ padding-left: 1em;
84
+ color: #495057;
85
+ margin: 1em 0;
86
+ background: #f1f3f5;
87
+ }
88
+ </style>
89
+ </head>
90
+ <body>
91
+ <header>
92
+ <img src="https://via.placeholder.com/1280x720.png?text=AI+News+Analyzer" alt="rejuvenation_2025-07-26 Banner">
93
+ </header>
94
+ <div class="container">
95
+ <main>
96
+
97
+ <h1 id="rejuvenation-sector-value-investor-memo-week-of-july-22-2025">Rejuvenation Sector – Value Investor Memo (Week of July 22, 2025)</h1>
98
+ <hr />
99
+ <h2 id="executive-summary">πŸ“Œ Executive Summary</h2>
100
+ <ul>
101
+ <li><strong>Sentiment:</strong> The rejuvenation and longevity space is heating up, driven by new research, partnerships, and acquisitions, but is mostly in β€œwatch” territory for public equity investors, with most innovation found in early-stage private startups.</li>
102
+ <li><strong>Risks:</strong> Many advances remain years from commercialization; the sector is hype-prone, and most investable stocks lack strong traditional value metrics (P/E, P/B, ROE).</li>
103
+ <li><strong>Catalysts:</strong> Partnerships (e.g., Novo Nordisk in China), growing M&amp;A activity (ZimVie, OSR Holdings), significant fundraising, and emerging AI-driven biomedical platform technologies are worth monitoring.</li>
104
+ <li><strong>Smart money:</strong> VCs are backing AI/biotech hybrids and noninvasive monitoring startups, while large strategics remain cautious but active in select buyouts.</li>
105
+ </ul>
106
+ <hr />
107
+ <h2 id="signals-and-analysis">πŸ“Š Signals and Analysis</h2>
108
+ <h3 id="1-ai-brain-aging-therapeutics">1. <strong>AI &amp; Brain Aging Therapeutics</strong></h3>
109
+ <ul>
110
+ <li><strong>What:</strong> New research uses machine learning to pinpoint brain cell rejuvenation compounds, with aging clock tech as a key enabler.</li>
111
+ <li><strong>Why it matters:</strong> Early-stage, but suggests future pipelines for biotech firms targeting Alzheimer’s and neurodegeneration. No direct investable company is named, suggesting to watch academic/AI-bio platform spinouts.</li>
112
+ <li><strong>Source:</strong> <a href="https://neurosciencenews.com/aging-clock-neurogenesis-29510/">Aging Clock Unveils Compounds That Rejuvenate Brain Cells - Neuroscience News</a></li>
113
+ </ul>
114
+ <h3 id="2-ma-undervalued-opportunities">2. <strong>M&amp;A &amp; Undervalued Opportunities</strong></h3>
115
+ <ul>
116
+ <li><strong>What:</strong> <strong>ZimVie</strong> (ZIMV), a post-spinout dental device company, is being acquired for $730M after a series of divestitures.</li>
117
+ <li><strong>Why it matters:</strong> Potential undervaluation after dramatic slimming and focus; its P/B and FCF should be monitored if still publicly listed pre-acquisition. Indicates smart money (private equity) snapping up legacy assets with strong cash flows.</li>
118
+ <li><strong>Source:</strong> <a href="https://www.medtechdive.com/news/zimvie--sell-archimed-730m/753691/">ZimVie to sell to investment firm for about $730M - MedTech Dive</a></li>
119
+ </ul>
120
+ <h3 id="3-ai-x-health-management-partnerships-in-china">3. <strong>AI x Health Management Partnerships in China</strong></h3>
121
+ <ul>
122
+ <li><strong>What:</strong> Fangzhou partners with <strong>Novo Nordisk</strong> to transform chronic disease management using AI.</li>
123
+ <li><strong>Why it matters:</strong> Global pharma tapping local AI, possibly opening up new data-driven health ecosystems in massive markets. Worth watching for new, scalable models if Fangzhou IPOs or if Novo’s deal delivers material financial impact.</li>
124
+ <li><strong>Sources:</strong> <ul>
125
+ <li><a href="https://hitconsultant.net/2025/07/21/fangzhou-and-novo-nordisk-china-partnership/">Fangzhou and Novo Nordisk Partner to Transform Chronic Disease Management with AI in China - HIT Consultant</a></li>
126
+ <li><a href="https://www.biospace.com/press-releases/fangzhou-and-novo-nordisk-signed-collaboration-memorandum-to-establish-a-new-ecosystem-for-health-management">Fangzhou and Novo Nordisk Signed Collaboration Memorandum to Establish a New Ecosystem for Health Management - BioSpace</a></li>
127
+ </ul>
128
+ </li>
129
+ </ul>
130
+ <h3 id="4-acquisition-in-noninvasive-monitoring">4. <strong>Acquisition in Noninvasive Monitoring</strong></h3>
131
+ <ul>
132
+ <li><strong>What:</strong> <strong>OSR Holdings</strong> to acquire Woori IO, a pioneer in noninvasive glucose tech.</li>
133
+ <li><strong>Why it matters:</strong> As noninvasive monitoring is a potential β€œplatform moat” for chronic conditions management, this type of tech could underpin future rejuvenation or wellness ecosystem companies. Acquisition signals strategic value; watch for Woori IO’s technology adoption curve.</li>
134
+ <li><strong>Source:</strong> <a href="https://www.biospace.com/press-releases/osr-holdings-enters-into-term-sheet-to-acquire-woori-io-a-pioneer-in-noninvasive-glucose-monitoring-technology">OSR Holdings Enters into Term Sheet to Acquire Woori IO, a Pioneer in Noninvasive Glucose Monitoring Technology - BioSpace</a></li>
135
+ </ul>
136
+ <h3 id="5-startups-and-funding-in-rejuvenation">5. <strong>Startups and Funding in Rejuvenation</strong></h3>
137
+ <ul>
138
+ <li><strong>What:</strong> Slingshot AI (mental healthcare chatbot) raised $50M; Makersite (manufacturing decisioning) raised €60M; 6 biotechs in the longevity space (undisclosed) highlighted.</li>
139
+ <li><strong>Why it matters:</strong> Rapid fundraising for health AI startups suggests a robust VC pipeline, but public market access is limited; premium on getting in at pre-IPO stages or via crossover funds.</li>
140
+ <li><strong>Source:</strong> <a href="https://www.axios.com/pro/all-deals/2025/07/22/pro-rata-premium-first-look">xAI's raise, Nudge's noninvasive brain implant, and Stripe's buy - Axios</a></li>
141
+ </ul>
142
+ <h3 id="6-fundamental-value-screen">6. <strong>Fundamental Value Screen</strong></h3>
143
+ <ul>
144
+ <li>Very few listed companies in the β€˜rejuvenation’/longevity/biotech AI fields have both value investor-friendly metrics and growth optionality. ZimVie possibly fits the bill short-term; <strong>Novo Nordisk</strong> is strong on fundamentals but is a large, fairly valued pharma stock.</li>
145
+ <li>Sectors with cash generative characteristics (e.g., dental/divested medtech, as with ZimVie) present special situations for patient investors.</li>
146
+ </ul>
147
+ <hr />
148
+ <h2 id="stocks-or-startups-to-watch">πŸ“ˆ Stocks or Startups to Watch</h2>
149
+ <ul>
150
+ <li><strong>ZimVie (ZIMV)</strong><ul>
151
+ <li><a href="https://www.medtechdive.com/news/zimvie--sell-archimed-730m/753691/">ZimVie to sell to investment firm for about $730M</a></li>
152
+ <li><em>Special situation: acquisition at premium post-business focus, but no longer a long-term pure rejuvenation play if going private soon.</em></li>
153
+ </ul>
154
+ </li>
155
+ <li><strong>Novo Nordisk (NVO)</strong><ul>
156
+ <li><a href="https://www.biospace.com/press-releases/fangzhou-and-novo-nordisk-signed-collaboration-memorandum-to-establish-a-new-ecosystem-for-health-management">Fangzhou &amp; Novo Nordisk partnership</a></li>
157
+ <li><em>Classic big pharma, but aggressively pursuing chronic disease management with AI. Strong FCF yield, moat, and attractive ROE.</em></li>
158
+ </ul>
159
+ </li>
160
+ <li><strong>OSR Holdings</strong> and <strong>Woori IO</strong> (private)<ul>
161
+ <li><a href="https://www.biospace.com/press-releases/osr-holdings-enters-into-term-sheet-to-acquire-woori-io-a-pioneer-in-noninvasive-glucose-monitoring-technology">OSR Holdings Acquires Woori IO</a></li>
162
+ <li><em>Pure play in noninvasive diagnostics. If/when OSR lists or expands, worth screening for value metrics.</em></li>
163
+ </ul>
164
+ </li>
165
+ </ul>
166
+ <hr />
167
+ <h2 id="investment-thesis">🧠 Investment Thesis</h2>
168
+ <p><strong>Current view:</strong><br />
169
+ This week’s rejuvenation news is most actionable for early-stage venture investors, with public equity players in β€œwatch and wait” mode except for special situations in medtech (ZimVie) and established innovative pharma (Novo Nordisk).</p>
170
+ <p><strong>Risk/Reward:</strong><br />
171
+ - <strong>Risks:</strong> Most developments are pre-commercial, limited liquidity and financial visibility in small caps, and hype-driven valuation risk in AI/biotech.
172
+ - <strong>Rewards:</strong> Secular tailwind from aging demographics, structural innovation in personalized/AI-driven health, and M&amp;A tailwinds for asset-rich legacy firms.
173
+ - <strong>Themes to Watch:</strong>
174
+ - Partnerships between global pharma and AI/diagnostics startups (could drive reratings if partnerships scale).
175
+ - M&amp;A among β€œorphaned” divested medtech assets with robust FCF.
176
+ - Emergence of platform technologies (aging clocks, noninvasive monitors) as moats.</p>
177
+ <p><strong>Macro:</strong><br />
178
+ - The value thesis remains challenging in the near term for public stocks; rising capital flowing into AI + longevity startups signals future wave of IPOs or M&amp;A.
179
+ - Watch regulatory ramp-up in diagnostics and digital health (esp. in China and US); successful early adoption could leverage global scale.</p>
180
+ <hr />
181
+ <h2 id="references">πŸ”— References</h2>
182
+ <ul>
183
+ <li><a href="https://neurosciencenews.com/aging-clock-neurogenesis-29510/">Aging Clock Unveils Compounds That Rejuvenate Brain Cells - Neuroscience News</a></li>
184
+ <li><a href="https://www.medtechdive.com/news/zimvie--sell-archimed-730m/753691/">ZimVie to sell to investment firm for about $730M - MedTech Dive</a></li>
185
+ <li><a href="https://hitconsultant.net/2025/07/21/fangzhou-and-novo-nordisk-china-partnership/">Fangzhou and Novo Nordisk Partner to Transform Chronic Disease Management with AI in China - HIT Consultant</a></li>
186
+ <li><a href="https://www.biospace.com/press-releases/fangzhou-and-novo-nordisk-signed-collaboration-memorandum-to-establish-a-new-ecosystem-for-health-management">Fangzhou and Novo Nordisk Signed Collaboration Memorandum - BioSpace</a></li>
187
+ <li><a href="https://www.biospace.com/press-releases/osr-holdings-enters-into-term-sheet-to-acquire-woori-io-a-pioneer-in-noninvasive-glucose-monitoring-technology">OSR Holdings Acquires Woori IO - BioSpace</a></li>
188
+ <li><a href="https://www.axios.com/pro/all-deals/2025/07/22/pro-rata-premium-first-look">xAI's raise, Nudge's noninvasive brain implant, and Stripe's buy - Axios</a></li>
189
+ </ul>
190
+ <hr />
191
+ <h1 id="conclusion-watch-for-turnkey-partnerships-asset-sales-and-ai-moat-formation"><strong>Conclusion: Watch for Turnkey Partnerships, Asset Sales, and AI Moat Formation</strong></h1>
192
+ <p>For deep value or moat strategies, eyes should remain on the strategic M&amp;A trend and on emerging partnerships between established pharma and new tech platforms. Near-term plays are special situation value (ZimVie, possibly OSR Holdings if public), while longer-term exposure may require hybrid VC or holding company vehicles as the sector matures and lists more investable companies with traditional value metrics.</p>
193
+ </main>
194
+ <aside>
195
+ <h3>🧠 Metrics</h3>
196
+ <ul><li>Topic: Rejuvenation</li><li>Articles Collected: 297</li><li>Generated: 2025-07-26 15:26</li></ul>
197
+ </aside>
198
+ </div>
199
+ </body>
200
+ </html>
201
+
investing_topics_prev.csv ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ topic,timespan_days
2
+ Rejuvenation,7
requirements.txt CHANGED
@@ -86,4 +86,4 @@ tzdata==2025.2
86
  urllib3==2.5.0
87
  zipp==3.23.0
88
  zstandard==0.23.0
89
-
 
86
  urllib3==2.5.0
87
  zipp==3.23.0
88
  zstandard==0.23.0
89
+ xhtml2pdf
src/main.py CHANGED
@@ -1,12 +1,14 @@
1
  import os
2
  import pandas as pd
3
  from datetime import datetime
 
 
 
4
  from md_html import convert_single_md_to_html as convert_md_to_html
5
  from news_analysis import fetch_deep_news, generate_value_investor_report
6
  from csv_utils import detect_changes
7
- from fin_interpreter import analyze_article # For FinBERT + FinGPT signals
8
 
9
- # === Paths ===
10
  BASE_DIR = os.path.dirname(os.path.dirname(__file__))
11
  DATA_DIR = os.path.join(BASE_DIR, "data")
12
  HTML_DIR = os.path.join(BASE_DIR, "html")
@@ -15,69 +17,128 @@ CSV_PATH = os.path.join(BASE_DIR, "investing_topics.csv")
15
  os.makedirs(DATA_DIR, exist_ok=True)
16
  os.makedirs(HTML_DIR, exist_ok=True)
17
 
18
- def run_pipeline(topics, openai_api_key=None, tavily_api_key=None):
19
- """
20
- Main pipeline:
21
- 1. Fetch articles for topics.
22
- 2. Analyze with FinBERT + FinGPT.
23
- 3. Generate markdown report.
24
- 4. Return (report_md, articles_df, insights_df).
25
- """
26
- all_articles = []
27
 
28
- # Fetch and analyze articles
29
- for topic, days in topics:
30
- try:
31
- articles = fetch_deep_news(topic, days, tavily_api_key)
32
- for article in articles:
33
- sentiment, confidence, signal = analyze_article(article.get("summary", ""))
34
- all_articles.append({
35
- "Title": article.get("title"),
36
- "URL": article.get("url"),
37
- "Summary": article.get("summary"),
38
- "Priority": article.get("priority", "Low"),
39
- "Date": article.get("date"),
40
- "Company": article.get("company", topic), # fallback if no company detected
41
- "Sentiment": sentiment,
42
- "Confidence": confidence,
43
- "Signal": signal
44
- })
45
- except Exception as e:
46
- print(f"Error fetching/analyzing articles for topic '{topic}': {e}")
47
-
48
- # Convert to DataFrame
49
- articles_df = pd.DataFrame(all_articles)
50
 
51
- # Generate Markdown report (existing behavior)
52
- report_md = ""
53
- try:
54
- articles_df = pd.DataFrame(all_articles)
55
- report_md = generate_value_investor_report(articles_df, openai_api_key)
 
 
 
56
 
57
- except Exception as e:
58
- import traceback
59
- traceback.print_exc()
60
- report_md = f"Error generating report: {e}"
61
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
62
 
63
- # Build insights (aggregated by company)
64
- insights_df = build_company_insights(articles_df)
65
 
66
- return report_md, articles_df, insights_df
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
67
 
68
 
69
  def build_company_insights(articles_df):
70
- """
71
- Aggregates article data into a company-level insights table.
72
- Columns: Company, Mentions, Avg Sentiment, Top Signal, Sector
73
- """
74
  if articles_df.empty:
75
  return pd.DataFrame()
76
-
77
- # Simple aggregation
78
  grouped = (
79
- articles_df
80
- .groupby("Company")
81
  .agg({
82
  "Title": "count",
83
  "Sentiment": lambda x: x.mode()[0] if not x.mode().empty else "Neutral",
@@ -86,39 +147,16 @@ def build_company_insights(articles_df):
86
  .reset_index()
87
  .rename(columns={"Title": "Mentions"})
88
  )
89
-
90
- # Add a placeholder Sector column (can improve later with classification)
91
- grouped["Sector"] = grouped["Company"].apply(lambda c: detect_sector_from_company(c))
92
-
93
  return grouped
94
 
95
 
96
- def detect_sector_from_company(company_name):
97
- """
98
- Simple keyword-based sector detection (can be replaced with GPT classification).
99
- """
100
- company_name = company_name.lower()
101
- if "energy" in company_name or "nuclear" in company_name:
102
- return "Energy"
103
- elif "fin" in company_name or "bank" in company_name:
104
- return "Finance"
105
- elif "chip" in company_name or "semiconductor" in company_name:
106
- return "Tech Hardware"
107
- else:
108
- return "General"
109
-
110
-
111
  if __name__ == "__main__":
112
- # Test run (local)
113
- test_topics = [("nuclear energy", 7)]
114
- md, art_df, ins_df = run_pipeline(test_topics)
115
- print(md)
116
- print(art_df.head())
117
- print(ins_df.head())
118
-
119
-
120
 
121
- # import os
122
  # import sys
123
  # from datetime import datetime
124
  # from dotenv import load_dotenv
@@ -227,3 +265,4 @@ if __name__ == "__main__":
227
  # convert_md_to_html(md, HTML_DIR)
228
  # print(f"🌐 All reports converted to HTML at: {HTML_DIR}")
229
 
 
 
1
  import os
2
  import pandas as pd
3
  from datetime import datetime
4
+ from dotenv import load_dotenv
5
+ import traceback
6
+
7
  from md_html import convert_single_md_to_html as convert_md_to_html
8
  from news_analysis import fetch_deep_news, generate_value_investor_report
9
  from csv_utils import detect_changes
10
+ from fin_interpreter import analyze_article
11
 
 
12
  BASE_DIR = os.path.dirname(os.path.dirname(__file__))
13
  DATA_DIR = os.path.join(BASE_DIR, "data")
14
  HTML_DIR = os.path.join(BASE_DIR, "html")
 
17
  os.makedirs(DATA_DIR, exist_ok=True)
18
  os.makedirs(HTML_DIR, exist_ok=True)
19
 
20
+ load_dotenv()
 
 
 
 
 
 
 
 
21
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
22
 
23
+ def build_metrics_box(topic, num_articles):
24
+ now = datetime.now().strftime("%Y-%m-%d %H:%M")
25
+ return f"""
26
+ > Topic: `{topic}`
27
+ > Articles Collected: `{num_articles}`
28
+ > Generated: `{now}`
29
+ >
30
+ """
31
 
 
 
 
 
32
 
33
+ def run_value_investing_analysis(csv_path, progress_callback=None):
34
+ """
35
+ Runs the analysis for all topics in the CSV.
36
+ Returns:
37
+ md_files (list of md file paths)
38
+ all_articles (list of article dicts)
39
+ """
40
+ current_df = pd.read_csv(csv_path)
41
+ prev_path = os.path.join(BASE_DIR, "investing_topics_prev.csv")
42
+
43
+ if os.path.exists(prev_path):
44
+ previous_df = pd.read_csv(prev_path)
45
+ changed_df = detect_changes(current_df, previous_df)
46
+ if changed_df.empty:
47
+ if progress_callback:
48
+ progress_callback("βœ… No changes detected. Skipping processing.")
49
+ return [], []
50
+ else:
51
+ changed_df = current_df
52
 
53
+ new_md_files = []
54
+ all_articles = []
55
 
56
+ for _, row in changed_df.iterrows():
57
+ topic = row.get("topic")
58
+ timespan = row.get("timespan_days", 7)
59
+ msg = f"πŸ” Processing: {topic} ({timespan} days)"
60
+ print(msg)
61
+ if progress_callback:
62
+ progress_callback(msg)
63
+
64
+ news = fetch_deep_news(topic, timespan)
65
+ if not news:
66
+ warning = f"⚠️ No news found for: {topic}"
67
+ print(warning)
68
+ if progress_callback:
69
+ progress_callback(warning)
70
+ continue
71
+
72
+ # Add articles to all_articles
73
+ for article in news:
74
+ try:
75
+ res = analyze_article(article.get("summary", ""))
76
+ if isinstance(res, dict):
77
+ sentiment = res.get("sentiment")
78
+ confidence = res.get("confidence")
79
+ signal = res.get("signal")
80
+ else:
81
+ sentiment, confidence, signal = res[0], res[1], res[2]
82
+ except Exception as e:
83
+ sentiment, confidence, signal = "Unknown", 0.0, "None"
84
+ print(f"Error analyzing article: {e}")
85
+
86
+ all_articles.append({
87
+ "Title": article.get("title"),
88
+ "URL": article.get("url"),
89
+ "Summary": article.get("summary"),
90
+ "Priority": article.get("priority", "Low"),
91
+ "Date": article.get("date"),
92
+ "Company": article.get("company", topic),
93
+ "Sentiment": sentiment,
94
+ "Confidence": confidence,
95
+ "Signal": signal
96
+ })
97
+
98
+ # Generate report
99
+ report_body = generate_value_investor_report(topic, news)
100
+ metrics_md = build_metrics_box(topic, len(news))
101
+ full_md = metrics_md + report_body
102
+
103
+ filename = f"{topic.replace(' ', '_').lower()}_{datetime.now().strftime('%Y-%m-%d')}.md"
104
+ filepath = os.path.join(DATA_DIR, filename)
105
+ counter = 1
106
+ while os.path.exists(filepath):
107
+ filename = f"{topic.replace(' ', '_').lower()}_{datetime.now().strftime('%Y-%m-%d')}_{counter}.md"
108
+ filepath = os.path.join(DATA_DIR, filename)
109
+ counter += 1
110
+
111
+ with open(filepath, "w", encoding="utf-8") as f:
112
+ f.write(full_md)
113
+
114
+ new_md_files.append(filepath)
115
+
116
+ if progress_callback:
117
+ progress_callback(f"βœ… Markdown saved to: {DATA_DIR}")
118
+ current_df.to_csv(prev_path, index=False)
119
+ return new_md_files, all_articles
120
+
121
+
122
+ def run_pipeline(csv_path, tavily_api_key, progress_callback=None):
123
+ os.environ["TAVILY_API_KEY"] = tavily_api_key
124
+
125
+ new_md_files, all_articles = run_value_investing_analysis(csv_path, progress_callback)
126
+ new_html_paths = []
127
+ for md_path in new_md_files:
128
+ convert_md_to_html(md_path, HTML_DIR)
129
+ html_path = os.path.join(HTML_DIR, os.path.basename(md_path).replace(".md", ".html"))
130
+ new_html_paths.append(html_path)
131
+
132
+ articles_df = pd.DataFrame(all_articles)
133
+ insights_df = build_company_insights(articles_df)
134
+ return new_html_paths, articles_df, insights_df
135
 
136
 
137
  def build_company_insights(articles_df):
 
 
 
 
138
  if articles_df.empty:
139
  return pd.DataFrame()
 
 
140
  grouped = (
141
+ articles_df.groupby("Company")
 
142
  .agg({
143
  "Title": "count",
144
  "Sentiment": lambda x: x.mode()[0] if not x.mode().empty else "Neutral",
 
147
  .reset_index()
148
  .rename(columns={"Title": "Mentions"})
149
  )
 
 
 
 
150
  return grouped
151
 
152
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
153
  if __name__ == "__main__":
154
+ md_files, _ = run_value_investing_analysis(CSV_PATH)
155
+ for md in md_files:
156
+ convert_md_to_html(md, HTML_DIR)
157
+ print(f"🌐 All reports converted to HTML at: {HTML_DIR}")
 
 
 
 
158
 
159
+ #import os
160
  # import sys
161
  # from datetime import datetime
162
  # from dotenv import load_dotenv
 
265
  # convert_md_to_html(md, HTML_DIR)
266
  # print(f"🌐 All reports converted to HTML at: {HTML_DIR}")
267
 
268
+