Tradingview: Track when something happened

As we saw in the Indexing tutorial, every variable in Pine script is actually a long list of values. One one hand this is great because we are easily able to check the historical value of the variable at any moment in the past. On the other hand, because we take a snapshot on every bar, it might not be immediately obvious how to track when something happened and access the correct historical values. This list is always changing so we cannot simply use Indexing on its own.

The Problem

Often we want to perform some type of check in the code and if it is true, assign a value to a variable. Once we have done this, it might seem natural to check the last value by writing myvar[1](where myvar is the name of the variable you created). However, unless you actually did just assign the value one bar ago, you are unlikely to get the value you are looking for. This is because “something” is always saved to the variable on every bar. This could be naor some other default value you wrote in the code. So what actually happens is that with each passing bar, the value you actually want moves further and further away in the list. To help visualize, imagine that the following list represents myvar:


So as you can see, the last time my condition returned true was 4 bars ago. On the next bar, it will be 5 bars ago. Since we do not know when our condition will be true again, we need to find a way to track and retrieve our data.

Use Cases

Before we head to the solutions, it is worth giving a couple of examples of when or why we may wish to track when something happened. Actually, there are a number of reasons why but for this post we shall focus on two:

  • You guessed it, we might need to retrieve the value of the variable at the time something happened for further comparison.
  • Also, we may want to know how long it has been since a certain condition was met. Either for indexing or to perform other actions within a time window.

Taking those two examples a step further, you might want to compare the close price first bar of the session with the close price on the first bar of the session yesterday. Or perhaps you want to go long only after an RSI drops below 30 AND breaks back above 30 within 5 bars.

These tasks can be even more difficult achieve if you want your script to work on multiple time-frames. For example, looking at the first example, you could not just count the number of bars in the session and use that as the index value. If you do this, the script will only work on the time-frame it was written on.

E.g. You are working on the hourly and there are 8 hours in the session. You could not simply reference close[-8] because if you moved to the 15-minute chart, 8 bars back would not be the start of the previous day’s session.


Since we have 2 problems, we shall also look at two possible solutions. Pine script actually provides us with built-in functions that are designed to help with these use-cases.

Value When

The valuewhen()function does exactly what it says on the tin. It returns the value when a certain condition was met. You can additionally set a parameter to return the Nth occurrence so that you can take a look at the value when the condition was true the time before last… and the time before that…. and so on.

Here is the official doc’s for valuewhen():


Source series value when the condition was true on the n-th most recent occurrence.
valuewhen(condition, source, occurrence) → series
Source value when condition was true

Let’s apply this to our first use case. The following code will provide a very basic strategy that compares the close of the current opening bar against the close of yesterdays opening bar.

When plotted on the chart, it should look something like this:

Using valuewhen()

Due to the way it was coded, this will take the opening bar on any time frame for comparison. You can try this on any intraday timeframe. It is a simple example but should be enough to see how the function works. Play around with the valuewhen()function. Change the close to high or volume. Additionally, you could change the number of days back or pass it a different variable like a simple moving average. Once you play around with it, it will become easy to see how useful this function can be.

Bars Since

Our second example looks at the barssince()built-in function. It will return a number that represents the number of bars that have passed since a condition was true. In this example, we are going to use the barssince()function to track how many bars it has been since the RSI crossed below 30. If it crosses back above 30 within 5 bars, we will go long.

Here are the official docs for barssince():


The barssince function counts a number of bars since condition was true.
barssince(condition) → series[integer]
Number of bars since condition was true.

Because barssince() will return a different value on each bar, we will code this example in two stages. The first stage will allow you to see the value returned and get a real feeling for how it works. As such, we will just plot the value returned from barssince() and feed it the output from a crossunder()check. We will ignore the long entry condition for now.

Track when something happened: RSI crossing under 30

In the image above, we have plotted an actual RSI indicator separately above our barssince() example code. This should make it easier to see how the barssince()values line up with the real indicator. We can see the values returned from barssince()grow by 1 for every bar that passes until the RSI crossed back below the 30 level.

Going a step further

Next, we will take it a step further and move onto the second stage. Here we will add our entry condition to go long if the RSI crosses back over within 5 bars.

So now that we are able to count the number of bars since the RSI crossed under a certain level, we just needed to simply make a check each bar to see if the RSI crosses back up AND the barssince()is less then our desired number of bars. If so, we enter a position.

Finally, to make this a complete strategy, we add a very simple exit condition. In this case, it is as simple as the RSI crossing up over a second level.

Now let’s take a look at how this looks on the chart.

RSI Barssince() Strategy Example

This chart was specifically selected as it shows 2 things which help us to verify that the code is working as expected. First, we can see that the RSI dropped below 30 on 3 occasions. However, during one of those dips, it took 6 bars before it crossed back above 30. As you will see on the chart, the strategy did not take the trade. Secondly, we are able to confirm the positive cases where the RSI dipped below 30, and then crossed back up within 5 bars.

Find This Post Useful?

If this post saved you time and effort, please consider support the site! There are many ways to support us and some won’t even cost you a penny.