Skip to content

About

A multi-agent conversational financial analytics platform that combines company fundamentals analysis, SEC filing intelligence, and machine learning-based stock price prediction through an intuitive chat interface.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Repository files navigation

Quantitative AI Agent

A multi-agent conversational financial analytics platform that combines company fundamentals analysis, SEC filing intelligence, and machine learning-based stock price prediction through an intuitive chat interface.

This project applies architectural principles from knowledge graphs and AI agents, adapting them from healthcare to finance and market analysis. The core idea demonstrates how a combination of graph databases, RAG (Retrieval-Augmented Generation), and predictive models can create powerful, domain-specific AI assistants. Data content was shrinked to comply with submission requirements.

Background Articles

This project builds on concepts from several technical articles of mine:

What This System Does

The Financial AI Assistant empowers investors, analysts, and researchers to analyze market data through natural language queries. Instead of writing complex database queries or manually sifting through lengthy SEC filings, users can simply ask questions like:

  • "What was the revenue for Apple in 2023?"
  • "Summarize the key risks mentioned in NVIDIA's latest 10-K filing?"

This natural language interface activates tools in the backend agent system to provide comprehensive answers.

Core Capabilities

The system provides three main capabilities via its agent tools:

  1. Corporate Financial Analysis: Query company fundamentals, financials, and key metrics from structured data
  2. SEC Filing Intelligence: Perform semantic search and summarization on the full text of annual 10-K reports to extract qualitative insights
  3. Predictive Analytics: Generate next-day price estimates for individual stocks using per-ticker LightGBM models. See Prediction model quality below — the models are measurably worse than assuming no change, and are included to demonstrate ML integration, not to forecast markets.

Technical Architecture

System Overview

The Financial AI Assistant uses a sophisticated multi-layered architecture:

  1. Frontend Layer: Clean web interface with HTML, CSS, and JavaScript chat interface
  2. API Layer: FastAPI server handling request validation and response formatting
  3. Agent Orchestration: Root/Sub-Agent architecture using Google's ADK (Agent Development Kit)
  4. Data Storage: Multi-modal Neo4j database serving as both graph and vector database
  5. External AI Services: Google Vertex AI for language understanding and embeddings

Agent Architecture

The system employs a Root/Sub-Agent pattern:

  • Root Agent: Acts as the "lead analyst," analyzing questions and delegating to appropriate specialists
  • Sub-Agents: Function as "specialist analysts" with specific tools:
    • Graph QA Agent: Generates Cypher queries for statistical questions about company financials
    • Document RAG Agent: Performs semantic search through SEC filings
    • Stock Predictor Agent: Runs ML models for next-day price predictions

Data Flow

  1. Query Analysis: Root Agent analyzes user intent
  2. Tool Selection: Appropriate sub-agent selected based on query type
  3. Data Retrieval: Sub-agent executes its tool (Cypher query, embedding search, or ML prediction)
  4. Response Synthesis: LLM processes results into natural language
  5. Delivery: Final answer sent through API to web interface

Technical Challenges & Solutions

Data Ingestion

  • Historical data pulled using yfinance library
  • SEC 10-K reports fetched from EDGAR database in complex iXBRL format

Handling "Noise"

  • SEC filings contain extensive boilerplate legal jargon
  • RAG pipeline uses UnstructuredHTMLLoader to extract core textual content

Prediction Modeling

  • Stock prediction demonstrates ML integration (not financial advice)
  • Per-ticker LightGBM model over historical price/volume
  • The target is the next-day return, not the next-day price level. A tree ensemble can only output values it saw in training, so a level target cannot extrapolate on a trending series — measured on held-out data, the original level-target version was worse than a naive "tomorrow equals today" baseline for all 22 tickers (median 2.1x the error, worst case 9.8x). Predicting a scale-free return narrows that to ~1.11x.
  • It still does not beat the naive baseline. See Prediction model quality.
  • Does not account for market sentiment, news, or macroeconomic factors

