┌──────────────────────────┐
user types ──▶ │ React + Vite frontend │
"AAPL" │ (Tailwind v4 · TS) │
└──────────────┬───────────┘
│ REST + SSE + WebSocket
┌──────────────▼───────────┐
│ FastAPI (Python 3.11) │
│ argus.main:app │
└──┬──────────┬────────────┘
│ │
┌────────────┘ └───────────────┐
▼ ▼
┌────────────────────┐ ┌──────────────────────────┐
│ market.adapters │ │ agents.committee │
│ US (yfinance) │ ── feeds ──▶ │ Technical · Fundamental │
│ CN (akshare) │ context │ Sentiment · Macro · Risk│
│ HK (akshare/yf) │ │ + CIO orchestrator │
└────────────────────┘ └──────────┬───────────────┘
│ uses
┌──────────────▼─────────────┐
│ agents.llm │
│ Anthropic / OpenAI / │
│ DeepSeek / Qwen / Ollama │
└────────────────────────────┘
| Path | Purpose |
|---|---|
argus/main.py |
FastAPI app, lifespan, route registration, static frontend |
argus/config.py |
Settings (pydantic-settings) loaded from .env |
argus/markets/base.py |
MarketAdapter ABC + Quote / Candle / Fundamentals |
argus/markets/{us,cn,hk}.py |
Per-market implementations |
argus/markets/registry.py |
Symbol-→-market detection, fanned-out search |
argus/analysis/indicators.py |
RSI/MACD/BBands/KDJ/ATR/OBV — pandas only, no ta-lib |
argus/analysis/screener.py |
Cross-market screener with criteria / presets |
argus/agents/llm.py |
LLM provider abstraction (streaming-only interface) |
argus/agents/committee.py |
Six analyst personas + CIO synthesis, async event stream |
argus/analysis/flow.py |
Smart-money flow aggregator (insider / SI / 北向 / 龙虎榜 / 融资) |
argus/storage/db.py |
SQLite (SQLModel) — watchlist + alert rules |
argus/routes/*.py |
REST + SSE + WS endpoints |
frontend/src/pages/* |
Dashboard · Stock · Screener · Watchlist · Settings |
frontend/src/components/committee/* |
The visual showpiece — agent cards + verdict card |
- UI calls
GET /api/committee/stream/{symbol}(Server-Sent Events). - Backend builds a context bundle (
gather_context):quote+fundamentalsfrom the matching market adapter- 2-year daily history → indicators (RSI, MACD, BB, KDJ, ATR, OBV)
- top 5-8 recent headlines
- Six analyst agents run concurrently (capped at
argus_committee_concurrency, default 3, so free LLM tiers don't drop streams):Technical— reads indicator valuesFundamental— reads valuation + business summarySentiment— reads headlines + recent price ladderMacro— places ticker in current macro regimeRisk— quantifies vol/beta/drawdown, sizes positionFlow— reads insider trades, short interest, 北向资金, 龙虎榜, 融资余额 — what smart money is doing
- The CIO receives every analyst's full text and is asked for strict JSON:
{ "action": "BUY", "conviction": 4, "horizon": "1-3M", "thesis": "...", "key_risks": ["...","..."], "entry_zone": "...", "stop_zone": "..." } - SSE emits
agent_start→agent_token*→agent_donefor each, ending with averdictevent.
SSE is a perfect fit for one-way token streaming, supports reconnection out of the
box, and is trivial to consume in the browser via EventSource. WebSocket is reserved
for the bi-directional quote-subscribe channel.
- Subclass
MarketAdapterinargus/markets/<m>.py. - Register in
argus/markets/registry._ADAPTERS. - (Optional) extend
detect_market()heuristics.
- Add a persona entry to
agents.committee.AGENT_PERSONAS. - Extend
_build_user_prompt()for that role. - Add the role to the loop in
InvestmentCommittee.stream(). - Add a
ROLE_THEMEentry infrontend/src/components/committee/AgentCard.tsx.