QuantDinger Documentation

AI quantitative trading platform for crypto, stocks, and forex with backtesting, live trading, market data, and multi-agent research.vibe-trading...

10,136 stars Python Python 1 file ยท ~20,852 tokens #agent#ai#alpaca#backtesting#binance#coinbase#crypto#exchange
RAW Doc

Docker & Self-Hosted Deployment Verified OCI

Deploy QuantDinger on any server, homelab, or cloud container platform.

1-Click Terminal Command
bash (docker run)
docker run -d --name quantdinger --restart always brokermr810/quantdinger:latest
Configured Services & Ports
โš™๏ธ frontend
image: build locally
โš™๏ธ mobile
image: build locally
docker-compose.yml
yaml (docker-compose.yml)
# Override file for local frontend builds.
# Usage:
#   git clone  ./QuantDinger-Vue
#   docker compose -f docker-compose.yml -f docker-compose.build.yml up --build
#
# Without this override, the main compose file only pulls the prebuilt
# frontend image from GHCR and never touches ./QuantDinger-Vue/.
#
# Tip: set `COMPOSE_FILE=docker-compose.yml:docker-compose.build.yml` in your
# root `.env` to make `docker compose up --build` pick this up automatically.

services:
  frontend:
    # Disable the `pull_policy: always` inherited from docker-compose.yml.
    # Without this, a plain `docker compose up` (or `pull frontend`) would
    # silently overwrite the locally-built image with the GHCR `:latest`,
    # discarding the user's local Vue edits.
    pull_policy: build
    build:
      context: ${FRONTEND_SRC_PATH:-./QuantDinger-Vue}
      dockerfile: Dockerfile
      args:
        APP_VERSION: ${APP_VERSION:-}
        GIT_TAG: ${GIT_TAG:-${FRONTEND_TAG:-${IMAGE_TAG:-}}}

  mobile:
    pull_policy: build
    build:
      context: ${MOBILE_SRC_PATH:-./QuantDinger-Mobile}
      dockerfile: Dockerfile
      args:
        APP_VERSION: ${APP_VERSION:-}
        GIT_TAG: ${GIT_TAG:-${MOBILE_TAG:-${IMAGE_TAG:-}}}

File: README.md

QuantDinger can submit real orders when live trading is explicitly enabled.
Start with paper trading, use restricted API keys, and review the risk and
compliance requirements for your jurisdiction. This project does not provide
investment advice.

What QuantDinger is

QuantDinger is an open-source AI Trading OS for independent traders, Python
strategy authors, and small teams. Its local-first, self-hosted design keeps
market data, strategy code, broker credentials, and deployment under the
operator's control.

The project combines:

  • multi-provider AI market research and analysis;
  • Python indicators and Strategy API V2 development;
  • server-side backtesting and experiment workflows;
  • paper and live execution across crypto exchanges and traditional brokers;
  • web, mobile H5, human API, Agent Gateway, and MCP access;
  • PostgreSQL-backed state, durable workers, audit logs, and optional monitoring.

It is not a black-box signal service. Strategy code, risk settings, credentials,
and deployment remain under the operator's control.

What changed in v5

The v5 backend is organized around explicit runtime and operational boundaries:

  • the HTTP API no longer owns long-running trading or scheduler loops;
  • trading, scheduling, Celery jobs, and migrations run as separate processes;
  • Celery handles finite, retryable work while long-lived strategy runtimes stay
    in the trading worker;
  • cache Redis and durable job Redis use separate instances and eviction policies;
  • high-risk API contracts are represented in OpenAPI and protected by tests;
  • JSON logs, request IDs, Prometheus metrics, dashboards, and alert rules are
    available through an optional observability overlay;
  • the production overlay runs backend processes as a non-root user with a
    read-only root filesystem, dropped capabilities, and resource limits;
  • CI checks syntax, lint, tests, release gates, Compose files, dependencies,
    source security, secrets, API compatibility, version drift, and text encoding.

The source version is declared in VERSION. Git release tags use the
same semantic version with a leading v, for example v5.0.1.

Architecture

The diagram above shows the complete product and process architecture. The
runtime topology below focuses on container-to-container ownership and data flow.

mermaid
flowchart TB
    C["Web / Mobile / API / MCP clients"]
    FE["Nginx frontend services"]
    API["Flask + Gunicorn API"]
    PG[("PostgreSQL")]
    CACHE[("Redis cache")]
    JOBS[("Redis jobs")]
    TW["Trading worker"]
    SW["Scheduler worker"]
    CW["Celery worker"]
    BEAT["Celery beat"]
    PROM["Prometheus"]
    GRAF["Grafana"]
    ALERT["Alertmanager"]

    C --> FE --> API
    API --> PG
    API --> CACHE
    API -->|"durable commands"| PG
    TW -->|"leases, orders, heartbeats"| PG
    SW -->|"schedules, monitoring, heartbeats"| PG
    API -->|"finite async jobs"| JOBS
    BEAT --> JOBS --> CW
    CW --> PG
    API -. metrics .-> PROM
    PG -. exporter .-> PROM
    CACHE -. exporter .-> PROM
    JOBS -. exporter .-> PROM
    PROM --> GRAF
    PROM --> ALERT

One backend image is reused by several containers with different commands:

Process Responsibility
migration Applies the database schema and exits before application services start.
backend Handles HTTP, authentication, validation, and durable command submission.
trading-worker Owns strategy runtimes, pending orders, broker sessions, and reconciliation.
scheduler-worker Runs portfolio, deployment, payment, and signal schedules.
celery-worker Executes finite AI, backtest, experiment, report, and maintenance jobs.
celery-beat Dispatches periodic Celery tasks.

See Backend process roles,
architecture, and
concurrency model for the ownership rules.

Quick start

Option A: prebuilt images

Prerequisites: Docker with Compose v2. Node.js and a local Python environment are
not required.

Linux or macOS:

bash
curl -fsSL https://raw.githubusercontent.com/OpenByteInc/QuantDinger/main/install.sh | bash

Windows PowerShell:

powershell
irm https://raw.githubusercontent.com/OpenByteInc/QuantDinger/main/install.ps1 | iex

The installer asks for the initial administrator credentials, generates the
required secrets, downloads the GHCR Compose stack, and starts it.

Open:

Docker administrator and settings notes

Detailed guides: English |
ไธญๆ–‡

On a fresh database, the backend creates the initial administrator from
ADMIN_USER, ADMIN_PASSWORD, and optional ADMIN_EMAIL. Passwords are stored
as hashes, never as plaintext. An existing PostgreSQL volume is not overwritten:
the backend only replaces the untouched legacy quantdinger / 123456
administrator when a non-default administrator is explicitly configured. It
never overwrites an account whose password was already changed, and it refuses
to promote an existing account that already uses the requested username.

Manual Docker deployments retain quantdinger / 123456 only for backward
compatibility when the administrator variables are left at their defaults. This
credential is not suitable for an internet-facing deployment; change it before
first start or immediately after the first login. The one-command installer does
not accept 123456 as the chosen password.

The Settings UI writes runtime configuration to /app/.env. In the GHCR stack
this is the host backend.env; in a source deployment it is
backend_api_python/.env. Current backend images automatically give runtime UID
10001 ownership and keep mode 600. Do not use chmod 755 or recursive 777:
these files contain passwords and API keys, and 755 still does not grant write
access to UID 10001 when root owns the file.

Verify write access with:

bash
docker compose exec -u 10001:10001 -T backend \
  sh -c 'test -w /app/.env && echo writable=yes || echo writable=no'

The hardened production override intentionally mounts /app/.env read-only.
When using docker-compose.production.yml, manage configuration on the host and
recreate the services instead of saving it from the Settings UI. See the
English guide or
ไธญๆ–‡ๆŒ‡ๅ— for
legacy-image recovery and rootless/NFS notes.

Option B: source checkout

bash
git clone https://github.com/OpenByteInc/QuantDinger.git
cd QuantDinger
cp backend_api_python/env.example backend_api_python/.env
cp .env.example .env

Before the first start, replace the example values in both environment files:

File Required production values
backend_api_python/.env SECRET_KEY, CREDENTIAL_ENCRYPTION_KEY, ADMIN_USER, ADMIN_PASSWORD
.env POSTGRES_PASSWORD, REDIS_PASSWORD, CELERY_REDIS_PASSWORD, GRAFANA_ADMIN_PASSWORD

Generate independent secrets with:

bash
python -c "import secrets; print(secrets.token_hex(32))"

Start the core stack from local backend source:

bash
docker compose up -d --build
docker compose ps

The base stack does not start Prometheus, Grafana, or Alertmanager. This keeps
the default open-source installation smaller.

For detailed installation paths, Windows notes, China mirror settings, and
PostgreSQL migration guidance, see
Installation troubleshooting and the
cloud deployment guide.

Production deployment

Validate secrets before starting a production stack:

bash
python backend_api_python/scripts/check_production_config.py \
  --env-file .env \
  --env-file backend_api_python/.env

Start the hardened runtime with optional observability:

