Spaces:
Running
Running
zykrix
commited on
Commit
·
bb4e28f
0
Parent(s):
Initial commit of FinSightX
Browse files- .gitignore +59 -0
- README.md +118 -0
- agents/client_advisor.py +11 -0
- agents/equity_analyst.py +14 -0
- agents/macro_strategist.py +7 -0
- agents/news_summarizer.py +7 -0
- agents/quant_backtester.py +23 -0
- agents/regu_radar.py +10 -0
- config/env.py +11 -0
- config/model_config.py +18 -0
- embeddings/embedder.py +6 -0
- embeddings/vector_store.py +11 -0
- llm/groq_llm.py +16 -0
- llm/summarizer.py +11 -0
- llm/tinyllama_runner.py +14 -0
- requirements.txt +10 -0
- space.yaml +9 -0
- tools/autorag_tool.py +6 -0
- tools/forecast_tool.py +16 -0
- tools/sentiment_tool.py +7 -0
- ui/streamlit_app.py +192 -0
.gitignore
ADDED
@@ -0,0 +1,59 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Python
|
2 |
+
__pycache__/
|
3 |
+
|
4 |
+
|
5 |
+
# Virtual environment
|
6 |
+
venv/
|
7 |
+
.env
|
8 |
+
|
9 |
+
|
10 |
+
# VSCode
|
11 |
+
.vscode/
|
12 |
+
|
13 |
+
|
14 |
+
|
15 |
+
# OS files
|
16 |
+
.DS_Store
|
17 |
+
Thumbs.db
|
18 |
+
|
19 |
+
# Logs
|
20 |
+
*.log
|
21 |
+
|
22 |
+
# Model files
|
23 |
+
*.pth
|
24 |
+
*.pt
|
25 |
+
*.bin
|
26 |
+
*.gguf
|
27 |
+
*.ckpt
|
28 |
+
*.safetensors
|
29 |
+
|
30 |
+
# Hugging Face transformers
|
31 |
+
tokenizer_config.json
|
32 |
+
config.json
|
33 |
+
special_tokens_map.json
|
34 |
+
pytorch_model.bin
|
35 |
+
sentence_bert_config.json
|
36 |
+
model.safetensors
|
37 |
+
|
38 |
+
# ChromaDB local data
|
39 |
+
chroma/
|
40 |
+
chroma.db/
|
41 |
+
chroma_data/
|
42 |
+
*.sqlite
|
43 |
+
|
44 |
+
# Streamlit cache
|
45 |
+
.streamlit/
|
46 |
+
.cache/
|
47 |
+
__pycache__/
|
48 |
+
|
49 |
+
# Misc
|
50 |
+
*.csv
|
51 |
+
*.parquet
|
52 |
+
*.zip
|
53 |
+
*.tar
|
54 |
+
*.h5
|
55 |
+
*.pdf
|
56 |
+
|
57 |
+
# Ignore test or temp files
|
58 |
+
*.bak
|
59 |
+
*.tmp
|
README.md
ADDED
@@ -0,0 +1,118 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# 📊 FinSightX – AI-Powered Financial Analyst Suite
|
2 |
+
|
3 |
+
**FinSightX** is an intelligent, agent-powered financial assistant built using Groq's ultra-fast LLaMA 3.1 models, AutoRAG, and open-source tools. It allows users to query equities, summarize news, run macroeconomic forecasts, test quant strategies, track regulatory changes, and receive client-style advisory responses — all in one lightweight app.
|
4 |
+
|
5 |
+
> 💡 Built with Groq API, Hugging Face Transformers, ChromaDB, and Streamlit.
|
6 |
+
|
7 |
+
---
|
8 |
+
|
9 |
+
## 🚀 Features
|
10 |
+
|
11 |
+
| Agent | Role |
|
12 |
+
|-------|------|
|
13 |
+
| **EquityAnalystAgent** | Answers stock-specific financial questions using live data and sentiment |
|
14 |
+
| **NewsSummarizerAgent** | Summarizes market headlines via LLM and retrieval |
|
15 |
+
| **MacroStrategistAgent** | Forecasts macroeconomic trends using NeuralProphet |
|
16 |
+
| **QuantBacktesterAgent** | Runs quant strategies using historical price data |
|
17 |
+
| **ReguRadarAgent** | Scans for key regulatory disclosures |
|
18 |
+
| **ClientAdvisorAgent** | Provides personalized financial advice based on user tone and goals |
|
19 |
+
|
20 |
+
---
|
21 |
+
|
22 |
+
## 🛠️ Tech Stack
|
23 |
+
|
24 |
+
- **LLM**: `llama-3.1-8b-instant` via Groq API (OpenAI-compatible)
|
25 |
+
- **Embedding**: `all-MiniLM-L6-v2` (SentenceTransformers)
|
26 |
+
- **Sentiment Analysis**: `ProsusAI/finbert`
|
27 |
+
- **Vector DB**: ChromaDB (local)
|
28 |
+
- **Forecasting**: NeuralProphet
|
29 |
+
- **Backtesting**: `bt` package
|
30 |
+
- **UI**: Streamlit
|
31 |
+
|
32 |
+
---
|
33 |
+
|
34 |
+
## ⚙️ Setup Instructions
|
35 |
+
|
36 |
+
1. Clone the repo
|
37 |
+
2. Install dependencies:
|
38 |
+
```bash
|
39 |
+
pip install -r requirements.txt
|
40 |
+
```
|
41 |
+
3. Create a .env file:
|
42 |
+
```bash
|
43 |
+
GROQ_API_KEY=your_groq_key
|
44 |
+
GROQ_API_URL=https://api.groq.com/openai/v1/chat/completions
|
45 |
+
```
|
46 |
+
4. Run the app:
|
47 |
+
```bash
|
48 |
+
streamlit run ui/streamlit_app.py
|
49 |
+
```
|
50 |
+
|
51 |
+
## 📉 Current Limitations
|
52 |
+
|
53 |
+
- ChromaDB does not yet include 10-K/10-Q or earnings data
|
54 |
+
- Macro indicators (CPI, interest rates) not integrated
|
55 |
+
- No real-time alerts or portfolio memory
|
56 |
+
- No backtest visualization (plotly optional)
|
57 |
+
- LLaMA 3.1 license is research-only (not commercial)
|
58 |
+
|
59 |
+
---
|
60 |
+
|
61 |
+
## 📂 Future Improvements
|
62 |
+
|
63 |
+
### 📄 Financial Documents to Integrate
|
64 |
+
|
65 |
+
| Document | Use |
|
66 |
+
|------------------------------|-----------------------------------------------|
|
67 |
+
| 10-K / 10-Q | Full financial analysis and risk sections |
|
68 |
+
| 8-K | Instant updates on events, deals, or risks |
|
69 |
+
| Earnings Transcripts | Management commentary and guidance |
|
70 |
+
| Investor Presentations | Visual and forward-looking insights |
|
71 |
+
| Proxy Statements (DEF 14A) | Governance and voting info |
|
72 |
+
|
73 |
+
### 📊 Financial Metrics to Add
|
74 |
+
|
75 |
+
- Free cash flow
|
76 |
+
- ROE / ROIC
|
77 |
+
- Altman Z-Score
|
78 |
+
- Piotroski F-Score
|
79 |
+
- Debt/equity & profitability ratios
|
80 |
+
|
81 |
+
### 🌐 Macroeconomic Indicators
|
82 |
+
|
83 |
+
| Indicator | Source |
|
84 |
+
|--------------------------|------------------------------------|
|
85 |
+
| CPI, GDP, Unemployment | FRED API / IMF / World Bank |
|
86 |
+
| Fed rates, Inflation | TradingEconomics / OpenBB |
|
87 |
+
| Currency / Commodities | Yahoo Finance / forex-python |
|
88 |
+
|
89 |
+
### 🔌 Tools & Libraries to Integrate
|
90 |
+
|
91 |
+
- `sec-api.io` or `sec-edgar-downloader` (for 10-Ks)
|
92 |
+
- `openbb` (for macro + financial aggregation)
|
93 |
+
- `plotly` (for backtesting visualization)
|
94 |
+
- `redis` or `duckdb` (for memory/session tracking)
|
95 |
+
|
96 |
+
---
|
97 |
+
|
98 |
+
## 🔮 Future Agent Extensions
|
99 |
+
|
100 |
+
| Agent Name | Description |
|
101 |
+
|------------------------|------------------------------------------------------------------------|
|
102 |
+
| `PortfolioBuilderAgent`| Recommends custom portfolio allocations based on user goals |
|
103 |
+
| `RiskMonitorAgent` | Tracks volatility, drawdowns, exposure and market risk |
|
104 |
+
| `AlertAgent` | Notifies users of macro shifts, earnings releases, or regulatory events|
|
105 |
+
|
106 |
+
---
|
107 |
+
|
108 |
+
## 📘 License
|
109 |
+
|
110 |
+
Currently for **research and educational purposes only**.
|
111 |
+
If using Groq-hosted LLaMA 3.1, ensure compliance with Meta’s licensing.
|
112 |
+
|
113 |
+
---
|
114 |
+
|
115 |
+
## 👨💻 Author
|
116 |
+
|
117 |
+
Developed by **Rahul Thakur**
|
118 |
+
Want to collaborate or contribute? Fork, star, and connect!
|
agents/client_advisor.py
ADDED
@@ -0,0 +1,11 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from tools.sentiment_tool import analyze_sentiment
|
2 |
+
from llm.groq_llm import call_groq_mistral
|
3 |
+
|
4 |
+
def advise_client(user_input: str) -> str:
|
5 |
+
sentiment = analyze_sentiment(user_input)
|
6 |
+
prompt = (
|
7 |
+
f"A client asked a financial question: '{user_input}'\n"
|
8 |
+
f"Their emotional tone is: {sentiment}.\n"
|
9 |
+
f"As a financial advisor, provide a thoughtful and empathetic response."
|
10 |
+
)
|
11 |
+
return call_groq_mistral(prompt)
|
agents/equity_analyst.py
ADDED
@@ -0,0 +1,14 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from tools.sentiment_tool import analyze_sentiment
|
2 |
+
from tools.autorag_tool import query_equity_kb
|
3 |
+
from llm.groq_llm import call_groq_mistral
|
4 |
+
|
5 |
+
def answer_equity_question(query: str) -> str:
|
6 |
+
context = query_equity_kb(query)
|
7 |
+
sentiment = analyze_sentiment(context)
|
8 |
+
|
9 |
+
prompt = (
|
10 |
+
f"Analyze this equity context:\n{context}\n\n"
|
11 |
+
f"Sentiment of the data: {sentiment}.\n"
|
12 |
+
f"Provide a concise financial analysis and any risks or opportunities."
|
13 |
+
)
|
14 |
+
return call_groq_mistral(prompt)
|
agents/macro_strategist.py
ADDED
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from tools.forecast_tool import forecast
|
2 |
+
import pandas as pd
|
3 |
+
|
4 |
+
def analyze_macro_trends(df: pd.DataFrame) -> dict:
|
5 |
+
forecast_df = forecast(df)
|
6 |
+
latest = forecast_df.tail(1)
|
7 |
+
return latest.to_dict(orient="records")[0]
|
agents/news_summarizer.py
ADDED
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from llm.summarizer import summarize
|
2 |
+
from tools.autorag_tool import query_equity_kb
|
3 |
+
|
4 |
+
def summarize_market_news(news_text: str) -> str:
|
5 |
+
# You can use summarizer directly or summarize context if preloaded into KB
|
6 |
+
context = query_equity_kb(news_text)
|
7 |
+
return summarize(context or news_text)
|
agents/quant_backtester.py
ADDED
@@ -0,0 +1,23 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import bt
|
2 |
+
|
3 |
+
def run_simple_backtest(
|
4 |
+
strategy_name="SMA Cross", tickers=["AAPL"], sma_short=20, sma_long=50
|
5 |
+
):
|
6 |
+
def strategy_logic():
|
7 |
+
prices = bt.get(tickers, start="2020-01-01")
|
8 |
+
sma_s = prices.rolling(sma_short).mean()
|
9 |
+
sma_l = prices.rolling(sma_long).mean()
|
10 |
+
# Note: Signal is not used in bt directly
|
11 |
+
return bt.Strategy(
|
12 |
+
strategy_name,
|
13 |
+
[
|
14 |
+
bt.algos.SelectAll(),
|
15 |
+
bt.algos.WeighEqually(),
|
16 |
+
bt.algos.Rebalance(),
|
17 |
+
]
|
18 |
+
)
|
19 |
+
|
20 |
+
s = strategy_logic()
|
21 |
+
data = bt.get(tickers)
|
22 |
+
test = bt.Backtest(s, data)
|
23 |
+
return bt.run(test)
|
agents/regu_radar.py
ADDED
@@ -0,0 +1,10 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from tools.autorag_tool import query_equity_kb
|
2 |
+
from llm.groq_llm import call_groq_mistral
|
3 |
+
|
4 |
+
def monitor_regulatory_changes(text: str) -> str:
|
5 |
+
context = query_equity_kb(text)
|
6 |
+
prompt = (
|
7 |
+
f"The following text contains a regulatory update:\n{context}\n\n"
|
8 |
+
f"Summarize the key implications for investors and compliance."
|
9 |
+
)
|
10 |
+
return call_groq_mistral(prompt)
|
config/env.py
ADDED
@@ -0,0 +1,11 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import os
|
2 |
+
from dotenv import load_dotenv
|
3 |
+
|
4 |
+
load_dotenv()
|
5 |
+
|
6 |
+
GROQ_API_KEY = os.getenv("GROQ_API_KEY")
|
7 |
+
GROQ_API_URL = os.getenv("GROQ_API_URL", "https://api.groq.com/openai/v1/chat/completions")
|
8 |
+
HF_TOKEN = os.getenv("HF_TOKEN")
|
9 |
+
CHROMA_DB_PATH = os.getenv("CHROMA_DB_PATH", "./chroma")
|
10 |
+
|
11 |
+
print("GROQ_API_KEY Loaded:", bool(GROQ_API_KEY))
|
config/model_config.py
ADDED
@@ -0,0 +1,18 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
MODEL_CONFIG = {
|
2 |
+
"llm": {
|
3 |
+
"provider": "groq",
|
4 |
+
"model": "mistral-7b-instruct",
|
5 |
+
},
|
6 |
+
"embedding_model": {
|
7 |
+
"name": "all-MiniLM-L6-v2",
|
8 |
+
"provider": "sentence-transformers"
|
9 |
+
},
|
10 |
+
"summarizer": {
|
11 |
+
"use_groq": True,
|
12 |
+
"fallback_model": "TinyLlama"
|
13 |
+
},
|
14 |
+
"sentiment_model": {
|
15 |
+
"name": "ProsusAI/finbert",
|
16 |
+
"provider": "huggingface"
|
17 |
+
}
|
18 |
+
}
|
embeddings/embedder.py
ADDED
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from sentence_transformers import SentenceTransformer
|
2 |
+
|
3 |
+
model = SentenceTransformer("all-MiniLM-L6-v2")
|
4 |
+
|
5 |
+
def get_embedding(text: str):
|
6 |
+
return model.encode([text])[0]
|
embeddings/vector_store.py
ADDED
@@ -0,0 +1,11 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import chromadb
|
2 |
+
|
3 |
+
client = chromadb.Client()
|
4 |
+
collection = client.get_or_create_collection("finsightx_kb")
|
5 |
+
|
6 |
+
def add_to_db(doc_id: str, text: str, embedding):
|
7 |
+
collection.add(ids=[doc_id], documents=[text], embeddings=[embedding])
|
8 |
+
|
9 |
+
def query(text: str, embed_fn) -> dict:
|
10 |
+
query_embedding = embed_fn(text)
|
11 |
+
return collection.query(query_embeddings=[query_embedding], n_results=3)
|
llm/groq_llm.py
ADDED
@@ -0,0 +1,16 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from config.env import GROQ_API_KEY, GROQ_API_URL
|
2 |
+
import httpx
|
3 |
+
|
4 |
+
def call_groq_mistral(prompt: str) -> str:
|
5 |
+
headers = {"Authorization": f"Bearer {GROQ_API_KEY}"}
|
6 |
+
body = {
|
7 |
+
"model": "llama-3.1-8b-instant",
|
8 |
+
"messages": [{"role": "user", "content": prompt}],
|
9 |
+
"temperature": 0.7
|
10 |
+
}
|
11 |
+
try:
|
12 |
+
response = httpx.post(GROQ_API_URL, json=body, headers=headers, timeout=10)
|
13 |
+
response.raise_for_status()
|
14 |
+
return response.json()["choices"][0]["message"]["content"]
|
15 |
+
except Exception as e:
|
16 |
+
return f"❌ Error calling Groq: {str(e)}"
|
llm/summarizer.py
ADDED
@@ -0,0 +1,11 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from config.model_config import MODEL_CONFIG
|
2 |
+
from llm.groq_llm import call_groq_mistral
|
3 |
+
# from llm.tinyllama_runner import tinyllama_chat # fallback if needed
|
4 |
+
|
5 |
+
def summarize(text: str) -> str:
|
6 |
+
prompt = f"Summarize the following article:\n{text}"
|
7 |
+
|
8 |
+
if MODEL_CONFIG["summarizer"]["use_groq"]:
|
9 |
+
return call_groq_mistral(prompt)
|
10 |
+
else:
|
11 |
+
return "🪫 Fallback LLM not enabled" # or: tinyllama_chat(prompt)
|
llm/tinyllama_runner.py
ADDED
@@ -0,0 +1,14 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from llama_cpp import Llama
|
2 |
+
|
3 |
+
# Load quantized TinyLlama
|
4 |
+
llm = Llama(model_path="models/tinyllama-1.1b-chat.gguf", n_ctx=2048)
|
5 |
+
|
6 |
+
def tinyllama_chat(prompt: str) -> str:
|
7 |
+
try:
|
8 |
+
response = llm.create_chat_completion(
|
9 |
+
messages=[{"role": "user", "content": prompt}],
|
10 |
+
temperature=0.7
|
11 |
+
)
|
12 |
+
return response["choices"][0]["message"]["content"]
|
13 |
+
except Exception as e:
|
14 |
+
return f"⚠️ TinyLlama failed: {str(e)}"
|
requirements.txt
ADDED
@@ -0,0 +1,10 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
streamlit
|
2 |
+
pandas
|
3 |
+
neuralprophet
|
4 |
+
sentence-transformers
|
5 |
+
chromadb
|
6 |
+
httpx
|
7 |
+
python-dotenv
|
8 |
+
transformers
|
9 |
+
torch
|
10 |
+
llama-cpp-python
|
space.yaml
ADDED
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
sdk: streamlit
|
2 |
+
app_file: ui/streamlit_app.py
|
3 |
+
python_version: 3.10
|
4 |
+
pinned: false
|
5 |
+
license: apache-2.0
|
6 |
+
title: FinSightX - Financial Agent Suite
|
7 |
+
emoji: 📊
|
8 |
+
colorFrom: blue
|
9 |
+
colorTo: green
|
tools/autorag_tool.py
ADDED
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from embeddings.embedder import get_embedding
|
2 |
+
from embeddings.vector_store import query
|
3 |
+
|
4 |
+
def query_equity_kb(text: str) -> str:
|
5 |
+
results = query(text, get_embedding)
|
6 |
+
return "\n".join(results["documents"][0]) if results and results["documents"] else "No relevant documents found."
|
tools/forecast_tool.py
ADDED
@@ -0,0 +1,16 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from neuralprophet import NeuralProphet
|
2 |
+
import pandas as pd
|
3 |
+
|
4 |
+
model = NeuralProphet()
|
5 |
+
|
6 |
+
def forecast(
|
7 |
+
df: pd.DataFrame,
|
8 |
+
time_col: str = "ds",
|
9 |
+
value_col: str = "y",
|
10 |
+
periods: int = 30
|
11 |
+
) -> pd.DataFrame:
|
12 |
+
df = df.rename(columns={time_col: "ds", value_col: "y"})
|
13 |
+
model.fit(df, freq="D")
|
14 |
+
future = model.make_future_dataframe(df, periods=periods)
|
15 |
+
forecast_df = model.predict(future)
|
16 |
+
return forecast_df[["ds", "yhat1"]]
|
tools/sentiment_tool.py
ADDED
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from transformers import pipeline
|
2 |
+
|
3 |
+
sentiment_pipe = pipeline("sentiment-analysis", model="ProsusAI/finbert")
|
4 |
+
|
5 |
+
def analyze_sentiment(text: str) -> str:
|
6 |
+
result = sentiment_pipe(text)
|
7 |
+
return result[0]["label"] if result else "NEUTRAL"
|
ui/streamlit_app.py
ADDED
@@ -0,0 +1,192 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import sys
|
2 |
+
import os
|
3 |
+
import streamlit as st
|
4 |
+
import pandas as pd
|
5 |
+
|
6 |
+
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), "..")))
|
7 |
+
|
8 |
+
from agents.equity_analyst import answer_equity_question
|
9 |
+
from agents.news_summarizer import summarize_market_news
|
10 |
+
from agents.macro_strategist import analyze_macro_trends
|
11 |
+
from agents.quant_backtester import run_simple_backtest
|
12 |
+
from agents.regu_radar import monitor_regulatory_changes
|
13 |
+
from agents.client_advisor import advise_client
|
14 |
+
|
15 |
+
# --- UI Setup ---
|
16 |
+
st.set_page_config(page_title="FinSightX", layout="wide")
|
17 |
+
|
18 |
+
st.title("📊 FinSightX: AI-Powered Financial Agent Suite")
|
19 |
+
|
20 |
+
# Sidebar
|
21 |
+
agent = st.sidebar.selectbox(
|
22 |
+
"Choose Agent",
|
23 |
+
[
|
24 |
+
"🏠 Home",
|
25 |
+
"Equity Analyst",
|
26 |
+
"News Summarizer",
|
27 |
+
"Macro Strategist",
|
28 |
+
"Quant Backtester",
|
29 |
+
"ReguRadar",
|
30 |
+
"Client Advisor"
|
31 |
+
]
|
32 |
+
)
|
33 |
+
|
34 |
+
# --- Agent Routing ---
|
35 |
+
|
36 |
+
if agent == "🏠 Home":
|
37 |
+
st.header("A Multi-Agent Financial Intelligence Assistant")
|
38 |
+
st.markdown("""
|
39 |
+
A **modular industry-grade application** where agents collaborate to handle:
|
40 |
+
|
41 |
+
- **Equity Research**
|
42 |
+
- **News Summarization**
|
43 |
+
- **Macroeconomic Analysis**
|
44 |
+
- **Quantitative Backtesting**
|
45 |
+
- **Regulatory Updates**
|
46 |
+
- **Client Portfolio Q&A**
|
47 |
+
""")
|
48 |
+
|
49 |
+
elif agent == "Equity Analyst":
|
50 |
+
st.subheader("🔍 Equity Analyst")
|
51 |
+
st.markdown("""
|
52 |
+
### Role:
|
53 |
+
Analyzes individual stocks or companies using:
|
54 |
+
- Financial filings (e.g., 10-K, 10-Q)
|
55 |
+
- Earnings call summaries
|
56 |
+
- Market sentiment
|
57 |
+
|
58 |
+
### Capabilities:
|
59 |
+
- Retrieve documents from a knowledge base using **AutoRAG**
|
60 |
+
- Run sentiment analysis (FinBERT)
|
61 |
+
- Generate insight using LLM (Groq Mistral)
|
62 |
+
- Summarize risks, opportunities, and outlook
|
63 |
+
|
64 |
+
### Example Use Cases:
|
65 |
+
- "What’s the market sentiment around Tesla this quarter?"
|
66 |
+
- "Give me an analysis of Apple’s earnings call."
|
67 |
+
""")
|
68 |
+
query = st.text_input("Enter your financial query about a stock or company:")
|
69 |
+
if st.button("Analyze"):
|
70 |
+
with st.spinner("Analyzing equity..."):
|
71 |
+
response = answer_equity_question(query)
|
72 |
+
st.markdown(response)
|
73 |
+
|
74 |
+
elif agent == "News Summarizer":
|
75 |
+
st.subheader("📰 News Summarizer")
|
76 |
+
st.markdown("""
|
77 |
+
### Role:
|
78 |
+
Digest and summarize **real-time or bulk market news** to extract insights and relevance.
|
79 |
+
|
80 |
+
### Capabilities:
|
81 |
+
- Accept raw headlines or long-form articles
|
82 |
+
- Retrieve context (e.g., related documents or sectors)
|
83 |
+
- Summarize using LLM (via Groq or fallback)
|
84 |
+
|
85 |
+
### Use Cases:
|
86 |
+
- "Summarize today’s financial news relevant to energy stocks."
|
87 |
+
- "Give me a brief on Nvidia's latest product announcement."
|
88 |
+
""")
|
89 |
+
news = st.text_area("Paste financial news or headlines:")
|
90 |
+
if st.button("Summarize News"):
|
91 |
+
with st.spinner("Summarizing..."):
|
92 |
+
summary = summarize_market_news(news)
|
93 |
+
st.markdown(summary)
|
94 |
+
|
95 |
+
elif agent == "Macro Strategist":
|
96 |
+
st.subheader("📉 Macro Trend Forecaster")
|
97 |
+
st.markdown("""
|
98 |
+
### Role:
|
99 |
+
Analyzes **macroeconomic indicators** and helps in trend forecasting.
|
100 |
+
|
101 |
+
### Capabilities:
|
102 |
+
- Forecasts economic time series (CPI, GDP, unemployment) using `neuralprophet`
|
103 |
+
- Returns structured future outlooks
|
104 |
+
- Used in multi-agent reasoning for “market climate”
|
105 |
+
|
106 |
+
### Use Cases:
|
107 |
+
- "Forecast US inflation for the next 3 months."
|
108 |
+
- "What does the GDP trend look like post-2023?"
|
109 |
+
""")
|
110 |
+
st.markdown("Upload a time series CSV with columns `ds` (date) and `y` (value).")
|
111 |
+
uploaded_file = st.file_uploader("Upload CSV", type=["csv"])
|
112 |
+
if uploaded_file:
|
113 |
+
df = pd.read_csv(uploaded_file)
|
114 |
+
if st.button("Forecast"):
|
115 |
+
with st.spinner("Forecasting..."):
|
116 |
+
forecast_result = analyze_macro_trends(df)
|
117 |
+
st.write("📈 Forecasted Value:")
|
118 |
+
st.json(forecast_result)
|
119 |
+
|
120 |
+
elif agent == "Quant Backtester":
|
121 |
+
st.subheader("💹 Quant Strategy Backtester")
|
122 |
+
st.markdown("""
|
123 |
+
### Role:
|
124 |
+
Tests trading strategies on historical price data.
|
125 |
+
|
126 |
+
### Capabilities:
|
127 |
+
- Define and run strategies using `bt` or `vectorbt`
|
128 |
+
- Simple moving average crossovers, rebalancing, etc.
|
129 |
+
- Return backtest performance metrics
|
130 |
+
|
131 |
+
### Use Cases:
|
132 |
+
- "Backtest an SMA crossover on AAPL from 2020 to 2023."
|
133 |
+
- "Run a balanced ETF strategy on SPY, QQQ, and VTI."
|
134 |
+
|
135 |
+
> This agent focuses on backtesting, not execution or portfolio construction (those can be added later).
|
136 |
+
""")
|
137 |
+
tickers = st.text_input("Enter tickers (comma-separated)", value="AAPL,MSFT")
|
138 |
+
sma_short = st.number_input("Short SMA", value=20)
|
139 |
+
sma_long = st.number_input("Long SMA", value=50)
|
140 |
+
if st.button("Run Backtest"):
|
141 |
+
with st.spinner("Backtesting strategy..."):
|
142 |
+
result = run_simple_backtest(
|
143 |
+
tickers=[t.strip() for t in tickers.split(",")],
|
144 |
+
sma_short=sma_short,
|
145 |
+
sma_long=sma_long
|
146 |
+
)
|
147 |
+
st.write("✅ Backtest completed. Check your terminal/logs for output.")
|
148 |
+
st.markdown("Note: Visual performance plots not yet integrated in Streamlit.")
|
149 |
+
|
150 |
+
elif agent == "ReguRadar":
|
151 |
+
st.subheader("📜 ReguRadar – Regulatory Monitor")
|
152 |
+
st.markdown("""
|
153 |
+
### Role:
|
154 |
+
Monitors and interprets **regulatory updates** that may affect sectors, firms, or compliance requirements.
|
155 |
+
|
156 |
+
### Capabilities:
|
157 |
+
- AutoRAG over legal and regulatory filings (e.g., RBI circulars, SEC rules)
|
158 |
+
- LLM summarization to extract impact
|
159 |
+
- Optional: track historical regulatory shifts
|
160 |
+
|
161 |
+
### Use Cases:
|
162 |
+
- "Has the RBI changed anything that affects crypto investors?"
|
163 |
+
- "Summarize the SEC’s latest ESG compliance memo."
|
164 |
+
""")
|
165 |
+
reg_query = st.text_area("Paste a regulatory update or query:")
|
166 |
+
if st.button("Analyze Regulation"):
|
167 |
+
with st.spinner("Scanning for relevance..."):
|
168 |
+
reg_response = monitor_regulatory_changes(reg_query)
|
169 |
+
st.markdown(reg_response)
|
170 |
+
|
171 |
+
elif agent == "Client Advisor":
|
172 |
+
st.subheader("🧑💼 Client Advisor")
|
173 |
+
st.markdown("""
|
174 |
+
### Role:
|
175 |
+
Acts as a **virtual financial advisor**, helping individual users based on their queries and emotional tone.
|
176 |
+
|
177 |
+
### Capabilities:
|
178 |
+
- Understand user intent + emotion using FinBERT
|
179 |
+
- Generate personalized advice using Groq LLM
|
180 |
+
- Can be expanded into user profile tracking (e.g., risk appetite, goals)
|
181 |
+
|
182 |
+
### Use Cases:
|
183 |
+
- "Should I invest in tech during a recession? I’m scared of losing money."
|
184 |
+
- "I’ve retired and need a low-risk investment plan."
|
185 |
+
|
186 |
+
> In the future, this can evolve into a memory-based portfolio coach.
|
187 |
+
""")
|
188 |
+
user_msg = st.text_area("What does your client say?")
|
189 |
+
if st.button("Advise"):
|
190 |
+
with st.spinner("Analyzing sentiment and crafting advice..."):
|
191 |
+
advice = advise_client(user_msg)
|
192 |
+
st.markdown(advice)
|