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 ignoringbarstate.isconfirmed
when needed.
Table of contents
- What causes repaint?
- Safer defaults and guard rails
- HTF filters without future leaks
- Testing like a pro
- Common mistakes to avoid
- Checklist for production readiness
- 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 handlena
withnz()
or guards. - Be explicit about series types. Don’t coerce
series
tofloat
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()
withbarmerge.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 asfloat
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
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.
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.