The real dashboard after login: paper accounts, orders at live prices and a risk calculator, with every practice trade clearly marked.
The challenge
Every crypto exchange has its own API, symbols, limits and quirks. A tool that works across several of them usually means duplicated code, and testing a strategy safely without risking real money is hard.
The solution
I built a trading hub with one secure API in front of 9 exchanges: Binance, Bybit, OKX, KuCoin, Kraken, Coinbase, Bitget, Gate.io and MEXC. Your app makes the same calls everywhere, and a paper-trading engine fills orders at live market prices without touching real money.
The dashboard
Paper accounts on any exchange, with simulated balances saved in the database.
Orders at live prices: in the real run, two 0.01 BTC buys filled at the live Binance price, marked as paper.
Risk calculator for position size and reward-to-risk before a trade.
One adapter layer in front of 9 exchanges, with a real position-size calculation and 12 built-in technical indicators.
How it works
One adapter layer over ccxt turns nine different exchange APIs into the same clean calls. Adding an exchange is one registry entry.
Market data: tickers, order books and candles. In the real run: BTC/USDT 81,850.09 on Binance, 81,881.80 on Kraken and ETH/USDT 2,420.80 on OKX.
Analytics: 12 dependency-free indicators, including RSI, MACD, Bollinger Bands, ATR and SuperTrend.
Risk tools: position sizing, R:R, PnL, liquidation price and guard rails checked before every order. For a 10,000 balance, 1% risk, entry 81,850 and stop 80,000, the API returned 0.054 BTC, a 100.00 risk and a 4,424.32 position.
Resilience: retries and a circuit breaker for exchange calls, rate limiting, Celery workers and Docker Compose.
Live trading is off by default: in the real run, an order on a live account still executed as paper. 285 tests at 96% coverage.
Security and quality
Live trading is off by default and enforced at one choke point. In the real run, an order sent to an account created as live was still executed as a paper trade. When enabled, it starts on testnet.
Exchange keys encrypted with Fernet and a rotatable master key; plain keys never reach the database or the logs.
Authentication: Argon2id passwords, rotating refresh tokens with reuse detection, single-use 2FA codes, account lockout and roles (viewer, trader, admin).
Unsafe setups refused: production won't start without a master key, a strong JWT secret, debug off and a strict CORS list.
285 automated tests at 96% coverage, plus gitleaks, pip-audit, CodeQL, ruff with bandit rules and mypy on every push.