bash
docker compose \
  -f docker-compose.yml \
  -f docker-compose.production.yml \
  -f docker-compose.observability.yml \
  up -d --build

Omit docker-compose.observability.yml when the host is resource-constrained or
monitoring is provided externally.

Production rules:

  • expose only a TLS reverse proxy on ports 80/443;
  • keep PostgreSQL, both Redis instances, Prometheus, Grafana, and Alertmanager
    off the public internet;
  • do not deploy with example passwords or empty encryption keys;
  • back up PostgreSQL and the durable redis-jobs volume;
  • keep cache Redis disposable and never use it as the Celery broker;
  • review worker health and application readiness after every deployment.

The full checklist is in Production hardening.

Local endpoints

All published ports bind to loopback by default.

Service Default URL Purpose
Web http://127.0.0.1:8888 Desktop web client and same-origin API proxy.
Mobile H5 http://127.0.0.1:8889 Mobile web client and same-origin API proxy.
Backend http://127.0.0.1:5000 Direct API access and health endpoints.
Grafana http://127.0.0.1:3000 Dashboards; available only with the observability overlay.
Prometheus http://127.0.0.1:9090 Metrics storage and queries; optional.
Alertmanager http://127.0.0.1:9093 Alert grouping, silencing, and delivery; optional.

Container-only ports such as the job Redis and exporters are not published to
the host.

Observability

The monitoring stack is optional by design:

  • Prometheus collects API, worker, PostgreSQL, and Redis metrics.
  • Grafana turns those metrics into operator dashboards.
  • Alertmanager groups alerts, manages silences, and sends notifications once
    a receiver is configured.

Start it for local diagnostics without the production overlay:

bash
docker compose \
  -f docker-compose.yml \
  -f docker-compose.observability.yml \
  up -d

Monitoring services stay on 127.0.0.1. Use a VPN, SSH tunnel, or authenticated
reverse proxy for remote administration. See
Observability for dashboards, alerts, retention, and
receiver configuration.

Security model

  • Broker credentials and MFA secrets are encrypted with a stable
    CREDENTIAL_ENCRYPTION_KEY.
  • Agent tokens are hashed, scoped, rate-limited, and audit-logged.
  • Agent trading is paper-only by default; live access requires both token and
    server-side authorization.
  • Long-running strategy ownership uses leases, heartbeats, and fencing tokens.
  • Production containers run without root privileges or Linux capabilities.
  • Host port defaults are loopback-only; public access should terminate at a TLS
    reverse proxy.

Report vulnerabilities privately according to SECURITY.md. Do
not include credentials, account data, or exploitable details in public issues.

Strategy and integration surfaces

Area Current surface
Indicators Python chart overlays, markers, bands, and signals.
Strategies Strategy API V2 intents, sizing, risk, backtests, and live runtime.
Crypto Binance, OKX, Bitget, Bybit, Gate, HTX, and adapter extensions.
Traditional brokers IBKR and Alpaca workflows.
AI providers OpenRouter, OpenAI-compatible APIs, Google, DeepSeek, Grok, MiniMax, and custom endpoints.
Automation Human API, Agent Gateway, MCP server, Celery jobs, schedules, and notifications.

Start with the Indicator guide,
Strategy guide, and
Extension guide.

AI agents and MCP

The Agent Gateway is exposed under /api/agent/v1. The included MCP server lets
clients such as Cursor, Claude Code, and Codex call approved tools without
receiving broker credentials or administrator JWTs.

Live trading through an agent requires all of the following:

  1. a token with trading scope;
  2. paper_only=false on that token;
  3. AGENT_LIVE_TRADING_ENABLED=true on the server;
  4. operator-configured limits and allowlists.

See MCP setup,
Agent quick start, and the
Agent OpenAPI document.

Development

Backend development uses Python 3.12:

bash
cd backend_api_python
python -m venv .venv
python -m pip install -r requirements-dev.txt
python -m pytest -m "not integration and not stress" --ignore=tests/release_gate -q
ruff check app scripts tests

Useful repository checks:

bash
python scripts/check_version.py
python scripts/check_mojibake.py
docker compose -f docker-compose.yml config -q
docker compose -f docker-compose.yml -f docker-compose.production.yml -f docker-compose.observability.yml config -q

API changes should follow API conventions, update the
OpenAPI artifact when required, and pass the compatibility workflow.

Repository layout

This repository contains the backend, worker processes, deployment definitions,
operations configuration, documentation, and MCP server. The desktop and mobile
client source code live in separate repositories; this repository consumes their
published images in the Compose stacks.

text
/* Detailed source-code truncated for AI context efficiency. */

Main execution paths

Flow Path through the repository
Synchronous API request app/routes -> app/services -> database, cache, market-data, or trading adapter
Durable strategy command API route -> PostgreSQL command record -> trading-worker -> strategy runtime and broker adapter
Finite background job API or Celery beat -> job Redis -> app/tasks in celery-worker -> PostgreSQL result
Scheduled domain work app/commands/scheduler.py -> scheduling services -> durable state and notifications
Monitoring API and workers -> app/observability metrics -> Prometheus -> Grafana and Alertmanager
Agent or MCP call MCP client -> mcp_server -> /api/agent/v1 -> the same service layer used by human APIs

Long-lived trading loops belong to the trading worker. Finite, retryable work
belongs to Celery. HTTP routes validate and delegate; they must not own trading
loops, exchange-specific behavior, or large database workflows.

Where changes belong

Change Primary location Usually update as well
Add or modify an HTTP endpoint backend_api_python/app/routes/ app/openapi/, route/contract tests, API docs
Add a business workflow backend_api_python/app/services/ focused service tests
Add an exchange or broker integration app/services/live_trading/ or the broker package credential policy, adapter tests, docs
Add a market-data source app/data_sources/ provider aggregation, cache keys, tests
Add dashboard, news, or macro aggregation app/data_providers/ route facade and cache policy
Add a finite asynchronous task app/tasks/ celery_app.py, queue routing, task tests
Add long-lived process behavior app/workers/, app/commands/, or app/runtime/ Compose command, health checks, ownership tests
Change the database schema backend_api_python/migrations/ migration/release-gate tests and docs
Add metrics or alerts app/observability/ and ops/ dashboard, alert rule, observability docs
Add an MCP tool mcp_server/src/quantdinger_mcp/ Agent Gateway scope, security tests, agent docs

The web and mobile repositories publish their own GHCR images. Node.js is only
needed when building those clients from source. For deeper ownership rules, read
Architecture,
Module boundaries, and
Process roles.

Documentation

The maintained documentation index is available at docs/README.md.

Topic Document
Contributor architecture Architecture
Module ownership Module boundaries
Process and task ownership Process roles
Production runtime Production hardening
Metrics and alerts Observability
Human API contracts API conventions
OpenAPI artifacts API documentation
Strategy development Strategy guide
Indicator development Indicator guide
MCP and agents Agent documentation
Cloud deployment Cloud deployment
Installation problems Troubleshooting

Contributing

Read CONTRIBUTING.md and DEVELOPMENT.md
before opening a pull request. Keep routes thin, preserve API compatibility,
place long-running behavior in the correct process, and include focused tests
for high-risk changes.

These are referral links. QuantDinger may receive a commission or trading-fee
rebate when a user registers through one of them. This does not add a separate
charge to the user; eligibility and terms are controlled by each venue and may
change. Always verify the destination domain before creating an account.

The same links are available in the application under Profile โ†’ Open account
and Broker Accounts โ†’ Open account.

Exchange Signup link
Binance Register
Bitget Register
Bybit Register
OKX Register
Gate.io Register
HTX Register

License and commercial terms

  • Backend source code is licensed under Apache License 2.0.
  • QuantDinger is a product of Open Byte Inc. The name, logo, product
    identity, and commercial licensing are managed separately from the code license.
  • Web frontend source is published in
    QuantDinger Frontend under
    its own source-available license.
  • Mobile H5 and native client source is published in
    QuantDinger Mobile under
    its own source-available license.
  • Trademark, branding, attribution, and watermark use is governed by
    TRADEMARKS.md. Apache 2.0 does not grant trademark rights.

For commercial licensing, frontend source access, branding authorization, or
deployment support:

QuantDinger is intended for lawful research, education, and compliant trading
only
. It must not be used for fraud, market manipulation, sanctions evasion,
money laundering, or other illegal activity. Operators are responsible for
following the laws, licensing requirements, tax rules, broker or exchange terms,
and data regulations that apply in every jurisdiction where they deploy or use
the software.

This project does not provide legal, tax, investment, financial, or regulatory
advice.
Trading, including automated and leveraged trading, can result in the
loss of some or all capital. Historical data, backtests, simulated results, AI
output, indicators, and strategy examples do not guarantee future performance.
Users must independently review strategies, permissions, order limits, and risk
controls before enabling live execution.

The software is provided under the terms of the applicable license and is used
at the operator's own risk. To the extent permitted by law, project maintainers
and contributors disclaim liability for trading losses, data loss, service
interruption, third-party failures, security incidents, or regulatory consequences
arising from use or misuse of the software.

