17 KiB
17 KiB
Codebase Structure
Analysis Date: 2025-02-23
Directory Layout
trading-bot/
├── alembic/ # Database migration versions and configuration
│ ├── env.py # Alembic runtime environment
│ ├── script.py.mako # Migration template
│ └── versions/ # Individual migration files
├── backtester/ # Historical replay engine
│ ├── __init__.py
│ ├── config.py # Backtester configuration
│ ├── data_loader.py # Load bars from database
│ ├── engine.py # Main replay loop with SimulatedBroker
│ ├── metrics.py # Equity curve, Sharpe, drawdown calculations
│ └── simulated_broker.py # Paper trading for backtests
├── dashboard/ # React/TypeScript frontend
│ ├── public/ # Static assets (favicon, manifest)
│ ├── src/
│ │ ├── api/ # API client (auth.ts, client.ts)
│ │ ├── assets/ # Images, fonts
│ │ ├── components/ # Reusable UI (PositionsTable, EquityCurve, etc.)
│ │ ├── hooks/ # Custom React hooks (useAuth, useWebSocket, usePortfolio)
│ │ ├── pages/ # Page components (Login, Portfolio, TradeLog, etc.)
│ │ ├── App.tsx # Router and layout
│ │ ├── main.tsx # Entry point
│ │ └── index.css # Tailwind styles
│ ├── index.html # HTML template
│ ├── package.json # npm dependencies (Vite, React, TypeScript)
│ └── vite.config.ts # Vite build config
├── docker/ # Dockerfiles and compose configs
│ ├── Dockerfile.service # Python service base image
│ ├── Dockerfile.dashboard # Node.js build + Nginx serve
│ └── nginx.conf # Nginx reverse proxy config
├── docs/ # Documentation and planning
│ └── plans/ # Implementation plans from GSD phases
├── scripts/ # Utility scripts
│ ├── seed_strategies.py # Initialize default strategies in DB
│ ├── smoke_test.sh # Health check / integration test script
│ └── __init__.py
├── services/ # Microservices (Python packages with underscores)
│ ├── api_gateway/ # FastAPI HTTP/WebSocket server
│ │ ├── main.py # App factory, lifespan, router registration
│ │ ├── config.py # ApiGatewayConfig (CORS, JWT secret, etc.)
│ │ ├── ws.py # WebSocket endpoint
│ │ ├── auth/
│ │ │ ├── routes.py # Register/login/logout endpoints
│ │ │ ├── jwt.py # JWT token encoding/decoding
│ │ │ └── middleware.py # get_current_user dependency
│ │ ├── routes/ # REST endpoints organized by domain
│ │ │ ├── news.py # GET /api/news
│ │ │ ├── signals.py # GET /api/signals
│ │ │ ├── trades.py # GET /api/trades
│ │ │ ├── portfolio.py # GET /api/portfolio (live account)
│ │ │ ├── strategies.py # GET/PUT /api/strategies
│ │ │ ├── controls.py # POST /api/controls/* (pause/resume/etc)
│ │ │ └── backtest.py # POST /api/backtest
│ │ └── tasks/
│ │ └── portfolio_sync.py # Background task: sync account data
│ ├── news_fetcher/ # Polls RSS + Reddit
│ │ ├── main.py # Entry point: fetch + deduplicate + publish
│ │ ├── config.py # NewsFetcherConfig (feed URLs, poll intervals)
│ │ └── sources/
│ │ ├── rss.py # RSSSource.fetch() via feedparser
│ │ └── reddit.py # RedditSource.fetch() via asyncpraw
│ ├── sentiment_analyzer/ # Score sentiment + extract tickers
│ │ ├── main.py # Entry point: consume raw → score → publish
│ │ ├── config.py # SentimentAnalyzerConfig (thresholds, model paths)
│ │ ├── ticker_extractor.py # Regex-based company name → ticker
│ │ └── analyzers/
│ │ ├── finbert.py # FinBERTAnalyzer (transformers model)
│ │ └── ollama_analyzer.py # OllamaAnalyzer (fallback LLM)
│ ├── signal_generator/ # Combine sentiment + market → signals
│ │ ├── main.py # Entry point: consume scored articles + bars → ensemble
│ │ ├── config.py # SignalGeneratorConfig (ensemble threshold)
│ │ ├── ensemble.py # WeightedEnsemble orchestration
│ │ └── market_data.py # MarketDataManager: SMA/RSI calculation per ticker
│ ├── trade_executor/ # Risk checks + order submission
│ │ ├── main.py # Entry point: consume signals → risk check → submit
│ │ ├── config.py # TradeExecutorConfig (risk limits, position size formula)
│ │ └── risk_manager.py # RiskManager: position limits, market hours, cooldowns
│ ├── learning_engine/ # Evaluate trades + adjust weights
│ │ ├── main.py # Entry point: consume executions → evaluate → adjust weights
│ │ ├── config.py # LearningEngineConfig (adjustment parameters)
│ │ ├── evaluator.py # TradeEvaluator: match opens to closes, calc P&L
│ │ └── weight_adjuster.py # WeightAdjuster: multi-armed bandit logic
│ ├── market_data/ # Fetch + stream OHLCV bars
│ │ ├── main.py # Entry point: fetch from Alpaca → publish bars
│ │ ├── config.py # MarketDataConfig (watchlist, timeframe, limits)
│ │ └── __main__.py # Allows `python -m services.market_data`
│ └── __init__.py
├── shared/ # Shared Python libraries (imported by all services)
│ ├── __init__.py
│ ├── config.py # BaseConfig: common settings (DB, Redis, logging)
│ ├── db.py # create_db(): async engine + sessionmaker
│ ├── redis_streams.py # StreamPublisher, StreamConsumer
│ ├── telemetry.py # setup_telemetry(): OpenTelemetry + Prometheus
│ ├── broker/ # Brokerage abstraction layer
│ │ ├── base.py # BaseBroker ABC (abstract interface)
│ │ └── alpaca_broker.py # AlpacaBroker: alpaca-py implementation
│ ├── models/ # SQLAlchemy ORM models
│ │ ├── __init__.py # Imports all models so Alembic discovers them
│ │ ├── base.py # Base (declarative), TimestampMixin
│ │ ├── auth.py # User, UserCredential
│ │ ├── news.py # Article, ArticleSentiment
│ │ ├── trading.py # Signal, Trade, Position, Strategy, StrategyWeightHistory
│ │ ├── learning.py # TradeOutcome, LearningAdjustment
│ │ └── timeseries.py # MarketData, PortfolioSnapshot, StrategyMetric
│ ├── schemas/ # Pydantic v2 message schemas
│ │ ├── __init__.py # Imports all schemas
│ │ ├── base.py # BaseSchema, TimestampSchema
│ │ ├── news.py # RawArticle, ScoredArticle
│ │ ├── trading.py # TradeSignal, TradeExecution, OrderRequest, etc.
│ │ └── learning.py # TradeOutcomeSchema, WeightAdjustment
│ └── strategies/ # Trading strategy implementations
│ ├── __init__.py # Exports BaseStrategy, concrete implementations
│ ├── base.py # BaseStrategy ABC
│ ├── momentum.py # MomentumStrategy
│ ├── mean_reversion.py # MeanReversionStrategy
│ └── news_driven.py # NewsDrivenStrategy
├── tests/ # Test suites
│ ├── __init__.py
│ ├── conftest.py # Pytest fixtures (fake Redis, DB, configs)
│ ├── test_*.py # Unit tests: models, schemas, broker, strategies, backtester
│ ├── services/ # Service-specific tests
│ │ ├── test_news_fetcher.py
│ │ ├── test_sentiment_analyzer.py
│ │ ├── test_signal_generator.py
│ │ ├── test_trade_executor.py
│ │ ├── test_learning_engine.py
│ │ ├── test_api_auth.py
│ │ ├── test_api_routes.py
│ │ ├── test_market_data.py
│ │ └── test_portfolio_sync.py
│ └── integration/ # Integration tests (require docker)
│ ├── test_news_pipeline.py
│ └── test_trading_flow.py
├── .claude/ # Project-specific Claude knowledge
│ └── CLAUDE.md # Architecture notes, patterns, known issues
├── .env.example # Example environment variables
├── alembic.ini # Alembic configuration
├── docker-compose.yml # Service orchestration (8 services + infra)
├── pyproject.toml # Python package config, dependencies, test config
└── README.md # Project overview
Directory Purposes
alembic/:
- Purpose: Database schema migrations using Alembic (SQLAlchemy migration tool)
- Contains: Migration scripts (timestamped Python files in
versions/) - Workflow:
alembic revision -m "message"creates migration,alembic upgrade headapplies to DB
backtester/:
- Purpose: Historical replay engine for strategy testing
- Contains: Engine loop, simulated broker, metrics calculation
- Used by: API endpoint
/api/backtest(triggered by dashboard) - Workflow: Load historical bars from DB, replay trades with
SimulatedBroker, output equity curve + metrics
dashboard/:
- Purpose: React TypeScript frontend for user interaction
- Contains: Pages (Login, Portfolio, TradeLog, News, etc.), components (charts, tables), API client, hooks
- Entry:
src/main.tsx→src/App.tsx - Build:
npm run buildoutputs todist/, served by Nginx in Docker
docker/:
- Purpose: Container images and deployment config
- Contains:
Dockerfile.service(Python services base),Dockerfile.dashboard(Node build + Nginx) - Used by: docker-compose.yml to build and run all services
scripts/:
- Purpose: Utility and setup scripts
- Key files:
seed_strategies.py: Inserts default strategies into DB (Momentum, MeanReversion, NewsDriven)smoke_test.sh: Checks all service health endpoints
services/*/main.py:
- Purpose: Entry point for each microservice
- Pattern: Each service has own
main.pythat can be run aspython -m services.SERVICE_NAME - Lifecycle: Setup config → connect to Redis/DB → start polling/consuming → handle shutdown gracefully
services/*/config.py:
- Purpose: Service-specific configuration
- Pattern: Extends
BaseConfig, adds service-specific settings - Example:
NewsFetcherConfigaddsrss_urls,reddit_subreddits,rss_poll_interval_seconds
shared/models/:
- Purpose: SQLAlchemy ORM models (database schema)
- Key tables:
trades,signals,articles,article_sentiments,market_data,positions,users,strategies,strategy_weight_history,learning_adjustments,portfolio_snapshots - Pattern: Each model imports in
__init__.pyso Alembic can auto-discover for migrations
shared/schemas/:
- Purpose: Pydantic v2 message schemas for validation
- Used by: Services to validate messages on consume/publish via Redis Streams
- Naming: Schemas mirror the Redis Stream message types (RawArticle, ScoredArticle, TradeSignal, TradeExecution, etc.)
shared/strategies/:
- Purpose: Pluggable trading strategy implementations
- Pattern: All extend
BaseStrategy, implementasync evaluate(ticker, market, sentiment) → TradeSignal | None - Used by: Signal generator via
WeightedEnsemble
tests/:
- Purpose: Unit and integration tests
- Pattern:
test_*.pyfiles match modules inshared/andservices/ - Marker:
@pytest.mark.integrationfor tests requiring live services (redis, postgres) - Run:
pytest tests/ -v -m "not integration"for unit, or with docker running for integration
Key File Locations
Entry Points:
services/news_fetcher/main.py: Polls RSS/Reddit, publishes tonews:rawservices/sentiment_analyzer/main.py: Consumesnews:raw, publishes tonews:scoredservices/signal_generator/main.py: Consumesnews:scored+market:bars, publishes tosignals:generatedservices/trade_executor/main.py: Consumessignals:generated, submits orders, publishes totrades:executedservices/learning_engine/main.py: Consumestrades:executed, adjusts strategy weightsservices/market_data/main.py: Fetches OHLCV bars, publishes tomarket:barsservices/api_gateway/main.py: HTTP server listening on port 8000 (configurable)dashboard/src/main.tsx: React app entry, connects to API gateway
Configuration:
.env: Runtime environment variables (database URL, Redis URL, API keys, etc.)pyproject.toml: Python project metadata, dependencies (split into optional groups per service)docker-compose.yml: Service orchestration, port mappings, environment variablesalembic.ini: Database migration tool configuration
Core Logic:
services/signal_generator/ensemble.py: Weighted ensemble combining strategiesservices/trade_executor/risk_manager.py: Risk checks before order submissionservices/learning_engine/weight_adjuster.py: Multi-armed bandit weight adjustmentbacktester/engine.py: Historical replay loopshared/broker/alpaca_broker.py: Alpaca order submission and account queries
Testing:
tests/conftest.py: Pytest fixtures for mock Redis, DB, service configstests/test_models.py: ORM model teststests/test_schemas.py: Pydantic schema validation teststests/services/: Service-specific unit teststests/integration/: End-to-end pipeline tests (require docker)
Naming Conventions
Files:
- Python service directories use underscores:
news_fetcher,api_gateway,signal_generator(matches Docker Compose service names with hyphens replaced) - Test files:
test_*.pyor*_test.py(pytest convention) - Database migration files:
{timestamp}_{description}.py(Alembic auto-generated) - React components: PascalCase
.tsxfiles (Login.tsx, Portfolio.tsx, PositionsTable.tsx) - React hooks:
use*.tsprefix (useAuth.ts, useWebSocket.ts, usePortfolio.ts) - Config classes:
*Configsuffix extendingBaseConfig(NewsFetcherConfig, ApiGatewayConfig)
Directories:
- Services under
services/: lowercase with underscores (news_fetcher, api_gateway) - Shared libraries under
shared/: logical grouping (broker/, models/, schemas/, strategies/) - Tests mirror source structure:
tests/services/test_*.pyforservices/*/modules - React pages: match route names (Portfolio.tsx for /portfolio, TradeLog.tsx for /trades)
Where to Add New Code
New Feature (End-to-End):
- Service-specific code:
services/{SERVICE_NAME}/{module}.py - Shared models:
shared/models/{domain}.py(if new entity type) - Shared schemas:
shared/schemas/{domain}.py(if new message type) - Tests:
tests/services/test_{SERVICE_NAME}.pyand/ortests/integration/
New Component/Module:
- Service: Create
services/{service_name}/directory with__init__.py,main.py,config.py - Strategy: Extend
BaseStrategyinshared/strategies/{strategy_name}.py - Broker adapter: Extend
BaseBrokerinshared/broker/{provider_name}_broker.py - API route: Add to
services/api_gateway/routes/{domain}.py - Dashboard page: Add
dashboard/src/pages/{PageName}.tsxand route inApp.tsx
Utilities:
- Shared helpers:
shared/{module}.py(e.g.,shared/redis_streams.py) - Service-specific helpers:
services/{SERVICE_NAME}/{helper}.py - API utilities:
services/api_gateway/{utility}.py
Database:
- New table: Add model in
shared/models/{domain}.py - Schema migration: Run
alembic revision -m "description", fill in migration file - Persist data: Service calls
session.add(model_instance)thensession.commit()
Tests:
- Unit test:
tests/test_{module}.pyfor shared,tests/services/test_{service}.pyfor services - Integration test:
tests/integration/test_{flow}.py - Fixtures: Add to
tests/conftest.py(database, Redis, mocked API responses)
Special Directories
.planning/codebase/:
- Purpose: Generated codebase mapping documents (ARCHITECTURE.md, STRUCTURE.md, etc.)
- Generated by:
/gsd:map-codebasecommand - Committed: Yes, part of repo for CI/CD reference
.pytest_cache/, __pycache__/:
- Purpose: Pytest and Python runtime caches
- Generated: Yes (auto-created by pytest/Python)
- Committed: No (in .gitignore)
trading_bot.egg-info/:
- Purpose: Build metadata from
setuptools.build_meta - Generated: Yes (auto-created during install)
- Committed: No (in .gitignore)
dashboard/dist/:
- Purpose: Built React app (HTML, JS, CSS bundles)
- Generated: Yes (by
npm run build) - Committed: No (in .gitignore)