How to avoid repainting when using security() - PineCoders FAQ

This indicator shows how to avoid repainting when using the security() function to retrieve information from higher timeframes.

What do we mean by repainting?
Repainting is used to describe three different things, in what we’ve seen in TV members comments on indicators:
1. An indicator showing results that change during the realtime bar, whether the script is using the security() function or not, e.g., a Buy signal that goes on and then off, or a plot that changes values.
2. An indicator that uses future data not yet available on historical bars.
3. An indicator that uses a negative offset= parameter when plotting in order to plot information on past bars.
The repainting types we will be discussing here are the first two types, as the third one is intentional—sometimes even intentionally misleading when unscrupulous script writers want their strategy to look better than it is.

Let’s be clear about one thing: repainting is not caused by a bug; it is caused by the different context between historical bars and the realtime bar, and script coders or users not taking the necessary precautions to prevent it.

Why should repainting be avoided?
Repainting matters because it affects the behavior of Pine scripts in the realtime bar, where the action happens and counts, because that is when traders (or our systems) take decisions where odds must be in our favor.
Repainting also matters because if you test a strategy on historical bars using only OHLC values, and then run that same code on the realtime bar with more than OHLC information, scripts not properly written or misconfigured alerts will alter the strategy’s behavior. At that point, you will not be running the same strategy you tested, and this invalidates your test results, which were run while not having the additional price information that is available in the realtime bar.
The realtime bar on your charts is only one bar, but it is a very important bar. Coding proper strategies and indicators on TV requires that you understand the variations in script behavior and how information available to the script varies between when the script is running on historical and realtime bars.

How does repainting occur?
Repainting happens because of something all traders instinctively crave: more information. Contrary to trader lure, more information is not always better. In the realtime bar, all TV indicators (a.k.a. studies) execute every time price changes (i.e. every tick). TV strategies will also behave the same way if they use the calc_on_every_tick = true parameter in their strategy() declaration statement (the parameter’s default value is false). Pine coders must decide if they want their code to use the realtime price information as it comes in, or wait for the realtime bar to close before using the same OHLC values for that bar that would be used on historical bars.
Strategy modelers often assume that using realtime price information as it comes in the realtime bar will always improve their results. This is incorrect. More information does not necessarily improve performance because it almost always entails more noise. The extra information may or may not improve results; one cannot know until the code is run in realtime for enough time to provide data that can be analyzed and from which somewhat reliable conclusions can be derived. In any case, as was stated before, it is critical to understand that if your strategy is taking decisions on realtime tick data, you are NOT running the same strategy you tested on historical bars with OHLC values only.

How do we avoid repainting?
It comes down to using reliable information and properly configuring alerts, if you use them. Here are the main considerations:
1. If your code is using security() calls, use the syntax we propose to obtain reliable data from higher timeframes.
2. If your script is a strategy, do not use the calc_on_every_tick = true parameter unless your strategy uses previous bar information to calculate.
3. If your script is a study and is using current timeframe information that is compared to values obtained from a higher timeframe, even if you can rely on reliable higher timeframe information because you are correctly using the security() function, you still need to ensure the realtime bar’s information you use (a cross of current close over a higher timeframe MA, for example) is consistent with your backtest methodology, i.e. that your script calculates on the close of the realtime bar. If your system is using alerts, the simplest solution is to configure alerts to trigger Once Per Bar Close. If you are not using alerts, the best solution is to use information from the preceding bar. When using previous bar information, alerts can be configured to trigger Once Per Bar safely.

What does this indicator do?
It shows results for 9 different ways of using the security() function and illustrates the simplest and most effective way to avoid repainting, i.e. using security() as in the example above. To show the indicator’s lines the most clearly, price on the chart is shown with a black line rather than candlesticks . This indicator also shows how misusing security() produces repainting. All combinations of using a 0 or 1 offset to reference the series used in the security(), as well as all combinations of values for the gaps= and lookahead= parameters are shown.
The close in the call labeled “BEST” means that once security has reached the upper timeframe (1 day in our case), it will fetch the previous day’s value.
The gaps= parameter is not specified as it is off by default and that is what we need. This ensures that the value returned by security() will not contain na values on any of our chart’s bars.
The lookaheadsecurity() to use the last available value for the higher timeframe bar we are using (the previous day, in our case). This ensures that security() will return the value at the end of the higher timeframe, even if it has not occurred yet. In our case, this has no negative impact since we are requesting the previous day’s value, with has already closed.

The indicator’s Settings/Inputs allow you to set:
- The higher timeframe security() calls will use
- The source security() calls will use
- If you want identifying labels printed on the lines that have no gaps (the lines containing gaps are plotted using very thick lines that appear as horizontal blocks of one bar in length)
For the lines to be plotted, you need to be on a smaller timeframe than the one used for the security() calls.
Comments in the code explain what’s going on.
Catatan Rilis: Simplified timeframe validation code and updated comments.
Catatan Rilis: v1.4
We present two new functions to help coders use `security()`:
f_secureSecurity(_symbol, _res, _src)
A worry-free way to use `security()` so that it never repaints, be it on historical or the realtime bar, and doesn't suffer from lookahead bias.
Use the 3 parameters exactly as you would with a normal call to `security()`. Do not include the offset for the source, as the function already takes care of it.