Community and support




Sponsors

QuantDinger's continued development and open-source community are supported by:

| Atlas Cloud

text
AI inference sponsor | **Amazon Web Services**
  
  Cloud infrastructure sponsor |

| --- | --- |

We are grateful to Atlas Cloud for supporting AI
model inference and to Amazon Web Services for
supporting the cloud infrastructure that helps QuantDinger serve its community.

Support the project

If QuantDinger is useful to you, a GitHub star, contribution, or donation helps
fund ongoing development and infrastructure.

Crypto donation address:

text
0x96fa4962181bea077f8c7240efe46afbe73641a7

Crypto transfers are irreversible. Confirm the address and intended network with
the project maintainers before sending funds.

Acknowledgements

QuantDinger stands on top of a strong open-source ecosystem. Special thanks to
the maintainers and contributors of projects including:

P.S. โ€” A note on the name

QuantDinger is a small tribute to
Erwin Schrรถdinger โ€”
the โ€œ-dingerโ€ in our name is the tail of โ€œSchrรถdingerโ€. The cat in the box was a
thought experiment; every un-fired strategy is its own little version of it โ€”
simultaneously winning and losing until the order actually fills. Backtests open
the box. Live trading collapses the wavefunction. Trade carefully.


File: backend_api_python/app/services/alpaca_trading/README.md

Alpaca Trading Module

Trade US stocks, ETFs, and crypto via Alpaca Markets REST API.
Mirrors ibkr_trading/ module structure for consistency.

