Personal automated trading bot for Binance BTCUSDT using a Bollinger Band mean-reversion strategy. Backend: FastAPI · Database: PostgreSQL · Frontend: Next.js 14
Make sure the following are installed before you begin.
| Tool | Version | Check |
|---|---|---|
| Python | 3.9+ | python3 --version |
| Node.js | 18+ | node --version |
| npm | 9+ | npm --version |
| Docker Desktop | latest | docker --version |
| Git | any | git --version |
Binance Testnet account required.
Register at testnet.binance.vision, log in with GitHub, then click Generate HMAC_SHA256 Key to get your API key and secret.
The bot will only ever connect to the testnet until you explicitly changeBINANCE_TESTNET=falsein.env.
git clone <your-repo-url> TradingBot
cd TradingBotcp .env.example .envOpen .env and fill in your values:
# Binance Testnet credentials (from testnet.binance.vision)
BINANCE_API_KEY=your_testnet_api_key_here
BINANCE_API_SECRET=your_testnet_api_secret_here
BINANCE_TESTNET=true # keep this true until strategy is validated
# Database (matches the docker-compose defaults — change if you use your own Postgres)
DATABASE_URL=postgresql+asyncpg://tradingbot:tradingbot@localhost:5432/tradingbot
# Telegram (optional — skip for now, configure later in the Settings page)
TELEGRAM_BOT_TOKEN=
TELEGRAM_CHAT_ID=
# App
APP_ENV=development
SECRET_KEY=change_me_to_a_random_string
LOG_LEVEL=INFO
# Frontend
NEXT_PUBLIC_API_URL=http://localhost:8000
CORS_ORIGINS=["http://localhost:3000"]Never commit
.envto version control. It is in.gitignoreby default.
PostgreSQL is the only stateful service; the backend and frontend run natively. Pick one of the two options below.
# Install once
brew install postgresql@16
# Start it (also restarts at login)
make db # = brew services start postgresql@16
# Create the role + database the app expects (one-time)
psql -d postgres -c "CREATE ROLE tradingbot WITH LOGIN PASSWORD 'tradingbot';"
psql -d postgres -c "CREATE DATABASE tradingbot OWNER tradingbot;"If psql isn't found, add the binaries to your PATH:
export PATH="/opt/homebrew/opt/postgresql@16/bin:$PATH"Verify the connection:
psql "postgresql://tradingbot:tradingbot@localhost:5432/tradingbot" -c "SELECT 1;"Stop it later with make db-stop.
make db-docker # = docker compose up -d postgres
docker ps # container "tradingbot_db" should be "Up"
docker compose down # stop itThe Docker image auto-creates the tradingbot role/database from the
compose env, so you skip the manual CREATE ROLE/CREATE DATABASE step.
cd backend
pip3 install -r requirements.txtThis installs FastAPI, SQLAlchemy, python-binance, APScheduler, and everything else the backend needs.
Virtual environment (recommended):
python3 -m venv .venv source .venv/bin/activate # Windows: .venv\Scripts\activate pip install -r requirements.txtIf you use a venv, activate it before every backend command.
# From the project root
make migrateOr manually (if alembic isn't on your PATH):
cd backend && python3 -m alembic upgrade headThis creates all five tables: trades, positions, daily_performances, account_snapshots, sent_alerts.
Expected output:
INFO [alembic.runtime.migration] Running upgrade -> <rev>, initial schema
alembic: command not found? ThealembicCLI may not be on your PATH.make migratehandles this automatically (python3 -m alembic). If you wantalembicon PATH, add~/Library/Python/3.x/bin(macOS) or~/.local/bin(Linux) to your shell profile.
# From the project root
python3 scripts/seed_db.pyExpected output:
Ensuring database tables exist...
Done. Database is ready.
# From the backend/ directory
uvicorn app.main:app --reload --host 0.0.0.0 --port 8000Or use the Makefile shortcut from the project root:
make backendVerify it's running:
- API root: http://localhost:8000/health
- Swagger UI: http://localhost:8000/docs
- ReDoc: http://localhost:8000/redoc
Expected console output:
INFO app.main — TradingBot starting (env=development, testnet=True)
INFO app.main — Scheduler started
INFO uvicorn — Application startup complete.
With the backend running, open Swagger at http://localhost:8000/docs and try:
GET /api/v1/market/server/status
{ "server_time_ms": 1234567890000, "testnet": true }GET /api/v1/market/price/BTCUSDT
{ "symbol": "BTCUSDT", "price": 67152.41 }If these return real numbers, the Binance testnet connection is working.
Open a new terminal (keep the backend running in the first one).
# From the project root
cd frontend
npm installThe file frontend/.env.local is already committed with the default:
NEXT_PUBLIC_API_URL=http://localhost:8000
Change this if your backend runs on a different host or port.
# From the frontend/ directory
npm run devOr from the project root:
make frontendOpen http://localhost:3000 in your browser.
Once everything is installed, your daily startup is just three commands in three terminals:
# Terminal 1 — Database
make db
# Terminal 2 — Backend
make backend
# Terminal 3 — Frontend
make frontend| Command | What it does |
|---|---|
make db |
Start PostgreSQL (Homebrew brew service) |
make db-stop |
Stop PostgreSQL (Homebrew brew service) |
make db-docker |
Start PostgreSQL via Docker instead |
make backend |
Start FastAPI on port 8000 with hot reload |
make frontend |
Start Next.js on port 3000 with hot reload |
make migrate |
Apply Alembic migrations (alembic upgrade head) |
make seed |
Seed the database with initial data |
make fetch-history |
Download 1 year of BTCUSDT 15m candles for backtesting |
TradingBot/
├── backend/ FastAPI app — all trading logic
├── frontend/ Next.js UI
├── docs/ Documentation (this file + STRATEGY, API, RISK, TUNING)
├── data/ Historical candle CSVs for backtesting
├── scripts/ One-off CLI tools
├── docker-compose.yml
├── Makefile
└── .env.example
Full architecture details: see STRATEGY.md, API.md, RISK.md.
PostgreSQL is not running. Run make db and wait 5 seconds.
You haven't filled in BINANCE_API_KEY / BINANCE_API_SECRET in .env.
Public endpoints (price, candles) still work — only account and order endpoints need keys.
Alembic's bin directory isn't on your PATH. Run it directly:
python3 -m alembic upgrade headOr add ~/.local/bin (Linux) or ~/Library/Python/3.x/bin (macOS) to your PATH.
Your system clock is out of sync. On macOS:
sudo sntp -sS time.apple.com# Kill whatever is on port 8000
lsof -ti:8000 | xargs kill -9
# Kill whatever is on port 3000
lsof -ti:3000 | xargs kill -9