Library · Pine Script v6 · Library

ValueAtTime

by ivansoft· code credited to TradingView

A Pine Script v6 library that stores timestamped values and retrieves the value at a past point in time, such as one week, one month or year-to-date ago.

View on GitHub

Repaints

GitHub stars1on the repository
Pine versionv6current
Lines of code485
Settings2inputs
LicenceNone statedfile: MPL-2.0
Last update1 year ago1 Mar 2025

Add It to Your TradingView Chart

  1. 1Copy the scriptPress Copy script above, or the copy button on the code below.
  2. 2Open the Pine EditorOpen a TradingView chart and choose Pine Editor at the bottom of the screen.
  3. 3Paste over the templateCreate a new library, select all of the template text and paste. Press Save and give it a name.
  4. 4Publish or import itA library draws nothing. Publish it from the editor, then import its functions in your own scripts.

Source Code

485 lines of Pine Script v6 from edu_lib/value_at_time.pine, published under MPL-2.0 (file header). Keep the author's credit and licence lines when you reuse it.

value_at_time.pine
// This Pine Script™ code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © TradingView

// @version=6
library("ValueAtTime")

// ValueAtTime Library
// v1, 2025.02.22

// This code was written using the recommendations from the Pine Script® User Manual's Style guide:
//    https://www.tradingview.com/pine-script-docs/writing/style-guide/



//#region ———————————————————— Types and functions



// @type                    A structure for storing successive timestamps and corresponding values from a dataset.
// @field times             An "int" array containing a UNIX timestamp for each value in the `values` array.
// @field values            A "float" array containing values corresponding to the timestamps in the `times` array.
export type Data
    array<int>   times
    array<float> values


// @function                Calculates the maximum number of bars covered by a specified time offset.
//                          The libary uses this helper function to limit the sizes of the arrays in `Data` objects.
// @param timeOffset        (series int) The millisecond time offset (range) from which to calculate the maximum number 
//                          of bars.
// @returns                 (int) The maximum number of bars included in the `timeOffset` range. 
calcLimit(series int timeOffset) =>
    math.ceil(timeOffset / (timeframe.in_seconds() * 1000))


// @function                Retrieves the multiplier from a "string" `period` and converts it to an "int" value.
//                          The library uses this helper function in the timestamp calculations of 
//                          the `periodToTimestamp()` function.
// @param period            (series string) A period string in the format `[multiplier]<unit>`. If the value does 
//                          not specify the `multiplier`, the function returns `1`.
// @returns                 (int) The period multiplier, as an integer. 
getTFMult(series string period) =>
    nz(int(str.tonumber(str.substring(period, 0, str.length(period) - 1))), 1)


// @function                Counts the number of confirmed bars on which the function call executes, raising a runtime 
//                          error when the count exceeds the total number of bars. The library uses this helper function 
//                          in error-handling logic to prevent calls to functions that collect data from executing 
//                          repeatedly inside loops.
checkCall() =>
    var int count = 0
    count += 1
    if count > bar_index + 1
        runtime.error(
             "This function call can execute up to once per bar. It cannot execute repeatedly inside a loop."
         )


// @function                Splits a "string" into an array of substrings using the comma (`,`) as the delimiter.
//                          The function trims surrounding whitespace characters from each substring, and it 
//                          excludes empty substrings from the result. 
// @param str               (series string) The "string" to split into an array based on its commas. 
// @returns                 (array<string>) An array of trimmed substrings from the specified `str`.
export getArrayFromString(series string str) =>
    array<string> result = str.split(str, ",")
    for [index, item] in result
        string trimmedItem = str.trim(item)
        if trimmedItem == ""
            result.remove(index)
            continue
        result.set(index, trimmedItem)
    result