Why Alpaca?

  • Zero commission on stocks/ETFs/crypto (vs IBKR's per-share or tiered fees)
  • No TWS/Gateway required โ€” pure stateless REST authentication
  • Paper trading built-in โ€” separate paper-api.alpaca.markets endpoint
  • Modern Python SDK โ€” alpaca-py is well-maintained, async-friendly
  • Crypto support โ€” same client handles stocks AND crypto (BTC/USD, ETH/USD, etc.)
  • Fractional shares โ€” buy $5 worth of TSLA without owning a full share

Installation

bash
pip install alpaca-py

Configuration

Add to backend_api_python/.env:

bash
# Paper trading (recommended for development)
ALPACA_API_KEY=PK********************
ALPACA_SECRET_KEY=********************
ALPACA_PAPER=true

# Live trading (only after thorough paper testing)
# ALPACA_API_KEY=AK********************  # Note: AK prefix = live
# ALPACA_SECRET_KEY=********************
# ALPACA_PAPER=false

Key prefix tells you what mode you're in:

  • PK* = paper account (paper-api.alpaca.markets, no real money)
  • AK* = live account (api.alpaca.markets, real money)

Get your keys at:

Basic usage

python
from app.services.alpaca_trading import AlpacaClient, AlpacaConfig

config = AlpacaConfig(
    api_key="PK********************",
    secret_key="********************",
    paper=True,  # paper trading
)
client = AlpacaClient(config)
client.connect()  # Verifies credentials via /account endpoint

# Account snapshot
acct = client.get_account_summary()
print(f"Buying power: ${acct['summary']['BuyingPower']['value']}")

# Place a market BUY of 1 share of SPY
result = client.place_market_order(symbol="SPY", side="buy", quantity=1)
print(f"Order {result.order_id}: filled={result.filled} @ ${result.avg_price}")

# Get current positions
for pos in client.get_positions():
    print(f"{pos['symbol']}: {pos['quantity']} @ ${pos['avgCost']}, unrealized=${pos['unrealizedPnL']:+.2f}")

# Cancel any open order
client.cancel_order(order_id="...")

client.disconnect()

Crypto trading

Alpaca supports crypto using the same client โ€” just pass market_type="crypto":

python
result = client.place_market_order(
    symbol="BTC/USD",  # or "BTCUSD" โ€” auto-normalized
    side="buy",
    quantity=0.01,
    market_type="crypto",
)

Note: crypto orders use time_in_force=GTC (good-till-cancelled) since the market is 24/7;
stock orders default to time_in_force=DAY.

Extended-hours trading

For limit orders on US equities, you can trade in pre-market (4:00-9:30 ET) or
after-hours (16:00-20:00 ET):

python
result = client.place_limit_order(
    symbol="SPY",
    side="buy",
    quantity=1,
    price=740.00,
    extended_hours=True,  # Enables pre/post-market trading
)

API endpoints (when registered as Flask blueprint)

All endpoints require @login_required:

Method Path Purpose
GET /api/alpaca/status Connection state
POST /api/alpaca/connect Connect with API key/secret
POST /api/alpaca/disconnect Clear local state
GET /api/alpaca/account Account summary (buying power, equity, etc.)
GET /api/alpaca/positions Current positions
GET /api/alpaca/orders Open orders
POST /api/alpaca/order Place market or limit order
DELETE /api/alpaca/order/ Cancel order
GET /api/alpaca/quote/<symbol>?marketType=USStock Latest bid/ask

Differences from IBKR module

Feature IBKR Alpaca
Auth TWS/Gateway socket (host/port/clientId) REST API key+secret
Order IDs Integer UUID string
Connection Stateful, persistent socket Stateless REST
Paper mode (IBKR TWS/Gateway) Port 7497/4002 Different base URL
Symbol format AAPL (stocks), 0700.HK (HK) AAPL (US), BRK.B (US class), BTC/USD (crypto)
Extended hours Configurable per-order Configurable per-order (limit only)
Crypto No (separate IBKR Crypto product) Yes, same client

Troubleshooting: WebSocket `400 invalid syntax`

QuantDinger connection test and live orders use the REST Trading API (TradingClient.get_account()), not the market-data WebSocket at wss://stream.data.alpaca.markets/....

If you see Alpaca error code 400 / invalid syntax from the streaming docs, that is almost always from a WebSocket client (custom script, another app, or a chart feed), not from /api/alpaca/connect or /strategies/test-connection.

Common causes:

Issue Fix
Subscribe before auth After connected, send {"action":"auth","key":"...","secret":"..."} within 10s
Wrong JSON shape Use action + channel keys, e.g. {"action":"subscribe","trades":["AAPL"]}
Invalid symbol US stocks: AAPL (no BTC/USDT). Crypto: BTC/USD (Alpaca does not use BTC/USDT)
Class shares BRK/B โ†’ BRK.B for REST; do not treat as a crypto pair

This module normalizes symbols (symbols.py): BTC/USDT โ†’ BTC/USD for crypto, BRK/B โ†’ BRK.B for equities.

Limitations / TODO

  • No bracket orders yet (Alpaca supports them; not yet wrapped)
  • No stop or stop-limit orders yet (alpaca-py supports StopOrderRequest, StopLimitOrderRequest)
  • No historical bar fetching helpers (use StockHistoricalDataClient.get_stock_bars() directly)
  • No WebSocket streaming (alpaca-py supports it; not yet wired)
  • No options trading (Alpaca recently added; not implemented)

Reference


File: backend_api_python/app/services/ibkr_trading/README.md

Interactive Brokers Trading Module

Supports US stocks trading via TWS or IB Gateway.

Installation

bash
pip install ib_insync

Or the dependency is already in requirements.txt.

Port Reference

Client Live Port Paper Port
TWS 7496 7497
IB Gateway 4001 4002

TWS / IB Gateway Configuration

  1. Open TWS or IB Gateway
  2. Go to Configure -> API -> Settings
  3. Enable the following options:
    • โœ… Enable ActiveX and Socket Clients
    • โœ… Allow connections from localhost only
  4. Set Socket port (refer to the table above)
  5. Click Apply / OK

Client ID (important)

Interactive Brokers allows one API connection per clientId. If two programs use the same id, the newer connection replaces the older โ€” often within a few seconds it looks like a random disconnect, and live orders then fail with โ€œFailed to connectโ€.

  • POST /api/ibkr/connect (admin UI test) defaults to clientId=1.
  • Strategy / live-order clients use ibkr_client_id from credentials (default 7 when omitted) or env IBKR_ORDER_CLIENT_ID (default 7).

Keep manual testing on 1 and automation on 7 (or any other unused id). If you still see drops on Windows, ensure ib_insync runs with asyncio patched (QuantDinger calls util.patchAsyncio() at app startup).

API Endpoints

Connection Management

text
GET  /api/ibkr/status          # Get connection status
POST /api/ibkr/connect         # Connect to TWS/Gateway
POST /api/ibkr/disconnect      # Disconnect

Account Queries

text
GET  /api/ibkr/account         # Account information
GET  /api/ibkr/positions       # Current positions
GET  /api/ibkr/orders          # Open orders

Trading

text
POST   /api/ibkr/order         # Place order
DELETE /api/ibkr/order/    # Cancel order

Market Data

text
GET  /api/ibkr/quote?symbol=AAPL&marketType=USStock

Usage Examples

Connect

bash
curl -X POST http://localhost:5000/api/ibkr/connect \
  -H "Content-Type: application/json" \
  -d '{"host": "127.0.0.1", "port": 7497, "clientId": 1}'  # TWS Paper default

Place Order

bash
# Market order: buy 10 shares of AAPL
curl -X POST http://localhost:5000/api/ibkr/order \
  -H "Content-Type: application/json" \
  -d '{"symbol": "AAPL", "side": "buy", "quantity": 10, "marketType": "USStock"}'

# Limit order: sell 100 shares of MSFT
curl -X POST http://localhost:5000/api/ibkr/order \
  -H "Content-Type: application/json" \
  -d '{"symbol": "MSFT", "side": "sell", "quantity": 100, "marketType": "USStock", "orderType": "limit", "price": 400}'

Get Positions

bash
curl http://localhost:5000/api/ibkr/positions

Symbol Format

Market Format Examples
US Stock Ticker symbol AAPL, TSLA, GOOGL

Important Notes

  1. TWS/Gateway must be running: Ensure TWS or IB Gateway is started and logged in before using the API
  2. Market data subscription: Real-time quotes may require market data subscription
  3. Client ID: Use different clientId if multiple programs connect to the same TWS/Gateway
  4. Readonly mode: Set readonly: true to only query without trading
  5. Multi-account: Specify account parameter if you have multiple sub-accounts

Troubleshooting

Error Cause Solution
Connection failed TWS/Gateway not running Start and login to TWS/Gateway
Connection failed Wrong port Check API port setting in TWS/Gateway
Connection failed API not enabled Enable Socket API in TWS/Gateway settings
Client ID conflict Same clientId already connected Use a different clientId
Invalid contract Wrong symbol format Check symbol format

Removing This Module

To remove this module, delete the following files/directories:

text
backend_api_python/app/services/ibkr_trading/    # Entire directory
backend_api_python/app/routes/ibkr.py            # Route file

Then remove the related import and registration code in app/routes/__init__.py.

Docker Note

When running in Docker, IBKR trading requires TWS/IB Gateway to be accessible from the container.
For local deployment, you can:

  1. Run TWS/Gateway on host machine
  2. Use host network mode or configure port mapping
  3. Set host to the host machine's IP address (e.g., host.docker.internal on Docker Desktop)

Note: IBKR connection parameters are configured per-strategy in the frontend, not via environment variables.


File: backend_api_python/README.md

QuantDinger Python Backend

This directory contains the Flask API, domain services, background workers,
database migrations, OpenAPI integration, and backend tests for QuantDinger.

Start with the project README for product installation. This
document is the backend contributor and operator quick reference.

Runtime model

The production deployment reuses one backend image across independent process
roles:

Role Command Ownership
API gunicorn -c gunicorn_config.py run:app HTTP, authentication, validation, and durable command submission.
Migration python -m app.commands.migrate Fail-fast schema application before services start.
Trading python -m app.commands.trading_worker Strategy runtimes, pending orders, broker sessions, and reconciliation.
Scheduler python -m app.commands.scheduler Portfolio, deployment, payment, and signal schedules.
Celery worker celery -A app.celery_app:celery_app worker Finite AI, backtest, experiment, report, and maintenance jobs.
Celery beat celery -A app.celery_app:celery_app beat Periodic task dispatch.

HTTP processes must not start trading or scheduler threads. Celery must not own
long-lived strategy loops or broker sessions. See
Process roles and durable tasks.

Storage model

  • PostgreSQL 18 is the system of record.
  • redis is an evictable application cache.
  • redis-jobs is the durable Celery broker/result tier with AOF and
    noeviction.
  • Strategy ownership uses PostgreSQL commands, leases, fencing tokens, and
    worker heartbeats.

Queue state must never share the cache Redis eviction policy.

Directory map

text
app/
  commands/             Process entry points and operational commands
  config/               Environment-backed configuration
  data_providers/       Aggregated market and global data providers
  data_sources/         Raw market data adapters
  observability/        Metrics and request instrumentation
  openapi/              Human API schemas, registration, and export metadata
  routes/               HTTP facades and compatibility routes
  services/             Domain workflows and integration orchestration
  tasks/                Celery task definitions
  utils/                Small infrastructure helpers
migrations/             PostgreSQL schema and incremental migrations
scripts/                Backend quality, export, and production checks
tests/                  Unit, integration, contract, and release-gate tests

Read Backend architecture and
Module boundaries before larger changes.

Configuration

Create the runtime environment file:

bash
cp env.example .env

At minimum, replace these values before a shared or production deployment:

dotenv
SECRET_KEY=
CREDENTIAL_ENCRYPTION_KEY=
ADMIN_USER=
ADMIN_PASSWORD=

Generate each secret independently:

bash
python -c "import secrets; print(secrets.token_hex(32))"

Docker-level database, Redis, Grafana, port, image, and resource settings belong
in the repository-root .env; application runtime settings belong here.

Docker workflow

Run these commands from the repository root.

Core development stack:

bash
docker compose up -d --build
docker compose ps

Production-hardened stack with optional monitoring:

bash
python backend_api_python/scripts/check_production_config.py \
  --env-file .env \
  --env-file backend_api_python/.env

docker compose \
  -f docker-compose.yml \
  -f docker-compose.production.yml \
  -f docker-compose.observability.yml \
  up -d --build

The production overlay uses UID/GID 10001, a read-only root filesystem,
dropped capabilities, bounded temporary filesystems, and CPU/memory limits.
Remove the observability overlay when monitoring is provided elsewhere.

Local Python workflow

Prerequisites:

  • Python 3.12;
  • PostgreSQL 18;
  • Redis 8 for cache and Celery-backed workflows.

Create an environment and install development dependencies:

bash
python -m venv .venv
python -m pip install --upgrade pip
python -m pip install -r requirements.lock -r requirements-dev.txt

Apply migrations:

bash
QD_PROCESS_ROLE=migration python -m app.commands.migrate

Windows PowerShell equivalent:

powershell
$env:QD_PROCESS_ROLE = "migration"
python -m app.commands.migrate

Start the API for local debugging:

bash
python run.py

Use the Docker process model when testing trading, scheduler, or Celery ownership
boundaries. A single local API process is not a substitute for production role
separation.

Health and operations

Endpoint Purpose
GET / Application identity and resolved version.
GET /api/health Basic liveness.
GET /api/health/ready PostgreSQL and Celery broker readiness.
GET /api/health/workers Trading, scheduler, and Celery heartbeat summary.
GET /metrics Prometheus metrics. Keep this private.

Container logs default to structured JSON and include process role and request
ID. The optional monitoring stack is documented in
Observability.

API contracts

Human API routes use the existing /api/... surface. AI agents use the scoped
/api/agent/v1/... gateway with a separate contract.

Regenerate the human API artifact after schema or route metadata changes:

bash
python scripts/export_openapi.py

With OPENAPI_ENABLED=true, interactive documentation is available at:

Quality checks

Run the normal backend suite:

bash
python -m compileall -q app scripts tests
ruff check app scripts tests
python scripts/backend_quality_check.py
python scripts/check_requirements_lock.py
python -m pytest -m "not integration and not stress" --ignore=tests/release_gate -q

Run release gates independently:

bash
python -m pytest tests/release_gate/test_cta_backtest_release_gate.py -q
python -m pytest tests/release_gate/test_live_execution_release_gate.py -q
python -m pytest tests/release_gate/test_robot_strategy_unification.py -q

Security CI additionally runs pip-audit, Bandit, Gitleaks, and CodeQL.

Contributor rules

  • Keep routes focused on parsing, authentication, service calls, and response
    mapping.
  • Keep Flask request objects out of domain services.
  • Put exchange-specific normalization and errors near the adapter.
  • Make state mutations idempotent and define their retry behavior.
  • Keep code comments, docstrings, logs, and internal errors in English.
  • Preserve existing paths and response fields unless an intentional contract
    change is documented and tested.
  • Add finite retryable work to Celery; keep long-lived ownership in the trading
    or scheduler process.

Versioning

The local fallback version is read from VERSION. Release builds can
inject APP_VERSION from a Git tag. Both v5.0.1 and 5.0.1 normalize to the
API display value 5.0.1.

Update checked-in version declarations from the repository root:

bash
python scripts/bump_version.py 5.0.1
python scripts/check_version.py

License

Apache License 2.0. See the repository-root LICENSE.


File: docs/api/README.md

QuantDinger Web API (OpenAPI)

Human-facing REST API specification generated from flask-smorest (app/openapi/).

File Purpose
openapi.yaml Committed SSOT โ€” update via backend_api_python/scripts/export_openapi.py
index.html Static Redoc viewer โ€” must be served over HTTP (see below)

View docs locally

ReDoc cannot load openapi.yaml when you double-click index.html (file:// is blocked by browser same-origin policy). Use any static server from the repo root or this folder:

bash
# Python (from docs/api/)
python -m http.server 8080
# open http://localhost:8080/index.html

# or from repo root
cd docs/api && npx --yes serve -p 8080

If you see process is not defined, refresh after pulling the latest index.html (includes a browser shim + pinned ReDoc 2.4.0).

Conventions

See ../architecture/API_CONVENTIONS.md for envelopes, auth, and Public/Internal tiers.

Agent API

AI agents use a separate contract: ../agent/agent-openapi.json.

Regenerate

bash
cd backend_api_python
pip install -r requirements.txt
python scripts/export_openapi.py

Local interactive docs

With the backend running in debug mode (or OPENAPI_ENABLED=true):


File: docs/agent/AGENT_ENVIRONMENT_DESIGN.md

QuantDinger โ€” Multi-Agent Runtime Environments (Design)

Item Value
Status Draft (for review and phased rollout)
Audience Maintainers and developers using Cursor, Claude Code, Codex, or similar coding agents
Repository QuantDinger โ€” self-hosted quant stack: research, strategies, backtests, live trading

1. Background and goals

1.1 Background

When multiple coding agents and IDE assistants (Cursor, Claude Code, OpenAI Codex, CLI/sandbox bots) work in the same repository without shared conventions, teams often see:

  • Agents re-reading a very long README, wasting context and misreading intent;
  • Guessed HTTP paths and payloads that do not match the backend;
  • Accidental touches to secrets, production databases, or money-adjacent paths;
  • Per-tool documentation that drifts from the repo.

1.2 Goals

Without locking into a single vendor, make this repository stable and predictable for many agent environments:

  1. Code collaboration โ€” When changing strategies, fixing bugs, or adding APIs, agents can quickly find directories and verification commands.
  2. Capability discovery โ€” Humans and machines can learn what is allowed, what is forbidden, and how to validate changes.
  3. Optional extensions โ€” MCP, OpenAPI, and similar layers can be added later without replacing this structure.

1.3 Non-goals (explicit for this phase)

  • Not every agent product must support MCP.
  • No real secrets, internal-only URLs, or production credentials in design docs.
  • No promise of fully unattended live trading in v1; live and capital flows stay behind human review and explicit strategy boundaries.

2. Design principles

Principle Meaning
Single source of truth (SSOT) โ€œHow to work in this repoโ€ for agents lives in one primary doc (see ยง8); the root README only indexes it briefly.
Layered contracts Documentation (intent) โ†’ commands (local) โ†’ API / MCP (product capabilities). Upper layers may depend on lower ones; do not mix layers in one blob.
Minimal context pack Token-limited environments get a short, linkable doc (quick path) instead of irrelevant full-tree context.
Secure by default Secrets, .env, production writes, and undocumented order APIs are not encouraged for autonomous agents; red lines must be explicit in Layer 1.
Decoupled from implementation This design states what should exist; filenames (e.g. AGENTS.md) may change at rollout time while semantics stay the same.

3. Architecture โ€” three layers

text
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  Layer 1 โ€” Documentation contract (humans + agents)         โ”‚
โ”‚  Repo map, red lines, recommended workflow, pointers to 2/3 โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                            โ”‚
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ–ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  Layer 2 โ€” Command contract (terminal / CI / CLI agents)    โ”‚
โ”‚  Stable scripts or Make: install, lint, test, docker compose โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                            โ”‚
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ–ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  Layer 3 โ€” Machine interfaces (HTTP / MCP, optional)        โ”‚
โ”‚  OpenAPI or equivalent schema; optional MCP tools (narrow)   โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

3.1 Layer 1 โ€” Documentation contract

Role: Any agent that can read repo text knows where to start and how to self-check without calling the network.

Suggested structure (may be split across files; one index is mandatory):

  • Top-level directory roles (backend_api_python/, frontend/, docs/, scripts/).
  • Indicator and strategy entry points (link to docs/trading/INDICATOR_DEV_GUIDE.md and docs/trading/STRATEGY_DEV_GUIDE.md โ€” avoid duplicating long excerpts).
  • Red lines โ€” Never commit .env; never put secrets in docs or examples; money/live changes require human review.
  • Happy path โ€” e.g. โ€œPython-only strategy change โ†’ how to bring up Docker โ†’ how to run backend testsโ€ in 3โ€“5 steps.

Relationship to the root README โ€” README keeps user-facing install and product story; add a short โ€œFor coding agentsโ€ pointer to docs/agent/.

3.2 Layer 2 โ€” Command contract

Role: Every action that should reproduce locally or in CI is exposed as a small set of stable commands, not ad-hoc shell one-liners.

Implementation choices (Make, npm scripts, invoke, etc.) are up to maintainers:

Category Example intent (names may vary)
Environment Copy env template, generate secrets (aligned with env.example, scripts/)
Run Documented equivalent of docker compose up / build
Quality lint, format, typecheck (if adopted)
Tests Backend unit/integration entrypoints matching the repoโ€™s stack

Constraint: One official entry per goal; if two spellings exist (docker-compose vs docker compose), document the recommended one and compatibility notes.

3.3 Layer 3 โ€” Machine interfaces (optional evolution)

Role: When an agent or external tool must drive product behavior (health, listings, backtests), it must not rely on guessing HTTP.

  • HTTP + OpenAPI (or equivalent) โ€” Machine-consumable contract for REST; update the contract when routes change.
  • MCP (Model Context Protocol) โ€” Expose narrow, auditable operations as tools (e.g. read-only health, read-only strategy list). Write and trading tools need separate review and allowlists.

Principle: Layer 3 is additive; agents without MCP should still complete most code tasks via Layers 1 + 2.


4. Mapping to agent environments

Product names evolve; map by capability, not brand-only details.

Environment Primary layers Notes
Cursor Layer 1 + optional .cursor/rules; optional MCP Rules: permanent red lines and repo terminology; MCP aligns with Layer 3.
Claude Code Layer 1 + Layer 2 Heavy use of terminal and in-repo docs; Bash/PowerShell must be explicit.
OpenAI Codex (CLI/IDE) Layer 1 + Layer 2 Similar to Claude Code; avoid vendor-only config as the sole source of truth.
Lightweight CLI / sandbox bots Minimal context pack in Layer 1 + Layer 2 Mount one short file or system prompt instead of the whole tree.
Vendor-hosted agents Layer 1 index + HTTP (Layer 3) If only APIs are visible, OpenAPI and auth docs are critical.

Note: For specific products (e.g. OpenClaw, NanoBot), add one appendix row at rollout: product โ†’ config / protocol โ†’ which layer(s). No separate architecture fork.


5. Security and compliance boundaries

5.1 Data and secrets

  • Keys, API tokens, and DB passwords come only from environment variables or local .env (and .env is gitignored).
  • Design docs, agent rules, and AGENTS.md-style files must not contain real secrets or production connection strings; use placeholders in examples.

5.2 Capital and live trading

  • Order placement, transfers, and exchange credential changes are not in unattended agent flows by default.
  • If a subset is ever exposed via MCP, require auth, audit logs, rate limits, human toggles, and document in Layer 1.

5.3 Strategy code and multi-tenancy

  • For multi-user deployments, distinguish platform core paths from user strategy / plugin paths so agents do not rewrite shared security logic.

6. Repository anchors (facts)

Keep implementation aligned with the current tree (update this section if layout changes):

Area Typical path Agent focus
Backend API backend_api_python/ Routes, services, env.example
Frontend frontend/ (includes prebuilt dist) Matches README โ€œNode optionalโ€ story
Ops / one-command stack docker-compose.yml, scripts/ Layer 2 commands should mirror this
Indicator / strategy guides docs/trading/INDICATOR_DEV_GUIDE.md, docs/trading/STRATEGY_DEV_GUIDE.md, localized variants Layer 1 links; do not duplicate long guides

7. Phased roadmap (suggested)

Phase Deliverable Value
P0 docs/agent/ index + one-line README link; red lines and repo map One SSOT for all agents
P1 3โ€“5 official commands (scripts or Make) listed in docs Fewer broken ad-hoc shells
P2 Exported or hand-maintained OpenAPI for the backend Reliable integrations and codegen
P3 Optional MCP server (read-only first, then expand) Deeper Cursor / Claude-style tooling

Phases are independently reviewable; P0 does not depend on P2/P3.


8. Document and file checklist (for implementation)

  • docs/agent/AGENT_ENVIRONMENT_DESIGN.md โ€” this design (English SSOT).
  • .cursor/skills/quantdinger-agent-workflow/ โ€” project Cursor skill (English) pointing agents here.
  • docs/agent/README.md โ€” short Layer 1 index for docs/agent/.
  • Root README.md โ€” dedicated โ€œFor coding agentsโ€ subsection pointing to the index above.
  • (Optional) Root AGENTS.md โ€” industry-style filename; may forward to docs/agent/.
  • (Optional) .cursor/rules/ โ€” repo-specific terms and red lines only; avoid duplicating Layer 1 at length.
  • Layer 2 โ€” scripts/agent-*.sh or Makefile targets (names TBD at implementation).
  • Layer 2 โ€” Windows PowerShell + Bash notes (consistent with root README).
  • P2/P3 โ€” OpenAPI location, MCP package location (separate ADR acceptable).

9. Open questions (for review)

  1. OpenAPI source โ€” Generate static JSON from Flask at runtime, or generate in CI and commit? Tradeoff: drift vs build deps.
  2. MCP packaging โ€” Monorepo next to the API vs small standalone repo for MCP-only installs?

Resolved: Agent-facing documentation and project .cursor/skills/ are English only; human product docs may remain multilingual elsewhere in docs/.


10. Revision history

Version Date Notes
0.1 2026-05-02 First draft: three layers, security, roadmap, checklist
0.2 2026-05-02 Language policy: agent design and project skills are English-only; consolidated from former CN draft

File: docs/agent/AGENT_QUICKSTART.md

Agent Gateway Quickstart

QuantDinger exposes a tenant-scoped Agent Gateway at /api/agent/v1. Agent tokens are separate from human JWT sessions and enforce capability scopes, market/instrument allowlists, rate limits, expiry, and paper-only restrictions.

The machine-readable contract is agent-openapi.json. MCP setup is documented in MCP_SETUP.md.

Authenticate

Create an Agent Token from the human admin UI, store the full token when it is shown once, and send it as a bearer token:

bash
curl -H "Authorization: Bearer $QUANTDINGER_AGENT_TOKEN" \
  http://localhost:8888/api/agent/v1/whoami

Scopes are R for reads, W for saved artifacts and deployment configuration, B for backtests, N for notification side effects, and T for runtime or order mutations. C is admin-only. Token permissions never bypass server-side live-trading controls.

Every mutating W/B/N/T request requires a unique Idempotency-Key header. Reuse the same key only when retrying the exact same method, route, query, and body. The gateway atomically reserves the key, returns a stored completed response on replay, and rejects concurrent or mismatched reuse.

Strategy API V2

Executable strategies use Strategy API V2. Code defines initialize(context), declares its universe and subscriptions, and provides handle_data, on_rebalance, or a scheduled callback. Markets, instruments, frequencies, dependencies, warmup, and leverage policy come from the compiled manifest.

The Agent Gateway exposes the complete source lifecycle:

  1. List starter code with GET /strategy-sources/templates.
  2. Compile code with POST /strategy-sources/compile.
  3. Save a private source with POST /strategy-sources.
  4. Inspect or update it through /strategy-sources/{source_id}.
  5. Review immutable snapshots through /strategy-sources/{source_id}/versions.
  6. Create a stopped deployment from the saved source id.

Source restoration requires an explicit confirm=true request and creates another immutable snapshot.

Create a stopped deployment from a saved source:

bash
curl -X POST http://localhost:8888/api/agent/v1/strategies \
  -H "Authorization: Bearer $QUANTDINGER_AGENT_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: deploy-spy-trend-v1" \
  -d '{
    "name": "spy-trend",
    "sourceId": 12,
    "initialCapital": 10000,
    "executionMode": "signal",
    "leverageEnabled": false,
    "params": {"lookback": 50}
  }'

Update the same canonical fields with PATCH /api/agent/v1/strategies/{id}. Starting a deployment is intentionally not part of the W-scope configuration endpoint. A T-scope token can stop a running deployment through /strategies/{id}/stop.

Backtests

Backtests accept Strategy API V2 code and run asynchronously:

bash
curl -X POST http://localhost:8888/api/agent/v1/backtest/run \
  -H "Authorization: Bearer $QUANTDINGER_AGENT_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: spy-trend-2025" \
  -d '{
    "code": "def initialize(context):\n    g.symbol = \"USStock:SPY\"\n    context.set_universe([g.symbol])\n    context.subscribe(frequency=\"1d\")\n\ndef handle_data(context, data):\n    pass",
    "startDate": "2025-01-01",
    "endDate": "2025-12-31",
    "initialCapital": 10000,
    "leverageEnabled": false,
    "params": {}
  }'

