How to avoid repainting when NOT using security()

Even when your code does not use security() calls, repainting dynamics still come into play in the realtime bar. Script coders and users must understand them and, if they choose to avoid repainting, need to know how to do so. This script demonstrates three methods to avoid repainting when NOT using the security() function.

Note that repainting dynamics when not using security() usually only come into play in the realtime bar, as historical data is fixed and thus cannot cause repainting, except in situations related to stock splits or dividend adjustments.

For those who don’t want to read
Configure your alerts to trigger “Once Per Bar Close” and you’re done.

For those who want to understand
Put this indicator on a 1 minute or seconds chart with a live symbol. As price changes you will see four of this script’s MAs (all except the two orange ones) move in the realtime bar. You are seeing repainting in action. When the current realtime bar closes and becomes a historical bar, the lines on the historical bars will no longer move, as the bar’s OHLC values are fixed. Note that you may need to refresh your chart to see the correct historical OHLC values, as exchange feeds sometimes produce very slight variations between the end values of the realtime bar and those of the same bar once it becomes a historical bar.

Some traders do not use signals generated by a script but simply want to avoid seeing the lines plotted by their scripts move during the realtime bar. They are concerned with repainting of the lines.

Other traders use their scripts to evaluate conditions, which they use to either plot markers on the chart, trigger alerts, or both. They may not care about the script’s plotted lines repainting, but do not want their markers to appear/disappear on the chart, nor their alerts to trigger for a condition that becomes true during the realtime bar but is no longer true once it closes. Those traders are more concerned with repainting of signals.

For each of the three methods shown in this script’s code, comments explain if its lines, markers and alerts will repaint or not. Through the Settings/Inputs you will be able to control plotting of lines and markers corresponding to each method, as well as experiment with the option, for method 2, of disabling only the lines plotting in the realtime bar while still allowing the markers and alerts to be generated.

An unavoidable fact is that non-repainting lines, markers or alerts are always late compared to repainting ones. The good news is that how late they are will in many cases be insignificant, so that the added reliability of the information they provide will largely offset the disadvantages of waiting.

Method 1 illustrates the usual way of going about things in a script. Its gray lines and markers will always repaint but repainting of the alerts the marker conditions generate can be avoided by configuring alerts to trigger “Once Per Bar Close”. Because this gray marker repaints, you will occasionally see it appear/disappear during the realtime bar when the gray MAs cross/un-cross.
Method 2 plots the same MAs as method 1, but in green. The difference is that it delays its marker condition by one bar to ensure it does not repaint. Its lines will normally repaint but its markers will not, as they pop up after the condition has been confirmed on the bar preceding the realtime bar. Its markers appear at the beginning of the realtime bar and will never disappear. When using this method alerts can be configured to trigger “Once Per Bar” so they fire the moment the marker appears on the chart at the beginning of the realtime bar. Note that the delay incurred between methods 1 and 2 is merely the instant between the close of a realtime bar and the beginning of the next one—a delay measured in milliseconds. Method 2 also allows its lines to be hidden in the realtime bar with the corresponding option in the script’s Settings/Inputs. This will be useful to those wishing to eliminate unreliable lines from the realtime bar. Commented lines in method 2 provide for a 2b option, which is to delay the calculation of the MAs rather than the cross condition. It has the obvious inconvenient of plotting delayed MAs, but may come in handy in some situations.
Method 3 is not the best solution when using MAs because it uses the open of bars rather than their close to calculate the MAs. While this provides a way of avoiding repainting, it is not ideal in the case of MA calcs but may come in handy in other cases. The orange lines and markers of method 3 will not repaint because the value of open cannot change in the realtime bar. Because its markers do not repaint, alerts may be configured using “Once Per Bar”.

Spend some time playing with the different options and looking at how this indicator’s lines plot and behave when you refresh you chart. We hope everything you need to understand and prevent repainting when not using security() is there.
Release Notes: Updated comments.
Release Notes: Vacuumed unnecessary plotshape() parameter.
Remove from Favorite Scripts Add to Favorite Scripts
Tools and ideas for all Pine coders:
Pine Wizards:
Our Pine FAQ & Code:
Get Pine news and tips on Telegram:


I'm using bar_index in my script and I'm defining alertcondition in it. Always when I'm adding alert based on this condition I have the warning saying that: "This alert may trigger differently than expected, since it's based on an indicator or strategy that can get repainted". How can I get rid of it when using bar_index. When I remove this variable there is no such warning.
I also noticed this warning appears when I will use any of barstate.* variable.
PineCoders Kapucha
@Kapucha, You are correct; using `bar_index` will trigger the warning even though the mere use of the variable does not entail the script will necessarily repaint. The logic detecting repainting cannot isolate with certainty only the uses that will cause repainting, which is why the warning's wording uses "can get repainted". We will be reassessing the warning with the Pine team to consider if the warning, which seemed like a good idea at the time, is causing more harm than good.

In the meantime, you can use code like this to forego use of `bar_index`:
var bar = -1
bar := bar + 1
Kapucha PineCoders
@PineCoders, Nice trick for now :) Thanks!
I think this solution is better:
study("Repainting into study", overlay = true)

repainting = input(true, "Repainting")
last_value = input(false, "last value when non repainting")

fastLength = input(10, "Fast Length")
slowLength = input(3, "Slow Length")
fast_sma = sma(close, fastLength)
slow_sma = sma(close, slowLength)

cross = cross(fast_sma, slow_sma)[1]

plot(barstate.ishistory ? fast_sma : repainting ? fast_sma :  barstate.isconfirmed ? fast_sma : last_value ? fast_sma[1] : na, "Fast SMA",, linewidth = 2)
plot(barstate.ishistory ? slow_sma : repainting ? slow_sma : barstate.isconfirmed ? slow_sma : last_value ? slow_sma[1] : na, "Slow SMA",, linewidth = 2)
alertcondition(cross, "Cross SMA", "Alert without repainting")
PineCoders kitoboynaya
@kitoboynaya, Good concept. It should work well and demonstrates you understand the underlying principles, but the optimal solution will vary with needs.
+1 Reply
Home Stock Screener Forex Screener Crypto Screener Economic Calendar How It Works Chart Features Pricing Refer a friend House Rules Help Center Website & Broker Solutions Widgets Charting Solutions Lightweight Charting Library Blog & News Twitter
Profile Profile Settings Account and Billing Referred friends Coins My Support Tickets Help Center Ideas Published Followers Following Private Messages Chat Sign Out