Skip to content

Strategy sections

A strategy contains declarations and rule blocks. The optional //@version=1 header selects version 1, which is also the default when omitted. Choose one instrument scope, and supply sizing plus either conditional entries or a target portfolio.

Declarations

Section Purpose Example
symbol: One instrument symbol: TCS
universe: Fixed eligible list universe: [TCS, INFY]
run: Schedule run: daily
size: Amount or sizing objective size: 5% per instrument
allocate: Relative shares of an eligible shared budget allocate: equal weight
resize: Scheduled volatility size adjustment resize: weekly
risk: Supported exposure caps risk: max 20% per instrument, gross <= 80%

allocate is not valid beside independent fixed quantities or stop-risk sizing. resize is for volatility targets. Read sizing details for combinations and defaults.

Conditional entry and exit

//@version=1
symbol: TCS
run: daily
size: 5% per instrument
entry:
    long when: close > ema(20)
exit:
    long when: close < ema(20)

Use long when: or short when: for side-specific conditions. A plain when: in exit: applies to whichever side is held.

long at HH:MM and short at HH:MM are exact-time rules. after N bars, after N days, and after N sessions at HH:MM describe different timed exits. See instruments and schedules.

Append even if holding to a long or short entry to permit another independent purchase while earlier ones remain open, for example long at 09:15 even if holding. Omitting it preserves existing behaviour. Each purchase keeps its own quantity, protection and timed exits. Read entering again while holding for condition frequency, sizing, recovery and supported combinations.

Target portfolio

//@version=1
universe: [TCS, INFY]
run: monthly
size: 50% in total
hold: equal weight

A hold strategy describes the target membership and allocation. Do not combine it with independent entry rules. Its exit clauses are ignored with a warning. Learn about portfolio strategies.

Named calculations

//@version=1
symbol: TCS
run: daily
size: 5% per instrument
define bullish = close > ema(20)
entry:
    long when: bullish
exit:
    long when: close < ema(20)

Definitions must reference earlier bindings and supported data/functions. A block definition ends in result =. No loops, raw code, or external calls.

Protection

Form Purpose
stop: 2% Fixed-percentage stop from entry.
target: 4% Fixed-percentage take-profit from entry.
trail: 2% Trailing percentage protection.
stop: 2 ATR ATR distance, requiring the appropriate data and provider.
stop_at: / target_at: Price-level expressions, subject to runtime and retained-state support.

Use explicit units. Price protection needs execution support and may behave differently across lifecycle states; a valid declaration does not establish broker-native protection. See stops and targets.

Conditions, comments and layout

Use a real newline between declarations, section headers and separate rules. Spaces are indentation, not a replacement for that newline. This section fragment (not a complete strategy):

entry:
    long when: rsi(14) < 30

must not be flattened to entry: long when: rsi(14) < 30. Indenting a body by four spaces is a readability convention, not a parser scope requirement: the next section header ends the current section even when flush-left. Keep top-level declarations/headers flush-left for a consistent readable layout.

An editor completion inserts only the missing text at its cursor. If the cursor follows entry:, a new rule needs an initial newline. If it follows a newline and four spaces already, the first rule must not repeat those four spaces. Continue a partial argument such as rsi( on the same line; preserve indentation on later inserted lines. A literal \n inside source is not a physical line break.

Comparisons: > < >= <= == !=. Logic: and or not. Arithmetic: + - * / ^. Use nonnegative constant offsets for history (close[1]). Chained comparisons are unsupported.

Conditions can continue across physical lines with operators or parentheses. New clauses/sections end a condition. Use # for line comments and /* ... */ for non-nested block comments. Ordinary // is not a comment.

See conditions and indicators, long and short rules, and supported features.

Declaration rules and omissions

If present, the version pragma must be the first non-comment line and appear only once. Without it, the strategy uses version 1. Malformed or unsupported explicit versions remain errors. Use one instrument scope and one sizing declaration; unique sections do not use last-one-wins semantics. Write a schedule explicitly so the intended interval/cadence is reviewable.

Omitted part Behaviour to understand
of ... in percentage sizing Uses the portfolio basis.
Percentage scope Per entering instrument with conditional entries; a shared selected-book budget with hold.
Shared percentage allocate: Equal split by default.
Signal exit: No implicit opposite exit is invented. Protection, if supplied, is separate.
stop: / target: / trail: No default protective price rule is added.
Volatility target period/history Annualized, with 63 completed daily returns by default.

An entry may carry an explicit local quantity such as long 10 units when: close > ema(20). This is an alternative to its compatible global target, not an additional repeated order. Every exposure-producing entry needs explicit sizing intent. Every hold book needs size:.

One header for each control

Each of these top-level sections may appear at most once: symbol, symbols, universe, pairs, options, run, size, allocate, resize, diagnostics, risk, stop, target, trail, stop_at, target_at, hedge, hold, and reduce. Instrument scopes are mutually exclusive even when their keywords differ. Recognising a keyword does not make a deferred strategy shape runnable; see supported features.

A repeated header produces TS-DUPLICATE-SECTION, naming the line and column of both the first declaration and the repeat. An earlier risk limit is never replaced by a later block. Combine limits under one header:

symbol: TCS
run: daily
size: 5% per instrument
risk:
    max 20% per instrument
    gross <= 80%
entry:
    long when: close > ema(20)

This declares both the 20% instrument cap and the 80% gross cap. Writing two separate risk: blocks used to discard the first block; it now rejects the strategy. To migrate, move both rows under one risk: header. If the rows repeat the same cap kind, choose the intended value; duplicate cap kinds are also errors. Likewise, put long: and short: price levels inside one stop_at: or target_at: block.

define, entry and exit retain their accumulating behaviour. Several define declarations name separate calculations. Multiple entry/exit rules may be grouped under one header; existing repeated entry/exit headers also keep all their rules in source order. A later rule does not overwrite an earlier one. This patch keeps language version 1, including the default when no pragma is present.

Risk and allocation syntax

allocate: equal weight
allocate: inverse volatility over 63 bars
allocate: {AAPL: 70%, MSFT: 30%}
risk: max 20% per instrument, gross <= 80%

Each allocation example is an alternative. Dictionary weights divide the shared objective, require every exact eligible name and total 100%. Exposure caps restrict admitted increases and are separate from the size: risk ... planned-loss method. Read risk and exposure limits and allocation for permitted combinations.

Supported protection units

stop, target and trail accept positive finite decimal percentages (%, percent, pct, percentage), ATR distances (ATR or N ATR, 14-period ATR), and price points (N point, N points, N pt, N pts). Units are case-insensitive. Other values produce TS-PROTECTION-VALUE; bare numbers retain TS-STOP-AMBIGUOUS. See the complete forms and worked example. stop_at: and target_at: use absolute expressions supplied for the entry. An ATR/points trailing distance is set at entry while its favourable anchor ratchets; it is not automatically recomputed on every bar.

Use # for line comments. A block comment opens with /* and closes with */; block comments do not nest. Indentation and blank lines help the reader, but a section header determines which rule block a clause belongs to.