Poll /api/agent/v1/jobs/{job_id} or consume /api/agent/v1/jobs/{job_id}/stream. Reuse an idempotency key when retrying the same submission.
Cancel a queued or running job with POST /jobs/{job_id}/cancel using B scope, confirmation at the MCP layer, and a new idempotency key. A running worker may finish its local computation, but it cannot overwrite the durable cancelled state.

Indicators

Indicators are chart-only. Fetch /indicators/authoring-contract, validate with /indicators/validate, and save through /indicators. Indicator code cannot be passed to the backtest endpoint; convert the trading idea to Strategy API V2 first.

Research, broker observations, and notifications

Research tools expose point-in-time universes, factor metadata, and the tenant watchlist under /research/*. Broker observation endpoints under /trading/* return safe credential metadata, account snapshots, account/strategy positions, pending orders, and cursor-paginated trade ledgers. They never return decrypted API keys, secrets, passphrases, or encrypted credential blobs.

N-scope signal-alert endpoints under /notifications/signal-alerts reuse the existing indicator notification service. Immediate evaluation requires explicit MCP confirmation because it may deliver a notification.

Runtime and orders

GET /runtime/overview returns compact tenant runtime state. Quick orders require T scope and an Idempotency-Key. Live execution additionally requires a live-capable token, server live-trading enablement, a credential reference, client-side explicit confirmation, and compliance with the token's max_order_notional and max_daily_notional caps.

The emergency stop at /quick-trade/kill-switch requires confirm=true. It attempts to cancel open agent-originated live orders, cancels open paper orders, revokes all active T-scope tokens for the tenant, and returns any exchange cancellation failures for mandatory human review.

Rate limiting is shared through Redis across API workers and enforces both token and tenant quotas. Responses include X-RateLimit-Limit, X-RateLimit-Remaining, and X-RateLimit-Reset; 429 responses also include Retry-After.

Never log tokens or credential material. Treat redacted values as terminal and do not attempt to reconstruct them.


File: docs/agent/AI_INTEGRATION_DESIGN.md

QuantDinger โ€” AI / Agent Integration (Design)

Item Value
Status Draft (for review and phased rollout)
Audience Maintainers; integrators wiring external AI agents into QuantDinger
Depends on AGENT_ENVIRONMENT_DESIGN.md โ€” three-layer contracts
Repository QuantDinger

Companion to the multi-agent runtime design. That doc explains how coding agents work inside the repo. This doc explains how external and embedded AI agents consume QuantDinger as a product โ€” research, strategy, backtest, and (carefully) execution.


1. Goals and non-goals

1.1 Goals

  1. Treat AI agents as first-class API consumers, alongside the existing human web UI and in-product AI chat.
  2. Provide a stable, documented capability surface so the same agent can do research, backtest, and supervised execution without screen-scraping the UI.
  3. Enforce least privilege, auditability, and kill-switches before any money-adjacent automation is allowed.
  4. Allow multiple front doors (HTTP / MCP / event stream) without forking business logic.

1.2 Non-goals (this phase)

  • Not a marketplace of third-party plugins.
  • No fully unattended live trading by an external LLM out-of-the-box. Live order routing requires explicit per-tenant opt-in and a documented allowlist.
  • Not replacing the in-product AI chat (ai_chat) โ€” this design is what that chat (and external agents) will call underneath.

2. Personas

Persona Example Primary needs
P1 Human trader (existing) QuantDinger user in browser UI + REST + JWT session
P2 In-product AI assistant (existing) ai_chat route, code-gen helpers Same backend services, on behalf of a logged-in user
P3 External coding agent Cursor / Claude Code / Codex working in the repo Repository contracts (covered by AGENT_ENVIRONMENT_DESIGN.md)
P4 External AI agent / app (new) Custom LLM workflow, MCP client, third-party automation Authenticated, scoped access to research / backtest / (optional) trading
P5 Autonomous strategy AI (gated) Generator โ†’ Strategy API V2 backtest โ†’ review โ†’ propose Programmatic strategy deployment and bounded backtest jobs; no autonomous experiment/tuning service

This document focuses on P4 + P5, keeping consistency with P1/P2.


3. Capability catalog

Capabilities are grouped by risk class. Every endpoint or MCP tool must declare exactly one class.

Class Examples Default for new tokens
R โ€” Read Market data, klines, indicators, strategy listing, backtest results, account read Allowed
W โ€” Workspace write Create/update Strategy API V2 deployments and save chart-indicator code Allowed (workspace-scoped)
B โ€” Backtest / simulation Run Strategy API V2 backtests Allowed
N โ€” Notifications & misc side-effects Send test notification, write user prefs Allowed (rate-limited)
C โ€” Credentials Store/rotate exchange or LLM credentials Denied by default; admin-only
T โ€” Trading / capital Quick trade, place/cancel order, adjust live strategy live capital Denied by default; per-tenant explicit opt-in + allowlist

Rule: A new agent token cannot acquire class C or T without an explicit operator action. Class T further requires a configured paper / sandbox path before it can be flipped to live.

Capability set is sourced from existing route groups: market, kline, indicator, backtest, strategy, portfolio, dashboard, quick_trade, ibkr, polymarket, credentials, settings, community, fast_analysis, ai_chat, health. The legacy experiment/tuning service is retired. New code should not add another way to trade; it should expose existing services with proper class tags.


4. Architecture

4.1 Layered view

text
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
                         โ”‚      External AI agents       โ”‚  P4 / P5
                         โ”‚  (LLM apps, MCP clients, ...) โ”‚
                         โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                                        โ”‚  HTTPS + Agent token
                                        โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”   โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  Browser UI (existing)      โ”‚   โ”‚  Agent Gateway (NEW)       โ”‚
โ”‚  /api/...  + JWT session    โ”‚   โ”‚  /api/agent/v1/...         โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜   โ”‚  โ€ข token auth + scopes     โ”‚
               โ”‚                  โ”‚  โ€ข rate limit + audit log  โ”‚
               โ”‚                  โ”‚  โ€ข idempotency-key support โ”‚
               โ”‚                  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
               โ”‚                                 โ”‚
               โ–ผ                                 โ–ผ
        โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
        โ”‚     Existing service layer (single source)    โ”‚
        โ”‚  market / strategies / backtest               โ”‚
        โ”‚  portfolio / quick_trade / credentials / ...  โ”‚
        โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                                โ”‚
                                โ–ผ
              โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
              โ”‚  Postgres โ€ข Redis โ€ข Workers       โ”‚
              โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

                Optional, additive:
                โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
                โ”‚  MCP server (read-mostly subset)   โ”‚  --> Cursor / Claude-style clients
                โ”‚  thin wrapper over /api/agent/v1   โ”‚
                โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Key decision: the Agent Gateway is a thin layer, not a parallel implementation. It reuses the same Flask services; it adds identity, scopes, rate limits, idempotency, and a stable URL/version.

4.2 URL and versioning convention

  • /api/agent/v1/... โ€” agent-facing namespace, stable contract.
  • The browser UI keeps using /api/... as today; it may continue to evolve more freely.
  • Breaking changes to the agent surface bump to /v2; /v1 is supported for a defined window.

4.3 Identity model

  • A Tenant is the existing QuantDinger user (single-user or multi-user mode).
  • An Agent token belongs to a Tenant and carries:
    • agent_id (human-readable label, e.g. cursor-mcp, strategy-bot-1)
    • scopes (subset of capability classes from ยง3)
    • markets allowlist (e.g. crypto, ibkr)
    • instruments allowlist (optional, for trading scope)
    • expires_at
    • paper_only flag (default true for any token with T)
  • Tokens are prefixed and hashed at rest (e.g. qd_agent_xxx); only the prefix is shown in audit logs.
  • Existing JWT user sessions are not valid for /api/agent/v1 and vice versa โ€” separate auth pipelines, no accidental cross-use.

5. Endpoint shape (illustrative)

These are contract sketches, not committed routes. Final names follow AGENT_ENVIRONMENT_DESIGN.md Layer 3 conventions.

text
/* Detailed source-code truncated for AI context efficiency. */

