---
title: "Pine Script: Strategies"
slug: "pine-script-strategies"
category: "coding"
tags: ["coding", "pine-script", "tradingview", "strategies", "backtesting", "trading"]
status: "stable"
last_updated: 2026-08-14
summary: "Declare Pine v6 strategies with strategy(), use strategy.entry and strategy.exit, configure backtesting parameters, and read the Strategy Tester."
related: ["[[coding/pine-script]]", "[[coding/pine-script-indicators]]", "[[coding/pine-script-libraries]]", "[[coding/pine-script-security]]", "[[coding/general-principles]]"]
---

## Overview

A Pine Script strategy simulates trade fills on historical bars and generates the Strategy Tester report. Use it when you need a PnL curve, win rate, drawdown, or Sharpe ratio. For visual-only analysis, use [[coding/pine-script-indicators]] instead. Strategies pay a computation cost: TradingView recalculates the entire backtest on every bar change, so they load more slowly than indicators. This page covers the declaration, the entry and exit functions, and how to read the backtest results honestly.

## Declare with `strategy()` and set capital parameters

The `strategy()` call defines the simulation environment. Get the parameters right before writing signal logic; they change every performance number.

```pine
//@version=6
strategy(
    title                  = "Donchian Breakout",
    overlay                = true,
    initial_capital        = 10000,
    default_qty_type       = strategy.percent_of_equity,
    default_qty_value      = 10,
    commission_type        = strategy.commission.percent,
    commission_value       = 0.1,
    slippage               = 2,
    pyramiding             = 0,
    calc_on_every_tick     = false
)
```

`initial_capital` and `default_qty_type` control position sizing. `strategy.percent_of_equity` sizes positions as a fraction of current equity, so the position grows as equity grows. `strategy.fixed` uses a fixed number of contracts or shares.

Set `commission_value` to a realistic value for your broker. A zero-commission backtest on a scalping strategy will look better than live trading by a large margin.

`calc_on_every_tick = false` means fills compute on bar close only. Combined with bar-close signals, this eliminates intrabar lookahead. Leave it false unless you are testing a tick-level strategy.

## Enter positions with `strategy.entry`

`strategy.entry` places a simulated market or limit order and automatically closes the opposite position if one is open.

```pine
length  = input.int(20, title="Donchian Length")
upper   = ta.highest(high, length)
lower   = ta.lowest(low, length)

// Use [1] to signal on the closed bar, not the forming bar
if close > upper[1]
    strategy.entry("long",  strategy.long)
if close < lower[1]
    strategy.entry("short", strategy.short)
```

Always signal on `[1]` or a closed higher-timeframe bar unless you have verified there is no lookahead. See [[coding/pine-script-security]] for the full repainting explanation.

Use `strategy.order` when you want unconditional fills regardless of position state. Use `strategy.entry` for signal-based entries; it handles position reversal automatically.

## Exit with `strategy.exit` for bracket orders

`strategy.exit` attaches a stop-loss and take-profit to a named entry. It is cleaner and more realistic than watching for price levels in `if` blocks.

```pine
atrVal = ta.atr(14)

strategy.entry("long", strategy.long, when = close > upper[1])
strategy.exit(
    id       = "long-exit",
    from_entry = "long",
    stop     = strategy.position_avg_price - 2 * atrVal,
    limit    = strategy.position_avg_price + 3 * atrVal,
    comment  = "SL/TP"
)
```

`stop` and `limit` can also be set as `loss` and `profit` in ticks or as `trail_offset` for a trailing stop. Use `strategy.close` to close a position by name without an explicit target price.

## Set `pyramiding` intentionally

`pyramiding = 0` means only one entry in the same direction is allowed at a time. `pyramiding = N` allows up to N additional entries. Most strategies should start with `pyramiding = 0`. Accidentally pyramiding inflates backtest returns by adding to winning positions, which live execution may not replicate at the same fill prices.

## Read the Strategy Tester with skepticism

The Strategy Tester reports net profit, win rate, profit factor, max drawdown, and Sharpe ratio. Read each number in context.

- Net profit on a long-only strategy during a bull market is not signal; it is beta.
- Profit factor above 3 on less than 50 trades often reflects overfitting.
- Max drawdown should be within your tolerable loss. A strategy with a 60% drawdown is not usable regardless of net profit.
- Compare against a buy-and-hold benchmark. If the benchmark beats the strategy, the strategy is adding noise.

Validate on out-of-sample data by setting a custom date range in the tester that excludes the period used to develop the parameters. If the out-of-sample results diverge sharply, the strategy is overfit.

## Use `strategy.risk` functions to enforce hard limits

```pine
strategy.risk.max_drawdown(20, strategy.percent_of_equity)
strategy.risk.max_position_size(5)
```

`max_drawdown` stops trading when the simulated drawdown exceeds the threshold. Wire it to the same value you would halt trading at in live use; backtests that ignore drawdown limits are not honest simulations.

## Related

- [[coding/pine-script]]
- [[coding/pine-script-indicators]]
- [[coding/pine-script-libraries]]
- [[coding/pine-script-security]]
- [[coding/general-principles]]
