> For the complete documentation index, see [llms.txt](https://docs.itradingbot.net/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.itradingbot.net/ai-strategy-builder/strategy-card.md).

# Strategy card format

> Knowledge package 0.6.1, checked 22 September 2026, build 03613bfa. If the copy you are reading does not carry that line, you have a cached or older revision: fetch this page again.

Machine contract: [strategy-card.schema.json](https://1830394604-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F6lHX8ZJXkBHNJALLsrDj%2Fuploads%2F1CmgL4K6axeSq5p0IyGg%2Fitb-ai-0.6.1-en-strategy-card.schema.json?alt=media). Allowed fields: [field-catalog.json](https://1830394604-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F6lHX8ZJXkBHNJALLsrDj%2Fuploads%2FFUok4dn22XsUwQnd6WG2%2Fitb-ai-0.6.1-en-field-catalog.json?alt=media). Completed educational example: [examples/ma-entry-demo.json](https://1830394604-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F6lHX8ZJXkBHNJALLsrDj%2Fuploads%2FrIpxpxBMKXARtz6ih3jN%2Fitb-ai-0.6.1-en-examples-ma-entry-demo.json?alt=media).

## Identity and context

`format` is `itb.strategy-card/0.5.0` and `knowledge_version` is `0.5.0`: this revision adds the optional Bybit break-even pair; `knowledge_policy` is `itb-only/1`. `id` identifies the card, `title` provides a readable name and `intent` explains the idea. Select `context_id` from the catalogue for the exchange and DCA mode. Preserve that context's exact `checks.schema_observation_id`.

`settings` contains 20 form fields with the `backtest.` prefix and six `profile.` annotations. `conditions` contains condition instances. Each one needs exactly four keys: `definition_id`, `role`, `fields` and `explanation`. `role` is `entry`, `filter` or `exit`. The selected parameters live under `fields`, not under a key called `parameters`. Two instances of the same filter type are allowed, such as two MA filters with different periods; each counts toward the limit.

`checks` needs all four keys: `schema_observation_id` with your own observation string, and `history_verified`, `backend_timezone_verified` and `deployed_engine_verified`. The last three must be `false`: this package validates a card against its own contracts and certifies nothing about your history, the server's timezone or the deployed engine. Do not set them to `true` to make a card look complete.

## Multi-pair test

An optional root `symbols` array turns the card into a multi-pair test: the same strategy is calculated on every listed pair separately. It is not a form field and does not live in `settings`.

* `profile.multi_enabled` is `true` exactly when `symbols` is present, and `false` when it is absent. Any other combination is an error (`multi.flag_required`).
* Each entry uses uppercase letters, digits and underscore, at most 40 characters, spelled as the exchange spells it: `BTCUSDT`, not `btcusdt` or `BTC/USDT`. A pair the form's loaded exchange list does not contain is not ticked and nothing reports it, so check the number of pairs in the form.
* From 2 to 600 pairs, without repeats. One pair is not a multi-pair test: omit `symbols` and keep `profile.multi_enabled` false, or the card is rejected as `multi.single_pair`. 600 is the pair ceiling of the calculation service for a VIP account; a repeated pair is counted against that ceiling before duplicates are dropped, so a repeat can turn an accepted list into a refused one.
* `symbols[0]` must equal `backtest.symbol`, the card's main pair. In a multi-pair link the form's own instrument selector does not follow the list, so do not describe this pair as the one the form will show. Every condition's Asset stays equal to that same pair, as in a single-pair card; the calculation service replaces it with the pair being calculated.
* **Calculating more than one pair is a VIP feature.** Without VIP the calculation service refuses the run with `400 Too many symbols`. The validator reports this as a warning, not an error: it never asserts what tier an account actually has. Tell the user before offering the link — see [Preset links](/ai-strategy-builder/preset-links.md).
* A multi-pair run is not a portfolio. Each pair trades the full deposit independently; more pairs means more results, not better ones.

[examples/multi-symbol-demo.json](https://1830394604-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F6lHX8ZJXkBHNJALLsrDj%2Fuploads%2FLVK0JyGKqSF6ltfXfVFf%2Fitb-ai-0.6.1-en-examples-multi-symbol-demo.json?alt=media) is a completed educational multi-pair card, with its [generator output](https://1830394604-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F6lHX8ZJXkBHNJALLsrDj%2Fuploads%2FPiQ6yGEiVxlalKe1F0bT%2Fitb-ai-0.6.1-en-examples-multi-symbol-demo.link.json?alt=media) and [readable view](https://1830394604-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F6lHX8ZJXkBHNJALLsrDj%2Fuploads%2F6lTmBc9cAZBFD1F23LHR%2Fitb-ai-0.6.1-en-examples-multi-symbol-demo.html.txt?alt=media). Older cards without `symbols` remain valid and unchanged.

### Optional Bybit break-even pair

Every card carries `profile.stop_be_enabled`. False means the two `backtest.stop_be_*` rows are absent. True means both rows are present and valid together. Do not represent an off switch as two zeroes: trigger zero is invalid, while level zero is a valid enabled value.

The pair is available only in BYBIT contexts and cannot be combined with hedge. Both values are percentages from the current average position price; trigger is greater than zero, level is at least zero and strictly below trigger.

## Values and origins

Each field record contains `field_id`, `value`, `origin` and `note`.

* `user`: the user explicitly supplied the value.
* `illustrative`: the number or selection belongs to an educational example.
* `derived`: the value follows unambiguously from another field; explain the relationship.
* `schema_default`: the default of a particular schema was retained; it is not a recommendation. Claim it only for a field whose catalogue entry actually carries a `schema_default`, and only when your value equals it. A field the catalogue marks with `constant` has no schema default at all: its value is fixed by the card profile, so record that one as `derived`. Claiming `schema_default` anywhere else is rejected as `field.default_origin`.
* `agent_choice`: the assistant proposed an allowed parameter as a hypothesis; it is not an optimum or a calculation result.
* `unknown`: the value is `null`, and `note` identifies the required question or source.

`needs_input` means that not every value came from the user; it permits unknown values and it does **not** block link generation. A card with any `null` value cannot be encoded, but a card whose missing answers were filled from a named source can be, and the generator reports every such value in `assumed_values`. `complete_example` is a fully populated **educational** example with `classification=educational_example`. `complete_proposal` is a populated hypothesis for the user's task with `classification=user_draft`. Both completed statuses require exactly one entry condition.

`complete_proposal` is the strict status: it means all eight of the symbol, start and end of the period, deposit, first-order size, both commissions and leverage came from the user and carry `origin=user`. Never pass an illustrative fee or an invented deposit off as a user input to reach it. A card where some of those came from elsewhere simply stays `needs_input` — that is not a failure, and it still produces a link. Keep `null` and `origin=unknown` only for a value with no defensible source, and ask for that one.

A draft without an entry may remain `needs_input`. In the reviewed ordinary BACKTEST a task without a MAIN condition is accepted and the entry is treated as always allowed, gated only by PRICE\_LIMIT filters; this package still requires an explicit MAIN condition in a card so that the entry rule stays visible to the user. There is no "ready for live trading" status. In version 0.5, `history_verified`, `backend_timezone_verified` and `deployed_engine_verified` are always `false`. Store factual verification evidence in a separate report; the card does not certify it.

## Human-readable view

Group fields as they appear in the panel, and write the card in the user's language: Russian when they write in Russian, Ukrainian when they write in Ukrainian, English otherwise. Names, option captions and the origin column all come from `field-labels.json`, which is published in full at the top of [Settings and card schema](https://docs.itradingbot.net/ai-strategy-builder/machine-settings) under **Names in Russian and Ukrainian**; `card_layout` there also gives the block order and the layout of an indicator block. A value that has a caption is shown through that caption and translated with it: the wire value `CL` is the caption `At bar close`, and a Russian card shows the Russian name the pack gives for that caption, never `CL` itself. Only a value with no caption at all — a ticker, a timeframe such as `1h`, a number, a moving-average type such as `EMA` — is printed as it stands, because that is what the panel prints. `origin: "schema_default"` is accepted only where the catalogue really publishes a `schema_default` for that field AND your value equals it in the context you chose. Condition fields carry one; `context_overrides` can replace it for a particular exchange and averaging mode, and the validator compares against the value for YOUR context, not the base one. The required main settings and the optional break-even pair carry no published default, so `schema_default` is never valid for them: when you keep one at the value the form itself shows, the origin is `agent_choice` and the note says so.

The card has three blocks, named the way the form names them: **Settings**, **Money Management** and **Risk Management**, in that order, followed by the condition sections **Entry**, **Filters** and **Exit**. Do not invent block names of your own, and do not translate these three yourself: the pack already carries them in all three languages. Assistants that reworded them produced headings that exist nowhere in the product, and a user has nothing on screen to match those against. Each block is a table of three columns: the name of the field, its value, and where the value came from. The titles of the blocks, the titles of the three condition sections and the three column headers are all published in `field-labels.json` in the user's language: copy them from there rather than translating them yourself. One row per field: never merge two fields into one row such as `Deposit / First Order` or `SOS / DSOS / Martingale`, because the user reads your table against a form where those are separate inputs.

The [HTML example](https://1830394604-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F6lHX8ZJXkBHNJALLsrDj%2Fuploads%2FaP1fuziGbHDErHIi3SNr%2Fitb-ai-0.6.1-en-examples-ma-entry-demo.html.txt?alt=media) is in English because this documentation is; run the renderer with `--lang ru` or `--lang uk` for the other two. It helps a user copy settings but does not imitate a saved user task.

The bundled [HTML renderer](https://1830394604-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F6lHX8ZJXkBHNJALLsrDj%2Fuploads%2FUlKHoetl6PuddVY51KQ1%2Fitb-ai-0.6.1-en-render_card.py.txt?alt=media) works with any validated catalogue card. Run `python render_card.py --card your-card.json --output your-card.html`. It creates English cards and the preset link from the same configuration, escapes supplied text, and loads no remote resources. Open the file locally; use the browser's Print / Save as PDF command for a printable copy. An incomplete card is rendered with its missing inputs and no link.

`enum_labels` contains the exact option labels; apply `context_overrides` to it along with enums and defaults. For example, the exit-group label for `CR` differs between DCA and ordinary mode. Use the signal guide for the exact mathematical meaning of each option code and the label to locate it in the interface. A code displayed literally by the interface is marked `source_ui_literal`.

The completed example uses EMA20, ordinary candles, bar close, timeframe 1h and LONG. All trading numbers, the selected symbol, period and fees are illustrative. The absence of filters, signal exits and additional orders is recorded explicitly. This demonstrates the format; it does not establish the idea's effectiveness.

## Validation

Run `python validate_card.py your-card.json --catalog field-catalog.json` from the folder where you saved the files. The validator runs locally without third-party libraries or network access. It checks fields, types, context-specific values, limits and dependencies against the [catalogue](https://1830394604-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F6lHX8ZJXkBHNJALLsrDj%2Fuploads%2FFUok4dn22XsUwQnd6WG2%2Fitb-ai-0.6.1-en-field-catalog.json?alt=media) and [condition contract](https://1830394604-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F6lHX8ZJXkBHNJALLsrDj%2Fuploads%2FCHG1WDgV2lChAvsqSDvn%2Fitb-ai-0.6.1-en-condition-constraints.json?alt=media). An unknown indicator or field, an unconfirmed condition constraint or an invalid condition value cannot pass into the link generator. For the main form fields, the checks also cover the [source-observed bounds](https://1830394604-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F6lHX8ZJXkBHNJALLsrDj%2Fuploads%2Fal06lQ1MzU9ddPZ2qxML%2Fitb-ai-0.6.1-en-main-settings-constraints.json?alt=media), their activation conditions, types, options, required fields, dates and profile relationships. Instrument-specific and runtime checks remain explicit. This is not a complete trading execution contract.

Integer signal-condition parameters must be exact JSON integers, without fractional notation, strings or rounding. This is an exact normalized input domain: some server paths convert values with `int(value)` and may discard the fractional part. Rejection of `20.5` by the validator therefore does not mean the server must reject it in the same way. If a fractional parameter has no explicit server step, its range alone does not create one. For example, the Bollinger width bounds do not justify assigning a mandatory step of `0.1`.

A successful check means that the card is consistent with this package. It does not prove that the selected history exists, that the deployed server matches the studied code, or that a future calculation will produce a particular result. After validation, the [generator](/ai-strategy-builder/preset-links.md) converts the card to the panel's existing link format; the card JSON itself is not the product's import format.

`sources` contains only paths in the catalogue's `allowed_sources`, relative to the package root — file names such as `field-catalog.json`, never page addresses and never page names. If you read this documentation as web pages, translate each page you used into its package file with this map, because the two are named differently:

| page                                   | package file                                                                                        |
| -------------------------------------- | --------------------------------------------------------------------------------------------------- |
| AI strategy builder                    | `README.md`                                                                                         |
| Rules for AI assistants                | `00-agent-contract.md`                                                                              |
| From signal to trade                   | `01-system-model.md`                                                                                |
| Compatibility and limits               | `02-compatibility.md`                                                                               |
| Strategy card format                   | `03-card-format.md`                                                                                 |
| Backtest workflow                      | `04-backtest-workflow.md`                                                                           |
| Signal passports                       | `05-signal-passports.md`                                                                            |
| Order-grid calculations                | `06-order-grid.md`                                                                                  |
| Preset links                           | `07-preset-links.md`                                                                                |
| Settings and card schema               | `field-catalog.json`, `main-settings-constraints.json` and `strategy-card.schema.json`              |
| a family reference, such as RSI fields | `passports/<family>.md`, plus `field-catalog.json` and `condition-constraints.json` for its numbers |

So a card built from the rules page and the RSI reference names `00-agent-contract.md` and `passports/rsi.md`, not `assistant-rules` or `machine-rsi`. External addresses, absolute paths, parent-directory traversal and unknown files are not allowed. `unresolved` preserves open questions even in a completed educational example. `execution.backtest_executed` and `execution.live_trade_executed` are always `false`; `execution.results` is always `null`. Store a real calculation report separately, referencing `id` and retaining a copy of the settings actually used.
