This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
# Install dependencies
pip install -e ".[dev]"
# Run all tests
pytest tests/ -v
# Run a single test file
pytest tests/test_llm.py -v
# NOTE: .python-version pins 3.9 (often not installed locally). The suite is
# verified under Python 3.13 — if `pytest` can't find an interpreter, run it
# explicitly, e.g. `python3.13 -m pytest tests/ -v`. Tests are fully offline
# (network/SDK/selenium boundaries are mocked); no API keys required.
# Generate analysis locally
python scripts/generate_analysis.py AAPL --analysis-type fundamental-analysis --provider claude
python scripts/generate_analysis.py MSFT --analysis-type technical-analysis --provider openai
# Build and preview docs site
python3 scripts/build_docs.py && mkdocs serve
# Trigger GitHub Actions workflow via CLI
gh workflow run daily_analysis.yml -f ticker=MSFT -f analysis_type=technical-analysis
# Trigger analysis via Makefile (fires GitHub Actions workflows)
make analyze TICKERS="NVDA TSLA" TYPES="fundamental-analysis,technical-analysis"
make analyze-mag7
make deep-dive TICKERS="NVDA"The codebase generates AI-powered investment research reports and publishes them via MkDocs to GitHub Pages. Full architecture is in docs/ARCHITECTURE.md.
scripts/generate_analysis.py
→ scripts/analysis/utils/data_fetch.py (yfinance + web scrapers → OHLCV, financials)
→ scripts/analysis/utils/context.py (assembles data into LLM-ready context, 12 branches)
→ scripts/analysis/prompts/*.txt (prompt templates, one per analysis type)
→ scripts/analysis/utils/llm.py (Claude or OpenAI API call)
→ ai_gen_report/fundamental/<ticker>/<type>_<date>.md (fundamental-analysis)
→ ai_gen_report/technical/<ticker>/<type>_<date>.md (technical-analysis, + chart PNGs)
→ ai_gen_report/stock/<ticker>/<type>_<date>.md (all other analysis types)
scripts/build_docs.py then mirrors ai_gen_report/ into docs/ and docs/zh/ so MkDocs can serve them.
scripts/analysis/config/__init__.py—ANALYSIS_TYPESdict (12 types), model/token defaultsscripts/analysis/config/providers.py— per-provider defaults (Claude: 8k tokens, OpenAI: 16k) plusFALLBACK_CHAIN+resolve_chain(): the ordered provider pool the generators try (currently gemini → openai; edit the list to add levels)scripts/analysis/utils/llm.py—run_with_fallback()runs an ordered(provider, model)chain, returning the first success; context is fetched once and reused across fallback attemptsscripts/analysis/utils/context.py— 12-branch context assembler; touch when adding analysis typesscripts/analysis/utils/llm.py—call_llm()dispatcher; handles rate-limit retries and refusal overridesscripts/analysis/data/prices.py— the committed OHLCV store (data/prices/<key>.csv); pure-stdlib read pathscripts/analysis/data/price_analytics.py— pure-stdlib statistics derived from the store (returns, drawdown, rolling volatility, return histogram, monthly grid); powers the Price Data section (docs/prices/). All chart maths lives here, never in JS — seedocs/PRICE_STORE_DESIGN.md§12scripts/.ticker_schedule.json— data-driven ticker list for daily CI jobs.github/workflows/daily_analysis.yml— cron that fires 42 jobs/day (21 tickers × 2 types)
- Add entry to
ANALYSIS_TYPESinscripts/analysis/config/__init__.py - Create prompt at
scripts/analysis/prompts/<type>.txt(placeholders:{ticker},{financial_context},{today}) - Add context-building branch in
scripts/analysis/utils/context.py - Test:
python scripts/generate_analysis.py AAPL --analysis-type <type>
- Edit
scripts/.ticker_schedule.json - Add cron entries in
.github/workflows/daily_analysis.yml
- Reports written as Markdown to
ai_gen_report/fundamental/<ticker>/,ai_gen_report/technical/<ticker>/, orai_gen_report/stock/<ticker>/depending on analysis type (see Core flow above) build_docs.pymerges all three per ticker and copies them intodocs/reports/<ticker>/anddocs/zh/reports/<ticker>/build_docs.pyalso publishesdata/prices/asdocs/prices/— an overview table plus a page per ticker (candles, drawdown, volatility, return distribution, monthly heatmap) with CSV / JSON / ZIP downloadsdocs/is auto-generated — edit source files inai_gen_report/andscripts/, not indocs/scripts/maintain_ai_gen_report.pyhandles re-splitting (reorg) and pruning old dated reports (prune --before YYYY-MM-DD)
.github/workflows/qa_report_quality.ymlruns nightly at 02:00 UTC:check_report_quality.py→qa/bad_reports_<date>.csv+qa/summary_<date>.txt, thencheck_mermaid.py, then regeneratesqa/README.mdscripts/prune_qa.py --keep 10keeps only the 10 most recent run dates inqa/; the workflow runs it before committing