| Tool | Version | Notes |
|---|---|---|
| Docker & Docker Compose | 20+ | required for the default setup |
| Python | 3.10+ | only if running backend outside Docker |
| Node.js | 18+ | only if you maintain the private QuantDinger-Vue repo |
# 1. Clone
git clone https://github.com/<your-org>/quantdinger.git
cd quantdinger
# 2. Configure
cp backend_api_python/env.example backend_api_python/.env
# Edit .env — at minimum set SECRET_KEY to a random value:
# SECRET_KEY=$(python3 -c "import secrets; print(secrets.token_hex(32))")
# Optional: project-root `.env` with `IMAGE_PREFIX` if Docker Hub pulls are slow (see .env.example).
# 3. Launch
docker compose up -d --build
# 4. Open http://localhost:8888The stack includes:
| Service | Port | Description |
|---|---|---|
frontend |
8888 | Nginx serving Vue SPA |
backend |
5000 | Flask API (gunicorn) |
postgres |
5432 | PostgreSQL 16 |
redis |
6379 | Cache layer (LRU, 128 MB) |
quantdinger/
├── backend_api_python/ # Flask API
│ ├── app/
│ │ ├── config/ # Settings, API keys, DB config
│ │ ├── data_providers/ # Market data fetchers (crypto, forex, …)
│ │ ├── data_sources/ # Exchange/broker adapters (CCXT, yfinance, …)
│ │ ├── routes/ # Flask Blueprints (REST endpoints)
│ │ ├── services/ # Business logic (strategy, trading, AI, …)
│ │ └── utils/ # DB helpers, auth, caching, logger
│ ├── migrations/ # SQL schema + seed data
│ ├── gunicorn_config.py # Production WSGI config
│ ├── run.py # App entrypoint
│ ├── Dockerfile
│ └── requirements.txt
├── docs/ # Changelog, architecture notes
├── docker-compose.yml # frontend service pulls ghcr.io/.../quantdinger-frontend
├── docker-compose.ghcr.yml # both services pulled from GHCR (zero-clone deploy)
└── README.md
cd backend_api_python
python -m venv .venv && source .venv/bin/activate # or .venv\Scripts\activate on Windows
pip install -r requirements.txt
cp env.example .env # edit .env
python run.pyThe dev server starts on http://localhost:5000 with auto-reload.
The open-source tree does not contain Vue source or build artefacts. UI work happens in the private QuantDinger-Vue repo. Releases are fully automated:
# In QuantDinger-Vue
git tag v3.0.9
git push origin v3.0.9The release-frontend.yml workflow there builds linux/amd64 + linux/arm64 images via buildx and pushes them to ghcr.io/brokermr810/quantdinger-frontend, tagged with the semver value, {major}.{minor}, and latest.
This repo's docker-compose.yml (and docker-compose.ghcr.yml) references that image by default. To pin a version while testing:
# Project-root .env (sibling of docker-compose.yml)
# Common: bump both sides together
echo "IMAGE_TAG=v3.0.9" >> .env
# Or pin only frontend (testing a UI hotfix against stable backend)
# echo "FRONTEND_TAG=v3.0.9" >> .env
docker compose pull frontend
docker compose up -d frontendResolution order: FRONTEND_TAG (or BACKEND_TAG) → IMAGE_TAG → latest.
The container reads BACKEND_URL at start time and substitutes it into the nginx config via the official nginx:alpine envsubst hook, so the same image works for compose, Railway, and direct docker run.
For iterating on Vue source (theme tweaks, debugging, customised UI), drop the source into the gitignored ./QuantDinger-Vue/ slot at the repo root and layer the docker-compose.build.yml override on top. The main docker-compose.yml only declares image: for frontend (so users who only pull never need the directory to exist); the override file adds the build: block:
# Expected layout — clone QuantDinger-Vue into ./QuantDinger-Vue/ at this repo root:
# QuantDinger/
# QuantDinger-Vue/ <- gitignored; clone goes here
# backend_api_python/
# docker-compose.yml
# docker-compose.build.yml <- enables local frontend build
git clone https://github.com/brokermr810/QuantDinger-Vue.git QuantDinger-Vue
# Build frontend from ./QuantDinger-Vue, pull everything else:
docker compose -f docker-compose.yml -f docker-compose.build.yml up -d --build
# Rebuild after editing Vue source:
docker compose -f docker-compose.yml -f docker-compose.build.yml build frontend
# Apply runtime config changes only:
docker compose restart frontendTip: drop COMPOSE_FILE=docker-compose.yml:docker-compose.build.yml into your root .env and plain docker compose up --build will pick up both files.
Key behaviour:
- Without the override: Compose pulls
ghcr.io/.../quantdinger-frontend:<tag>as usual;./QuantDinger-Vue/does not need to exist. - With the override: Compose builds from
./QuantDinger-Vue/(orFRONTEND_SRC_PATHif set) and tags the result with whateverFRONTEND_TAG/IMAGE_TAGresolves to. The locally built image then satisfies plaindocker compose upfor subsequent runs until youdocker compose pull frontendto overwrite it.
Source path override (keep the Vue clone somewhere else than ./QuantDinger-Vue/):
FRONTEND_SRC_PATH=/abs/path/to/QuantDinger-Vue \
docker compose -f docker-compose.yml -f docker-compose.build.yml up -d --buildDefault backend behaviour is unaffected — it still builds from this repo's backend_api_python/. Only the frontend service uses the image/override-build split.
- Create
backend_api_python/app/data_sources/<name>.pyimplementing a class withget_ticker(symbol)andget_kline(symbol, timeframe, limit). - Register it in
data_sources/factory.py. - If it serves the global market dashboard, add a fetcher in
data_providers/and wire it into the fallback chain.
- Create
backend_api_python/app/services/live_trading/<exchange>.pyinheriting fromBaseLiveTrading. - Implement
place_order,cancel_order,get_balance, etc. - Register in
live_trading/factory.py.
See backend_api_python/env.example for the full list. Key variables:
| Variable | Required | Description |
|---|---|---|
SECRET_KEY |
yes | JWT signing key — must be changed from default |
ADMIN_USER / ADMIN_PASSWORD |
yes | Initial admin credentials |
TWELVE_DATA_API_KEY |
no | Twelve Data for forex/commodities |
ADANOS_API_KEY |
no | Optional Adanos Market Sentiment for US stock tickers |
OPENAI_API_KEY or OPENROUTER_API_KEY |
no | AI analysis features |
CACHE_ENABLED |
no | Set true to use Redis (auto-set in Docker) |
cd backend_api_python
pip install pytest
pytest tests/ -v- "apikey parameter is incorrect" from Twelve Data — verify
TWELVE_DATA_API_KEYin.env; Chinese stock data requires a paid plan. - Heatmap "暂无数据" — usually caused by NaN in yfinance data; the global JSON encoder now sanitises all NaN/Inf to
null. - Redis connection refused — ensure
redisservice is running (docker compose up -d redis); setCACHE_ENABLED=falseto fall back to in-memory cache.