version: "3.9" # TradeFinder - Automated Crypto Trading System # Mount point: /opt/trading/crypto (configurable via DATA_ROOT) x-common: &common restart: unless-stopped networks: - tradefinder-net logging: driver: json-file options: max-size: "10m" max-file: "3" services: # ========================================================================== # CORE TRADING ENGINE # ========================================================================== engine: <<: *common build: context: . dockerfile: Dockerfile target: engine container_name: tf-engine env_file: - .env environment: - PYTHONUNBUFFERED=1 - DUCKDB_PATH=/data/engine/tradefinder.duckdb volumes: - ${DATA_ROOT:-/opt/trading/crypto}/engine:/data/engine - ${DATA_ROOT:-/opt/trading/crypto}/shared:/data/shared depends_on: - redis healthcheck: test: ["CMD", "python", "-c", "import tradefinder; print('ok')"] interval: 30s timeout: 10s retries: 3 command: ["python", "-m", "tradefinder.core.main"] # ========================================================================== # STREAMLIT UI # ========================================================================== ui: <<: *common build: context: . dockerfile: Dockerfile target: ui container_name: tf-ui env_file: - .env environment: - PYTHONUNBUFFERED=1 - DUCKDB_PATH=/data/engine/tradefinder.duckdb ports: - "${STREAMLIT_PORT:-8501}:8501" volumes: - ${DATA_ROOT:-/opt/trading/crypto}/engine:/data/engine:ro - ${DATA_ROOT:-/opt/trading/crypto}/shared:/data/shared depends_on: - engine healthcheck: test: ["CMD", "curl", "-f", "http://localhost:8501/_stcore/health"] interval: 30s timeout: 10s retries: 3 command: ["streamlit", "run", "src/tradefinder/ui/app.py", "--server.port=8501", "--server.address=0.0.0.0"] # ========================================================================== # OPTIMIZER (runs weekly via scheduler or manually) # ========================================================================== optimizer: <<: *common build: context: . dockerfile: Dockerfile target: engine container_name: tf-optimizer env_file: - .env environment: - PYTHONUNBUFFERED=1 - DUCKDB_PATH=/data/engine/tradefinder.duckdb volumes: - ${DATA_ROOT:-/opt/trading/crypto}/engine:/data/engine - ${DATA_ROOT:-/opt/trading/crypto}/optimizer:/data/optimizer - ${DATA_ROOT:-/opt/trading/crypto}/shared:/data/shared profiles: - optimizer # Only runs when explicitly started: docker compose --profile optimizer up optimizer command: ["python", "-m", "tradefinder.core.optimize"] # ========================================================================== # REDIS (for real-time state, pub/sub, caching) # ========================================================================== redis: <<: *common image: redis:7-alpine container_name: tf-redis volumes: - ${DATA_ROOT:-/opt/trading/crypto}/redis:/data healthcheck: test: ["CMD", "redis-cli", "ping"] interval: 10s timeout: 5s retries: 3 command: ["redis-server", "--appendonly", "yes", "--maxmemory", "256mb", "--maxmemory-policy", "allkeys-lru"] # ========================================================================== # BACKTESTER (runs on-demand) # ========================================================================== backtester: <<: *common build: context: . dockerfile: Dockerfile target: engine container_name: tf-backtester env_file: - .env environment: - PYTHONUNBUFFERED=1 - DUCKDB_PATH=/data/engine/tradefinder.duckdb volumes: - ${DATA_ROOT:-/opt/trading/crypto}/engine:/data/engine - ${DATA_ROOT:-/opt/trading/crypto}/backtest:/data/backtest - ${DATA_ROOT:-/opt/trading/crypto}/shared:/data/shared profiles: - backtest # Only runs when explicitly started command: ["python", "-m", "tradefinder.core.backtest"] networks: tradefinder-net: driver: bridge name: tradefinder-network # Volume labels for clarity # All data persisted under ${DATA_ROOT:-/opt/trading/crypto}/ # ├── engine/ # DuckDB, order logs, positions # ├── optimizer/ # Optuna studies, best params # ├── backtest/ # Backtest results, reports # ├── redis/ # Redis AOF persistence # └── shared/ # Shared configs, FX rates cache