PineCoders

ConditionalAverages

█  OVERVIEW


This library is a Pine Script™ programmer’s tool containing functions that average values selectively.



█  CONCEPTS


Averaging can be useful to smooth out unstable readings in the data set, provide a benchmark to see the underlying trend of the data, or to provide a general expectancy of values in establishing a central tendency. Conventional averaging techniques tend to apply indiscriminately to all values in a fixed window, but it can sometimes be useful to average values only when a specific condition is met. As conditional averaging works on specific elements of a dataset, it can help us derive more context-specific conclusions. This library offers a collection of averaging methods that not only accomplish these tasks, but also exploit the efficiencies of the Pine Script™ runtime by foregoing unnecessary and ​​​resource-intensive for loops.



█  NOTES


To Loop or Not to Loop

Though for and while loops are essential programming tools, they are often unnecessary in Pine Script™. This is because the Pine Script™ runtime already runs your scripts in a loop where it executes your code on each bar of the dataset. Pine Script™ programmers who understand how their code executes on charts can use this to their advantage by designing loop-less code that will run orders of magnitude faster than functionally identical code using loops. Most of this library's function illustrate how you can achieve loop-less code to process past values. See the User Manual page on loops for more information. If you are looking for ways to measure execution time for you scripts, have a look at our LibraryStopwatch library.

Our `avgForTimeWhen()` and `totalForTimeWhen()` are exceptions in the library, as they use a while structure. Only a few iterations of the loop are executed on each bar, however, as its only job is to remove the few elements in the array that are outside the moving window defined by a time boundary.


Cumulating and Summing Conditionally

The ta.cum() or math.sum() built-in functions can be used with ternaries that select only certain values. In our `avgWhen(​src, ​cond)` function, for example, we use this technique to cumulate only the occurrences of `src` when `cond` is true:
float cumTotal = ta.cum(cond ? ​src : 0)
We then use:
float cumCount = ta.cum(cond ? 1 : 0)
to calculate the number of occurrences where `cond` is true, which corresponds to the quantity of values cumulated in `cumTotal`.


Building Custom Series With Arrays

The advent of arrays in Pine has enabled us to build our custom data series. Many of this library's functions use arrays for this purpose, saving newer values that come in when a condition is met, and discarding the older ones, implementing a queue.


`avgForTimeWhen()` and `totalForTimeWhen()`

These two functions warrant a few explanations. They operate on a number of values included in a moving window defined by a timeframe expressed in milliseconds. We use a 1D timeframe in our example code. The number of bars included in the moving window is unknown to the programmer, who only specifies the period of time defining the moving window. You can thus use `avgForTimeWhen()` to calculate a rolling moving average for the last 24 hours, for example, that will work whether the chart is using a 1min or 1H timeframe. A 24-hour moving window will typically contain many more values on a 1min chart that on a 1H chart, but their calculated average will be very close.

Problems will arise on non-24x7 markets when large time gaps occur between chart bars, as will be the case across holidays or trading sessions. For example, if you were using a 24H timeframe and there is a two-day gap between two bars, then no chart bars would fit in the moving window after the gap. The `minBars` parameter mitigates this by guaranteeing that a minimum number of bars are always included in the calculation, even if including those bars requires reaching outside the prescribed timeframe. We use a minimum value of 10 bars in the example code.


Using var in Constant Declarations

In the past, we have been using var when initializing so-called constants in our scripts, which as per the Style Guide's recommendations, we identify using UPPER_SNAKE_CASE. It turns out that var variables incur slightly superior maintenance overhead in the Pine Script™ runtime, when compared to variables initialized on each bar. We thus no longer use var to declare our "int/float/bool" constants, but still use it when an initialization on each bar would require too much time, such as when initializing a string or with a heavy function call.



█  FUNCTIONS


avgWhen(​src, ​cond)
  Gathers values of the source when a condition is true and averages them over the total number of occurrences of the condition.
  Parameters:
    src: (series int/float) The source of the values to be averaged.
    cond: (series bool) The condition determining when a value will be included in the set of values to be averaged.
  Returns: (float) A cumulative average of values when a condition is met.

avgWhenLast(​src, ​cond, ​cnt)
  Gathers values of the source when a condition is true and averages them over a defined number of occurrences of the condition.
  Parameters:
    src: (series int/float) The source of the values to be averaged.
    cond: (series bool) The condition determining when a value will be included in the set of values to be averaged.
    cnt: (simple int) The quantity of last occurrences of the condition for which to average values.
  Returns: (float) The average of `src` for the last `x` occurrences where `cond` is true.

avgWhenInLast(​src, ​cond, ​cnt)
  Gathers values of the source when a condition is true and averages them over the total number of occurrences during a defined number of bars back.
  Parameters:
    src: (series int/float) The source of the values to be averaged.
    cond: (series bool) The condition determining when a value will be included in the set of values to be averaged.
    cnt: (simple int) The quantity of bars back to evaluate.
  Returns: (float) The average of `src` in last `cnt` bars, but only when `cond` is true.

avgSince(​src, ​cond)
  Averages values of the source since a condition was true.
  Parameters:
    src: (series int/float) The source of the values to be averaged.
    cond: (series bool) The condition determining when the average is reset.
  Returns: (float) The average of `src` since `cond` was true.

avgForTimeWhen(​src, ​ms, ​cond, ​minBars)
  Averages values of `src` when `cond` is true, over a moving window of length `ms` milliseconds.
  Parameters:
    src: (series int/float) The source of the values to be averaged.
    ms: (simple int) The time duration in milliseconds defining the size of the moving window.
    cond: (series bool) The condition determining which values are included. Optional.
    minBars: (simple int) The minimum number of values to keep in the moving window. Optional.
  Returns: (float) The average of `src` when `cond` is true in the moving window.

totalForTimeWhen(​src, ​ms, ​cond, ​minBars)
  Sums values of `src` when `cond` is true, over a moving window of length `ms` milliseconds.
  Parameters:
    src: (series int/float) The source of the values to be summed.
    ms: (simple int) The time duration in milliseconds defining the size of the moving window.
    cond: (series bool) The condition determining which values are included. Optional.
    minBars: (simple int) The minimum number of values to keep in the moving window. Optional.
  Returns: (float) The sum of `src` when `cond` is true in the moving window.

Tools and ideas for all Pine coders: http://www.pinecoders.com
Our Pine FAQ & Code: http://www.pinecoders.com/faq_and_code/
Pine news broadcasts: https://t.me/PineCodersSquawkBox or https://twitter.com/PineCoders
Pine library

In true TradingView spirit, the author has published this Pine code as an open-source library so that other Pine programmers from our community can reuse it. Cheers to the author! You may use this library privately or in other open-source publications, but reuse of this code in a publication is governed by House Rules.

Disclaimer

The information and publications are not meant to be, and do not constitute, financial, investment, trading, or other types of advice or recommendations supplied or endorsed by TradingView. Read more in the Terms of Use.

Want to use this library?

Copy the following line and paste it in your script.