Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
- Learning engine: expand default weights from 3 to all 9 strategies - Learning engine: resolve placeholder strategy_id with DB lookup - Learning engine: pass strategy_sources from trade execution - Trade executor: respect trading:paused Redis flag in RiskManager - Portfolio sync: compute actual daily P&L from day-start snapshot - Portfolio API: cumulative P&L from first snapshot, read pause flag - Portfolio metrics: compute max drawdown and avg hold duration - Add strategy_sources field to TradeExecution schema - Add dev_mode config (TRADING_DEV_MODE) to bypass auth for local dev - Dashboard: VITE_DEV_MODE bypasses ProtectedRoute and 401 redirects - Vite proxy target configurable via VITE_API_TARGET - Add top-level README.md and remaining-work-plan.md - Update CLAUDE.md with correct counts and remove stale TODOs - 404 tests passing Made-with: Cursor
6.1 KiB
6.1 KiB
Trading Bot — Project Knowledge
Project Overview
Automated stock trading bot combining news sentiment analysis with technical strategies. Event-driven Python microservices communicating via Redis Streams, with a React/TypeScript dashboard.
Architecture
- 7 microservices: news-fetcher, sentiment-analyzer, signal-generator, trade-executor, learning-engine, api-gateway, dashboard
- Shared libraries in
shared/: config, redis_streams, telemetry, db, models, schemas, broker abstraction, 9 strategies, fundamentals providers - Infra: PostgreSQL+TimescaleDB, Redis Streams, Ollama (local LLM), Docker Compose
- CI/CD: Woodpecker pipeline → Docker build → Kubernetes deploy
- Brokerage: Alpaca (paper trading) via abstraction layer in
shared/broker/
Key Design Decisions
- Services use underscores in Python package names (e.g.,
services/news_fetcher/) but hyphens in docker-compose service names (e.g.,news-fetcher) - Redis Streams for inter-service messaging:
news:raw,news:scored,signals:generated,trades:executed - Sentiment analysis is tiered: FinBERT first, Ollama fallback when confidence < threshold
- Learning uses multi-armed bandit style weight adjustment with guardrails (min trades, max shift, weight floor)
- Auth is passkey/WebAuthn (py-webauthn on backend, @simplewebauthn/browser on frontend) with JWT sessions
- OpenTelemetry + Prometheus
/metricsendpoints (no Prometheus/Grafana deployed — uses existing infra)
Tech Stack
- Backend: Python 3.12, FastAPI, SQLAlchemy 2.0 (async, mapped_column style), Pydantic v2, alpaca-py
- Frontend: React 18, TypeScript, Vite, Tailwind CSS, TanStack Query, TradingView lightweight-charts, Recharts
- ML: transformers (FinBERT), ollama-python
- Testing: pytest, pytest-asyncio (asyncio_mode="auto"), React Testing Library
- Database: PostgreSQL 16 + TimescaleDB extension, Alembic for migrations
Project Structure
trading-bot/
├── shared/ # Shared Python libraries
│ ├── config.py # Pydantic BaseSettings (env_prefix="TRADING_")
│ ├── redis_streams.py # StreamPublisher + StreamConsumer
│ ├── telemetry.py # OpenTelemetry setup
│ ├── db.py # Async engine + sessionmaker
│ ├── models/ # SQLAlchemy models (16 tables)
│ ├── schemas/ # Pydantic v2 schemas (message types)
│ ├── broker/ # BaseBroker ABC + AlpacaBroker
│ ├── fundamentals/ # Alpha Vantage, FMP, Yahoo providers + cache
│ └── strategies/ # BaseStrategy + 9 implementations
├── services/
│ ├── news_fetcher/ # RSS + Reddit → news:raw
│ ├── sentiment_analyzer/ # FinBERT + Ollama → news:scored
│ ├── signal_generator/ # Weighted ensemble → signals:generated
│ ├── trade_executor/ # Risk mgmt + Alpaca → trades:executed
│ ├── learning_engine/ # Multi-armed bandit weight adjustment
│ └── api_gateway/ # FastAPI + WebAuthn + WebSocket
├── backtester/ # Historical replay engine
├── dashboard/ # React/TypeScript (Vite)
├── docker/ # Dockerfile.service, Dockerfile.dashboard, nginx.conf
├── scripts/ # seed_strategies.py, smoke_test.sh
├── tests/ # Unit + integration tests
├── alembic/ # Database migrations
├── docker-compose.yml
└── pyproject.toml # Monorepo with optional dep groups
Development Workflow
- Use
.venv:python3 -m venv .venv && source .venv/bin/activate - Install all deps:
pip install -e ".[api,news,sentiment,trading,backtester,dev]" - Run unit tests:
python -m pytest tests/ -v -m "not integration" - Run integration tests (requires docker):
python -m pytest tests/ -v -m integration - Dashboard dev:
cd dashboard && npm install && npm run dev - Dashboard build:
cd dashboard && npm run build - Full stack:
docker compose up -d
Test Coverage (246 unit tests)
tests/test_redis_streams.py— 5 teststests/test_models.py— 21 teststests/test_schemas.py— 49 teststests/test_broker.py— 18 teststests/test_strategies.py— 24 teststests/test_backtester.py— 13 teststests/services/test_news_fetcher.py— 10 teststests/services/test_sentiment_analyzer.py— 19 teststests/services/test_signal_generator.py— 17 teststests/services/test_trade_executor.py— 16 teststests/services/test_learning_engine.py— 28 teststests/services/test_api_auth.py— 13 teststests/services/test_api_routes.py— 13 teststests/integration/— 9 integration tests (news pipeline + trading flow)
Important Patterns
- Each service extends
shared.config.BaseConfigfor its own settings - Services use
StreamConsumer/StreamPublisherfor Redis Streams messaging - Broker abstraction: all trading goes through
BaseBrokerinterface (swap Alpaca for another broker without changing services) - Strategy abstraction: all strategies implement
BaseStrategy.evaluate()returningTradeSignal | None - The pyproject.toml uses optional dependency groups per service:
[api],[news],[sentiment],[trading],[backtester] - The webauthn package on PyPI is called
webauthn(notpy-webauthn)
Known Issues / TODO
- Code review was started but not completed — should be done before production use
- JWT test warnings about short HMAC keys (test-only, production keys should be 32+ bytes)
- Integration tests mock FinBERT and Alpaca — need real integration tests with live services
- Twitter/X source not implemented in news fetcher (only RSS + Reddit)
- Dashboard has no unit tests (only build verification)
How This Was Built
- Built in 6 sprints using parallel subagent worktrees
- Each sprint had 2-3 agents working independently on non-overlapping files
- Worktree branches merged into master after each sprint
- Tests verified after every merge (246 tests, 0 failures)
- Agent teams didn't work well (idle notification issues) — switched to direct subagent Task calls with worktree isolation