// @function                Calculates a UNIX timestamp representing the point offset behind a reference 
//                          time by the amount of time within the specified `period`. 
// @param period            (series string) The period string, which determines the time offset of the returned 
//                          timestamp. The specified argument must contain a unit and an optional multiplier 
//                          (e.g., "1Y", "3M", "2W", "YTD"). Supported units are:
//                          - "Y" for years.
//                          - "M" for months.
//                          - "W" for weeks.
//                          - "D" for days.
//                          - "YTD" (Year-to-date) for the span from the start of the `referenceTime` value's year in 
//                            the exchange time zone. An argument with this unit cannot contain a multiplier.
// @param referenceTime     (series int) The millisecond UNIX timestamp from which to calculate the offset time.  
// @returns                 (int) A millisecond UNIX timestamp representing the offset time point behind the 
//                          `referenceTime`.
export periodToTimestamp(series string period, series int referenceTime) =>
    int refYear  = year(referenceTime)
    int refMonth = month(referenceTime)
    int refDay   = dayofmonth(referenceTime)
    int refHour  = hour(referenceTime)
    int refMin   = minute(referenceTime)
    int result = switch
        period == "YTD"           => timestamp(refYear, 1, 1, 0, 0)
        str.endswith(period, "Y") => timestamp(refYear - getTFMult(period), refMonth, refDay, refHour, refMin)
        str.endswith(period, "M") =>
            int totalMonths = refYear * 12 + refMonth - getTFMult(period)
            int pastYear    = int(totalMonths / 12)
            int pastMonth   = totalMonths % 12
            if pastMonth == 0
                pastYear  -= 1
                pastMonth := 12
            timestamp(pastYear, pastMonth, refDay, refHour, refMin)
        str.endswith(period, "W") or (str.endswith(period, "D") and not str.contains(period, "YTD")) => 
            referenceTime - timeframe.in_seconds(period) * 1000
        => 
            runtime.error(
                 str.format(
                     "Invalid period: {1}{0}{1}.
                     The period must use one of the following units: {1}Y{1}, {1}M{1}, {1}W{1}, {1}D{1}, {1}YTD{1}.
                     All options except for {1}YTD{1} can include a multiplier prefix (e.g., {1}3D{1}).", 
                     period, "'"
                 )
             ), na
    result


// @function                Collects `source` and `time` data successively across bars. The function stores the 
//                          information within a `Data` object for use in other exported functions/methods, such as 
//                          `valueAtTimeOffset()` and `valueAtPeriodOffset()`.
//                          Any call to this function cannot execute more than once per bar or realtime tick. 
// @param source            (series float) The source series to collect. The function stores each value in the series 
//                          with an associated timestamp representing its corresponding bar's opening time. 
// @param timeOffsetLimit   (simple int) Optional. A time offset (range) in milliseconds. If specified, the function 
//                          limits the collected data to the maximum number of bars covered by the range, with a minimum 
//                          of one bar. If the call includes a non-empty `timeframeLimit` value, the function limits the 
//                          data using the largest number of bars covered by the two ranges. The default is `na`.
// @param timeframeLimit    (simple string) Optional. A valid timeframe string. If specified and not empty, the 
//                          function limits the collected data to the maximum number of bars covered by the timeframe, 
//                          with a minimum of one bar. If the call includes a non-na `timeOffsetLimit` value, the 
//                          function limits the data using the largest number of bars covered by the two ranges. The 
//                          default is `na`.
// @returns                 (Data) A `Data` object containing collected `source` values and corresponding timestamps 
//                          over the allowed time range. 
export collectData(series float source, simple int timeOffsetLimit = na, simple string timeframeLimit = na) =>
    checkCall()
    var int sizeLimit = 
         na(timeOffsetLimit) and na(timeframeLimit) ? na 
             : math.max(
                 nz(calcLimit(timeOffsetLimit)), 
                 calcLimit(timeframe.in_seconds(timeframeLimit) * 1000)
             )
    var Data data = Data.new(array.new<int>(sizeLimit), array.new<float>(sizeLimit))
    data.times.push(time)
    data.values.push(source)
    while data.times.size() > sizeLimit
        data.times.shift()
        data.values.shift()
    data


// @function                (Overload 1 of 2) Retrieves value and time data from a `Data` object's fields at the index 
//                          of the earliest timestamp closest to the specified `timestamp`. Callable as a method or a 
//                          function.
// @param data              (series Data) The `Data` object containing the collected time and value data.
// @param timestamp         (series int) The millisecond UNIX timestamp to search. The function returns data for the 
//                          earliest saved timestamp that is closest to the value. 
// @returns                 ([float, int]) A tuple containing the following data from the `Data` object:
//                          - The stored value corresponding to the identified timestamp ("float").
//                          - The earliest saved timestamp that is closest to the specified `timestamp` ("int").
export method valueAtTime(series Data data, series int timestamp) =>
    int index = data.times.binary_search_leftmost(timestamp)
    [data.values.get(index), data.times.get(index)]


