Appearance

Personalize your experience

Mode
Accent Color
Direction
Strategy DSL Format

Strategy DSL Format

Reference

The engine JSON a strategy saves as. The form, node and JSON editors all edit this one document, and the C++ engine runs it unchanged in backtests and live.

Why the format is worth knowing

Everything the builder collects ends up in one JSON document. That document is the : the form and node editors are of it, and the JSON editor (Code ) edits it directly. Once you can read it you can diff two versions, generate variants in a script, and review a strategy the way you review code.

Nothing reinterprets the document on the way. The builder saves it, backtests send it to dslx_cli, and deployed strategies send the same JSON to the .

The JSON editor

  • It opens on the whole as engine JSON. Every keystroke is validated against the engine : unknown names, bad parameters and conditions that can never be true are underlined at their line, with the engine's message and a “did you mean” hint.
  • Apply DSL (or Ctrl+S) loads the document into the builder, so the form and node editors show it straight away. Apply is disabled while there are errors; warnings do not block it.
  • Autocomplete offers indicator names, parameters, outputs, operators, bar fields and timeframes from the . The side shows the reference for the indicator under the , or an outline of the document. Ctrl+Shift+F formats.
  • Changes made in the form or node editor show up in the JSON the next time Code opens, because all three editors read and write the same builder state.

Top-level shape

Only entry is required. Everything else has a default, so a document can be much smaller than what the builder saves.

FieldTypeDefaultDescription
versionnumber2Written by the builder.
name / descriptionstring—Display only.
symbolobject—exchange, symbol, segment, timeframe, sessionMode, sessionStart / sessionEnd, utcOffsetMinutes.
quantityobject—, quantity, capital, maxPositions, leverage.
costsobjectnonecommissionPercent, commissionPerOrder, slippagePercent.
entry*object—side, instant, signals, reEntry, + entries, exitOverride.
exitobject—signals, , takeProfit (one target or several), maxDailyLossPercent.

Every field, default and allowed is in Strategy DSL — Language Reference.

Conditions are a logic tree

a condition
// a condition: left operand + operator + right-hand side
{
  "indicator": "RSI",              // a catalog name, case-sensitive
  "params": { "period": 14 },      // optional; missing params take the catalog defaults
  "output": "value",               // optional; multi-output indicators default to the first
  "offset": 0,                     // optional; bars ago
  "interval": "1h",                // optional; read on a higher timeframe
  "operator": "crossesAbove",      // one of the eleven operators
  "value": 30                      // number | bar field ("close") | another operand { "indicator": ... }
}

Conditions combine with and, or and not. Each node has exactly one of the three and any child can be another node.

and: [ leaf, { or: [...] }, { not: ... } ]andLogicNodeconditionRSI(14) < 45ConditionNode — a leaforconditionVolume > 1e5conditionATR(14) < 25either satisfies the groupnotconditionClose < EMAexactly one childOne key per nodeexactly one of and / or / not · an empty and is FALSE · an empty or is FALSEa node carrying both and and or is a parse error, with the path of the node
Leaves, groups and negation
OperatorEditor labelRight-hand side
>is abovenumber, bar field or indicator
<is belownumber, bar field or indicator
>=is at or abovenumber, bar field or indicator
<=is at or belownumber, bar field or indicator
==equalsnumber, bar field or indicator
!=does not equalnumber, bar field or indicator
crossesAbovecrosses abovenumber, bar field or indicator
crossesBelowcrosses belownumber, bar field or indicator
crossescrosses (either way)number, bar field or indicator
risingrising for N barsa whole number of bars, 1…100
fallingfalling for N barsa whole number of bars, 1…100

Signals, flow and entry sets

Entries and exits are lists of signals. Each signal has an id, its conditions, and optionally a cooldown, a higher timeframe, candles and a flow. The decides what happens once the conditions hold: if / elif / else blocks with their own conditions, or a switch on an operand such as DayOfWeek. In the example the entry is skipped on Thursdays.

entries adds layered entry sets. Each set opens one more position when its own signals fire and price has moved by its gap from the previous layer (layering: adverse for DCA, favorable for a pyramid, any). A set's exitOverride gives its positions their own stop, targets, time exit and max loss in place of the global ones.

Exits

Any closes every open position at the . Stops and targets are checked first on every bar and fill at their level (or at the open if price gapped through). A trailing stop follows the . With takeProfit.targets each target closes its exitPercent of the position, nearest first.

!
Caution:A riskReward target is a multiple of the . Without a stop it has nothing to from: the target is skipped and the backtest result carries a saying so.

A complete strategy

The document below uses most of the schema: a signal with a cooldown and a switch , a layered add with its own stop and time exit, a trailing stop, two staged targets and a daily loss limit. It validates with no errors or warnings.

