Skip to content

Your first strategy ​

How do you test a trading rule on past bars? Write it as a strategy: strategy() where an indicator has indicator(), and orders where it has only plots. Add it to the chart, and the Strategy Tester shows every trade the rule would have made.

pine
//@version=6
strategy("Moving average cross", overlay = true, initial_capital = 10000,
     default_qty_type = strategy.percent_of_equity, default_qty_value = 90,
     commission_type = strategy.commission.percent, commission_value = 0.1)
fast = ta.sma(close, input.int(10, "Fast length"))
slow = ta.sma(close, input.int(30, "Slow length"))
if ta.crossover(fast, slow)
    strategy.entry("Long", strategy.long)   // fills at the next open
if ta.crossunder(fast, slow)
    strategy.close("Long")
plot(fast, "Fast", color = color.teal)
plot(slow, "Slow", color = color.orange)

New strategy, in the Script Editor's menu, starts you on a rule much like this one.

What the rule says ​

The strategy buys when the 10-bar average crosses above the 30-bar one and sells when it crosses back below. strategy.entry opens a position under the name "Long", and strategy.close closes the position of that name. Each call places an order. On a bar where neither condition holds, nothing is placed and the position stays as it is.

How the backtest is sized ​

The arguments of strategy() set the account the backtest trades. With none of them, it starts with 1,000,000 in the chart's currency and trades one unit at a time, free of commission, which rarely matches what you would trade.

ArgumentIn this exampleWithout it
initial_capital10,000 to start1,000,000
default_qty_type, default_qty_valueeach entry spends 90% of equityone unit
commission_type, commission_value0.1% of each fillno commission

Why 90 and not 100? An entry takes its size at the close that placed it and fills at the next open. If that open is higher, an entry sized at 100% costs more than the account holds and is refused, and one that fills leaves the commission short, so small margin calls sell slivers of it. Size the orders has the rule.

When an order fills ​

Your script runs at the close of each bar. An order it places there fills at the next bar's open, because the close it read is already over. A trade's entry price is therefore the open after the cross, not the close where you saw it.

A fill at the close you saw is a lookahead

process_orders_on_close = true fills orders at the same close that triggered them. That can't be done in real trading unless you place the order before the bar closes, so a backtest with it can look better than any account would do. Leave it off unless your rule really trades at the close.

Read the results ​

After Add to chart, the editor's status line gives the count of closed trades and the net profit, as in Strategy, 10 trades, net +16.62%. Your numbers depend on your chart's bars. The chart marks each entry and exit.

For the whole report, type TESTER in the command field to open the Strategy Tester. It reports the strategy on the chart you added it to:

ViewWhat it shows
EquityThe account's equity bar by bar beside buy and hold, with the drawdown beneath.
MetricsThe report: net profit from closed trades, total P&L with what's still open added, drawdown, profit factor, Sharpe and more.
MonthlyThe return of each month.
TradesEach trade, from its entry to its exit, with its profit.

Change the fast or slow length in the study's settings, and the Tester reads the new run.

See also ​

AmenoScript is compatible with Pine Script v6. Pine Script is a trademark of TradingView, Inc., which has no part in AmenoScript.