Strategy vs Indicator in Pine Script: Which to Use?

jayadev rana Avatar

Quick answer: Use indicator() when you only need to see something on the chart — plots, bands, signal arrows, tables, or alerts — and use strategy() when you need to simulate trades, run a backtest in TradingView’s Strategy Tester, and drive automated, paper, or live orders. An indicator visualizes and alerts; a strategy places hypothetical orders and reports performance metrics like net profit, drawdown and win rate. If you’re stuck, ask one question: do I need a backtest and order simulation? Yes means strategy(); no means indicator().

I’m Jayadev Rana, a TradingView-certified Pine Script developer. As of July 2026 I’ve spent 8+ years building 7,700+ scripts for traders across 14+ countries, and the indicator-or-strategy question is still one of the first decisions I lock down on nearly every project. Below is the exact rule I use, working Pine Script v6 code for both, a side-by-side table, and the alert and execution gotchas that catch most people.

Indicator vs strategy: the core difference

Every Pine script opens with exactly one declaration statement — either indicator() or strategy() — and that single line decides what your script is allowed to do.

An indicator is a visualization and analysis tool. It can draw plots, lines, histograms, shapes, backgrounds, labels and tables, and it can raise alerts. What it cannot do is open, size, or close a position, or produce a backtest report. There is no strategy.* namespace available to it.

A strategy can do almost everything an indicator does — it still plots and labels — but it additionally unlocks the strategy.* namespace: strategy.entry(), strategy.exit(), strategy.close(), strategy.order() and read-only variables like strategy.position_size. Those orders are sent to TradingView’s broker emulator, which fills them on historical and realtime bars so you get a full performance report in the Strategy Tester.

Put simply: a strategy is a superset of an indicator’s drawing ability plus a simulated trading engine bolted on top. That extra engine is exactly why you don’t make every script a strategy.

What indicator() is best for

Reach for indicator() when the deliverable is information, not trades:

  • Custom oscillators, moving-average systems, volume or volatility studies.
  • Buy and sell arrows or visual signals a human will act on manually.
  • Screener-style scripts and dashboards built with tables.
  • Alert-only tools that fire a webhook to an external bridge while the order logic lives outside Pine.

Indicators are also lighter to work with. They recalculate on every realtime tick by default, so their on-chart values update live as price moves. If most of my indicator development work is any guide, a large share of make-it-trade requests actually only need a clean indicator plus a reliable alert.

What strategy() is best for

Choose strategy() when you need evidence and execution:

  • Backtesting an idea across historical data with net profit, max drawdown, profit factor and win-rate stats.
  • Position sizing, pyramiding, stop-loss, take-profit and trailing-stop logic.
  • Forward-testing on realtime bars before risking capital.
  • Automating entries and exits by wiring strategy alerts into a broker or paper account.

The catch: a strategy’s realism depends entirely on how you configure commission, slippage, order type and fill assumptions. A backtest is a model of the past, not a promise about the future. I’ve reviewed plenty of strategy development code where a beautiful equity curve collapsed the moment realistic commission and slippage were added.

Indicator vs strategy comparison table

Capability indicator() strategy()
Declaration indicator(...) strategy(...)
Plots, shapes, tables Yes Yes
Places simulated orders No Yes (strategy.*)
Backtest / Strategy Tester report No Yes
Position & PnL tracking No Yes
alertcondition() support Yes No (ignored)
alert() and order-fill alerts alert() only Both
Default recalculation Every realtime tick Bar close only (once per bar)
Best for Visuals, signals, screeners Backtests, automation

Minimal indicator() example (Pine Script v6)

Here’s a compact EMA-cross indicator. It plots two EMAs, marks crosses, and exposes an alert — but it can never place an order:

//@version=6
indicator("EMA Cross Signal", overlay = true)

fastLen = input.int(9, "Fast EMA")
slowLen = input.int(21, "Slow EMA")

fast = ta.ema(close, fastLen)
slow = ta.ema(close, slowLen)

plot(fast, "Fast EMA", color.aqua)
plot(slow, "Slow EMA", color.orange)

goLong  = ta.crossover(fast, slow)
goShort = ta.crossunder(fast, slow)

plotshape(goLong,  "Long",  shape.triangleup,   location.belowbar, color.green, size = size.small)
plotshape(goShort, "Short", shape.triangledown, location.abovebar, color.red,   size = size.small)

alertcondition(goLong, "Long signal", "EMA crossed up")

Minimal strategy() example (Pine Script v6)

Now the same logic as a strategy. Notice two things: the declaration is strategy() with backtest settings, and orders are gated with plain if blocks. In v6 the old when parameter on order functions is gone, so you control execution with if conditions instead:

//@version=6
strategy("EMA Cross Strategy", overlay = true, initial_capital = 100000, default_qty_type = strategy.percent_of_equity, default_qty_value = 10, commission_type = strategy.commission.percent, commission_value = 0.03)