5.1 Cross-cutting requirements

  • Idempotency-Key header required for mutating class W, B, N, and T calls. The server atomically reserves method + route + key + request hash, replays completed responses, and rejects in-progress or mismatched reuse.
  • Async job pattern for backtests to avoid long-lived HTTP and let LLMs poll.
  • Pagination is explicit (?limit=&cursor=); no implicit caps.
  • Errors follow a single envelope (code, message, details, retriable).
  • X-RateLimit-* headers always returned.

6. Optional MCP layer

When integrators want tool-style rather than REST:

  • Ship an MCP server that wraps a curated subset of /api/agent/v1 (start with class R and B).
  • The MCP server reads an agent token from its own config; it never asks the model for credentials.
  • Tool descriptions explicitly state risk class and scope (e.g. run_backtest (B, paper)).

MCP is additive: REST stays the source of truth, MCP only re-shapes it for clients that prefer the protocol (Cursor, Claude-style, future tools).


7. Safety, audit, and ops

7.1 Trading safety (class T)

  • Tokens default to paper_only=true. Real-money flip requires:
    1. Operator confirmation in the UI.
    2. A documented allowlist of instruments and max notional per order / per day.
    3. A kill switch that revokes all T tokens with one click and cancels open agent-originated orders.
  • The Agent Gateway tags every order with source=agent:<agent_id> so portfolio, audit, and kill-switch logic can scope by agent.

