The strategy declaration
Every property of the strategy declaration, its type, default and effect on the simulated account.
The strategy(...) declaration turns a script into a strategy and configures the
simulated account and the broker emulator. It is a top-level declaration like
input or plot, may appear once, and usually follows the script header.
Properties are named arguments; leave out what you want at its default.
script "Declaration demo"
strategy(
initialCapital: 25000.0,
defaultQtyType: strategy.percentOfEquity,
defaultQtyValue: 10.0,
commissionType: strategy.commission.percent,
commissionValue: 0.05,
slippage: 2,
pyramiding: 2,
leverage: 5.0
)
data chart = subscribe(data.ohlcv)
on chart.close {
if ta.crossover(chart.close, ta.sma(chart.close, 50)) {
strategy.entry("Long", strategy.long)
}
}strategy() with no arguments is valid and takes every default.
Properties
The names are TradingView’s Pine strategy() arguments in camelCase.
| Property | Type | Default | Meaning |
|---|---|---|---|
title | string | the script name | Name in the Strategy Tester. |
initialCapital | float | 1000000.0 | Starting equity of the simulated account. |
currency | string | the quote asset | Account currency label. P&L is computed in the market’s quote currency. |
defaultQtyType | QtyType | strategy.fixed | How orders without a qty are sized: strategy.fixed, strategy.cash or strategy.percentOfEquity. |
defaultQtyValue | float | 1.0 | Contracts, cash or percent of equity, per defaultQtyType. |
pyramiding | int | 0 | Entries allowed in the same direction; 0 and 1 both allow one. |
commissionType | CommissionType | strategy.commission.percent | percent of the order value, cashPerContract or cashPerOrder. |
commissionValue | float | 0.0 | Commission amount per commissionType. |
slippage | int | 0 | Ticks added against you to market and stop fills. |
marginLong | float | 100.0 | Margin for longs, percent of the position value. 100 is no leverage, 0 turns margin checks off. |
marginShort | float | 100.0 | Margin for shorts. |
leverage | float | — | Shorthand for both margins: leverage: 5.0 sets them to 20 %. |
processOrdersOnClose | bool | false | Fill orders at the close of the bar that placed them instead of the next open. |
closeEntriesRule | string | "fifo" | "fifo": exits close the oldest entry first. "any": strategy.close("id") closes that entry’s trades. |
backtestFillLimitsAssumption | int | 0 | Ticks price must trade through a limit before it fills. |
fillOrdersOnStandardOhlc | bool | false | Pine compatibility; charts already fill on standard bars. |
useBarMagnifier | bool | false | Fill along lower-timeframe bars when the host provides them. Charts do not yet, so this has no effect there. |
calcOnOrderFills | bool | false | Pine compatibility; not applied when a script runs on a chart. |
calcOnEveryTick | bool | false | Pine compatibility; strategies trade on confirmed bars. |
fundingCosts | bool | true | Charge or credit funding on perpetual markets at the venue’s settlements. |
riskFreeRate | float | 2.0 | Annual rate in percent for the Sharpe and Sortino ratios. |
Property values may reference inputs, so traders can change sizing or costs from the script settings without editing code:
script "Sizing from inputs"
input (
equityPct = input.float(10.0, title: "Position size (% equity)", min: 0.1, max: 100.0)
feePct = input.float(0.04, title: "Taker fee (%)", min: 0.0)
)
strategy(
defaultQtyType: strategy.percentOfEquity,
defaultQtyValue: equityPct,
commissionType: strategy.commission.percent,
commissionValue: feePct
)
data chart = subscribe(data.ohlcv)
on chart.close {
if ta.crossover(ta.ema(chart.close, 9), ta.ema(chart.close, 21)) {
strategy.entry("Long", strategy.long)
}
}Order size
An entry without qty takes its size from defaultQtyType and defaultQtyValue:
defaultQtyType | Size of an order |
|---|---|
strategy.fixed | defaultQtyValue contracts (base units, e.g. 0.25 BTC). |
strategy.cash | defaultQtyValue / price contracts: a fixed notional. |
strategy.percentOfEquity | equity × defaultQtyValue / 100 / price contracts. |
Sizes are rounded down to context.stepSize when the market reports one; charts do
not know venue quantity steps yet, so sizes are not rounded there. An explicit qty (the third
argument of strategy.entry and strategy.order) is a number of contracts; compute
it in the script for other sizing rules, as in Risk.
Commission
Commission is charged on every fill, entry and exit alike, and is part of each trade’s profit.
script "Maker and taker"
strategy(commissionType: strategy.commission.cashPerOrder, commissionValue: 1.5)
data chart = subscribe(data.ohlcv)
on chart.close {
if ta.crossover(chart.close, ta.sma(chart.close, 20)) {
strategy.entry("Long", strategy.long)
}
if ta.crossunder(chart.close, ta.sma(chart.close, 20)) {
strategy.close("Long")
}
}Margin and leverage
With margin below 100 %, the account can hold positions worth more than its equity. An entry the account cannot fund is skipped, never shrunk. When open losses eat into the margin, the emulator liquidates part of the position, as TradingView does; see Broker emulator.
Funding costs
On perpetual markets (Binance futures, Bybit, OKX, Hyperliquid, and aggregated
markets that include them) positions pay or receive funding. With
fundingCosts: true the backtest charges the funding rate the data hub recorded at
each settlement the position is held through: rate × position value, longs paying a
positive rate and shorts receiving it. It is booked at the first bar opening at or
after the settlement, at that bar’s open, and is part of the trade’s profit and of
the Strategy Tester’s Funding paid. Aggregated markets use the open-interest
weighted rate of their venues. Spot markets have no funding.
script "Without funding"
// Compare a run with and without funding to see what it costs the edge.
strategy(fundingCosts: false, leverage: 2.0)
data chart = subscribe(data.ohlcv)
on chart.close {
if ta.crossover(ta.ema(chart.close, 20), ta.ema(chart.close, 50)) {
strategy.entry("Long", strategy.long)
}
}A long held for days in a market paying 0.01 % every 8 hours gives up about 1 % of its value per month.