DSL grammar¶
The qkt DSL is a small declarative language for trading strategies. This page documents every accepted keyword and shape.
Living reference
Maintained alongside the parser. Discrepancies are bugs — file an issue.
File-level shapes¶
Every .qkt file is one of:
STRATEGY— a single strategy, the most common casePORTFOLIO— a composition of strategies with regime-gated activation (Phase 13b/14)
STRATEGY¶
STRATEGY <name> VERSION <int>
[ DEFAULTS { ... } ]
SYMBOLS
<alias> = <BROKER>:<symbol> EVERY <timeframe>
[ ... more streams ... ]
[ LET <name> = <expression> ... ]
RULES
WHEN <condition>
THEN <action> [ ; <action> ... ]
[ ... more rules ... ]
[ FOR EACH <ident> IN <stream-list> DO ... ]
PORTFOLIO¶
PORTFOLIO <name> VERSION <int>
[ SYMBOLS ... ]
IMPORT '<path>' AS <alias> [ HOLD ]
[ ... more imports ... ]
RULES
[ WHEN <condition> ] RUN <alias>
[ ... more rules ... ]
HOLD keeps a child's positions when the supervisor deactivates it. Without HOLD, deactivation flattens.
Stream declaration¶
<BROKER>resolves against the broker registry: built-ins (BACKTEST,BYBIT,INTERACTIVE,ALPACA) plus any profile inqkt.config.yaml(e.g.EXNESS,ICMARKETS).<symbol>is the canonical symbol qkt sees (EURUSD,BTCUSDT). Per-broker translation (suffix, alias) happens at the broker boundary — see broker integration.<timeframe>is1m,5m,15m,1h,1d, etc. Drives the candle aggregator.
Actions¶
| Action | Effect |
|---|---|
BUY <stream> [SIZING ...] [BRACKET ...] [STACK ...] |
Long entry |
SELL <stream> [SIZING ...] [BRACKET ...] [STACK ...] |
Short entry |
CLOSE <stream> |
Flatten position on the stream's symbol |
CLOSE_ALL |
Flatten every open position |
CANCEL <stream> |
Cancel pending orders on the stream's symbol |
CANCEL_ALL |
Cancel all pending orders |
LOG [LEVEL] "<msg>" [field=expr ...] |
Emit a log line — see logging and Phase 15 |
Sizing¶
SIZING <quantity>
SIZING <pct> PCT OF (EQUITY | BALANCE)
SIZING <usd> USD
SIZING POSITION(<stream>) -- full current position
Bracket¶
BRACKET STOP_LOSS BY <pct> PCT TAKE_PROFIT BY <pct> PCT
BRACKET STOP_LOSS AT <price-expr> TAKE_PROFIT AT <price-expr>
BRACKET STOP_LOSS BY ATR(<symbol>, 14) * 2
The compiler routes BRACKET to native broker support if the broker has the BRACKET capability (MT5, PaperBroker), else falls back to engine-managed SL/TP via separate orders.
Stack (Phase 13a)¶
BUY btc SIZING 0.1 STACK 3 SPACING 100 ABOVE WITHIN 1h
BUY btc STACK [ 0.1, 0.2 AT entry + 100, 0.3 LIMIT AT entry + 200 ]
Pyramiding — one signal becomes N price-triggered entries.
Expressions¶
Literals¶
- Number:
100,1.5,0.001 - Boolean:
TRUE,FALSE - String (in
LOGfield positions only):'BUY',"BUY"
Stream fields¶
<stream>.close,.open,.high,.low,.volume
Indicators¶
ema(<stream>, <period>),sma(...),rsi(...),atr(<symbol>, <period>),vwap(...), etc.- See
com.qkt.indicators.catalog.*for the full list (linked from the API reference)
Operators¶
- Arithmetic:
+ - * / % - Comparison:
< <= > >= = != - Boolean:
AND OR NOT - Crosses:
<a> CROSSES ABOVE <b>,CROSSES BELOW - Ranges:
<x> BETWEEN <lo> AND <hi>,<x> IN [<a>, <b>, <c>] - Conditional:
CASE WHEN <cond> THEN <expr> [ELSE <expr>] END
Account / position references¶
ACCOUNT.equity,ACCOUNT.balance,ACCOUNT.realized_pnl,ACCOUNT.unrealized_pnl,ACCOUNT.total_pnlPOSITION.<stream>— current quantity (signed)POSITION.<stream>.entry_price,.pnl,.unrealized_pnl,.realized_pnl,.holding_duration
Defaults¶
DEFAULTS {
sizing = 1.0
stopLoss = childBy(atr(SYMBOL, 14) * 2)
takeProfit = childRr(3.0)
tif = GTC
}
Apply to every action that doesn't override.
LET clauses¶
Reusable expression aliases. Evaluated lazily per tick.
FOR EACH¶
Iterates over streams; the loop variable substitutes textually into the rule body. Phase 11.
See also¶
- Architecture — what happens when a rule fires
- Backtest model — what the engine guarantees
- API reference — every parser AST node, every action class (built by CI)