A web app for group trading and copying orders across sub-accounts, with real-time market data, PnL monitoring, and Tradovate integration.
- About
- Features
- Tech Stack
- Installation
- Usage
- Configuration
- Screenshots & Demo
- API Documentation
- Troubleshooting
- Acknowledgements
- License
TradeCopier provides an intuitive interface for managing group-based trading and copying orders across sub-accounts. It solves the need to route and mirror trades in real time while keeping accounts, orders, and positions in sync. The project combines a lightweight React + TypeScript frontend with a FastAPI backend and integrates Tradovate for execution and market data, plus DataBento-style SSE streams for PnL and price snapshots.
Key goals:
- Centralized order routing (market, limit, optional SL/TP) for groups
- Real-time quotes and PnL via WebSocket and server-sent events
- Account, order, and position syncing with a clean dashboard
- Group-based order routing – Route market/limit orders (optional SL/TP) across sub-accounts from a single interface
- Real-time quotes – Live price stream via Tradovate WebSocket and complementary SSE endpoints
- Live PnL stream and dashboard – Server-sent events for PnL and current-price updates with fallback when market is closed
- Account, order, and position syncing – Broker accounts, orders, and positions kept in sync with the backend
| Category | Technologies |
|---|---|
| Languages | Python, TypeScript, JavaScript |
| Frameworks | FastAPI, React, Vite |
| Database | PostgreSQL (async via SQLAlchemy + asyncpg) |
| Tools | Tailwind CSS, Axios, Lightweight Charts, Tradovate API, DataBento-style SSE |
# Clone the repository
git clone https://github.com/yourusername/TradeCopier.git
# Navigate to the project directory
cd TradeCopiercd backend
pip install -r requirements.txt
# Configure .env (see Configuration)
# Run migrations / DB setup as per backend/README.mdcd frontend
npm installFrom the project root:
cd backend
uvicorn main:app --reload --host 0.0.0.0 --port 8000(Or use the run command documented in backend/.)
cd frontend
npm run devThen open your browser and go to:
(Vite default port is 5173; adjust if your config differs.)
Create frontend/.env (or .env.local) with:
VITE_BACKEND_URL=http://localhost:8000If omitted, the app defaults to http://localhost:8000 (or http://localhost:8000/api/v1 where used in API modules).
Copy backend/env.example to backend/.env and fill in your values. Required and optional variables:
| Group | Variables |
|---|---|
| Database | DATABASE_URL, ASYNC_DATABASE_URL (use postgresql+asyncpg://... for async) |
| App | FRONTEND_URL, DEBUG, ENVIRONMENT, APP_VERSION, APP_ID |
| JWT | SECRET_KEY, ALGORITHM, ACCESS_TOKEN_EXPIRE_MINUTES |
| Email (EmailJS) | EMAILJS_SERVICE_ID, EMAILJS_OTP_TEMPLATE_ID, EMAILJS_PUBLIC_KEY, EMAILJS_RRIVATE_KEY, OTP_EXPIRE_MINUTES |
| Google OAuth | GOOGLE_CLIENT_ID |
| Tradovate | CID, SEC, TRADOVATE_LIVE_API_URL, TRADOVATE_DEMO_API_URL, TRADOVATE_REDIRECT_URL, TRADOVATE_AUTH_URL, TRADOVATE_EXCHANGE_URL, TRADOVATE_API_ME_URL |
| Market data | DATABENTO_KEY |
Backend requires valid Tradovate API credentials for execution and WebSocket tokens. For SSE/DataBento PnL and price streams, set DATABENTO_KEY and ensure the corresponding endpoints are configured.
Watch a short walkthrough of TradeCopier:
Add more images to docs/images/ and reference them with .
The backend exposes REST and SSE endpoints. Summary:
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/v1/broker/positions |
List positions |
| GET | /api/v1/broker/orders |
List orders |
| GET | /api/v1/broker/accounts |
List broker accounts |
| Method | Endpoint | Description |
|---|---|---|
| POST | /api/v1/broker/execute-order/market |
Submit market order |
| POST | /api/v1/broker/execute-order/limit |
Submit limit order |
| POST | /api/v1/broker/execute-order/limitwithsltp |
Submit limit order with SL/TP |
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/v1/broker/websockettoken |
Get Tradovate WebSocket token |
| GET | /databento/market-status |
Market open/closed status |
| GET | /databento/historical |
Historical snapshot |
| POST | /databento/sse/current-price |
Start current-price SSE |
| GET | /databento/sse/pnl?user_id=<id> |
PnL SSE stream |
Adjust base paths if your backend uses different prefixes. For full API details, see the backend docs or OpenAPI schema (e.g. /docs when the server is running).
- No quotes updating – Check
VITE_BACKEND_URLand thatGET /api/v1/broker/websockettokenreturns an access token. Ensure backend has valid Tradovate credentials and market data permissions. - SSE not connecting – Verify CORS and cookies; frontend uses
axios.defaults.withCredentials = true. Ensure backend SSE endpoints are reachable and not blocked by a proxy. - Symbols not found / market closed – The UI falls back to a historical snapshot and marks the price stream idle when the market is closed or the API key is missing.
- Tradovate API and example-api-js (WebSockets) for market data and execution
- DataBento-style SSE for PnL and current-price streams
- Libraries: FastAPI, React, Vite, Tailwind CSS, Lightweight Charts, Axios
Proprietary (update as appropriate).