// @function                (Overload 2 of 2) Retrieves `source` and time information for the earliest bar whose opening 
//                          timestamp is closest to the specified `timestamp`. Any call to this function cannot execute 
//                          more than once per bar or realtime tick.
// @param source            (series float) The source series to analyze. The function stores each value in the series 
//                          with an associated timestamp representing its corresponding bar's opening time. 
// @param timestamp         (series int) The millisecond UNIX timestamp to search. The function returns data for the 
//                          earliest bar whose timestamp is closest to the value. 
// @param timeOffsetLimit   (simple int) Optional. A time offset (range) in milliseconds. If specified, the function 
//                          limits the collected data to the maximum number of bars covered by the range, with a minimum 
//                          of one bar. If the call includes a non-empty `timeframeLimit` value, the function limits the 
//                          data using the largest number of bars covered by the two ranges. The default is `na`.
// @param timeframeLimit    (simple string) Optional. A valid timeframe string. If specified and not empty, the 
//                          function limits the collected data to the maximum number of bars covered by the timeframe, 
//                          with a minimum of one bar. If the call includes a non-na `timeOffsetLimit` value, the 
//                          function limits the data using the largest number of bars covered by the two ranges. The 
//                          default is `na`.
// @returns                 ([float, int, float]) A tuple containing the following data:
//                          - The `source` value corresponding to the identified timestamp ("float").
//                          - The earliest bar's timestamp that is closest to the specified `timestamp` ("int").
//                          - The current bar's `source` value ("float").
export valueAtTime(
     series float source, series int timestamp, simple int timeOffsetLimit = na, simple string timeframeLimit = na
 ) =>
    Data data = collectData(source, timeOffsetLimit, timeframeLimit)
    [foundValue, foundTime] = data.valueAtTime(timestamp)
    [foundValue, foundTime, source]


// @function                (Overload 1 of 2) Retrieves value and time data from a `Data` object's fields at the index 
//                          of the earliest saved timestamp closest to `timeOffset` milliseconds behind the current 
//                          bar's opening time. Callable as a method or a function.
// @param data              (series Data) The `Data` object containing the collected time and value data.
// @param timeOffset        (series int) The millisecond offset behind the bar's opening time. The function returns  
//                          data for the earliest saved timestamp that is closest to the calculated offset time. 
// @returns                 ([float, int]) A tuple containing the following data from the `Data` object:
//                          - The stored value corresponding to the identified timestamp ("float").
//                          - The earliest saved timestamp that is closest to `timeOffset` milliseconds before the
//                            current bar's opening time ("int").
export method valueAtTimeOffset(series Data data, series int timeOffset) =>
    int index = data.times.binary_search_leftmost(time - timeOffset)
    [data.values.get(index), data.times.get(index)]


// @function                (Overload 2 of 2) Retrieves `source` and time information for the earliest bar whose opening 
//                          timestamp is closest to `timeOffset` milliseconds behind the current bar's opening time. 
//                          Any call to this function cannot execute more than once per bar or realtime tick.
// @param source            (series float) The source series to analyze. The function stores each value in the series 
//                          with an associated timestamp representing its corresponding bar's opening time. 
// @param timeOffset        (series int) The millisecond offset behind the bar's opening time. The function returns  
//                          data for the earliest bar's timestamp that is closest to the calculated offset time. 
// @param timeOffsetLimit   (simple int) Optional. A time offset (range) in milliseconds. If specified, the function 
//                          limits the collected data to the maximum number of bars covered by the range, with a minimum 
//                          of one bar. If the call includes a non-empty `timeframeLimit` value, the function limits the 
//                          data using the largest number of bars covered by the two ranges. The default is `na`.
// @param timeframeLimit    (simple string) Optional. A valid timeframe string. If specified and not empty, the 
//                          function limits the collected data to the maximum number of bars covered by the timeframe, 
//                          with a minimum of one bar. If the call includes a non-na `timeOffsetLimit` value, the 
//                          function limits the data using the largest number of bars covered by the two ranges. The 
//                          default is `na`.
// @returns                 ([float, int, float]) A tuple containing the following data:
//                          - The `source` value corresponding to the identified timestamp ("float").
//                          - The earliest bar's timestamp that is closest to `timeOffset` milliseconds before the 
//                            current bar's opening time ("int").
//                          - The current bar's `source` value ("float").
export valueAtTimeOffset(
     series float source, series int timeOffset, simple int timeOffsetLimit = na, simple string timeframeLimit = na
 ) =>
    Data data = collectData(source, timeOffsetLimit, timeframeLimit)
    [value, timestamp] = data.valueAtTimeOffset(timeOffset)
    [value, timestamp, source]