7.2 Audit log

  • One append-only log per tenant: (ts, agent_id, route, scope_class, status, idempotency_key, redacted_request_summary).
  • Stored alongside existing user activity; viewable per agent and per class in admin UI.
  • Class T writes additionally include (market, instrument, side, qty, est_notional, paper_or_live).

7.3 Rate limits and quotas

  • Per-token: requests/min and concurrent backtest-job caps.
  • Per-tenant: aggregate cap across all that tenantโ€™s tokens.
  • LLM-cost-bearing endpoints (e.g. anything proxying to LLM_PROVIDER) carry their own quota and are denied for tokens without an explicit ai-llm sub-scope.

7.4 Secrets and credentials

  • Class C is admin-only; the Agent Gateway must never accept exchange API keys in request bodies for non-admin tokens.
  • Existing encryption-at-rest (SECRET_KEY โ†’ Fernet for qd_exchange_credentials.encrypted_config) stays unchanged.

7.5 Multi-tenancy

  • All queries through the Agent Gateway are forced through tenant-scoped service calls (no cross-tenant data leakage even on internal bugs).
  • Test plan: an integration test that issues a token for tenant A and asserts every class-R route returns 404/403 for tenant B objects.

8. Deployment topologies (self-hosted vs SaaS)

QuantDinger ships as a single backend that intentionally supports two operational topologies. The Agent Gateway code is identical in both; the differences are entirely operator-controlled environment variables and where the database lives.

8.1 Topologies

Dimension Self-hosted (default) SaaS / shared / hosted
Selector env var QUANTDINGER_DEPLOYMENT_MODE unset (or self/local) QUANTDINGER_DEPLOYMENT_MODE=saas (also hosted/shared/multitenant)
Tenants per instance 1 (the operator) N (one per signup)
Token issuance Operator decides every field Tenant users may issue T tokens; paper_only=true remains the default and C remains admin-only
Live trading (AGENT_LIVE_TRADING_ENABLED) Operator may flip to true Requires risk acknowledgement, a live-capable token, notional caps, and the deployment-wide server flag
Exchange credentials Operator may store + use them Recommended: do not accept; if you do, encrypt-at-rest and never expose via Agent Gateway (class C is admin-only)
Rate limits Redis-backed per-token + per-tenant quotas Same gateway quotas plus a per-IP outer proxy cap
Audit visibility Operator SaaS operator (you) sees everyone; tenant admins see only their own (already enforced by user_id filter in /admin/audit)
MCP BASE_URL http://localhost:8888 (or LAN URL) https://ai.quantdinger.com (or your hosted URL)

8.2 The hosted-mode guard (V3.1.0+)

When QUANTDINGER_DEPLOYMENT_MODE is a hosted spelling, self-service issuance still excludes C scope and defaults every T token to paper-only. A live-capable T token requires ack_live_trading_risk=true, positive per-order and per-day notional caps, and AGENT_LIVE_TRADING_ENABLED=true. The emergency stop revokes all tenant T tokens and reports any live exchange order that could not be cancelled.

This policy is covered by tests/test_agent_v1_saas_guard.py.

