QuantRisk
# Safety-First MCP Quant Risk Orchestration Engine
This project is a production-like paper-trading and risk orchestration platform designed around deterministic pre-trade validation, auditability, and fail-closed operational controls. It includes a browser dashboard, REST API, MCP tools, PostgreSQL persistence, Redis controls, and Docker deployment.
> Safety posture: live order routing is disabled by default and hard-coded to paper mode. This repository is designed to support controlled paper trading and operational validation, not live broker execution.
## Architecture Overview
```text
MCP Client / Agent
|
v
FastMCP Server
|
+--> Risk Engine (VaR, drawdown, max position)
+--> Order State Machine (QUEUED -> VALIDATED -> APPROVED -> PAPER_FILLED)
+--> PostgreSQL persistence (orders, positions, audit_logs)
+--> Redis cache and token-bucket rate limiter
+--> FastAPI gateway (dashboard, REST API, /healthz, /metrics)
+--> Prometheus + Grafana observability
```
## Portfolio Application
The FastAPI gateway serves the dashboard at `http://localhost:8000/`. The dashboard provides:
- synthetic market state and order-book depth
- risk evaluation before execution
- paper-order submission
- open positions and recent orders
- immutable audit events
- portfolio and circuit-breaker status
- explicit `PAPER MODE` and `FAIL-CLOSED` safety indicators
The dashboard is intentionally a live paper-trading console, not a real-money trading interface.
### Is the website hard-coded?
The UI does not fabricate order results. It calls the FastAPI endpoints, which execute the risk engine and persist orders, positions, and audit events in PostgreSQL. Redis supplies rate limiting and alert publishing.
The market feed is intentionally synthetic and deterministic. A ticker produces a repeatable demonstration quote, depth, spread, and feature vector instead of connecting to an exchange. This keeps the demo safe and reproducible. Replacing `_market_state()` with a validated market-data adapter is the production integration boundary.
### Browser-only workflow
You can use the complete paper-trading application from the website without an MCP client:
1. Enter a ticker to inspect its market state.
2. Evaluate a BUY or SELL order against the risk controls.
3. Submit the order through guarded paper execution.
4. View the persisted order, position, and audit records.
5. Run a portfolio risk report.
6. Run a deterministic stress scenario.
7. Monitor the circuit breaker and system status.
MCP clients and the website are two interfaces over the same workflow skills. The website is the easiest human interface; MCP is the automation interface for agents.
## REST API
The dashboard uses these HTTP endpoints:
| Method | Endpoint | Purpose |
| --- | --- | --- |
| `GET` | `/api/status` | Paper mode, portfolio, and breaker status |
| `GET` | `/api/market/{ticker}` | Synthetic market state |
| `POST` | `/api/risk/evaluate` | Evaluate ticker, side, and quantity |
| `POST` | `/api/orders/paper` | Validate and fill a paper order; requires `X-Idempotency-Key` |
| `GET` | `/api/orders` | Recent persisted orders |
| `GET` | `/api/positions` | Persisted paper positions |
| `GET` | `/api/audit-events` | Recent risk and execution events |
| `POST` | `/api/circuit-breaker` | Operator-triggered trading pause |
| `GET` | `/api/skills` | Discover available workflow skills |
| `GET` | `/api/portfolio/risk-report` | Run the portfolio risk-report skill |
| `POST` | `/api/portfolio/stress-test?shock_percent=-5` | Run the portfolio stress-test skill |
Example PowerShell request:
```powershell
$body = @{ ticker = "AAPL"; side = "BUY"; qty = 10 } | ConvertTo-Json
Invoke-RestMethod http://localhost:8000/api/orders/paper -Method Post `
-Headers @{ "X-Idempotency-Key" = "demo-aapl-order-001" } `
-ContentType "application/json" -Body $body
```
Each order key is cached in Redis for 24 hours. Repeating the same key returns the original completed payload without re-running risk or filling another order. Execution also acquires `lock:position:{ticker}` with a 500ms deadline; if another worker holds that ticker lock, the API returns `409 Conflict` and records `distributed_lock_timeout` in the audit log.
## MCP Tools and Skills
MCP tools are the machine-callable skills of this application. An MCP client or agent can discover and invoke them through the FastMCP server. They all use the same risk and order-control concepts as the dashboard API:
| MCP tool | Skill |
| --- | --- |
| `get_market_state` | Inspect synthetic quote, depth, spread, and GNN features |
| `evaluate_risk` | Validate an order against position, VaR, drawdown, and rate limits |
| `execute_trade` | Create a queued order, apply controls, and paper-fill approved orders; accepts optional `idempotency_key` |
| `list_skills` | Discover the available quant workflow skills |
| `portfolio_risk_report` | Summarize positions, exposure, limits, and breaker state |
| `stress_test_portfolio` | Project portfolio P&L under a deterministic price shock |
The same catalog is available to browser and API clients at:
```text
GET /api/skills
```
Example skill-oriented agent flow:
```text
1. list_skills
2. get_market_state("AAPL")
3. evaluate_risk("AAPL", "BUY", 10)
4. execute_trade("AAPL", "BUY", 10)
5. portfolio_risk_report()
6. stress_test_portfolio(-5)
```
Skills are intentionally workflow-level capabilities, while tools remain the individual callable operations. Both entry points use the same fail-closed risk engine, order state machine, PostgreSQL records, Redis controls, and audit events.
The reusable skill pattern is:
```text
request -> rate limit -> risk evaluation -> state transition -> persistence -> audit + alert
```
You can add future skills as new `@mcp.tool()` functions and corresponding REST routes, but they should call shared domain services rather than duplicate risk logic. Current higher-level skills include portfolio-risk reporting and scenario stress testing. Appropriate future skills include reconciliation checks, operator health summaries, and model-drift checks.
## Order State Machine
The order lifecycle is deliberately strict and fail-closed:
```text
QUEUED -> VALIDATED -> APPROVED -> PAPER_FILLED
\-> REJECTED
VALIDATED -> REJECTED
APPROVED -> REJECTED
REJECTED -> * (terminal)
PAPER_FILLED -> * (terminal)
```
Any invalid transition raises an explicit domain exception via `OrderStateTransitionError`.
## Risk Architecture
The risk engine enforces:
- max position size per asset
- account-level VaR threshold
- dynamic daily drawdown circuit breaker
- audit-log immutability for rejected trades
- Redis pub/sub alerting on risk breaches
If any limit is breached, the system writes the rejection event to `audit_logs`, rejects the order, and triggers the alert channel.
## Database Layout
The project uses PostgreSQL + SQLAlchemy Async ORM. Core schema:
- `orders`: id, ticker, side, qty, price, status, created_at, updated_at
- `positions`: ticker, qty, avg_entry_price, unrealized_pnl
- `audit_logs`: id, order_id, event_type, details (JSONB), timestamp
A SQL migration script is provided in `migrations/001_init_schema.sql`.
## Runtime Components
- `mcp_server.py`: MCP tools and higher-level skills for market state, risk, execution, reporting, and stress testing
- `core/risk.py`: deterministic risk engine and fail-closed breaker
- `core/cache.py`: Redis-backed state and token-bucket limiter
- `core/db.py`: Async SQLAlchemy session and table definitions
- `core/state_machine.py`: order lifecycle enforcement
- `api/gateway.py`: FastAPI dashboard, REST API, health, and Prometheus metrics endpoints
- `frontend/`: responsive browser dashboard served by FastAPI
- `migrations/001_init_schema.sql`: PostgreSQL schema migration
- `.github/workflows/ci.yml`: automated tests, formatting, and lint checks
## Quick Start
```bash
python -m venv .venv
source .venv/bin/activate # or .\.venv\Scripts\Activate.ps1 on Windows
python -m pip install -e .[dev]
cp .env.example .env
python -m uvicorn api.gateway:app --host 0.0.0.0 --port 8000
```
Open the dashboard at `http://localhost:8000/`.
Local MCP runner:
```bash
python mcp_server.py
```
## Testing and Quality Gates
```bash
pytest -q
black --check .
flake8 .
```
The verified local integration flow is:
```text
healthz -> market state -> paper order -> PostgreSQL order/position/audit records
```
The test suite covers state transitions, risk rejection, drawdown/VaR controls, Redis rate limiting, and database initialization.
## Deployment Stack
The repository includes container health checks and a full local observability stack:
- PostgreSQL
- Redis
- Prometheus
- Grafana
- trading-engine service
Run the full stack:
```bash
docker compose up --build
```
If port `8000` is already used on your machine, choose another host port in PowerShell:
```powershell
$env:APP_PORT = "8001"
docker compose up -d --build
```
Then open `http://localhost:8001/`.
For a detached deployment:
```bash
docker compose up -d --build
```
Then visit:
- http://localhost:8000/healthz
- http://localhost:8000/metrics
- http://localhost:3000 (Grafana)
- http://localhost:9090 (Prometheus)
Check the running stack:
```powershell
Invoke-RestMethod http://localhost:8000/healthz | ConvertTo-Json
```
Expected health response includes:
```json
{"status":"ok","database":true,"redis":true,"paper_mode":true}
```
## Operational Safety Guarantees
This design intentionally enforces the following:
1. paper-only execution by default
2. explicit validation before execution
3. immutable audit records for every risk decision
4. fail-closed circuit breaker for drawdown and VaR violations
5. Redis-backed rate limiting for order spam mitigation
6. structured telemetry for trade execution and risk rejection events
## Production Hardening Path
This project is production-oriented but still intentionally constrained to paper trading. It is resume-ready as a deployed portfolio application, but it is not a live brokerage system. Before any real-money integration, the next milestones are:
1. migrate from synthetic market data to a validated feed provider
2. add durable approvals and secrets management
3. enforce multi-party sign-off for live execution
4. replace process-local risk state with fully shared transactional state
5. add authentication, authorization, HTTPS, restricted CORS, and managed secrets
6. add broker execution, idempotency, reconciliation, and exchange-level controls
Never set a public demo to live mode. The intended public deployment is a paper-trading demonstration with protected infrastructure dependencies.
See [docs/architecture.md](docs/architecture.md), [docs/operational-controls.md](docs/operational-controls.md), and [docs/threat-model.md](docs/threat-model.md).
TDQS
Scored across 5 tools
Each tool maps to a clearly distinct concern: signal generation, market data, pre-trade validation, paper order submission, and circuit breaking. There is no meaningful overlap or ambiguity between the tools.
Most tools follow a clear verb_noun pattern like generate_alpha_signal, validate_order, and submit_paper_order. The exception is market_snapshot, which is noun-only and breaks the otherwise consistent convention.
Five tools is a well-scoped size for a focused quant risk and paper trading server. Each tool serves a distinct step in the intended workflow without redundancy or bloat.
The core flow of generating a signal, validating an order, submitting a paper order, and tripping a breaker is covered. However, there is no way to query or cancel submitted paper orders, and no visibility into the circuit breaker state, leaving notable lifecycle gaps.