RiskFlow API & Dashboard is a high-throughput, production-grade microservice and real-time quantitative trading terminal engineered for prop firm traders, hedge funds, and discretionary investment portfolios. It combines an asynchronous backend with a high-fidelity dark-themed React dashboard, performing automated risk evaluation (Win Rate, Profit Factor, Peak-to-Trough Drawdown, Risk/Reward Ratio, and Mathematical Expectancy), sub-millisecond Redis caching, and continuous WebSocket event streaming.
RiskFlow follows strict Clean Architecture (Hexagonal Architecture) principles, ensuring total separation of concerns, high testability, and decoupling between domain logic, data access, and transport layers.
riskflow-api/
โโโ frontend/ # React 18 + TypeScript + Vite + Tailwind CSS + Recharts
โ โโโ src/
โ โ โโโ components/ # Navbar, KpiGrid, EquityChart, TradeTable, Modals, LoginView
โ โ โโโ context/ # AuthContext (JWT session), AccountContext (active portfolio)
โ โ โโโ hooks/ # useRiskFlowWebSocket (auto-reconnect, query invalidation)
โ โ โโโ services/ # Axios API client with 401 interceptor
โ โ โโโ types/ # Strict TypeScript interfaces for all data models
โ โโโ nginx.conf # Production Nginx reverse proxy (port 3000)
โ โโโ Dockerfile # Multi-stage Docker build for frontend
โโโ .github/workflows/ci.yml # Automated CI/CD (Ruff, Mypy, Pytest >=80% Coverage)
โโโ docker/
โ โโโ Dockerfile # Multi-stage Python build (Builder -> Minimal Runner)
โ โโโ entrypoint.sh # DB Readiness probe, Alembic migrations, Auto-seed
โโโ docker-compose.yml # Orchestration for Frontend, API, Postgres 16 & Redis 7
โโโ alembic/ # Versioned database migrations
โ โโโ versions/
โ โโโ env.py # Asynchronous migration runner
โโโ src/ # Backend Core, Domain, Schemas, Repositories, Services, Routers
โโโ tests/ # Pytest test suite (>80% coverage with async HTTPX)
โโโ scripts/
โ โโโ seed_data.py # Deterministic demo dataset generator (50 realistic trades)
โโโ pyproject.toml # Tooling configuration (Ruff, Mypy, Pytest)
flowchart TD
subgraph Clients["Clients & Producers"]
WebClient["Web Dashboard / TradingView"]
AlgoBot["Algorithmic Trading Bot / MT5"]
end
subgraph API["RiskFlow API Service (FastAPI)"]
Router["HTTP / WebSocket Router"]
AuthMiddleware["JWT Authentication Middleware"]
TradeService["Trade Ingestion Service"]
RiskEngine["Pure Mathematical Risk Engine"]
ConnManager["Multiplexed WebSocket Manager"]
end
subgraph Data["Persistence & Caching"]
Postgres[("PostgreSQL 16\n(ACID & Relational Storage)")]
Redis[("Redis 7\n(Metrics Cache TTL 60s & Pub/Sub Bus)")]
end
WebClient -->|"1. Ingest Trade (POST /trades)"| Router
AlgoBot -->|"1. Ingest Trade (POST /trades)"| Router
Router --> AuthMiddleware
AuthMiddleware --> TradeService
TradeService -->|"2. Persist Trade & Update Balance"| Postgres
TradeService -->|"3. Invalidate Metrics Cache"| Redis
TradeService -->|"4. Publish 'TRADE_CREATED' Event"| Redis
Redis -.->|"5. Pub/Sub Subscription"| ConnManager
ConnManager -->|"6. Real-Time WebSocket Push"| WebClient
WebClient -->|"7. Query Analytics (GET /analytics)"| RiskEngine
RiskEngine -->|"Check Cache"| Redis
RiskEngine -.->|"On Miss: Read Trades"| Postgres
The mathematical engine in src/services/analytics.py executes without floating-point inaccuracies using Python's Decimal type:
-
Win Rate (%):
$$\text{Win Rate} = \left(\frac{N_{\text{winning}}}{N_{\text{closed}}}\right) \times 100$$ -
Profit Factor:
$$\text{Profit Factor} = \frac{\sum \text{Gross Profits}}{\sum |\text{Gross Losses}|}$$ (Returnsnullif no losses have occurred, indicating infinite profit factor). -
Maximum Peak-to-Trough Drawdown (Monetary & Percentage): For chronological equity trajectory
$E_t = \text{Initial Balance} + \sum_{i=1}^t \text{PnL}_i$ : $$\text{Peak}t = \max{1 \le k \le t}(E_k)$$$$\text{Drawdown}_t = \text{Peak}_t - E_t$$ $$\text{Max Drawdown %} = \max_t \left(\frac{\text{Drawdown}_t}{\text{Peak}_t} \times 100\right)$$ -
Average Risk/Reward Ratio (RRR):
$$\text{RRR} = \frac{\text{Average Win}}{\text{Average Loss}}$$ -
Mathematical Expectancy:
$$\text{Expectancy} = (\text{Win Rate} \times \text{Avg Win}) - (\text{Loss Rate} \times \text{Avg Loss}) = \frac{\text{Net Profit}}{N_{\text{closed}}}$$
To boot the entire stack (React Frontend, FastAPI Backend, PostgreSQL 16, Redis 7, automated migrations, and demo seed data) in a single command:
docker compose up -d --build
### ๐ Accessing the Services
Once the containers are running:
- **Frontend Dashboard:** [http://localhost:3000](http://localhost:3000)
- **API Swagger UI:** [http://localhost:8000/docs](http://localhost:8000/docs)The containerized healthchecks will automatically ensure:
db(Postgres) andredisare healthy.alembic upgrade headruns to apply all schema revisions.scripts/seed_data.pypopulates a demo user, 2 accounts, and 50 realistic trades.app(FastAPI) starts onhttp://localhost:8000.frontend(React + Nginx) builds and serves onhttp://localhost:3000.
- Trading Terminal Web Dashboard: http://localhost:3000
- Swagger Interactive API Docs: http://localhost:8000/docs
- ReDoc Documentation: http://localhost:8000/redoc
- Backend Healthcheck: http://localhost:8000/health
| Attribute | Value |
|---|---|
demo@riskflow.io |
|
| Password | DemoPassword123! |
| Pre-configured Accounts | 1. FTMO Funded $100k (PropFirm, USD)2. Interactive Brokers Swing Portfolio (Personal, EUR) |
{
"email": "trader@example.com",
"password": "SecurePassword123!"
}Response (201 Created):
{
"id": "e2a4a34b-4bbf-4c7c-9b7e-9626e2e505ec",
"email": "trader@example.com",
"created_at": "2026-10-03T16:00:00Z"
}{
"email": "demo@riskflow.io",
"password": "DemoPassword123!"
}Response (200 OK):
{
"access_token": "eyJhbGciOi...",
"refresh_token": "eyJhbGciOi...",
"token_type": "bearer",
"expires_in": 1800
}Headers: Authorization: Bearer <token>
{
"name": "Evaluation Step 1",
"broker_type": "PropFirm",
"initial_balance": "100000.00",
"currency": "USD"
}Ingests a trade, updates account equity, invalidates Redis analytics cache, and broadcasts to WebSockets.
{
"account_id": "4161bb7a-364e-4f3d-9d41-a164985ca88b",
"symbol": "XAUUSD",
"direction": "BUY",
"entry_price": "2350.50",
"lot_size": "2.0",
"status": "OPEN"
}{
"exit_price": "2365.00",
"pnl": "2900.00"
}Retrieves calculated risk metrics with 60s Redis caching.
{
"account_id": "4161bb7a-364e-4f3d-9d41-a164985ca88b",
"total_trades": 50,
"closed_trades": 45,
"open_trades": 5,
"winning_trades": 26,
"losing_trades": 19,
"break_even_trades": 0,
"win_rate_pct": "57.78",
"loss_rate_pct": "42.22",
"gross_profit": "28450.00",
"gross_loss": "12100.00",
"net_profit": "16350.00",
"profit_factor": "2.3512",
"max_drawdown_amount": "3450.00",
"max_drawdown_pct": "3.18",
"average_win": "1094.23",
"average_loss": "636.84",
"risk_reward_ratio": "1.7182",
"expectancy": "363.33",
"cached": true,
"calculated_at": "2026-10-03T16:05:00Z"
}Connect to:
ws://localhost:8000/api/v1/ws/accounts/{account_id}?token=<jwt_access_token>
Upon connection:
{
"event_type": "CONNECTED",
"account_id": "4161bb7a-364e-4f3d-9d41-a164985ca88b",
"message": "Successfully subscribed to real-time events for account 4161bb7a-364e-4f3d-9d41-a164985ca88b"
}When a new trade is created or closed, connected clients immediately receive:
{
"event_type": "TRADE_CREATED",
"account_id": "4161bb7a-364e-4f3d-9d41-a164985ca88b",
"trade": {
"id": "c1f7b76a-3958-4770-b747-d1cb89b6f52e",
"account_id": "4161bb7a-364e-4f3d-9d41-a164985ca88b",
"symbol": "US100",
"direction": "BUY",
"entry_price": "19250.00",
"exit_price": null,
"lot_size": "1.0",
"pnl": null,
"opened_at": "2026-10-03T16:08:12Z",
"closed_at": null,
"status": "OPEN"
},
"timestamp": "2026-10-03T16:08:12Z"
}python -m venv .venv
source .venv/bin/activate # On Windows: .venv\Scripts\activate
pip install -r requirements-dev.txtruff check .
ruff format --check .mypypytest -v --cov=src --cov-report=term-missing --cov-fail-under=80A fully automated CI pipeline is configured at .github/workflows/ci.yml. On every push and pull request to main and develop:
- Spawns ephemeral PostgreSQL 16 and Redis 7 service containers.
- Checks code style and imports with Ruff.
- Enforces static typing with Mypy.
- Runs integration and unit tests with Pytest.
- Fails the build if test coverage drops below 80%.
- Archives and uploads coverage reports.
This project is open-source and distributed under the MIT License.