// @function                (Overload 1 of 2) Retrieves value and time data from a `Data` object's fields at the index 
//                          of the earliest timestamp closest to a calculated offset behind the current bar's opening 
//                          time. The calculated offset represents the amount of time covered by the specified 
//                          `period`. Callable as a method or a function. 
// @param data              (series Data) The `Data` object containing the collected time and value data.
// @param period            (series string) The period string, which determines the calculated time offset. The 
//                          specified argument must contain a unit and an optional multiplier 
//                          (e.g., "1Y", "3M", "2W", "YTD"). Supported units are:
//                          - "Y" for years.
//                          - "M" for months.
//                          - "W" for weeks.
//                          - "D" for days.
//                          - "YTD" (Year-to-date) for the span from the start of the current bar's year in 
//                            the exchange time zone. An argument with this unit cannot contain a multiplier.
// @returns                 ([float, int]) A tuple containing the following data from the `Data` object:
//                          - The stored value corresponding to the identified timestamp ("float").
//                          - The earliest saved timestamp that is closest to the calculated offset behind the bar's 
//                            opening time ("int").
export method valueAtPeriodOffset(series Data data, series string period) =>
    int   targetTime = periodToTimestamp(period, time)
    int   index      = data.times.binary_search_leftmost(targetTime)
    int   foundTime  = data.times.get(index)
    float foundValue = data.values.get(index)
    [foundValue, foundTime]


// @function                (Overload 2 of 2) Retrieves `source` and time information for the earliest bar whose opening 
//                          timestamp is closest to a calculated offset behind the current bar's opening time. The 
//                          calculated offset represents the amount of time covered by the specified `period`. 
//                          Any call to this function cannot execute more than once per bar or realtime tick.
// @param source            (series float) The source series to analyze. The function stores each value in the series 
//                          with an associated timestamp representing its corresponding bar's opening time. 
// @param period            (series string) The period string, which determines the calculated time offset. The 
//                          specified argument must contain a unit and an optional multiplier 
//                          (e.g., "1Y", "3M", "2W", "YTD"). Supported units are:
//                          - "Y" for years.
//                          - "M" for months.
//                          - "W" for weeks.
//                          - "D" for days.
//                          - "YTD" (Year-to-date) for the span from the start of the current bar's year in 
//                            the exchange time zone. An argument with this unit cannot contain a multiplier.
// @param timeOffsetLimit   (simple int) Optional. A time offset (range) in milliseconds. If specified, the function 
//                          limits the collected data to the maximum number of bars covered by the range, with a minimum 
//                          of one bar. If the call includes a non-empty `timeframeLimit` value, the function limits the 
//                          data using the largest number of bars covered by the two ranges. The default is `na`.
// @param timeframeLimit    (simple string) Optional. A valid timeframe string. If specified and not empty, the 
//                          function limits the collected data to the maximum number of bars covered by the timeframe, 
//                          with a minimum of one bar. If the call includes a non-na `timeOffsetLimit` value, the 
//                          function limits the data using the largest number of bars covered by the two ranges. The 
//                          default is `na`.
// @returns                 ([float, int, float]) A tuple containing the following data:
//                          - The `source` value corresponding to the identified timestamp ("float").
//                          - The earliest bar's timestamp that is closest to the calculated offset behind the 
//                            current bar's opening time ("int").
//                          - The current bar's `source` value ("float").
export valueAtPeriodOffset(
     series float source, series string period, simple int timeOffsetLimit = na, simple string timeframeLimit = na
 ) =>
    Data data = collectData(source, timeOffsetLimit, timeframeLimit)
    [foundValue, foundTime] = data.valueAtPeriodOffset(period)
    [foundValue, foundTime, source]


