Is QuantDinger worth using? As something to learn from, yes. As a self-hosted
platform for real money, not yet, in my reading. The order plumbing is careful
(idempotent orders, leases, several layers of reconciliation) and the backtester goes
out of its way to avoid look-ahead. But the account-level risk limits exist in the code
without being called from live trading, there's no global kill switch, and user strategy
code runs in the same process that holds the exchange API keys.

This is part 2 of the series. In part 1 I read 19 public Jev
finance projects; QuantDinger was the biggest and the only full platform, so it gets
three posts of its own, starting with the platform as a whole.

What QuantDinger is

A self-hosted, multi-user trading platform, open source (backend under Apache-2.0,
about 12,000 GitHub stars, version 5.4.1) and also sold as a SaaS by its authors. The
pitch: write a strategy in Python, backtest, paper trade, go live, monitor. Plus a lot
of AI: strategy code generation, market analysis, an agent gateway over MCP, and the Jev
entry filter I look at in part 4.

The backend is big: 787 Python files, 291 test files with roughly 2,200 test functions,
24 SQL migrations. The frontend lives in a separate repo under a source-available
licence, and the brand needs a commercial licence.

How I reviewed it

I read the architecture docs and the backend code at commit 96cec2d (21 Sep 2026). I
checked the heaviest claims below directly in the source. I didn't run it; that needs
Docker, Postgres and Redis, and I wasn't going to connect exchange keys to it anyway. So
this is a code review, not a live test, and a newer version may have fixed some of this.

What does it do well?

Area What I found
Process layout API, trading worker, scheduler and Celery can run as separate roles; orders are claimed with FOR UPDATE ... SKIP LOCKED and workers hold a lease with a heartbeat
Order idempotency a fixed client order id per pending order, saved before sending
Reconciliation order status over REST, WebSocket for five exchanges, periodic position sync, recovery of fills that were never acknowledged
Manual positions if you hold more than the strategies' allocation, the bot won't close your part
Look-ahead higher-timeframe bars only become visible once closed; the unfinished live bar is dropped; fundamentals carry an available_at date; there are tests for this
CI ruff, pytest on real Postgres, pip-audit, bandit, Gitleaks, CodeQL

The look-ahead handling is more careful than in many retail backtesters. If you build
your own multi-timeframe system, the "higher timeframe only after it closes" rule is the
one to copy.

Is the backtest realistic?

Partly. The event order inside each bar is sensible: pending orders fill at the open,
then SL/TP are checked against the bar's high and low, then your code runs and its
orders fill at the next open. When SL and TP are both hit in one bar, the default
assumes the stop hit first.

But the cost model is thin:

Setting Value
Fee 0.05% fixed
Slippage 0.05% fixed
Spread none
Limit orders filled as soon as high or low touches the price
Metrics return, max drawdown, Sharpe, win rate, profit factor; no walk-forward, no in/out-of-sample split
Data cached in Redis with a TTL, re-downloaded from free sources, so a rerun can give different numbers
Range limits 1m bars up to 30 days; H1/D1 up to 3 years

No spread is a big deal for forex and gold. And "touch equals fill" on limit orders
flatters any strategy that trades at round levels.

Where are the risks with real money?

Ranked by how much they'd worry me:

1. Strategy code runs next to the exchange keys. Strategy scripts run through
exec inside the same process, guarded by a home-made blocklist (regex, AST checks,
trimmed builtins) rather than a container or RestrictedPython. A comment in the code
records that the sandbox was bypassed once, in August 2026. There's a 10-second timeout
on loading the module, but none on initialize or handle_data, and resource limits are
off by default. That process also has the database connection and the key that decrypts
users' exchange API keys. On a multi-user install, escaping the sandbox means reaching
other people's keys. An infinite loop in handle_data is enough to hang the API.
(Indicator scripts, by contrast, run in a properly isolated subprocess.)

2. Account-level risk limits aren't connected. account_risk.py has limits for total
notional, margin, leverage and per-symbol exposure. I couldn't find it called anywhere
except the tests. There's no daily loss limit or drawdown stop for user-written
strategies. The "emergency stop" cancels orders placed by the AI agent; it doesn't stop
strategies or close positions, and there's no stop-everything button.

3. An agent token with write scope can edit live strategies. Letting the AI agent
trade live needs several gates: the right scope, an explicit risk acknowledgement, a
feature flag, allowed markets, per-order and per-day notional caps. But a token with
only write scope can create or edit a strategy with execution_mode=live, swap its
exchange keys and change leverage, which skips all of those gates. It can't start a
strategy, but it can change one that's already running. Agent tokens don't expire by
default.

4. One key protects every exchange key. API keys are encrypted with Fernet using a
single key from the environment, with no KDF, no KMS and no rotation. That environment
file can be edited from the admin page. A few code paths fall back to user 1 (the admin)
when a user id is missing.

5. Stop losses can quietly fail. On perpetual swaps, the SL/TP order is placed on the
exchange after the entry fills; if placing it fails, that's logged and the position stays
open. On spot, IBKR and Alpaca, strategy SL/TP is checked by polling.

Smaller items: after a restart, orders stuck for 90 seconds are resent with the same
client id without first asking the exchange whether they exist. Manual installs default
to admin password 123456 and database password quantdinger123 (the install script
generates random ones). Alertmanager ships seven rules and no receiver, so alerts go
nowhere, and there are no trading metrics (fills, reconciliation drift, P&L). Webhook
URLs aren't checked against internal IPs.

Can I use it for forex or MT5?

No. Live trading covers Binance, OKX, Bitget, Bybit, Gate, HTX, Interactive Brokers and
Alpaca. There's no forex broker and no MetaTrader connector. Forex exists only as data
(Twelve Data, Tiingo, yfinance) for charts and backtests, and those backtests have no
spread.

Who is it for?

  • Developers building their own platform: read it. The process roles, idempotent
    order flow, reconciliation and look-ahead rules are worth studying.
  • A single user on a private machine, crypto only: risks 1 and 3 shrink a lot if
    nobody else can reach it. Risks 2 and 5 don't.
  • Anyone self-hosting for other people's money: I wouldn't, until the sandbox, the
    account-level limits and the key handling are fixed.

What I didn't verify

  • I didn't run the platform or place an order with it.
  • The SaaS may be hardened beyond the open-source defaults.
  • The August 2026 sandbox bypass is from a code comment; I didn't reproduce it.
  • Anything after commit 96cec2d.

Next in this series: the trade-management ideas in QuantDinger's bots that I'd actually
copy into an EA, and the one I wouldn't touch.