Docker Architecture
Three containers run on the same isolated bridge network (openclaw_9router_net):
┌──────────────────────────────────────────────────────┐
│ openclaw_9router_net │
│ │
│ ┌──────────┐ ┌──────────┐ │
│ │ openclaw │ │ 9router │ │
│ │ :18789 │ │ :20128 │ │
│ └────┬─────┘ └──────────┘ │
│ │ http://opentrader:8000 │
│ ▼ │
│ ┌────────────────────────────────────┐ │
│ │ opentrader │ │
│ │ ┌─────────────────────────────┐ │ │
│ │ │ uvicorn FastAPI :8000 │ │ │
│ │ └─────────────────────────────┘ │ │
│ │ ┌─────────────────────────────┐ │ │
│ │ │ trend-scan-1h (background)│ │ │
│ │ │ runs on startup + every 1h │ │ │
│ │ └─────────────────────────────┘ │ │
│ └────────────────────────────────────┘ │
└──────────────────────────────────────────────────────┘
OpenClaw agents call the bot via HTTP rather than invoking python3 directly — completely separating the Python runtime from the Node.js container.
Entrypoint
entrypoint.sh (at the repo root, mounted into the image) is the Docker CMD. It starts two processes inside opentrader:
scripts/trend_scan.sh— runs in the background. Waits 20 s for uvicorn to be ready, then runs the 1H trend scan immediately and repeats everyTREND_SCAN_INTERVAL_SECseconds (default: 3600).uvicorn app.main:app— runs in the foreground. The container stays alive as long as uvicorn is running.
Scout can always call GET /api/trend/{symbol} to get an on-demand single-TF TrendResult. Cached scan snapshots are exposed via GET /api/trend/all.