Beyond the gateway controls, a hosted deployment should add at the proxy / infra layer:

  • HTTPS-only with HSTS; no plaintext Agent token traffic.
  • Per-IP rate limiting in front of the app, in addition to the Redis-backed token and tenant quotas.
  • CORS: /api/agent/v1/* should not be exposed to browser CORS โ€” agents call from servers / IDE subprocess / native code, not from web pages.
  • Quota / billing hook: wrap agent_jobs.submit_job in billing middleware when future job kinds consume paid services.
  • Token reveal hygiene: full token shown once in the Vue admin UI, never logged, never echoed back from /admin/tokens GET. Already enforced.

8.4 Migration between topologies

Switching a running deployment from self-hosted to SaaS is non-destructive:

bash
# Add to the env file used by docker-compose
QUANTDINGER_DEPLOYMENT_MODE=saas
docker compose up -d backend

After restart:

  • Existing T-scope tokens continue to work (the guard runs at issuance, not on each request) โ€” the operator should DELETE /admin/tokens/{id} for any token they no longer want active under SaaS rules. A future enhancement may add a one-shot "revoke all T tokens on mode change" startup task.
  • New issuances follow SaaS rules immediately.

8.5 Why a single binary serves both

We deliberately did not fork SaaS into a separate codebase:

  • Less drift: every bug fix and feature ships to both topologies on the same release.
  • Self-host parity: enterprise/private users get bit-for-bit identical Agent Gateway behavior to the hosted demo, so trust transfers.
  • Test surface: the _is_saas_mode() branch is a single env-var check, easy to cover (and is, in test_agent_v1_saas_guard.py).

9. Mapping to existing code

Concern Existing code Reuse strategy
User auth (JWT) app/routes/auth.py, app/utils/auth.py Keep. Agent tokens live in a parallel module (app/utils/agent_auth.py proposed).
Trading quick_trade, ibkr, polymarket Wrap in T-class endpoints; reuse service layer; do not fork order logic.
Backtest backtest, app/services/strategy_v2/* Keep long-running entrypoints behind the async job table; agent endpoints remain thin submit/poll wrappers.
AI chat / code-gen ai_chat Refactor to call internal services; agent endpoints expose the same services without the chat shell.
Health health Reuse for /api/agent/v1/health.

No new Python packages are required for the gateway itself; storage uses existing Postgres (new tables: qd_agent_tokens, qd_agent_jobs, qd_agent_audit).


10. Phased roadmap

Phase Deliverable Risk class enabled Human action required
A0 Spec freeze: this doc + endpoint table + scope schema โ€” Review and merge
A1 Agent token issuance + /api/agent/v1/health, markets, symbols, klines, indicators/run R Issue first token in admin UI
A2 Strategies CRUD + backtest async jobs + audit log v1 R, W, B Per-tenant opt-in for W
A3 Per-token rate limits and bounded job streaming R, W, B โ€”
A4 Optional MCP server wrapping the current Agent Gateway R, B, W Configure MCP client
A5 Trading endpoints in paper-only mode + per-agent kill switch T (paper) Explicit per-token opt-in
A6 Live trading promotion path: instrument allowlist, notional caps, dual-control toggle T (live) Operator dual confirmation

A1โ€“A4 are safe to ship without trading exposure. A5/A6 are gated and reversible.


11. Open questions

  1. Token storage location โ€” share qd_users table family vs new schema namespace?
  2. Job runner โ€” reuse existing worker toggles (ENABLE_PENDING_ORDER_WORKER, etc.) or introduce a dedicated agent-jobs worker? Prefer the latter for blast-radius isolation.
  3. OpenAPI generation โ€” auto-derive from Flask blueprints or hand-maintain a single agent-openapi.json checked into docs/agent/?
  4. MCP transport โ€” stdio first (simplest for desktop IDEs), HTTP later for cloud agents.
  5. Cost passthrough โ€” when class B triggers LLM use indirectly (e.g. NLโ†’code helpers), should the response include token-cost telemetry?

12. Implementation status

Area Status Where it lives
Schema (tokens / jobs / audit / paper-orders) Shipped backend_api_python/migrations/init.sql (section 30) + runtime ensure in app/utils/agent_auth.py
Token auth + scopes + distributed token/tenant quotas + audit Shipped app/utils/agent_auth.py
Atomic idempotency for W/B/N/T mutations Shipped qd_agent_idempotency + agent_required
Async job runner, progress, and cancellation Shipped app/utils/agent_jobs.py
Read endpoints (R) Shipped app/routes/agent_v1/{health,markets,strategies,jobs,portfolio,research,trading_data}.py
Workspace endpoints (W) Shipped app/routes/agent_v1/{strategies,strategy_sources,indicators,research}.py
Notification automation (N) Shipped app/routes/agent_v1/notifications.py
Strategy API V2 backtest endpoint (B) Shipped app/routes/agent_v1/backtests.py
Trading endpoints (T) โ€” paper and hard-gated live Shipped app/routes/agent_v1/quick_trade.py (allowlists, token notional caps, server flag, emergency stop)
Admin token CRUD + audit viewer Shipped app/routes/agent_v1/admin.py
OpenAPI 3.0 spec Shipped docs/agent/agent-openapi.json
MCP server (Python) Shipped mcp_server/ โ€” stdio (default), sse, and streamable-http transports via QUANTDINGER_MCP_TRANSPORT
Operator quickstart Shipped docs/agent/AGENT_QUICKSTART.md
Job progress streaming (SSE) Shipped GET /api/agent/v1/jobs/{id}/stream โ€” snapshot / progress / ping / result frames; resume via ?since= or Last-Event-ID
Token UI (Profile + admin audit) Shipped ProfileAgentTokens.vue at Profile โ†’ My Agent Token (/api/agent/v1/me/tokens); admin route /agent-tokens retained
Hosted-mode hardening (QUANTDINGER_DEPLOYMENT_MODE=saas) Shipped C scope stays admin-only; T defaults paper-only and live eligibility requires explicit risk acknowledgement
Published MCP package on PyPI Shipped quantdinger-mcp โ€” install via pipx, uvx, or pip
Live quick-order execution (T, self-host only) Shipped, hard-gated app/routes/agent_v1/quick_trade.py; requires live-capable token, explicit MCP confirmation, credential, and server flag

13. Revision history

Version Date Notes
0.1 2026-05-02 First draft: personas, capability classes, gateway, MCP, safety, roadmap
0.2 2026-05-02 A0โ€“A5 implemented (schema, auth, R/W/B + paper-only T, admin, MCP, tests, OpenAPI, quickstart)
0.3 2026-05-02 Added: SSE progress streaming for jobs, MCP HTTP/SSE transport, Vue admin UI for token & audit management
0.4 2026-05-02 Added ยง8 Deployment topologies; shipped hosted-mode guard (QUANTDINGER_DEPLOYMENT_MODE=saas โ†’ T-scope rejected, paper_only pinned); MCP package published to PyPI; README EN/CN now documents the SaaS vs self-host paths side-by-side
0.5 2026-07-31 Added full research/observation/notification MCP surface, atomic idempotency, Redis quotas, job cancellation, notional caps, and tenant emergency stop

File: docs/agent/MCP_SETUP.md

MCP Setup

QuantDinger's MCP server wraps the Agent Gateway and keeps the REST API as the source of truth.

Install

bash
pip install "quantdinger-mcp==0.5.0"

For repository development, use pip install -e ./mcp_server instead.

Set these environment variables in the MCP client process:

text
QUANTDINGER_BASE_URL=http://localhost:8888
QUANTDINGER_AGENT_TOKEN=qd_agent_xxx

Run quantdinger-mcp for the default stdio transport. For network use, set QUANTDINGER_MCP_TRANSPORT=sse or streamable-http, plus optional QUANTDINGER_MCP_HOST and QUANTDINGER_MCP_PORT.

Non-loopback network listeners are denied by default unless QUANTDINGER_MCP_AUTH_TOKEN is set to a distinct secret of at least 32 characters. Configure QUANTDINGER_MCP_PUBLIC_URL to the externally reachable HTTPS base URL and send the inbound token as a Bearer token from the MCP client. The inbound token protects the MCP listener; QUANTDINGER_AGENT_TOKEN remains the separate upstream tenant credential.

Client configuration

A typical stdio client entry is:

json
{
  "mcpServers": {
    "quantdinger": {
      "command": "quantdinger-mcp",
      "env": {
        "QUANTDINGER_BASE_URL": "http://localhost:8888",
        "QUANTDINGER_AGENT_TOKEN": "qd_agent_xxx"
      }
    }
  }
}

Keep the configuration private. Prefer an environment-secret facility when the client supports one.

Expected workflow

  • Use market tools for discovery and OHLCV reads.
  • Use universe, factor, and watchlist tools for research workspace inputs.
  • Use indicator tools only for chart artifacts.
  • Compile Strategy API V2 code before saving it.
  • Save private Strategy API V2 sources and inspect version history.
  • Create stopped deployments from saved V2 source IDs.
  • Use bounded job polling or SSE streaming for backtest results.
  • Use broker and execution observation tools only for reads; credential secrets are never exposed.
  • Use N-scope signal-alert tools for notification automation.
  • Supply a unique idempotency_key to every mutating W/B/N/T tool.
  • Require explicit confirmation before restoring source versions, cancelling jobs, deleting alerts, delivering notifications, stopping runtime state, emergency-stopping trading, or placing any order.

The strategy manifest owns market, instrument, frequency, warmup, dependency, and leverage scope. Do not pass those as alternate backtest fields.

For the exact tool signatures, see the MCP package README and Agent OpenAPI.


File: docs/agent/README.md

Agent documentation (English)

This folder holds agent-facing material for coding assistants (Cursor, Claude Code, Codex, CLI bots, etc.).

Document Purpose
MCP_SETUP.md Wire Cursor / Claude Code / Codex / remote agents to a QuantDinger backend via the quantdinger-mcp MCP server (local stdio + remote HTTP)
AGENT_ENVIRONMENT_DESIGN.md Architecture: layered contracts (docs โ†’ commands โ†’ API/MCP), security boundaries, roadmap, implementation checklist
AI_INTEGRATION_DESIGN.md How external AI agents (P4) and autonomous strategy AIs (P5) consume QuantDinger via a versioned, scoped Agent Gateway
AGENT_QUICKSTART.md Operator + integrator walkthrough: issue a token, call the Gateway, run paper trades
agent-openapi.json Machine-readable contract for /api/agent/v1 (OpenAPI 3.0)
../architecture/API_CONVENTIONS.md Shared HTTP conventions (envelopes, auth, Public/Internal tiers)
../api/openapi.yaml Human Web API spec (flask-smorest; migration in progress)

Language policy: Agent-oriented docs and .cursor/skills/ in this repository are English only so the same text works across tools and locales.

For human product overviews in other languages, see the root README.md and docs/README_CN.md.