Pine Script trading bot: from TradingView strategy to live orders
Pine Script is TradingView’s built-in language, and it is where a huge number of retail strategies are first written and backtested. But Pine alone cannot place a real trade — it lives inside TradingView’s charts. To turn a Pine strategy into a live bot you write a strategy() script, fire an alert when it signals, and bridge that alert to your exchange through a webhook receiver. This guide shows the Pine strategy code, the alert syntax, how the webhook bridge works, and the repaint trap that makes a beautiful Pine backtest lie.
What Pine Script can and cannot do
Pine Script runs inside TradingView. It can compute indicators, define entry/exit rules in a strategy() script, and backtest them on the chart with a built-in performance report. What it cannot do is touch your exchange account — there is no order API in Pine. The live link is an alert plus an external receiver, the same architecture as the TradingView webhook bot.
A strategy() script
pine · sma_cross.pine//@version=5
strategy("SMA Cross", overlay=true)
fast = ta.sma(close, 20)
slow = ta.sma(close, 50)
if ta.crossover(fast, slow)
strategy.entry("long", strategy.long)
if ta.crossunder(fast, slow)
strategy.close("long")
The Strategy Tester panel then reports return, drawdown and win rate — but treat those numbers with the same scepticism as any backtest.
Firing the alert
Add an alert() call (or a strategy alert) whose message is a JSON payload your receiver understands:
pine · alert payloadif ta.crossover(fast, slow)
alert('{"action":"buy","symbol":"BTCUSDT","qty":0.001}',
alert.freq_once_per_bar_close)
Fire on bar close, never intrabar — an intrabar alert can trigger then vanish when the candle reverses.
The webhook bridge
The receiver is a small server that validates a shared secret and calls the exchange. The security model — secret token, IP allow-list — is the same as the webhook bot guide, and the order placement is plain ccxt.
The repaint trap
If a script uses future-referencing functions or intrabar values, signals can repaint — appear in hindsight where they never occurred live — producing a gorgeous, fictional backtest. Always test with bar-close confirmation, avoid lookahead_on, and verify the live alerts match the backtested entries before trusting a single result.
Getting started
Write the strategy() script, confirm the Strategy Tester result is repaint-free, wire the alert to a receiver, and run it through a paper exchange first. Cross-check the live equity curve against the backtester before going live.
Frequently asked questions
Can Pine Script place real trades?
No. Pine Script runs inside TradingView and has no order API, so it cannot touch your exchange account directly. To trade live you write a strategy() script, fire an alert when it signals, and bridge that alert to your exchange through an external webhook receiver that places the order.
How do I turn a Pine Script strategy into a bot?
Write the rules in a strategy() script, add an alert() call whose message is a JSON payload, and point the alert webhook at a small receiver server. The receiver validates a shared secret and uses a library like ccxt to place the order on your exchange.
Why should Pine alerts fire on bar close?
An intrabar alert can trigger and then disappear if the candle reverses before it closes, sending a phantom order your backtest never recorded. Firing once per bar close ensures the live signal matches the confirmed historical signal and avoids acting on a condition that did not actually hold.
What is repainting in Pine Script?
Repainting is when a script uses future-referencing or intrabar values so that signals appear in hindsight where they never occurred in real time, producing a beautiful but fictional backtest. Avoiding lookahead, testing on bar-close confirmation, and checking that live alerts match backtested entries prevent this trap.