fastLen = input.int(9, "Fast EMA")
slowLen = input.int(21, "Slow EMA")

fast = ta.ema(close, fastLen)
slow = ta.ema(close, slowLen)

plot(fast, "Fast EMA", color.aqua)
plot(slow, "Slow EMA", color.orange)

goLong  = ta.crossover(fast, slow)
goShort = ta.crossunder(fast, slow)

if goLong
    strategy.entry("Long", strategy.long)

if goShort
    strategy.close("Long")

Same signals, completely different capability. The strategy version produces a Strategy Tester report and can fire order alerts; the indicator version only draws and warns. For price-based exits you would add strategy.exit() with stop, limit or trail_points arguments — that is the function for stop-loss and take-profit brackets, while strategy.close() is for a plain flatten-this-position-now exit.

Want your indicator turned into a backtestable, alert-ready strategy — or the reverse — without the repainting and fill surprises? Message me on WhatsApp at +91 77352 68199 and I’ll tell you which declaration your project actually needs.

Alerts work differently — the number one gotcha

The declaration also changes how alerts behave, and this catches even experienced coders:

  • alertcondition() only works in indicators. If you put it in a strategy it is silently ignored and never appears in the Create Alert dialog.
  • In strategies you use the alert() function inside your logic, and you also get built-in order-fill alerts whenever the broker emulator fills a simulated order.
  • Either way, alerts only trigger on the realtime bar, never on historical bars.

Because a strategy calculates once per bar at bar close by default while an indicator updates every tick, the timing of your signals can differ between the two even with identical logic. I’ve written more about that in my guides on calc_on_every_tick and alert frequencies — worth reading before you automate anything.

Pine Script v6 specifics to keep in mind

A few v6 behaviors matter for this decision as of 2026:

  • The when parameter is removed. Order functions no longer accept when; wrap calls in if blocks, as shown above.
  • Dynamic requests are on by default. request.*() calls run dynamically without the old dynamic_requests = true flag.
  • Stricter booleans. A bool is now always true or false and never na, and and / or use short-circuit evaluation.
  • Default strategy margin is 100% for both long and short, meaning no simulated leverage unless you change it.

If you’re upgrading older scripts, my write-up on the latest Pine Script version covers the migration flags in detail.

How I actually decide on client projects

In 8+ years I’ve settled on a workflow that removes the guesswork. I keep two skeleton files in my template library — one starting with indicator() and one with strategy() — sharing the same signal block, so I can port logic between them in minutes. My default is to prototype the signal as an indicator first, because it is faster to eyeball on the chart and lighter to iterate on. Only once the signal looks right do I promote it to a strategy to measure it honestly with commission and slippage baked in.

The most common request I get is some version of my indicator has perfect arrows but it will not auto-trade. Nine times out of ten the fix is not more logic — it is rebuilding the same script under strategy(), or routing the indicator’s alert into an external bridge. Picking the right declaration up front saves that entire round trip. If you want a second opinion on your own script, you can see how I approach custom builds on my Pine Script development page.

Frequently asked questions

Can a Pine Script indicator place trades or auto-trade?

No. Only a strategy() script can place simulated orders and connect to order-based automation. An indicator can fire an alert, and you can route that alert through a webhook to an external broker bridge, but the indicator itself never opens or closes a position.

Can I convert an indicator into a strategy?

Usually yes. If your signal conditions are already clean booleans, you change the declaration from indicator() to strategy() and add strategy.entry() and strategy.exit() calls gated by those conditions. The plotting code carries over unchanged.

Does a strategy repaint more than an indicator?

Not inherently, but they can differ. Because strategies default to calculating at bar close and indicators to every tick, and because the broker emulator makes intrabar fill assumptions, live behavior can diverge from the backtest. Configure calc_on_every_tick, process_orders_on_close and realistic fills deliberately.

Which is better for TradingView-to-broker automation?

Both are used in practice. Many automated setups use an indicator() with alert() or alertcondition() firing webhooks, while others use a strategy() and its order-fill alerts. The right choice depends on your bridge and whether you need position tracking inside Pine.

Do indicators and strategies have the same plot limit?

Yes — both are capped at 64 plot counts, and a single plot*() call can consume several counts. If you hit the limit, consolidate plots or move some visuals into other drawing types.

Risk disclaimer: Trading and algorithmic trading involve substantial risk of loss and are not suitable for every investor. Backtested and simulated results do not guarantee future performance. Nothing in this article is financial advice — always test thoroughly and trade only capital you can afford to lose.

Need a specific indicator or strategy built, converted, or debugged in Pine Script v6? Message me directly on WhatsApp at +91 77352 68199 and I’ll help you ship it right the first time.

Leave a Reply

Your email address will not be published. Required fields are marked *