Cost Optimization

  • Cloud deployment scales to zero to minimize idle costs

Project Structure

financial-assistant/
├── app/
│   ├── agents/
│   │   └── agents.py
│   ├── graph_db/
│   │   └── connection.py
│   ├── models/
│   │   ├── predict.py
│   │   ├── train_predictor.py
│   │   └── saved_models/        <- .joblib models + metrics.json
│   ├── templates/
│   │   └── index.html
│   └── main.py
├── data/
│   ├── structured/
│   │   ├── financials/
│   │   └── prices/
│   └── unstructured/
│       └── 10k/
├── fetch_data.py
├── populate_graph.py
├── companies.csv
├── .env                 (gitignored; create from .env.example)
├── .env.example
├── Dockerfile
├── README.md
└── requirements.txt

Quick Start

Prerequisites

  • Google Cloud Platform account with Vertex AI enabled
  • Neo4j database instance (Neo4j AuraDB Free Tier recommended)
  • Python 3.11 or higher
  • Docker (for deployment)

Environment Setup

  1. Create the virtual environment:
python3 -m venv venv
source venv/bin/activate
pip install -r requirements.txt
  1. Configure environment variables by creating a .env file from .env-example:
GOOGLE_PROJECT_ID="your-gcp-project-id"
GOOGLE_LOCATION="us-central1"
NEO4J_URI="neo4j+s://your-instance.databases.neo4j.io"
NEO4J_USERNAME="neo4j"
NEO4J_PASSWORD="your-password"
SEC_USER_AGENT="Your Name your.email@provider.com"
  1. Run the complete data pipeline:
# Step 1: Create the list of target companies
python3 create_companies.py

# Step 2: Download all raw data from APIs (this will take a while)
python3 fetch_data.py

# Step 3: Populate the Neo4j database (Graph + Embeddings)
python3 app/graph_db/2_populate_graph.py

# Step 4: Train the predictive models (one for each stock)
python3 app/models/train_predictor.py
  1. Start the development server:
uvicorn app.main:app --reload --port 8080
  1. Open your browser to http://127.0.0.1:8080 and start asking questions.

Example Queries

Company Fundamentals (Graph QA)

  • "How many companies are in the technology sector?"
  • "What was the net income for MSFT in 2023?"
  • "List the major events for TSLA in their 2024 filing."

SEC Filing Insights (Document RAG)

  • "What did Google say about their AI strategy in the last 10-K?"
  • "Summarize Amazon's management outlook from their 2024 filing."
  • "What are the common concerns about supply chain disruptions?"

Predictive Analytics (Prediction Tool)

  • "Predict the next closing price for AAPL."
  • "What is the stock price prediction for NVDA tomorrow?"

Screenshots of the Neo4j Graph Database

A screenshot showing text in Neo4j

A general screenshot of Neo4j

Deployment

Google Cloud Run

The system is containerized for easy deployment to Google Cloud Run.

gcloud auth login
gcloud config set project YOUR-PROJECT

gcloud artifacts repositories create financial-assistant-repo \
    --repository-format=docker \
    --location=us-central1 \
    --description="Docker repository for financial assistant service"

gcloud builds submit --tag us-central1-docker.pkg.dev/YOUR-PROJECT/financial-assistant-repo/assistant-service:latest

gcloud run deploy financial-assistant-service \
    --image=us-central1-docker.pkg.dev/YOUR-PROJECT/financial-assistant-repo/assistant-service:latest \
    --platform=managed \
    --region=us-central1 \
    --allow-unauthenticated \
    --set-env-vars-from-file=.env \
    --min-instances 0 \
    --max-instances 3 \
    --cpu 4 \
    --memory 8192Mi \
    --concurrency 10

The frontend calls /chat relatively and is served by the same app, so no post-deployment edit is needed.

