Products Get started
From install to a live setup, one step at a time.
Install qkt, write a strategy, backtest it with real costs, read the report, then set up a production folder. Every command is here to copy.
On a phone, rotate it or tap full screen: the code is easier to read.
Downloads the latest release and installs it under ~/.local/share/qkt, with a qkt launcher in ~/.local/bin. On Linux x64 it ships its own Java runtime, so you need no Java. macOS and other platforms need a system JDK 21.
What you will see (shortened)4 lines
✓ Installed: qkt 0.56.1 (3a44fea) built 2026-10-12T17:04:48.294049876Z $ qkt --version qkt 0.56.1 (3a44fea) built 2026-10-12T17:04:48.294049876Z
A named, versioned strategy. This file is the whole thing.
Parses and compiles the file. It prints ok, or every error with its line and column.
What you will see2 lines
$ qkt parse momentum.qkt ok
Runs the file over that month as a one-shot backtest.
Costs need tick data and per-instrument prices, so this part uses the two-day tick sample from the qkt repo. It downloads only that folder, not the repo's history.
What you will see (shortened)28 lines
$ qkt fetch BINANCE_UM:BTCUSDT --from 2026-08-25 --to 2026-10-01 --tf 15m qkt fetch: BINANCE_UM:BTCUSDT @ 15m from 2026-08-25 to 2026-10-01 (38 days) [1/38] 2026-08-25 fetched 96 bars ... [38/38] 2026-10-01 fetched 96 bars qkt fetch: done — fetched=38 empty=0 skipped=0 total=38 $ qkt backtest momentum.qkt --from 2026-09-01 --to 2026-10-01 --starting-balance 10000 --seed 1 --report-dir out qkt: starting balance 10000 from --starting-balance Report saved: out Backtest 2026-09-01 to 2026-10-01 (31 trading days) Account 10,000.00 USD Result Profit -701.10 USD (-7.0%) Round trips 26 closed, 6 won (23.1%) Open at the end BINANCE_UM:BTCUSDT +0.1 worth -50.66 USD Worst drop 9.1% biggest fall from a peak Worst day 2.6% Sharpe ratio -3.82 return per unit of risk Costs none modeled (no spread, commission or swap) Assumptions Fills at the middle price, no spread or slippage: results are optimistic. Try --broker mt5-sim for a realistic fill model. More detail: --verbose (full output), --report-dir DIR (files), --json (for tools). qkt: note: paper broker fills at mid with no spread/slippage — results are optimistic. Use --broker mt5-sim and set commissionPerLot + slippagePoints in instruments.yaml for cost-realistic backtests.
This month lost money. It was picked by date, not by result, and costs are not modelled here, so a real account would have done worse. One month is still too short to judge a strategy: test several before you trust it.
Progress lines: the account size and where it came from, and where the report went.
Run exactly the same thing again, into a second folder.
What you will see16 lines
$ ls out equity_daily.csv equity_global.csv equity_momentum.csv financing.csv manifest.json monthly_returns.csv orders.jsonl pnl_components.csv rejections.csv report.html result.json trades.csv $ cmp out/trades.csv again/trades.csv && echo identical identical
Opens it in your default browser on Linux; on macOS use open. It makes no network requests and needs nothing else.
The setup in full: version, strategy hash, fill model, latency, data source. A warning here says the data store can change under you.
What was checked14 lines
Opened in Chromium from file://: How this test was run Costs and adjustments Runaway breaker Equity over time Biggest losing streaks (drawdowns) Profit from closed trades Trade audit Trades Monte Carlo Rejections Reproduce this run 1 chart, 0 console errors, 0 network requests.
Before you start: you need Docker with Compose, and a demo account with a broker that offers MetaTrader 5 and allows automated trading. The gateway image is large (about 2.75 GB) and its first boot takes several minutes.
Writes a complete, runnable project: compose file, config, env example and short commands.
The project folder. There are 15 files; these are the ones you will touch.
What you will see (shortened)2 lines
$ qkt create template ./my-qkt Created 15 files at ./my-qkt
The same strategy, pointed at a broker instead of recorded data.
The gateway image. The generated .env.example already sets the current one; leave it unless you are told to upgrade.
You do not add this: qkt create template wrote it. The gateway is MetaTrader 5 running headless under Wine in a container, with an HTTP API in front. The default image in this line is the current one, and MT5_GATEWAY_IMAGE in .env overrides it.
Starts only the gateway. Checked from a cold start with a real demo login on image 0.3.19: it came up ready and connected in about 20 seconds.
What you will see when it is ready (shortened)2 lines
$ curl -H "Authorization: Bearer $MT5_API_KEY" http://127.0.0.1:5020/health/ready
{"status": "ready", "mt5_status": "connected", ...}Starts the gateway and qkt. The first boot can take several minutes while MT5 starts under Wine.
The checks, run offline against the template (shortened)15 lines
$ docker compose config -q (no output, exit 0) $ qkt preflight strategies/momentum.qkt --production --offline --state-dir ./state --config qkt.config.yaml PASS runtime.mode: production PASS strategy.parse: momentum v1 PASS strategy.compile: momentum v1 PASS risk.config: explicit risk block present PASS broker.config: 1 broker profile(s) configured PASS broker.metadata: 1 MT5 profile(s) resolved WARN broker.gateway.mt5: offline: gateway reachability skipped WARN notify.alerts: waived: demo-account PASS symbol.metadata: 1 symbol(s) PASS symbol.calendar: 1 symbol(s) on a matching calendar PASS data.fields: close/price only
Gets the gateway. It builds from source for now, so Docker is all you need.
What you will see (shortened)6 lines
$ docker compose ps
NAME SERVICE STATUS
...gateway-paper-1 gateway-paper Up (healthy) 127.0.0.1:8443->8443/tcp
$ curl -H "Authorization: Bearer $PAPER_TRADER_TOKEN" http://127.0.0.1:8443/v1/health
{"protocol":"vgp1","adapter":"paper","adapter_version":"0.1.0","account_login":"paper","trade_mode":"demo","venue_connected":true,"kill_switch":{"all":false,"symbols":[]},"server_time":1791759610661,"stream":"50822d24-477d-440c-be75-dab3a2d52b97","seq":0,"capabilities":["bars","quotes","settlements","funding","funding_rates"]}The broker's name is the prefix your strategy uses, like PAPER:BTC_USDC_PERPETUAL. type: gateway means a venue gateway, not MetaTrader.
The same kind of file as before, pointed at the venue. Dashes in a Deribit name become underscores.
qkt reads the token from your environment.
What you will see (shortened)5 lines
$ qkt run venue.qkt --config qkt.config.yaml [INFO] qkt 0.56.1 — strategy momentum v1 — paper-trading [INFO] subscribed: PAPER:BTC_USDC_PERPETUAL ... warmup: seeded hub for strategy=momentum alias=perp symbol=PAPER:BTC_USDC_PERPETUAL bars=21 [INFO] observability: http://127.0.0.1:44189
Starts the qkt-insights service. It is already in your docker-compose.yml, but only runs when this profile is on, so you add lines to .env and leave the compose file alone.
Starts the dashboard and restarts qkt with Insights on.
Which gateway to watch. The address is the gateway inside your compose network, and the key is the one already in your .env.
Add this under services: in your existing docker-compose.yml. It runs the watchdog next to qkt and reads the config above. Pin a version tag, never latest, on a real account.
Starts the watchdog. Run its drills before you trust it with money.
Turns on Telegram alerts for daemon_started, strategy_error, halted and resumed.
Restarts qkt with the new settings.
qkt is pre-1.0 and its own docs recommend paper and demo accounts only. These are the safeguards to put in place before you ever consider real money. They are not a sign that it is ready.
Daily loss, per-order size and notional, the price collar, and total and daily drawdown. All come from .env, where the template's .env.example sets starting values (for example a 100 USD daily loss and a maximum order of 1 lot). Change them to fit your account.
Questions