f_security(_symbol, _res, _src, _repaint)
This is for coders who want to offer their users the choice of a repainting/no-repainting version of the HTF data. It uses only one `security()` call for both.
The first three parameters are identical to the `security()` ones. The fourth is a boolean: false for the non-repainting version, true for the repainting version.

Other changes
• The identification of each line has been simplified.
• You can now choose to show different subsets of the lines.
• The default HTF resolution is 5min, so a 1-minute chart will show the lines clearly.
Skrip open-source

Sejalan dengan semangat TradingView, penulis skrip ini telah mempublikasikannya secara open-source, sehingga para trader dapat memahami dan memverifikasinya. Salut untuk sang penulis! Anda dapat menggunakannya secara gratis, tetapi penggunaan kembali kode ini dalam publikasi diatur oleh Tata Tertib. Anda dapat memfavoritkannya untuk dapat menggunakannya didalam sebuah chart.

Inggin menggunakan skrip ini pada chart?
Tools and ideas for all Pine coders:
Our Pine FAQ & Code:
Pine news broadcasts: or


Please help me understand, if I add the following code to your code above to Enter_Long and create an alert condition to Enter_Long, TV gives the repaint warning when creating an alert.
Enter_Long = sec1ft > sec1ft(1) parentheses used instead of brackets
alertcondition(Enter_Long, title='EnterLong', message='EnterLong')

Warning: this alert is based on an indicator that can get repainted.

How can your method be used to not repaint on an alert?
+4 Jawab
PineCoders tstanton4
@tstanton4, The warning message is conservative and preventive. Notice it says "may trigger differently". If you followed our recommendations in your code and alert setup, you can trust that your script will not repaint, warning or not.
@PineCoders ... help please.
I took the most basic (new) strategy and added this:
getSecurity(t, res, src) => security(t, res, src, lookahead = barmerge.lookahead_on)

hlc3_10m = getSecurity(syminfo.tickerid, "10", high)
And when alerting, it gives me the repainting warning.
I tried the 3 minute time-frame, and the 1 minute.
+3 Jawab
sketchytraida Electrified
@Electrified, Read the comments, someone already asked this and the author replied. He said ignore the warning because it can be inaccurate
PineCoders sketchytraida
@sketchytraida, Thx 💙. Had missed that comment.
sketchytraida PineCoders
@PineCoders, no problem at all. I myself learned a lot from your answer on that. Very interesting to know tradingview only guesses that we have repainting. I always thought it would be nice if they showed us what line they think is causing the repainting. But upon trying to find out myself I found your information and it's helped me a lot to understand it
@PineCoders thanks for the great reference. Question - can multiple use of security() function in the same script cause repainting by itself even if all the rules to avoid repainting is there? Maybe some TradingView issue, system overloading?

Example from my code-

myvar = security(syminfo.tickerid, TimeFrame, highest(high, len), gaps = barmerge.gaps_off, lookahead = barmerge.lookahead_on)
myvar2 = security(syminfo.tickerid, TimeFrame, lowest(low, len), gaps = barmerge.gaps_off, lookahead = barmerge.lookahead_on)

I have several of those for highest, lowest and in a couple of different timeframes - 1D, 3D. So in total, I can have 6 or 9 security() calls in the script. The script then compares them and fires an indicator if certain condition is met. I can see it repaints every couple of days.

thanks for your thoughts.
+1 Jawab
btrades77 btrades77
little correction, the code actual has this -

myvar = security(syminfo.tickerid, TimeFrame, highest(high, len), gaps = barmerge.gaps_off, lookahead = barmerge.lookahead_on)
myvar2 = security(syminfo.tickerid, TimeFrame, lowest(low, len), gaps = barmerge.gaps_off, lookahead = barmerge.lookahead_on)
btrades77 btrades77
looks like TradingView removes brakets 1 after 'high' and 'low', I have them in the code.
PineCoders btrades77
1. You can use
 before and 
after your code (without spaces) to post code and preserve brackets.
2. No, using multiple security() calls should not impact results, as long as you are fetching from higher TFs. Using security() at lower TFs than the chart's sometimes produces anomalies.
3. What exactly do you mean when you say "I can see it repaints every couple of days"? A chart would be helpful to understand.
+1 Jawab
Beranda Penyaring Saham Penyaring Forex Penyaring Crypto Kalender Ekonomi Tentang Fitur-Fitur Chart Harga Akun Refer seorang teman Tata Tertib Pusat Bantuan Solusi Website & Broker Widget-Widget Solusi Charting Perpustakaan Charting Ringan Blog & Berita Twitter