--allow-unauthenticated makes the service public. /chat has no application-level authentication or rate limit, and each request costs Vertex AI tokens. For anything beyond a demo, deploy with --no-allow-unauthenticated and grant roles/run.invoker to the identities that should reach it.

--set-env-vars-from-file=.env puts the Neo4j password in the service's configuration, where it shows up in gcloud run services describe. Prefer Secret Manager: --set-secrets=NEO4J_PASSWORD=neo4j-password:latest.

Prediction model quality

python -m app.models.train_predictor writes app/models/saved_models/metrics.json, holding out the last 20% of each price series in time order and comparing against the naive baseline "tomorrow's close equals today's close":

Metric Meaning
mae Mean absolute error of the model on held-out days
naive_lag1_mae Same error for "assume no change"
mae_vs_naive_ratio mae / naive_lag1_mae. Above 1.0 means the model is less accurate than assuming no change.
beats_naive_baseline true only if the model is genuinely better
direction_accuracy Fraction of days the sign of the predicted move was right

Current result across the 22 tickers with price history: 0 of 22 beat the baseline, median ratio ≈ 1.11x. This is the expected outcome — next-day price movement is close to unpredictable from price and volume history alone — and it is reported rather than hidden. Every prediction response carries a model_quality string stating its own ratio, plus a disclaimer.

If you extend this, the honest bar to clear is mae_vs_naive_ratio < 1.0.


Data coverage

The README notes the dataset was reduced for submission. Concretely:

Layer Coverage
Company profiles (companies.csv) 402 tickers
Financials (JSON) 401 tickers
Price history (CSV) 22 tickers (AAL through AMGN)
SEC 10-K filings (HTML) 2 companies — AAPL and ABBV, 5 years each

The agent instructions used to advertise a hardcoded {NVDA, MSFT, AAPL, GOOGL, AMZN}. Of those, only AAPL has price history here and none had a trained model, so every prediction request was accepted and then failed. The prediction tool now derives its ticker list from what is actually on disk. Note that DocumentRAG can only answer about AAPL and ABBV, since those are the only filings present.


Running the tests

pip install pytest pytest-asyncio
pytest -q

73 tests, no network access and no GCP credentials required — tests/conftest.py mocks the ADK, Vertex AI and Neo4j modules before importing the app. tests/test_regressions.py covers the defects found in the code audit.


Known limitations

  • Sessions are in-memory. InMemorySessionService means conversation history is lost on restart and is not shared across Cloud Run instances. A client that passes a stable session_id will still get a fresh session after a cold start.
  • Generated Cypher is constrained to reads. assert_read_only() in app/agents/agents.py rejects any generated statement containing a write clause before it reaches the database. For defence in depth, also connect with a Neo4j user that has no write privileges.
  • Re-running populate_graph.py wipes the graph. It begins with a batched DETACH DELETE of every node, with no confirmation prompt.
  • Entity extraction reads only the first 20,000 characters of each filing, and embeds the first 80,000 — so questions about later sections of a 10-K (often including much of the risk discussion) have no supporting context.

Key Design Decisions

Why Neo4j for Financial Data?

Financial information is inherently interconnected. Companies operate in sectors, have competitors, file reports, and are affected by market events. A graph database makes exploring these complex relationships natural and efficient.

Root/Sub-Agent Architecture

Using Google's ADK, the separation between a root agent (orchestrator) and specialist sub-agents creates a clean division of responsibilities, making the system modular and easier to extend with new tools.

Hybrid Search Strategy

Different financial questions require different approaches. The system automatically selects the right tool: structured graph queries for quantitative facts (e.g., revenue) and semantic vector search for qualitative insights (e.g., management sentiment).

LLM-Powered Entity Extraction

SEC filings are dense and unstructured. Using an LLM to intelligently extract key entities like risks, events, and strategies is far more flexible and robust than building rigid parsers.

About

A multi-agent conversational financial analytics platform that combines company fundamentals analysis, SEC filing intelligence, and machine learning-based stock price prediction through an intuitive chat interface.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages