Stock sentiment analysis + RSI calculation platform. Fetches news and topics from Longbridge, analyzes them via multi-provider LLM, and computes sentiment-based RSI indicators to detect overbought/oversold conditions.
- Multi-provider LLM Support: OpenAI, Anthropic Claude, Ollama (local), OpenRouter, Alibaba DashScope, Zhipu BigModel — switch via single env var
- Batch Sentiment Analysis: Sends up to 40 items per LLM call with id-based result matching; missing results auto-retry individually
- RSI Calculation: Traditional Wilder's RSI applied to sentiment score changes, supporting News / Topics / Combined sources
- Configurable Signals: Adjustable period (default 14), overbought (70) and oversold (30) thresholds
- Scheduled Analysis: APScheduler-driven automatic runs (default 60 min), per-stock timeout (600s)
- Web Dashboard: React + TypeScript frontend with Vercel/Geist design system — real-time cards, RSI charts, source data drill-down
- CLI Tool: Check stocks, run analysis, manage watch list, view config
- Docker Compose: One-command deployment with PostgreSQL 17 backend
┌─────────────┐ ┌───────────────┐ ┌──────────────────┐ ┌──────────────┐
│ Longbridge │────▶│ Scheduler │────▶│ Sentiment │────▶│ RSI │
│ API │ │ (APScheduler) │ │ Analyzer (LLM) │ │ Engine │
└─────────────┘ └───────────────┘ └──────────────────┘ └──────┬───────┘
│
┌────────▼────────┐
│ PostgreSQL │
│ (asyncpg) │
└─────────────────┘
Frontend (React/Vite) ←── FastAPI Backend ←── Database Manager (SQLAlchemy async)
- Python 3.14+ (uv recommended)
- PostgreSQL 17+
- Node.js 18+ (for frontend dev)
# 1. Clone & install
git clone <repo> && cd horacersius
uv venv --python 3.14 && source .venv/bin/activate
uv pip install -e ".[dev]"
# 2. Configure environment
cp .env.example .env
# Edit .env: set LLM provider keys, Longbridge credentials, DATABASE__URL
# 3. Initialize database
horacersius db migrate
# 4. Install frontend dependencies
cd frontend && npm install && cd ..
# 5. Start backend (terminal 1)
horacersius serve --port 8000
# 6. Start frontend (terminal 2)
cd frontend && npm run devOpen http://localhost:5173 in your browser.
cp .env.example .env
# Edit .env with your API keys
docker compose up -d --buildThis starts PostgreSQL 17 + Horacersius backend on port 8000. The frontend can still be run separately with npm run dev for development.
All settings are managed through .env using SECTION__KEY naming convention:
# --- LLM Provider (choose one) ---
LLM__PROVIDER=openai # openai | anthropic | ollama | openrouter | dashscope | bigmodel
LLM__MODEL=gpt-4o-mini
LLM__OPENAI_API_KEY=sk-... # or ANTHROPIC_API_KEY, OLLAMA_BASE_URL, etc.
LLM__TEMPERATURE=0.3
LLM__MAX_TOKENS=0 # 0 = use LLM default
LLM__BATCH_SIZE=40 # Items per batch LLM call
# --- Longbridge API (required) ---
LONGBRIDGE__API_KEY=your_key
LONGBRIDGE__API_SECRET=your_secret
LONGBRIDGE__ACCESS_TOKEN=your_token
LONGBRIDGE__REGION=CN # CN | US | HK
# --- Database ---
DATABASE__URL=postgresql+asyncpg://user:password@localhost:5432/horacersius
# --- Watch List ---
STOCKS__WATCH_LIST=.SPX.US,TSLA.US,NVDA.US,META.US,MSFT.US,.IXIC.US
# --- Scheduler ---
SCHEDULER__ENABLED=true
SCHEDULER__INTERVAL_MINUTES=60
SCHEDULER__MAX_CONCURRENCY=2
# --- Logging ---
LOG_LEVEL=INFO
LOGGING__DIR=logsSee .env.example for all available options.
# Check sentiment + RSI for a stock
horacersius check AAPL.US
# Trigger immediate analysis for all watched stocks
horacersius scheduler --run-now
# Start background scheduler (runs every interval)
horacersius scheduler
# Start web API server
horacersius serve --port 8000
# Manage watch list
horacersius watch-list
# Run database migrations
horacersius db migrate
# View current configuration
horacersius config| Page | URL | Description |
|---|---|---|
| Dashboard | / |
Stock cards with RSI values, signals, price data |
| Stock Detail | /stock/:symbol |
News RSI, Topics RSI, combined signal, source item drill-down, RSI history chart |
| Settings | /settings |
Live configuration viewer (sensitive values masked by backend) |
| Method | Path | Description |
|---|---|---|
| GET | /api/stocks |
List watched symbols |
| GET | /api/sentiment/{symbol} |
Full sentiment + RSI data (news, topics, combined) |
| POST | /api/analysis/{symbol}/trigger |
Manually trigger LLM analysis |
| GET | /api/analysis/{symbol}/{source} |
Paginated source items (NEWS/TOPICS) with scores |
| GET | /api/settings |
Application configuration (masked) |
- Data Fetching — Scheduler calls Longbridge API for news articles and discussion topics per watched stock; price snapshots captured via
quote()API - Incremental Save — New items upserted into PostgreSQL (
ON CONFLICT DO UPDATEon(symbol, external_id)); duplicates deduped automatically - Sentiment Analysis — Unanalyzed items batched (configurable size) and sent to LLM with stock symbol context; each item carries its DB id so returned scores map correctly; if LLM omits any result, that item is retried singly
- RSI Calculation — Wilder's smoothing RSI computed from sequential sentiment score changes; three sources tracked independently (News RSI, Topics RSI) then merged as Combined RSI
- Visualization — Dashboard polls every 5 seconds (pauses when tab hidden); cards show RSI value, signal (overbought/oversold/neutral), and latest price
horacersius/
├── src/horacersius/
│ ├── api/routes/ # FastAPI route handlers (stocks, sentiment, settings, analysis)
│ ├── cli/main.py # Click CLI entry point
│ ├── config.py # Pydantic Settings (env-driven config)
│ ├── data/longbridge_client.py # Longbridge SDK wrapper
│ ├── db/
│ │ ├── manager.py # Async database operations (CRUD, upserts, queries)
│ │ └── models.py # SQLAlchemy ORM models
│ ├── logging_config.py # RotatingFileHandler setup
│ ├── scheduler/tasks.py # Core pipeline: fetch → save → analyze → RSI
│ └── sentiment/
│ ├── analyzer.py # Multi-provider LLM client with batch/retry logic
│ └── prompts.py # System prompts (single + batch modes)
├── frontend/
│ └── src/
│ ├── theme.ts # Vercel/Geist design tokens (colors, shadows, fonts)
│ ├── api/client.ts # API client with typed responses
│ ├── pages/ # Dashboard, StockDetail, Settings
│ └── components/ # RSIChart (Recharts line chart)
├── alembic/ # Database migrations
├── tests/ # pytest suite (asyncio_mode=auto)
├── docker-compose.yml # PostgreSQL 17 + Backend service
├── Dockerfile # Multi-stage Python build
├── .env.example # Configuration template
└── DESIGN.md # Frontend design system specification
# Run tests
uv run python -m pytest tests/ -v
# Type check frontend
cd frontend && npx tsc --noEmit| Layer | Technology |
|---|---|
| Backend | Python 3.14, FastAPI, SQLAlchemy (async), Pydantic Settings |
| Database | PostgreSQL 17 (asyncpg driver) |
| LLM | OpenAI, Anthropic, Ollama, OpenRouter, DashScope, BigModel |
| Data Source | Longbridge SDK (US/CN/HK regions) |
| Scheduling | APScheduler (misfire handling, coalesce, timeout guards) |
| Frontend | React 18, TypeScript, Vite, Recharts |
| Design | Vercel/Geist design system (shadow-as-border, Geist fonts) |
| Deployment | Docker Compose, uv package manager |
MIT