supertrend-scalper.json
{
  "version": 2,
  "name": "Supertrend Scalper",
  "description": "5-minute Supertrend flip with an RSI filter, one add on a pullback",
  "symbol": {
    "exchange": "zerodha", "symbol": "NIFTY", "segment": "futures", "timeframe": "5m",
    "sessionMode": "intraday", "sessionStart": "09:15", "sessionEnd": "15:15",
    "utcOffsetMinutes": 330
  },
  "quantity": { "mode": "fixed", "quantity": 50, "capital": 1000000, "maxPositions": 2 },
  "costs": { "commissionPerOrder": 20, "slippagePercent": 0.01 },
  "entry": {
    "side": "long",
    "signals": [{
      "id": "flip",
      "name": "Supertrend turns up, RSI not stretched",
      "repetitive": false,
      "cooldownBars": 10,
      "conditions": { "and": [
        { "indicator": "Supertrend", "params": { "period": 10, "multiplier": 3 }, "output": "direction",
          "operator": "crossesAbove", "value": 0 },
        { "indicator": "RSI", "params": { "period": 14 }, "operator": "<", "value": 70 }
      ] },
      "flow": [
        { "type": "switch", "operand": { "indicator": "DayOfWeek" },
          "cases": [{ "value": 4, "action": "none" }], "defaultAction": "entry" }
      ]
    }],
    "layering": "adverse",
    "entries": [{
      "id": "add",
      "label": "Add on a pullback to the EMA 20",
      "gap": { "type": "percentage", "value": 0.3 },
      "signals": [{
        "id": "pullback",
        "conditions": { "indicator": "Low", "operator": "<=",
          "value": { "indicator": "EMA", "params": { "period": 20 } } }
      }],
      "exitOverride": {
        "enabled": true,
        "stopLoss": { "enabled": true, "type": "percentage", "value": 0.8 },
        "timeExit": { "enabled": true, "minutes": 45 }
      }
    }]
  },
  "exit": {
    "signals": [{
      "id": "flip-down",
      "conditions": { "indicator": "Supertrend", "params": { "period": 10, "multiplier": 3 }, "output": "direction",
        "operator": "crossesBelow", "value": 0 }
    }],
    "stopLoss": { "enabled": true, "type": "atr", "value": 2, "atrPeriod": 14,
      "trailingEnabled": true, "trailingValue": 1.5 },
    "takeProfit": { "enabled": true, "targets": [
      { "type": "riskReward", "value": 1.5, "exitPercent": 50 },
      { "type": "riskReward", "value": 3,   "exitPercent": 50 }
    ] },
    "maxDailyLossPercent": 2
  }
}

What the parser rejects

The parser is strict. Nothing falls back silently, and every error carries the JSON of the mistake.

MistakeResult
An unknown indicator, parameter, output, operator, bar field or timeframeError, with a suggestion
A parameter of the wrong type or outside its rangeError at the parameter
A node with both and and orError: a logic node must have exactly one of and, or, not
A condition or AND group that can never be true ( > 120, RSI < 30 AND RSI > 70)Error, see “Conditions That Can Never Be True”
An unknown field; the field is ignored
A signal with no conditions, comparing unrelated units

Working with the format

★
Pro tip:Keep exported DSL files in version control. A is configuration and it drifts; “what changed between the run that worked and this one” is a question only a diff can answer. The is a set of working documents to start from.

See also

Related articles

  • Condition Evaluator

    Automation / Strategy Builder / Reference

    How a condition becomes true on a bar: series computed up front, no value during warm-up, the exact cross and rising rules, and the order of work on each…

  • DSL Bots

    Automation / Strategy Builder / Reference

    The 49 ready-made strategy-DSL bots: where to find them, how to load and adapt one, the file format, and what every bot is tested for.

  • Indicator Reference

    Automation / Strategy Builder / Reference

    All 94 indicators the strategy engine computes, grouped as in the builder's picker, with their parameters, outputs and the range of values each output can take.

  • Pitfalls & Anti-Patterns

    Automation / Strategy Builder / Reference

    The failure modes that show up repeatedly, what each one looks like from inside the builder, and the change that actually fixes it.

  • Strategy Builder FAQ

    Automation / Strategy Builder / Reference

    The questions that come up most often, answered with what the engine actually does rather than what would be convenient.

  • Variables Reference

    Automation / Strategy Builder / Reference

    What can appear on either side of a condition — bar fields, earlier bars, higher timeframes, statistics, clock and calendar values, and formulas — and how…

  • Writing DSL by Hand

    Coding / Strategy DSL

    Authoring strategy JSON directly: the minimum document, small constructors that keep it readable, validating before anything runs, generating variants, and…

  • Step 5 — Entry Signals

    Automation / Strategy Builder / Wizard Steps

    Where the strategy is actually written. Conditions, operators, nesting, order configuration, multiple entry sets, and the re-entry engine behind Grid, DCA…

  • Step 6 — Exit & Risk

    Automation / Strategy Builder / Wizard Steps

    Exit conditions, stop loss, take profit, staged partial exits and portfolio-level limits. The step that decides whether a losing trade costs you a percent…

Browse all knowledge base articles →