Skip to content

Latest commit

 

History

64 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Bull vs Bear — an agent-debate system for pre-earnings stock analysis

Multi-agent LLM system that, for every stock with an upcoming earnings report, builds the strongest bull case and bear case in parallel, then runs a synthesis agent that debates them into a single actionable outlook. Delivered as a daily digest and a dashboard.

Built as a personal exploration of multi-agent architectures — specifically the debate-then-synthesize pattern — grounded in real financial data (Finnhub, FRED, SEC EDGAR, yfinance) and using Gemini as the reasoning backbone.

See it work

The dashboard ranks upcoming earnings by conviction score, then surfaces the full bull-vs-bear breakdown per stock. The same agents produce different verdicts depending on what the data actually says — that's the point.

Intelligence Feed
Intelligence Feed — upcoming earnings ranked by conviction score
AMZN — Bullish Watch
AMZN → BULLISH WATCH (conviction 8.5) — bull agent wins on operating leverage + AWS thesis
WDFC — High Risk Avoid
WDFC → HIGH RISK AVOID (value trap) — bear agent wins on premium-to-TBV + declining fundamentals

Delivered as a daily digest

The batch job emails the top-N ranked stocks every morning so the analysis is where you already read the news, not on yet another dashboard tab.

Daily digest email

Architecture

                       ┌─────────────────────────┐
                       │  Finnhub · earnings cal │
                       │  FRED · macro context   │
                       │  SEC EDGAR · 10-K/10-Q  │
                       │  yfinance · fundamentals│
                       └───────────┬─────────────┘
                                   │
                                   ▼
                       ┌─────────────────────────┐
                       │   analytics_pipeline    │
                       │  (Go, batch/scheduled)  │
                       └───────────┬─────────────┘
                                   │
                    ┌──────────────┼──────────────┐
                    ▼              ▼              ▼
              ┌──────────┐   ┌──────────┐   ┌────────────┐
              │  Bull    │   │  Bear    │   │ Industry   │
              │  agent   │   │  agent   │   │ playbooks  │
              └────┬─────┘   └────┬─────┘   └─────┬──────┘
                   └───────┬──────┴───────────────┘
                           ▼
                   ┌───────────────┐
                   │  Synthesis    │      → email digest
                   │  agent        │      → dashboard
                   └───────────────┘
  • Bull agent — role-prompted as a growth-fund manager building the "hidden upside" thesis.
  • Bear agent — role-prompted as a short-seller stress-testing the consensus.
  • Synthesis agent — receives both cases + industry rule playbooks, produces the final actionable outlook.
  • Industry playbooks — hand-tuned prompt templates (bull, bear, synthesis) per sector so the agents ground their reasoning in industry-specific dynamics.

Tech stack

  • Backend: Go 1.25 · sqlc-generated SQL · Chi/net-http services · Docker
  • Data: Python 3.13 (yfinance + edgar for SEC filings) piped into Go — chose Python only for the two library ecosystems (yfinance and edgar-crawler) that don't have solid Go equivalents
  • LLM: Gemini (via google.golang.org/genai), configurable model
  • Data providers: Finnhub (earnings calendar), FRED (macro), SEC EDGAR (filings), yfinance (fundamentals + news)
  • Frontend: React + TypeScript + Vite dashboard
  • Auth: Google OAuth + JWT cookies
  • Infra: Cloud Run + Cloud Build + Artifact Registry + Secret Manager
  • Tests: go test with HTTP mocks + go-vcr-style cassettes for e2e coverage

Running locally

Requires: Go 1.25+, Python 3.13+, Docker, and API keys for Finnhub, FRED, and Gemini.

# 1. Copy the env template and fill in your keys
cp .env.example .env
# edit .env with FINNHUB_API_KEY, GEMINI_API_KEY, FRED_API_KEY, DATABASE_URL

# 2. Install Python deps
pip install -r requirements.txt

# 3. Run the analytics batch job (dry-run over the next day of earnings)
go run ./batch_jobs/pre_earnings_analysis/main --earning-outlook-num-days=1 --gemini-model=gemini-2.5-flash

# 4. Run the dashboard backend
go run ./services/pre_earnings_dashboard

# 5. Run the frontend
cd frontend/pre-earnings-dashboard
npm install && npm run dev

Or bring the whole stack up in Docker:

docker compose up --build

Deploying (Cloud Run)

cloudbuild.yaml is provided as a template. Set the substitutions to your own values:

  • _PROJECT_ID — your GCP project
  • _LOCATION — your preferred region
  • URLs for _FRONTEND_URL, _BACKEND_URL, _USER_MGMT_URL
  • All secrets should live in Secret Manager (never committed): FINNHUB_API_KEY, GEMINI_API_KEY, FRED_API_KEY, DATABASE_URL, JWT_SECRET, GOOGLE_OAUTH_CLIENT_ID, GOOGLE_OAUTH_CLIENT_SECRET, EMAIL_PASSWORD

Notes on design choices

  • Why debate-then-synthesize? A single-prompt "give me a stock analysis" agent tends to be milquetoast — bland, hedged, unhelpful. Forcing two agents to build the strongest opposing cases first, then reconciling, produces sharper reasoning.
  • Why hand-tuned industry playbooks? LLMs are okay at generic financial reasoning but often miss sector-specific dynamics (e.g., what "growth" means for a REIT vs. a semiconductor). The playbooks are prompt scaffolding that pins the agents to sector-appropriate frameworks.
  • Why Go for the pipeline? Concurrency for fan-out over the earnings calendar, and single-binary deploy. LLM latency dominates the wall-clock time, so goroutines pay off.

Status

Personal side project — actively iterated on. Not investment advice.

License

MIT — see LICENSE.

About

Multi-agent LLM system that debates bull vs bear cases on upcoming earnings and synthesizes a verdict. Gemini + Go + React.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages