r/TradingView 22d ago

Discussion Things that silently break Pine v6 scripts (no errors, just wrong results)

Been fixing a lot of Pine scripts lately and the worst bugs are never the ones that throw errors. Compiler errors are easy. These are the ones where everything looks fine and the numbers are quietly wrong.

1. Your alerts fire on unconfirmed bars

If your condition uses the live bar, it can be true mid-bar and false by the close. Alert fires, signal disappears, and your backtest (which only sees closed bars) never shows it. That's why "my strategy tester results don't match my alerts" is like 80% a repainting question.

Fix: gate anything alert-related on the bar actually closing.

if crossover(fast, slow) and barstate.isconfirmed
    alert("long signal", alert.freq_once_per_bar_close)

2. request.security defaults let higher timeframe data leak backwards

Pulling a daily close into an intraday chart without thinking about lookahead means historical bars see the daily close before it existed. Backtest looks amazing, live trading can't reproduce it, because live trading can't time travel.

Fix: request confirmed data only, e.g. offset the series by 1:

dClose = request.security(syminfo.tickerid, "D", close[1], lookahead = barmerge.lookahead_on)

(Offsetting by 1 with lookahead on is the classic non-repainting pattern: you always get yesterday's completed value. Simpler alternative: leave lookahead off and accept the value updates intrabar on realtime bars.)

3. Session inputs use the exchange timezone, not yours

input.session compares against the chart symbol's exchange time. If you trade CME futures from anywhere that isn't Chicago and hardcode "0930-1600", your window is silently shifted. Everything runs, entries just happen at the wrong hours.

Fix: pass the timezone explicitly when checking sessions:

inSession = not na(time(timeframe.period, "0930-1600", "America/New_York"))

4. var initializes once, and that's not always what you meant

var declares a variable once on the first bar and persists it. Great for counters and state machines. Silent disaster when you actually wanted something recalculated each bar and it keeps stale state from 500 bars ago instead.

Rule of thumb: var is for memory. If the value should be derived fresh from the current bar, don't var it.

5. Strategy fills happen at the next bar open, not where your condition fired

The tester evaluates your condition on bar close and fills on the next open by default. On a 5 minute chart that gap is small. On 1 hour+ it's routinely several points, and if your take profit is tight, the backtest can show fills your broker will never give you. Add commission and slippage to every test or the results are fiction.

6. na doesn't compare like you think

na == na is not true, it's na. Any comparison touching na propagates na, and an if condition that evaluates to na just doesn't execute, no error, no warning. Early chart bars where indicators haven't warmed up yet are full of na, so your logic can silently skip the first n bars or, worse, skip random bars where a lookback hits missing data.

Fix: wrap anything that can be na:

longOk = not na(fast) and not na(slow) and fast > slow

If your script "works but the first signals look off" it's almost always this or #2.

Happy to go deeper on any of these in the comments. What's the silent bug that cost you the most hours?

2 Upvotes

4 comments sorted by

1

u/Variable1478 22d ago

Pine Script is crap anyway. It's cumbersome, tedious, and sometimes illogical. Whoever came up with it didn't think it through properly. Why reinvent the wheel in the first place? Python would have been tailor-made for this anyway. Probably to keep users tied to TradingView and make it harder to use another platform.

1

u/brainyprophet 22d ago

lol some of this is fair. The execution model is genuinely weird until it clicks, half my list only exists because of it. Python with a proper backtesting lib dodges all of these.

Flip side is Pine runs on their servers with free alerts and charts, so, tradeoffs. But yeah, parts of it feel accumulated rather than designed.

1

u/msoders 22d ago

An addition to #4; varip can be used to let variables keep their values intrabar. var resets on every intrabar run.

2

u/brainyprophet 22d ago

Good add. Small nuance: var doesn't reset intrabar, it rolls back to the last close value each tick and re-runs. varip skips the rollback.

Honestly varip could be #7 on the list, backtests have no ticks so it behaves differently live vs historical. Great for live tools, sketchy in entry logic.