Aug 11, 2025 • 12 min read

Pine Script v6 Best Practices: Avoiding Repaint and Common Pitfalls

Repaint and subtle type issues are the fastest way to undermine a strategy. Here’s how to write robust Pine v6 code that behaves the same in backtests and real-time.

What causes repaint?

  • Using future data implicitly (e.g., request.security() with lookahead, or referencing unconfirmed HTF bars).
  • Calculations that depend on the final close of the bar while viewing intra-bar updates.
  • Misusing barstate.* and ignoring barstate.isconfirmed when needed.

Table of contents

  1. What causes repaint?
  2. Safer defaults and guard rails
  3. HTF filters without future leaks
  4. Testing like a pro
  5. Common mistakes to avoid
  6. Checklist for production readiness
  7. FAQ

Safer defaults and guard rails

  • Prefer request.security(s, tf, expr, barmerge.gaps_off, barmerge.lookahead_off) and use HTF signals only whenbarstate.isconfirmed is true.
  • Initialize persistent variables with var and always handle na with nz() or guards.
  • Be explicit about series types. Don’t coerce series to float inadvertently; let the compiler help you.

Example: HTF filter with minimal repaint risk

//@version=6
strategy("HTF EMA Filter", overlay=true)

htf = input.timeframe("60", "HTF")
len = input.int(50, "EMA Length", minval=1)

emaHtf = request.security(syminfo.tickerid, htf, ta.ema(close, len), barmerge.gaps_off, barmerge.lookahead_off)

// Use only confirmed HTF info
htfConfirmed = timeframe.isintraday ? barstate.isconfirmed : true
long = htfConfirmed and close > emaHtf and ta.crossover(close, ta.ema(close, 20))
short = htfConfirmed and close < emaHtf and ta.crossunder(close, ta.ema(close, 20))

if long
    strategy.entry("L", strategy.long)
if short
    strategy.entry("S", strategy.short)

Common mistakes to avoid

  • Using request.security() with barmerge.lookahead_on (or implicitly allowing lookahead), which leaks future information.
  • Acting on HTF values before the HTF bar is confirmed. If you need intrabar responsiveness, gate entries with additional conditions and accept the trade-off.
  • Treating series values as float scalars and vice versa; let the compiler guide you and avoid unnecessary casting.
  • Forgetting var initialization for persistent state, which can cause one-bar-lag or undefined behavior at bar 0.

Checklist for production readiness

  • HTF references use lookahead_off and act only on confirmed HTF bars when needed.
  • Inputs expose key knobs and have reasonable defaults; text labels clarify units and intent.
  • Risk management is explicit (stop, take profit, or fail-safe exit) and tested across regimes.
  • Visual plots validate the logic; signals align with expectations in bar replay.
  • Backtest properties reflect real execution (commission, slippage, sizing, pyramiding).

Explore deeper MTF patterns in our guide: MTF Strategy Design. For backtest fidelity, see Optimizing TradingView Backtests.

FAQ

Is repaint always bad?

Not always. Some indicators (e.g., ZigZag) are designed to update with future information for clarity. For strategies and alerts, avoid repaint in decision logic to keep backtests meaningful.

How do I detect hidden repaint?

Compare normal backtests with bar replay near entry points and around session boundaries. Watch for signals that disappear or move. Confirm HTF gates and lookahead settings.

Testing like a pro

  • Compare bar-replay results with normal backtests to spot hidden repaint.
  • Set realistic commission, slippage, and order size in the Strategy Properties panel.
  • Prefer closed-bar logic for signals, then add intra-bar refinements carefully.

Tools that help

PineScripter.app is optimized for Pine v6 and adds validation to reduce repaint risks. It also structures outputs with safer defaults. Alternatives likePineify andPine Script Wizard are useful for quick drafts, but you’ll often want to review their outputs for v6 nuances.