// @function                Retrieves `source` and time information for each bar whose opening timestamp is the earliest
//                          one closest to one of the UNIX timestamps specified in the `timestamps` array. 
//                          Any call to this function cannot execute more than once per bar or realtime tick.
// @param timestamps        (array<int>) An array of "int" values representing UNIX timestamps. The function retrieves 
//                          `source` and time data for each element in this array.
// @param source            (series float) The source series to analyze. The function stores each value in the series 
//                          with an associated timestamp representing its corresponding bar's opening time.
// @param timeOffsetLimit   (simple int) Optional. A time offset (range) in milliseconds. If specified, the function 
//                          limits the collected data to the maximum number of bars covered by the range, with a minimum 
//                          of one bar. If the call includes a non-empty `timeframeLimit` value, the function limits the 
//                          data using the largest number of bars covered by the two ranges. The default is `na`.
// @param timeframeLimit    (simple string) Optional. A valid timeframe string. If specified and not empty, the 
//                          function limits the collected data to the maximum number of bars covered by the timeframe, 
//                          with a minimum of one bar. If the call includes a non-na `timeOffsetLimit` value, the 
//                          function limits the data using the largest number of bars covered by the two ranges. The 
//                          default is `na`.
// @returns                 ([array<float>, array<int>, float, string]) A tuple of the following data:
//                          - An array containing a `source` value for each identified timestamp (array<float>).
//                          - An array containing an identified timestamp for each item in the `timestamps` array 
//                            (array<int>).
//                          - The current bar's `source` value ("float").
//                          - The symbol's description from `syminfo.description` ("string").
export getDataAtTimes(
     array<int> timestamps, series float source, simple int timeOffsetLimit = na, simple string timeframeLimit = na
 ) =>
    Data data = collectData(source, timeOffsetLimit, timeframeLimit)
    array<float> values = array.new<float>()
    array<int>   times  = array.new<int>()
    for eachTime in timestamps
        [foundValue, foundTime] = valueAtTime(data, eachTime)
        values.push(foundValue)
        times.push(foundTime)
    [values, times, source, syminfo.description]


// @function                Retrieves `source` and time information for each bar whose opening timestamp is the earliest 
//                          one closest to one of the time offsets specified in the `timeOffsets` array. Each offset in 
//                          the array represents the absolute number of milliseconds behind the current bar's opening 
//                          time. Any call to this function cannot execute more than once per bar or realtime tick.
// @param timeOffsets       (array<int>) An array of "int" values representing the millisecond time offsets used in the 
//                          search. The function retrieves `source` and time data for each element in this array. For 
//                          example, the array `[86400000, 604800000]` specifies that the function returns data for the 
//                          timestamps closest to one day and one week behind the current bar's opening time. 
// @param source            (series float) The source series to analyze. The function stores each value in the series 
//                          with an associated timestamp representing its corresponding bar's opening time.
// @param timeOffsetLimit   (simple int) Optional. A time offset (range) in milliseconds. If specified, the function 
//                          limits the collected data to the maximum number of bars covered by the range, with a minimum 
//                          of one bar. If the call includes a non-empty `timeframeLimit` value, the function limits the 
//                          data using the largest number of bars covered by the two ranges. The default is `na`.
// @param timeframeLimit    (simple string) Optional. A valid timeframe string. If specified and not empty, the 
//                          function limits the collected data to the maximum number of bars covered by the timeframe, 
//                          with a minimum of one bar. If the call includes a non-na `timeOffsetLimit` value, the 
//                          function limits the data using the largest number of bars covered by the two ranges. The 
//                          default is `na`.
// @returns                 ([array<float>, array<int>, float, string]) A tuple of the following data:
//                          - An array containing a `source` value for each identified timestamp (array<float>).
//                          - An array containing an identified timestamp for each offset specified in the 
//                            `timeOffsets` array (array<int>).
//                          - The current bar's `source` value ("float").
//                          - The symbol's description from `syminfo.description` ("string").
export getDataAtTimeOffsets(
     array<int> timeOffsets, series float source, simple int timeOffsetLimit = na, simple string timeframeLimit = na
 ) =>
    Data data = collectData(source, timeOffsetLimit, timeframeLimit)
    array<float> values = array.new<float>()
    array<int>   times  = array.new<int>()
    for timeOffset in timeOffsets
        [foundValue, foundTime] = valueAtTimeOffset(data, timeOffset)
        values.push(foundValue)
        times.push(foundTime)
    [values, times, source, syminfo.description]


