This library is a Pine Script™ programmer's tool offering the ability to compute relative values, which represent comparisons of current data points, such as volume, price, or custom indicators, with their analogous historical data points from corresponding time offsets. This approach can provide insightful perspectives into the intricate dynamics of relative market behavior over time.
In this library, a relative value is a metric that compares a current data point in a time interval to an average of data points with corresponding time offsets across historical periods. Its purpose is to assess the significance of a value by considering the historical context within past time intervals.
For instance, suppose we wanted to calculate relative volume on an hourly chart over five daily periods, and the last chart bar is two hours into the current trading day. In this case, we would compare the current volume to the average of volume in the second hour of trading across five days. We obtain the relative volume value by dividing the current volume by this average.
This form of analysis rests on the hypothesis that substantial discrepancies or aberrations in present market activity relative to historical time intervals might help indicate upcoming changes in market trends.
Cumulative and non-cumulative values
In the context of this library, a cumulative value refers to the cumulative sum of a series since the last occurrence of a specific condition (referred to as `anchor` in the function definitions). Given that relative values depend on time, we use time-based conditions such as the onset of a new hour, day, etc. On the other hand, a non-cumulative value is simply the series value at a specific time without accumulation.
Calculating relative values
Four main functions coordinate together to compute the relative values: `maintainArray()`, `calcAverageByTime()`, `calcCumulativeSeries()`, and `averageAtTime()`. These functions are underpinned by a `collectedData` user-defined type (UDT), which stores data collected since the last reset of the timeframe along with their corresponding timestamps. The relative values are calculated using the following procedure:
1. The `averageAtTime()` function invokes the process leveraging all four of the methods and acts as the main driver of the calculations. For each bar, this function adds the current bar's source and corresponding time value to a `collectedData` object.
2. Within the `averageAtTime()` function, the `maintainArray()` function is called at the start of each anchor period. It adds a new `collectedData` object to the array and ensures the array size does not exceed the predefined `maxSize` by removing the oldest element when necessary. This method plays an essential role in limiting memory usage and ensuring only relevant data over the desired number of periods is in the calculation window.
3. Next, the `calcAverageByTime()` function calculates the average value of elements within the `data` field for each `collectedData` object that corresponds to the same time offset from each anchor condition. This method accounts for cases where the current index of a `collectedData` object exceeds the last index of any past objects by using the last available values instead.
4. For cumulative calculations, the `averageAtTime()` function utilizes the `isCumulative` boolean parameter. If true, the `calcCumulativeSeries()` function will track the running total of the source data from the last bar where the anchor condition was met, providing a cumulative sum of the source values from one anchor point to the next.
To summarize, the `averageAtTime()` function continually stores values with their corresponding times in a `collectedData` object for each bar in the anchor period. When the anchor resets, this object is added to a larger array. The array's size is limited by the specified number of periods to be averaged. To correlate data across these periods, time indexing is employed, enabling the function to compare corresponding points across multiple periods.
█ USING THIS LIBRARY
The library simplifies the complex process of calculating relative values through its intuitive functions. Follow the steps below to use this library in your scripts.
Step 1: Import the library and declare inputs
Import the library and declare variables based on the user's input. These can include the timeframe for each period, the number of time intervals to include in the average, and whether the calculation uses cumulative values. For example:
//@version=5 import TradingView/RelativeValue/1 as TVrv indicator("Relative Range Demo") string resetTimeInput = input.timeframe("D") int lengthInput = input.int(5, "No. of periods")
Step 2: Define the anchor condition
With these inputs declared, create a condition to define the start of a new period (anchor). For this, we use the change in the time value from the input timeframe:
bool anchor = timeframe.change(resetTimeInput)
Step 3: Calculate the average
At this point, one can calculate the average of a value's history at the time offset from the anchor over a number of periods using the `averageAtTime()` function. In this example, we use True Range (TR) as the `source` and set `isCumulative` to false:
float pastRange = TVrv.averageAtTime(ta.tr, lengthInput, anchor, false)
Step 4: Display the data
You can visualize the results by plotting the returned series. These lines display the non-cumulative TR alongside the average value over `lengthInput` periods for relative comparison:
plot(pastRange, "Past True Range Avg", color.new(chart.bg_color, 70), 1, plot.style_columns) plot(ta.tr, "True Range", close >= open ? color.new(color.teal, 50) : color.new(color.red, 50), 1, plot.style_columns)
This example will display two overlapping series of columns. The green and red columns depict the current TR on each bar, and the light gray columns show the average over a defined number of periods, e.g., the default inputs on an hourly chart will show the average value at the hour over the past five days. This comparative analysis aids in determining whether the range of a bar aligns with its typical historical values or if it's an outlier.
• The foundational concept of this library was derived from our initial Relative Volume at Time script. This library's logic significantly boosts its performance. Keep an eye out for a forthcoming updated version of the indicator. The demonstration code included in the library emulates a streamlined version of the indicator utilizing the library functions.
• Key efficiencies in the data management are realized through array.binary_search_leftmost(), which offers a performance improvement in comparison to its loop-dependent counterpart.
• This library's architecture utilizes user-defined types (UDTs) to create custom objects which are the equivalent of variables containing multiple parts, each able to hold independent values of different types. The recently added feature was announced in this blog post.
• To enhance readability, the code substitutes array functions with equivalent methods.
Look first. Then leap.
This library contains the following functions:
Calculates the cumulative sum of `source` since the last bar where `anchor` was `true`.
source (series float): Source used for the calculation.
anchor (series bool): The condition that triggers the reset of the calculation. The calculation is reset when `anchor` evaluates to `true`, and continues using the values accumulated since the previous reset when `anchor` is `false`.
Returns: (float) The cumulative sum of `source`.
averageAtTime(source, length, anchor, isCumulative)
Calculates the average of all `source` values that share the same time difference from the `anchor` as the current bar for the most recent `length` bars.
source (series float): Source used for the calculation.
length (simple int): The number of reset periods to consider for the average calculation of historical data.
anchor (series bool): The condition that triggers the reset of the average calculation. The calculation is reset when `anchor` evaluates to `true`, and continues using the values accumulated since the previous reset when `anchor` is `false`.
isCumulative (simple bool): If `true`, `source` values are accumulated until the next time `anchor` is `true`. Optional. The default is `true`.
Returns: (float) The average of the source series at the specified time difference.
This version release comes with the following changes:
• The `calcCumulativeSeries()` function now includes an optional `adjustRealtime` parameter. When enabled, the function estimates the potential closing value of the cumulative series on unclosed bars based on the data accumulated since the last anchor condition. Specifically, the function calculates a value-to-time ratio from the cumulative data and uses the result to project a possible closing value. The purpose of this estimation is to allow users to compare a hypothetical closing value to the historical average of closing values on realtime bars whose final values are not yet known.
• We've enhanced the `averageAtTime()` function to address calculation inaccuracies. Previously, the function used the first bar's time from the current period as a reference for offset calculations. While this approach is fine for symbols with consistent sessions, it can cause calculation errors on symbols with varied session open times. To remedy this issue, we've added an overload for the function that uses the input `timeframe` time as its reference, providing more consistency without relying on a specific session's opening time. The previous version (i.e., the first overload) remains available for users who wish to reset periods based on factors other than timeframe changes.
• We've refined the library's code comments and annotations for clarity and readability.
The enhanced `calcCumulativeSeries()` function:
calcCumulativeSeries(source, anchor, adjustRealtime)
Calculates the cumulative sum of the `source` since the last bar where `anchor` was `true`.
source (float): (series float) Source used for the calculation.
anchor (bool): (series bool) The condition that triggers the reset of the calculation. The calculation resets when `anchor` is `true`, and continues accumulating values since the previous reset when `anchor` is `false`.
adjustRealtime (simple bool): (simple bool) If `true`, estimates the cumulative value on unclosed bars based on the data since the last `anchor` condition. Optional. The default is `false`.
Returns: (float) The cumulative sum of the `source`.
The newly overloaded `averageAtTime()` function:
averageAtTime(source, length, timeframe, isCumulative)
Calculates the average `source` value over `length` periods, where the values in the average are from each bar whose time offset from the start of its respective period is closest to that of the current bar in the most recent period.
source (float): (series float) Source used for the calculation.
length (simple int): (simple int) The number of reset periods to consider for the average calculation of historical data.
timeframe (simple string): (series string) Specifies the size of each period in the average calculation. A new period begins when a new bar opens on the specified timeframe.
isCumulative (simple bool): (simple bool) If `true`, calculates the average of cumulative `source` values in each period at the current time offset. Optional. The default is `true`.
Returns: (float) The historical average of the `source` series at the current time offset.
Read more about the new tools and features we're building for you: www.tradingview.com/blog/en/
В истинном духе TradingView автор опубликовал этот код Pine как библиотеку с открытым исходным кодом, чтобы другие разработчики Pine из нашего сообщества могли использовать его повторно. Поблагодарим автора! Вы можете использовать эту библиотеку приватно или в других публикациях с открытым исходным кодом, но повторное использование этого кода в публикации регулируется Правилами поведения.
Все виды контента, которые вы можете увидеть на TradingView, не являются финансовыми, инвестиционными, торговыми или любыми другими рекомендациями. Мы не предоставляем советы по покупке и продаже активов. Подробнее — в Условиях использования TradingView.
Скопируйте текст в буфер обмена и вставьте в свой скрипт.