Fix a strategy error¶
Start with the reported line and error code. Make the smallest correction, then check the draft again.
Common mistakes¶
| Problem | Check | Correction |
|---|---|---|
| Unknown section | Spelling and colon | entry: instead of enrty: |
| Invalid version header | If present, place one valid header before declarations | //@version=1, or omit it to use version 1 |
| Missing instrument | symbol or fixed universe |
symbol: TCS |
| Missing size | Explicit quantity or objective | size: 5% per instrument |
| Invalid percentage phrase | Number spacing, basis and scope | size: 5% of portfolio per instrument; keep 5% together. |
| Unknown indicator | Name and parameters | rsi(14) instead of ris(14) |
| Incomplete condition | Comparisons and connectors | rsi(14) > 45 and close > ema(20) |
| Lookahead | Historical index | close[1] for previous bar; never close[-1] |
| Conflicting stops | Inline and separate stops | Use one consistent percentage. |
Error or warning?¶
An error blocks validation. A warning/advisory asks you to check behaviour or capability. Some validators report an unknown function as an advisory; this does not establish that it is available when the strategy runs.
Python builtin names are reserved except for the intentional expression helpers
abs, min, max, len, sum and round. This includes execution/reflection
names such as eval, exec, compile, getattr and double-underscore names,
as well as quit, exit, help, print and type. For example,
quit() > 0 is a TS-RESERVED error, not a custom provider. Reserved names
cannot be passed as arguments or introduced through a define, even if an
environment could supply them. The price series open remains valid in
close > open, but open(...) is reserved.
Earlier non-stub runs could accidentally call Python builtins for unsupported
provider names. Those names now fail validation and lowering. Ordinary custom
providers remain supported: use a non-reserved name, arrange its binding in the
execution environment, and update both places if you rename it. The language
header remains //@version=1.
TS-MEMBER means an expression tries to read an unsupported object member.
Only documented fields on a declared session_range(...) binding are allowed,
such as orb.high. Use an injected plain-name provider such as
custom_signal(10), not library.custom_signal or a local alias of that member.
Lowering now rejects these expressions even when validation was skipped;
demo stubs do not bypass this check. A reserved base such as __builtins__
also produces TS-RESERVED. Do not suppress the error to load an older generated
strategy: correct the expression and regenerate it.
An unresolved name during a real-provider run means the environment has not
supplied that value or function when the expression needs it. A catalog entry or
a successful demo-stub run is not evidence of a real binding. For example,
custom_signal(10) > 0.7 needs the custom score provider; it cannot borrow an
unrelated function from the host. See provider availability
for a complete entry/exit example and the information to confirm with its owner.
Resolve unknown names using the supported catalog. Errors and warnings maps each code to a cause and correction.
TS-LOOKAHEAD also covers invalid bar offsets. An offset must calculate to a
finite, non-negative constant integer: close[1000-1000] reads the current
bar, and close[4/2] reads two bars ago. Division by zero, an overflowing power,
a fractional result such as close[3/2], or a dynamic value is rejected.
Use a small explicit integer when debugging. Before 4.11.0, unrelated arithmetic
could overflow while validating a valid subtraction; this is now diagnosed or
evaluated using only the operation actually written.
Valid syntax, unexpected behaviour¶
Check the instrument, schedule, sizing, data, and position state. Validation does not promise a fill, data availability, or profit. Use the backtest checklist and supported features.
Fix the first cause, then check again¶
A missing parenthesis or section delimiter can cause several later diagnostics. Start with the earliest relevant syntax error, fix it, then re-check before changing unrelated lines. Keep a working version of the draft so you can compare the last edit.
| Diagnostic situation | Next step |
|---|---|
| A name has a suggested spelling | Compare with the function catalog and correct the spelling. |
| An unknown name is only an advisory | Confirm that the execution environment actually supplies it. |
| A size or allocation is rejected | Check the full phrase, strategy shape and allowed combination. |
| A valid rule produces no entry | Check history, schedule, position state and quantity/capital limits. |
| A position remains open unexpectedly | Read the explicit exit; false entry does not imply exit. |
If you need to report the problem¶
Include the relevant strategy excerpt, exact diagnostic code and line, selected language, instrument and signal interval. For an unexpected trade, include its timestamp and the values used by the condition. This makes the issue reproducible without guessing what the editor or backtest saw.