// @function                Retrieves `source` and time information for each bar whose opening timestamp is the earliest 
//                          one closest to a calculated offset behind the current bar's opening time. Each calculated 
//                          offset represents the amount of time covered by a period specified in the `periods` 
//                          array. Any call to this function cannot execute more than once per bar or realtime tick.
// @param periods           (array<string>) An array of period strings, which determines the time offsets used in 
//                          the search. The function retrieves `source` and time data for each element in this array. 
//                          For example, the array `["1D", "1W", "1M"]` specifies that the function returns 
//                          data for the timestamps closest to one day, week, and month behind the current bar's 
//                          opening time. Each "string" in the array must contain a unit and an optional multiplier. 
//                          Supported units are:
//                          - "Y" for years.
//                          - "M" for months.
//                          - "W" for weeks.
//                          - "D" for days.
//                          - "YTD" (Year-to-date) for the span from the start of the current bar's year in 
//                            the exchange time zone. An argument with this unit cannot contain a multiplier.
// @param source            (series float) The source series to analyze. The function stores each value in the series 
//                          with an associated timestamp representing its corresponding bar's opening time.
// @param timeOffsetLimit   (simple int) Optional. A time offset (range) in milliseconds. If specified, the function 
//                          limits the collected data to the maximum number of bars covered by the range, with a minimum 
//                          of one bar. If the call includes a non-empty `timeframeLimit` value, the function limits the 
//                          data using the largest number of bars covered by the two ranges. The default is `na`.
// @param timeframeLimit    (simple string) Optional. A valid timeframe string. If specified and not empty, the 
//                          function limits the collected data to the maximum number of bars covered by the timeframe, 
//                          with a minimum of one bar. If the call includes a non-na `timeOffsetLimit` value, the 
//                          function limits the data using the largest number of bars covered by the two ranges. The 
//                          default is `na`.
// @returns                 ([array<float>, array<int>, float, string]) A tuple of the following data:
//                          - An array containing a `source` value for each identified timestamp (array<float>).
//                          - An array containing an identified timestamp for each period specified in the 
//                            `periods` array (array<int>).
//                          - The current bar's `source` value ("float").
//                          - The symbol's description from `syminfo.description` ("string").
export getDataAtPeriodOffsets(
     array<string> periods, series float source, simple int timeOffsetLimit = na, simple string timeframeLimit = na
 ) =>
    Data data = collectData(source, timeOffsetLimit, timeframeLimit)
    array<float> values = array.new<float>()
    array<int>   times  = array.new<int>()
    for period in periods 
        [foundValue, foundTime] = valueAtPeriodOffset(data, period)
        values.push(foundValue)
        times.push(foundTime)
    [values, times, source, syminfo.description]
//#endregion



//#region ———————————————————— Example code


// @variable A user-defined symbol to calculate periodic returns from. 
string symbolInput = input.symbol("", "Symbol")
// @variable A comma-separated "string" list of valid periods.
string tfListInput = input.text_area("1W, 1M, 3M, 6M, 12M, YTD, 5Y", "Period list")

// @variable An array of period strings generated by splitting the `tfListInput` based on its commas.
var array<string> periods = getArrayFromString(tfListInput)
// @variable The number of periods in the `periods` array.
var int numPeriods = periods.size()

// Retrieve an array of daily `close` values at different period offsets, an array of corresponding opening timestamps, 
// the current daily `close`, and the symbol's description.
[values, anchors, currClose, description] = request.security(
     symbolInput, "1D", getDataAtPeriodOffsets(periods, close), lookahead = barmerge.lookahead_on
 )

// Logic to display period returns in a table on the last bar. 
if barstate.islast
    // @variable A `table` object that displays the latest change percentages for each listed period. 
    var table changesTable = table.new(position.middle_center, numPeriods + 1, 2, border_width = 3)
    // Calculate cell dimensions based on the number of periods.
    float cellWidth  = 100 / (numPeriods + 1)
    float cellHeight = 25.0
    // Display the symbol's description in the first cell of the second row.
    changesTable.cell(
         0, 1, description,  bgcolor = color.new(color.gray, 80), text_color = chart.fg_color, width = cellWidth, 
         height = cellHeight
     )
    // Populate the first row with the user-specified periods.
    for [index, period] in periods
        changesTable.cell(
             index + 1, 0, period, bgcolor = color.new(color.gray, 80), text_color = chart.fg_color, 
             width = cellWidth, height = cellHeight
         )
    // Loop to calculate and display the percentage change for each period.
    for [index, value] in values
        float changePercent = (currClose - value) / value * 100
        // @variable The base color of the table's cells. Has a green or red hue, depending on the `changePercent`.
        color cellColorBase = changePercent >= 0 ? #089981 : #F23745
        // @variable A gradient color that applies varying transparency to the `cellColorBase`.
        color cellColor = color.from_gradient(
             changePercent, 0, 10, color.new(cellColorBase, 90), color.new(cellColorBase, 70)
         )
        // @variable A formatted "string" expressing the `changePercent` value with the `format.percent` format.
        string cellText = str.tostring(changePercent, format.percent)
        // @variable A formatted "string" representing the past sample's date in the exchange time zone.
        string cellTooltip = str.format_time(anchors.get(index), "'Since' dd MMM yyyy")
        // Reset the cell components if the `changePercent` is `na`. 
        if na(changePercent)
            cellColorBase := chart.fg_color
            cellColor     := color.new(color.gray, 90)
            cellText      := "No data"
            cellTooltip   := na
        // Populate the table cell with the calculated values.
        changesTable.cell(
             index + 1, 1, cellText, tooltip = cellTooltip, bgcolor = cellColor, text_color = cellColorBase, 
             width = cellWidth, height = cellHeight
         )
//#endregion

Overview

ValueAtTime defines a data type with parallel time and value arrays, helper functions that limit array size to the bars covered by an offset, and a parser for a comma-separated period list. Inputs set the symbol and the period list. It draws nothing itself and is imported by other scripts.

Details

Published by

ivansoft on GitHub

Code credit

TradingView, as written in the script's header

Type

Library, Pine Script v6

Draws

Library (no plots)

Markets

Any symbol

Timeframes

Any timeframe

Risk Notes

  • Reads higher-timeframe data with lookahead on, so the history can show signals that were not there in real time

Topics

pinescripttradingvew

Settings

The inputs you can change from the gear icon on the chart. Defaults are the author's.

SettingTypeDefaultVariable
SymbolsymbolsymbolInput
Period listtext1W, 1M, 3M, 6M, 12M, YTD, 5YtfListInput
Third-party code. ForexR did not write, test or endorse this script, and the summary above was generated automatically from its code and README. Indicators describe the past, and a strategy's backtest can look better than live trading, especially when a script repaints. Check it in the Strategy Tester and on a demo account before you rely on it.

Similar Pine Scripts

261 stars

AIActivationFunctionsBipolarSigmoid is a Pine Script library that provides mathematical implementations of the bipolar sigmoid activation function and its derivatives for machine learning algorithms. It calculates bipolar sigmoid values bounded between -1 and

Library v5 AI / machine learning
Updated 4 years ago · None stated GitHub repository of AIActivationFunctionsBipolarSigmoid

KernelFunctions

by artificial-intelligence-edge
75 stars

KernelFunctions is a Pine Script v5 library that exports kernel weight functions for Nadaraya-Watson style estimation. It calculates a Rational Quadratic kernel, a Gaussian kernel based on a radial basis function, and a periodic kernel that models repeating be

Library v5
Updated 3 days ago · MIT GitHub repository of KernelFunctions

Ta

by nersent
29 stars

This Pine Script v5 library exports thin wrappers around built-in technical analysis functions. It covers moving averages, momentum measures such as RSI and CCI, volatility tools including ATR and standard deviation, range extremes, cross detection, and runnin

Library v5
Updated 11 months ago · Custom licence GitHub repository of Ta

Bands

by heyphat
26 stars

This library exports a Band type and functions that build a simple-moving-average basis with upper and lower envelopes from standard deviation. It classifies a source as above, below, or inside those envelopes, measures band width, and scales an imported z-sco

Library v6 Volatility & bandsMoving averages
Updated 2 months ago · AGPL-3.0 GitHub repository of Bands

Mylib

by ferranbt
21 stars

This script serves as a minimal utility library written in Pine Script v6. It provides an exported helper function that calculates the sum of two numeric arguments. As a reusable code library, it produces no visual plots, charts, or trading signals, and it con

Library v6
Updated 7 weeks ago · MPL-2.0 GitHub repository of Mylib

HLevel

by stupenkov
14 stars

HLevel is a Pine Script v5 utility library designed to manage horizontal price levels for cryptocurrency charts. It defines custom types for pivots and levels, along with methods to initialize, add, track, and expire price levels based on pivot high and pivot

Library v5
Updated 3 years ago · None stated GitHub repository of HLevel

More libraries

Trade Your Charts With a Regulated Broker

Compare brokers that connect to TradingView, with spreads, minimum deposits and leverage side by side.

Compare brokers