ValueAtTime█ OVERVIEW 
This library is a Pine Script® programming tool for accessing historical values in a time series using  UNIX timestamps . Its data structure and functions index values by time, allowing scripts to retrieve past values based on absolute timestamps or relative time offsets instead of relying on bar index offsets. 
 █ CONCEPTS 
 UNIX timestamps 
In Pine Script®, a  UNIX timestamp  is an integer representing the number of milliseconds elapsed since January 1, 1970, at 00:00:00 UTC (the  UNIX Epoch ). The timestamp is a unique,  absolute  representation of a specific point in time. Unlike a calendar date and time, a UNIX timestamp's meaning does not change relative to any  time zone . 
This library's functions process series values and corresponding UNIX timestamps in  pairs , offering a simplified way to identify values that occur at or near distinct points in time instead of on specific bars. 
 Storing and retrieving time-value pairs 
This library's `Data`  type  defines the structure for collecting time and value information in pairs.  Objects  of the `Data` type contain the following two fields:
 • `times` – An array of "int" UNIX timestamps for each recorded value.
 • `values` – An array of "float" values for each saved timestamp.
Each index in both  arrays  refers to a specific time-value pair. For instance, the `times` and `values` elements at index 0 represent the  first  saved timestamp and corresponding value. The library functions that maintain `Data` objects  queue  up to one time-value pair per bar into the object's arrays, where the saved timestamp represents the bar's  opening time . 
Because the `times` array contains a distinct UNIX timestamp for each item in the `values` array, it serves as a custom mapping for retrieving saved values. All the library functions that return information from a `Data` object use this simple two-step process to identify a value based on time:
 1. Perform a  binary search  on the `times` array to find the earliest saved timestamp closest to the specified time or offset and get the element's index.
 2. Access the element from the `values` array at the retrieved index, returning the stored value corresponding to the found timestamp. 
 Value search methods 
There are several techniques programmers can use to identify historical values from corresponding timestamps. This library's functions include three different search methods to locate and retrieve values based on absolute times or relative time offsets:
 Timestamp search  
Find the value with the earliest saved timestamp closest to a specified timestamp. 
 Millisecond offset search  
Find the value with the earliest saved timestamp closest to a specified number of milliseconds behind the current bar's opening time. This search method provides a time-based alternative to retrieving historical values at specific bar offsets. 
 Period offset search  
Locate the value with the earliest saved timestamp closest to a defined period offset behind the current bar's opening time. The function calculates the span of the offset based on a  period string . The "string" must contain one of the following unit tokens: 
 • "D" for days
 • "W" for weeks
 • "M" for months
 • "Y" for years
 • "YTD" for year-to-date, meaning the time elapsed since the beginning of the bar's opening year in the exchange time zone. 
The period string can include a multiplier prefix for all supported units except "YTD" (e.g., "2W" for two weeks). 
Note that the precise span covered by the "M", "Y", and "YTD" units varies across time. The "1M" period can cover 28, 29, 30, or 31 days, depending on the bar's opening month and year in the exchange time zone. The "1Y" period covers 365 or 366 days, depending on leap years. The "YTD" period's span changes with each new bar, because it always measures the time from the start of the current bar's opening year.  
 █ CALCULATIONS AND USE 
This library's functions offer a flexible, structured approach to retrieving historical values at or near specific timestamps, millisecond offsets, or period offsets for different analytical needs.
See below for explanations of the exported functions and how to use them. 
 Retrieving single values 
The library includes three functions that retrieve a single stored value using timestamp, millisecond offset, or period offset search methods:
 • `valueAtTime()` – Locates the saved value with the earliest timestamp closest to a specified timestamp. 
 • `valueAtTimeOffset()` – Finds the saved value with the earliest timestamp closest to the specified number of milliseconds behind the current bar's opening time. 
 • `valueAtPeriodOffset()` – Finds the saved value with the earliest timestamp closest to the period-based offset behind the current bar's opening time. 
Each function has  two overloads  for advanced and simple use cases. The first overload searches for a value in a user-specified `Data` object created by the `collectData()` function (see below). It returns a  tuple  containing the found value and the corresponding timestamp. 
The second overload maintains a `Data` object  internally  to store and retrieve values for a specified `source` series. This overload returns a tuple containing the historical `source` value, the corresponding timestamp, and the current bar's `source` value, making it helpful for comparing past and present values from requested contexts. 
 Retrieving multiple values 
The library includes the following functions to retrieve values from multiple historical points in time, facilitating calculations and comparisons with values retrieved across several intervals:
 • `getDataAtTimes()` – Locates a past `source` value for each item in a `timestamps` array. Each retrieved value's timestamp represents the earliest time closest to one of the specified timestamps. 
 • `getDataAtTimeOffsets()` – Finds a past `source` value for each item in a `timeOffsets` array. Each retrieved value's timestamp represents the earliest time closest to one of the specified millisecond offsets behind the current bar's opening time. 
 • `getDataAtPeriodOffsets()` – Finds a past value for each item in a `periods` array. Each retrieved value's timestamp represents the earliest time closest to one of the specified period offsets behind the current bar's opening time. 
Each function returns a tuple with arrays containing the found `source` values and their corresponding timestamps. In addition, the tuple includes the current `source` value and the symbol's description, which also makes these functions helpful for multi-interval comparisons using data from requested contexts. 
 Processing period inputs 
When writing scripts that retrieve historical values based on several user-specified period offsets, the most concise approach is to create a single text input that allows users to list each period, then process the "string" list into an array for use in the `getDataAtPeriodOffsets()` function. 
This library includes a `getArrayFromString()` function to provide a simple way to process strings containing comma-separated lists of periods. The function splits the specified `str` by its commas and returns an array containing every  non-empty  item in the list with surrounding whitespaces removed. View the example code to see how we use this function to process the value of a  text area input . 
 Calculating period offset times 
Because the exact amount of time covered by a specified period offset can vary, it is often helpful to verify the resulting times when using the `valueAtPeriodOffset()` or `getDataAtPeriodOffsets()` functions to ensure the calculations work as intended for your use case. 
The library's `periodToTimestamp()` function calculates an offset timestamp from a given period and reference time. With this function, programmers can verify the time offsets in a period-based data search and use the calculated offset times in additional operations. 
For periods with "D" or "W" units, the function calculates the time offset based on the absolute number of milliseconds the period covers (e.g., `86400000` for "1D"). For periods with "M", "Y", or "YTD" units, the function calculates an offset time based on the reference time's  calendar date  in the exchange time zone. 
 Collecting data 
All the `getDataAt*()` functions, and the second overloads of the `valueAt*()` functions, collect and maintain data internally, meaning scripts do not require a separate `Data` object when using them. However, the first overloads of the `valueAt*()` functions  do not  collect data, because they retrieve values from a  user-specified  `Data` object. 
For cases where a script requires a separate `Data` object for use with these overloads or other custom routines, this library exports the `collectData()` function. This function queues each bar's `source` value and opening timestamp into a `Data` object and returns the object's ID. 
This function is particularly useful when searching for values from a specific series more than once. For instance, instead of using multiple calls to the second overloads of `valueAt*()` functions with the same `source` argument, programmers can call `collectData()` to store each bar's `source` and opening timestamp, then use the returned `Data` object's ID in calls to the  first  `valueAt*()` overloads to reduce memory usage. 
The `collectData()` function and all the functions that collect data internally include two optional parameters for limiting the saved time-value pairs to a sliding window: `timeOffsetLimit` and `timeframeLimit`. When either has a non-na argument, the function restricts the collected data to the maximum number of recent bars covered by the specified millisecond- and timeframe-based intervals. 
 NOTE : All calls to the functions that collect data for a `source` series can execute up to  once  per bar or realtime tick, because each stored value requires a unique corresponding timestamp. Therefore, scripts  cannot  call these functions iteratively within a  loop . If a call to these functions executes more than once inside a loop's scope, it causes a runtime error. 
 █ EXAMPLE CODE 
The example code at the end of the script demonstrates one possible use case for this library's functions. The code retrieves historical price data at user-specified period offsets, calculates price returns for each period from the retrieved data, and then populates a  table  with the results. 
The example code's process is as follows:
  1. Input a list of periods  – The user specifies a comma-separated list of period strings in the script's "Period list" input (e.g., "1W, 1M, 3M, 1Y, YTD"). Each item in the input list represents a period offset from the latest bar's opening time. 
  2. Process the period list  – The example calls `getArrayFromString()` on the first bar to split the input list by its commas and construct an array of period strings. 
  3. Request historical data  – The code uses a call to `getDataAtPeriodOffsets()` as the `expression` argument in a  request.security()  call to retrieve the closing prices of "1D" bars for each period included in the processed `periods` array. 
  4. Display information in a table  – On the latest bar, the code uses the retrieved data to calculate price returns over each specified period, then populates a two-row table with the results. The cells for each return percentage are color-coded based on the magnitude and direction of the price change. The cells also include tooltips showing the compared daily bar's opening date in the exchange time zone. 
 █ NOTES 
 • This library's architecture relies on a  user-defined type (UDT)  for its data storage format. UDTs are blueprints from which scripts create  objects , i.e., composite structures with fields containing independent values or references of any supported type. 
 • The library functions search through a `Data` object's `times` array using the  array.binary_search_leftmost()  function, which is more efficient than looping through collected data to identify matching timestamps. Note that this built-in works only for arrays with elements sorted in  ascending order . 
 • Each function that collects data from a `source` series updates the values and times stored in a local `Data` object's arrays. If a single call to these functions were to execute in a  loop , it would store multiple values with an  identical  timestamp, which can cause erroneous search behavior. To prevent looped calls to these functions, the library uses the `checkCall()` helper function in their scopes. This function maintains a counter that increases by one each time it executes on a confirmed bar. If the count  exceeds  the total number of bars, indicating the call executes more than once in a loop, it raises a  runtime error . 
 • Typically, when requesting  higher-timeframe  data with  request.security()  while using  barmerge.lookahead_on  as the `lookahead` argument, the `expression` argument should be  offset  with the  history-referencing operator  to prevent  lookahead bias  on historical bars. However, the call in this script's example code enables lookahead without offsetting the `expression` because the script displays results only on the last historical bar and all realtime bars, where there is  no future data  to leak into the past. This call ensures the displayed results use the latest data available from the context on realtime bars.
 Look first. Then leap. 
 █ EXPORTED TYPES 
 Data 
  A structure for storing successive timestamps and corresponding values from a dataset.
  Fields:
     times (array) : An "int" array containing a UNIX timestamp for each value in the `values` array.
     values (array) : A "float" array containing values corresponding to the timestamps in the `times` array.
 █ EXPORTED FUNCTIONS 
 getArrayFromString(str) 
  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.
  Parameters:
     str (series string) : The "string" to split into an array based on its commas.
  Returns: (array) An array of trimmed substrings from the specified `str`.
 periodToTimestamp(period, referenceTime) 
  Calculates a UNIX timestamp representing the point offset behind a reference time by the amount of time within the specified `period`.
  Parameters:
     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.
     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`.
 collectData(source, timeOffsetLimit, timeframeLimit) 
  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.
  Parameters:
     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.
     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`.
     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.
 method valueAtTime(data, timestamp) 
  (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.
  Parameters:
     data (series Data) : The `Data` object containing the collected time and value data.
     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: ( ) 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").
 valueAtTime(source, timestamp, timeOffsetLimit, timeframeLimit) 
  (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.
  Parameters:
     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.
     timestamp (series int) : The millisecond UNIX timestamp to search. The function returns data for the earliest bar whose timestamp is closest to the value.
     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`.
     timeframeLimit (simple string) : (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: ( ) 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").
 method valueAtTimeOffset(data, timeOffset) 
  (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.
  Parameters:
     data (series Data) : The `Data` object containing the collected time and value data.
     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: ( ) 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").
 valueAtTimeOffset(source, timeOffset, timeOffsetLimit, timeframeLimit) 
  (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.
  Parameters:
     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.
     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.
     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`.
     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: ( ) 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").
 method valueAtPeriodOffset(data, period) 
  (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.
  Parameters:
     data (series Data) : The `Data` object containing the collected time and value data.
     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: ( ) 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").
 valueAtPeriodOffset(source, period, timeOffsetLimit, timeframeLimit) 
  (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.
  Parameters:
     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.
     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.
     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`.
     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: ( ) 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").
 getDataAtTimes(timestamps, source, timeOffsetLimit, timeframeLimit) 
  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.
  Parameters:
     timestamps (array) : An array of "int" values representing UNIX timestamps. The function retrieves `source` and time data for each element in this array.
     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.
     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`.
     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: ( ) A tuple of the following data:
- An array containing a `source` value for each identified timestamp (array).
- An array containing an identified timestamp for each item in the `timestamps` array (array).
- The current bar's `source` value ("float").
- The symbol's description from `syminfo.description` ("string").
 getDataAtTimeOffsets(timeOffsets, source, timeOffsetLimit, timeframeLimit) 
  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.
  Parameters:
     timeOffsets (array) : 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 ` ` specifies that the function returns data for the timestamps closest to one day and one week behind the current bar's opening time.
     source (float) : (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.
     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`.
     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: ( ) A tuple of the following data:
- An array containing a `source` value for each identified timestamp (array).
- An array containing an identified timestamp for each offset specified in the `timeOffsets` array (array).
- The current bar's `source` value ("float").
- The symbol's description from `syminfo.description` ("string").
 getDataAtPeriodOffsets(periods, source, timeOffsetLimit, timeframeLimit) 
  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.
  Parameters:
     periods (array) : 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 ` ` 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.
     source (float) : (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.
     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`.
     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: ( ) A tuple of the following data:
- An array containing a `source` value for each identified timestamp (array).
- An array containing an identified timestamp for each period specified in the `periods` array (array).
- The current bar's `source` value ("float").
- The symbol's description from `syminfo.description` ("string").
Metrics
Request█   OVERVIEW 
This library is a tool for Pine Script™ programmers that consolidates access to a wide range of lesser-known data feeds available on TradingView, including metrics from the FRED database, FINRA short sale volume, open interest, and COT data. The functions in this library simplify requests for these data feeds, making them easier to retrieve and use in custom scripts. 
█   CONCEPTS 
 Federal Reserve Economic Data (FRED) 
 FRED  (Federal Reserve Economic Data) is a comprehensive online database curated by the Federal Reserve Bank of St. Louis. It provides free access to extensive economic and financial data from U.S. and international sources. FRED includes numerous economic indicators such as GDP, inflation, employment, and interest rates. Additionally, it provides financial market data, regional statistics, and international metrics such as exchange rates and trade balances. 
Sourced from reputable organizations, including U.S. government agencies, international institutions, and other public and private entities, FRED enables users to analyze over 825,000 time series, download their data in various formats, and integrate their information into analytical tools and programming workflows. 
On TradingView, FRED data is available from ticker identifiers with the "FRED:" prefix. Users can search for FRED symbols in the "Symbol Search" window, and Pine scripts can retrieve data for these symbols via `request.*()` function calls.
 FINRA Short Sale Volume 
FINRA (the Financial Industry Regulatory Authority) is a non-governmental organization that supervises and regulates U.S. broker-dealers and securities professionals. Its primary aim is to protect investors and ensure integrity and transparency in financial markets. 
FINRA's  Short Sale Volume data  provides detailed information about daily short-selling activity across U.S. equity markets. This data tracks the volume of short sales reported to FINRA's trade reporting facilities (TRFs), including shares sold on FINRA-regulated Alternative Trading Systems (ATSs) and over-the-counter (OTC) markets, offering transparent access to short-selling information not typically available from exchanges. This data helps market participants, researchers, and regulators monitor trends in short-selling and gain insights into bearish sentiment, hedging strategies, and potential market manipulation. Investors often use this data alongside other metrics to assess stock performance, liquidity, and overall trading activity. 
It is important to note that FINRA's Short Sale Volume data does not consolidate short sale information from public exchanges and excludes trading activity that is not publicly disseminated.
TradingView provides ticker identifiers for requesting Short Sale Volume data with the format "FINRA:_SHORT_VOLUME", where "" is a supported U.S. equities symbol (e.g., "AAPL"). 
 Open Interest (OI) 
 Open interest  is a cornerstone indicator of market activity and sentiment in derivatives markets such as options or futures. In contrast to volume, which measures the number of contracts opened or closed within a period, OI measures the number of  outstanding contracts  that are not yet settled. This distinction makes OI a more robust indicator of how money flows through derivatives, offering meaningful insights into liquidity, market interest, and trends. Many traders and investors analyze OI alongside volume and price action to gain an enhanced perspective on market dynamics and reinforce trading decisions. 
TradingView offers many ticker identifiers for requesting OI data with the format "_OI", where "" represents a derivative instrument's  ticker ID  (e.g., "COMEX:GC1!").
 Commitment of Traders (COT) 
 Commitment of Traders  data provides an informative weekly breakdown of the aggregate positions held by various market participants, including commercial hedgers, non-commercial speculators, and small traders, in the U.S. derivative markets. Tallied and managed by the  Commodity Futures Trading Commission (CFTC) , these reports provide traders and analysts with detailed insight into an asset's open interest and help them assess the actions of various market players. COT data is valuable for gaining a deeper understanding of market dynamics, sentiment, trends, and liquidity, which helps traders develop informed trading strategies.
TradingView has numerous ticker identifiers that provide access to time series containing data for various COT metrics. To learn about COT ticker IDs and how they work, see our  LibraryCOT  publication. 
█   USING THE LIBRARY 
 Common function characteristics 
 • This library's functions construct ticker IDs with valid formats based on their specified parameters, then use them as the `symbol` argument in  request.security()  to retrieve data from the specified context. 
 • Most of these functions automatically select the timeframe of a data request because the data feeds are not available for all timeframes. 
 • All the functions have  two  overloads. The first overload of each function uses values with the  "simple"  qualifier to define the requested context, meaning the context does not change after the first script execution. The second accepts  "series"  values, meaning it can request data from different contexts across executions. 
 • The `gaps` parameter in most of these functions specifies whether the returned data is `na` when a new value is unavailable for request. By default, its value is `false`, meaning the call returns the last retrieved data when no new data is available. 
 • The `repaint` parameter in applicable functions determines whether the request can fetch the latest unconfirmed values from a higher timeframe on realtime bars, which might repaint after the script restarts. If `false`, the function only returns confirmed higher-timeframe values to avoid repainting. The default value is `true`.
 `fred()` 
The `fred()` function retrieves the most recent value of a specified series from the Federal Reserve Economic Data (FRED) database. With this function, programmers can easily fetch macroeconomic indicators, such as GDP and unemployment rates, and use them directly in their scripts. 
 How it works 
The function's `fredCode` parameter accepts a "string" representing the unique identifier of a specific FRED series. Examples include "GDP" for the "Gross Domestic Product" series and "UNRATE" for the "Unemployment Rate" series. Over 825,000 codes are available. To access codes for available series, search the  FRED website .  
The function adds the "FRED:" prefix to the specified `fredCode` to construct a valid FRED ticker ID (e.g., "FRED:GDP"), which it uses in  request.security()  to retrieve the series data.
 Example Usage 
This line of code requests the latest value from the Gross Domestic Product series and assigns the returned value to a `gdpValue` variable:
 float gdpValue = fred("GDP") 
 `finraShortSaleVolume()` 
The `finraShortSaleVolume()` function retrieves  EOD  data from a FINRA  Short Sale Volume  series. Programmers can call this function to retrieve short-selling information for equities listed on supported exchanges, namely NASDAQ, NYSE, and NYSE ARCA. 
 How it works 
The `symbol` parameter determines which symbol's short sale volume information is retrieved by the function. If the value is  na , the function requests short sale volume data for the chart's symbol. The argument can be the name of the symbol from a supported exchange (e.g., "AAPL") or a ticker ID with an exchange prefix ("NASDAQ:AAPL"). If the `symbol` contains an exchange prefix, it must be one of the following: "NASDAQ", "NYSE", "AMEX", or "BATS". 
The function constructs a ticker ID in the format "FINRA:ticker_SHORT_VOLUME", where "ticker" is the symbol name  without  the exchange prefix (e.g., "AAPL"). It then uses the ticker ID in  request.security()  to retrieve the available data. 
 Example Usage 
This line of code retrieves short sale volume for the chart's symbol and assigns the result to a `shortVolume` variable:
 float shortVolume = finraShortSaleVolume(syminfo.tickerid) 
This example requests short sale volume for the "NASDAQ:AAPL" symbol, irrespective of the current chart:
 float shortVolume = finraShortSaleVolume("NASDAQ:AAPL") 
 `openInterestFutures()` and `openInterestCrypto()` 
The `openInterestFutures()` function retrieves  EOD  open interest (OI) data for futures contracts. The `openInterestCrypto()` function provides more granular OI data for cryptocurrency contracts. 
 How they work 
The `openInterestFutures()` function retrieves EOD closing OI information. Its design is focused primarily on retrieving OI data for futures, as only EOD OI data is available for these instruments. If the chart uses an intraday timeframe, the function requests data from the "1D" timeframe. Otherwise, it uses the chart's timeframe. 
The `openInterestCrypto()` function retrieves opening, high, low, and closing OI data for a cryptocurrency contract on a specified timeframe. Unlike `openInterest()`, this function can also retrieve granular data from intraday timeframes. 
Both functions contain a `symbol` parameter that determines the symbol for which the calls request OI data. The functions construct a valid OI ticker ID from the chosen symbol by appending "_OI" to the end (e.g., "CME:ES1!_OI"). 
The `openInterestFutures()` function requests and returns a two-element tuple containing the futures instrument's EOD closing OI and a "bool" condition indicating whether OI is rising.
The `openInterestCrypto()` function requests and returns a five-element tuple containing the cryptocurrency contract's opening, high, low, and closing OI, and a "bool" condition indicating whether OI is rising. 
 Example usage 
This code line calls `openInterest()` to retrieve EOD OI and the OI rising condition for a futures symbol on the chart, assigning the values to two variables in a tuple:
  = openInterestFutures(syminfo.tickerid) 
This line retrieves the EOD OI data for "CME:ES1!", irrespective of the current chart's symbol:
  = openInterestFutures("CME:ES1!") 
This example uses `openInterestCrypto()` to retrieve OHLC OI data and the OI rising condition for a cryptocurrency contract on the chart, sampled at the chart's timeframe. It assigns the returned values to five variables in a tuple:
  = openInterestCrypto(syminfo.tickerid, timeframe.period) 
This call retrieves OI OHLC and rising information for "BINANCE:BTCUSDT.P" on the "1D" timeframe:
  = openInterestCrypto("BINANCE:BTCUSDT.P", "1D") 
 `commitmentOfTraders()` 
The `commitmentOfTraders()` function retrieves data from the Commitment of Traders (COT) reports published by the Commodity Futures Trading Commission (CFTC). This function significantly simplifies the COT request process, making it easier for programmers to access and utilize the available data. 
 How It Works 
This function's parameters determine different parts of a valid ticker ID for retrieving COT data, offering a streamlined alternative to constructing complex COT ticker IDs manually. The `metricName`, `metricDirection`, and `includeOptions` parameters are required. They specify the name of the reported metric, the direction, and whether it includes information from options contracts. 
The function also includes several optional parameters. The `CFTCCode` parameter allows programmers to request data for a specific report code. If unspecified, the function requests data based on the chart symbol's root prefix, base currency, or quoted currency, depending on the `mode` argument. The call can specify the report type ("Legacy", "Disaggregated", or "Financial") and metric type ("All", "Old", or "Other") with the `typeCOT` and `metricType` parameters. 
Explore the  CFTC website  to find valid report codes for specific assets. To find detailed information about the metrics included in the reports and their meanings, see the  CFTC's Explanatory Notes . 
View the function's documentation below for detailed explanations of its parameters. For in-depth information about COT ticker IDs and more advanced functionality, refer to our previously published  COT library . 
 Available metrics 
Different COT report types provide  different metrics . The tables below list all available metrics for each type and their applicable directions:
 +------------------------------+------------------------+
|  Legacy (COT) Metric Names   |       Directions       |
+------------------------------+------------------------+
| Open Interest                | No direction           |
| Noncommercial Positions      | Long, Short, Spreading |
| Commercial Positions         | Long, Short            |
| Total Reportable Positions   | Long, Short            |
| Nonreportable Positions      | Long, Short            |
| Traders Total                | No direction           |
| Traders Noncommercial        | Long, Short, Spreading |
| Traders Commercial           | Long, Short            |
| Traders Total Reportable     | Long, Short            |
| Concentration Gross LT 4 TDR | Long, Short            |
| Concentration Gross LT 8 TDR | Long, Short            |
| Concentration Net LT 4 TDR   | Long, Short            |
| Concentration Net LT 8 TDR   | Long, Short            |
+------------------------------+------------------------+
+-----------------------------------+------------------------+
| Disaggregated (COT2) Metric Names |       Directions       |
+-----------------------------------+------------------------+
| Open Interest                     | No Direction           |
| Producer Merchant Positions       | Long, Short            |
| Swap Positions                    | Long, Short, Spreading |
| Managed Money Positions           | Long, Short, Spreading |
| Other Reportable Positions        | Long, Short, Spreading |
| Total Reportable Positions        | Long, Short            |
| Nonreportable Positions           | Long, Short            |
| Traders Total                     | No Direction           |
| Traders Producer Merchant         | Long, Short            |
| Traders Swap                      | Long, Short, Spreading |
| Traders Managed Money             | Long, Short, Spreading |
| Traders Other Reportable          | Long, Short, Spreading |
| Traders Total Reportable          | Long, Short            |
| Concentration Gross LE 4 TDR      | Long, Short            |
| Concentration Gross LE 8 TDR      | Long, Short            |
| Concentration Net LE 4 TDR        | Long, Short            |
| Concentration Net LE 8 TDR        | Long, Short            |
+-----------------------------------+------------------------+
+-------------------------------+------------------------+
| Financial (COT3) Metric Names |       Directions       |
+-------------------------------+------------------------+
| Open Interest                 | No Direction           |
| Dealer Positions              | Long, Short, Spreading |
| Asset Manager Positions       | Long, Short, Spreading |
| Leveraged Funds Positions     | Long, Short, Spreading |
| Other Reportable Positions    | Long, Short, Spreading |
| Total Reportable Positions    | Long, Short            |
| Nonreportable Positions       | Long, Short            |
| Traders Total                 | No Direction           |
| Traders Dealer                | Long, Short, Spreading |
| Traders Asset Manager         | Long, Short, Spreading |
| Traders Leveraged Funds       | Long, Short, Spreading |
| Traders Other Reportable      | Long, Short, Spreading |
| Traders Total Reportable      | Long, Short            |
| Concentration Gross LE 4 TDR  | Long, Short            |
| Concentration Gross LE 8 TDR  | Long, Short            |
| Concentration Net LE 4 TDR    | Long, Short            |
| Concentration Net LE 8 TDR    | Long, Short            |
+-------------------------------+------------------------+ 
 Example usage 
This code line retrieves "Noncommercial Positions (Long)" data, without options information, from the "Legacy" report for the chart symbol's root, base currency, or quote currency:
 float nonCommercialLong = commitmentOfTraders("Noncommercial Positions", "Long", false) 
This example retrieves "Managed Money Positions (Short)" data, with options included, from the "Disaggregated" report:
 float disaggregatedData = commitmentOfTraders("Managed Money Positions", "Short", true, "", "Disaggregated") 
█   NOTES 
 • This library uses  dynamic requests , allowing dynamic ("series") arguments for the parameters defining the context (ticker ID, timeframe, etc.) of a `request.*()` function call. With this feature, a single `request.*()` call instance can flexibly retrieve data from different feeds across historical executions. Additionally, scripts can use such calls in the  local scopes  of loops, conditional structures, and even exported library functions, as demonstrated in this script. All scripts coded in Pine Script™ v6 have dynamic requests enabled by default. To learn more about the behaviors and limitations of this feature, see the  Dynamic requests  section of the Pine Script™ User Manual.
 • The library's example code offers a simple demonstration of the exported functions. The script retrieves available data using the function specified by the "Series type" input. The code requests a FRED series or COT (Legacy), FINRA Short Sale Volume, or Open Interest series for the chart's symbol with specific parameters, then plots the retrieved data as a step-line with diamond markers. 
 Look first. Then leap.  
█   EXPORTED FUNCTIONS 
This library exports the following functions:
 fred(fredCode, gaps) 
  Requests a value from a specified Federal Reserve Economic Data (FRED) series. FRED is a comprehensive source that hosts numerous U.S. economic datasets. To explore available FRED datasets and codes, search for specific categories or keywords at fred.stlouisfed.org Calls to this function count toward a script's `request.*()` call limit.
  Parameters:
     fredCode (series string) : The unique identifier of the FRED series. The function uses the value to create a valid ticker ID for retrieving FRED data in the format `"FRED:fredCode"`. For example, `"GDP"` refers to the "Gross Domestic Product" series ("FRED:GDP"), and `"GFDEBTN"` refers to the "Federal Debt: Total Public Debt" series ("FRED:GFDEBTN").
     gaps (simple bool) : Optional. If `true`, the function returns a non-na value only when a new value is available from the requested context. If `false`, the function returns the latest retrieved value when new data is unavailable. The default is `false`.
  Returns: (float) The value from the requested FRED series.
 finraShortSaleVolume(symbol, gaps, repaint) 
  Requests FINRA daily short sale volume data for a specified symbol from one of the following exchanges: NASDAQ, NYSE, NYSE ARCA. If the chart uses an intraday timeframe, the function requests data from the "1D" timeframe. Otherwise, it uses the chart's timeframe. Calls to this function count toward a script's `request.*()` call limit.
  Parameters:
     symbol (series string) : The symbol for which to request short sale volume data. If the specified value contains an exchange prefix, it must be one of the following: "NASDAQ", "NYSE", "AMEX", "BATS".
     gaps (simple bool) : Optional. If `true`, the function returns a non-na value only when a new value is available from the requested context. If `false`, the function returns the latest retrieved value when new data is unavailable. The default is `false`.
     repaint (simple bool) : Optional. If `true` and the chart's timeframe is intraday, the value requested on realtime bars may change its time offset after the script restarts its executions. If `false`, the function returns the last confirmed period's values to avoid repainting. The default is `true`.
  Returns: (float) The short sale volume for the specified symbol or the chart's symbol.
 openInterestFutures(symbol, gaps, repaint) 
  Requests EOD open interest (OI) and OI rising information for a valid futures symbol. If the chart uses an intraday timeframe, the function requests data from the "1D" timeframe. Otherwise, it uses the chart's timeframe. Calls to this function count toward a script's `request.*()` call limit.
  Parameters:
     symbol (series string) : The symbol for which to request open interest data.
     gaps (simple bool) : Optional. If `true`, the function returns non-na values only when new values are available from the requested context. If `false`, the function returns the latest retrieved values when new data is unavailable. The default is `false`.
     repaint (simple bool) : Optional. If `true` and the chart's timeframe is intraday, the value requested on realtime bars may change its time offset after the script restarts its executions. If `false`, the function returns the last confirmed period's values to avoid repainting. The default is `true`.
  Returns: ( ) A tuple containing the following values:
    - The closing OI value for the symbol.
    - `true` if the closing OI is above the previous period's value, `false` otherwise.
 openInterestCrypto(symbol, timeframe, gaps, repaint) 
  Requests opening, high, low, and closing open interest (OI) data and OI rising information for a valid cryptocurrency contract on a specified timeframe. Calls to this function count toward a script's `request.*()` call limit.
  Parameters:
     symbol (series string) : The symbol for which to request open interest data.
     timeframe (series string) : The timeframe of the data request. If the timeframe is lower than the chart's timeframe, it causes a runtime error.
     gaps (simple bool) : Optional. If `true`, the function returns non-na values only when new values are available from the requested context. If `false`, the function returns the latest retrieved values when new data is unavailable. The default is `false`.
     repaint (simple bool) : Optional. If `true` and the `timeframe` represents a higher timeframe, the function returns unconfirmed values from the timeframe on realtime bars, which repaint when the script restarts its executions. If `false`, it returns only confirmed higher-timeframe values to avoid repainting. The default is `true`.
  Returns: ( ) A tuple containing the following values:
    - The opening, high, low, and closing OI values for the symbol, respectively.
    - `true` if the closing OI is above the previous period's value, `false` otherwise.
 commitmentOfTraders(metricName, metricDirection, includeOptions, CFTCCode, typeCOT, mode, metricType) 
  Requests Commitment of Traders (COT) data with specified parameters. This function provides a simplified way to access CFTC COT data available on TradingView. Calls to this function count toward a script's `request.*()` call limit. For more advanced tools and detailed information about COT data, see TradingView's  LibraryCOT  library.
  Parameters:
     metricName (series string) : One of the valid metric names listed in the library's documentation and source code.
     metricDirection (series string) : Metric direction. Possible values are: "Long", "Short", "Spreading", and "No direction". Consult the library's documentation or code to see which direction values apply to the specified metric.
     includeOptions (series bool) : If `true`, the COT symbol includes options information. Otherwise, it does not.
     CFTCCode (series string) : Optional. The CFTC code for the asset. For example, wheat futures (root "ZW") have the code "001602". If one is not specified, the function will attempt to get a valid code for the chart symbol's root, base currency, or main currency.
     typeCOT (series string) : Optional. The type of report to request. Possible values are: "Legacy", "Disaggregated", "Financial". The default is "Legacy".
     mode (series string) : Optional. Specifies the information the function extracts from a symbol. Possible modes are:
  - "Root": The function extracts the futures symbol's root prefix information (e.g., "ES" for "ESH2020").
  - "Base currency": The function extracts the first currency from a currency pair (e.g., "EUR" for "EURUSD").
  - "Currency": The function extracts the currency of the symbol's quoted values (e.g., "JPY" for "TSE:9984" or "USDJPY").
  - "Auto": The function tries the first three modes (Root -> Base currency -> Currency) until it finds a match.
  The default is "Auto". If the specified mode is not available for the symbol, it causes a runtime error.
     metricType (series string) : Optional. The metric type. Possible values are: "All", "Old", "Other". The default is "All".
  Returns: (float) The specified Commitment of Traders data series. If no data is available, it causes a runtime error.
analytics_tablesLibrary  "analytics_tables" 
📝  Description 
This library provides the implementation of several performance-related statistics and metrics, presented in the form of tables.
The metrics shown in the afforementioned tables where developed during the past years of my in-depth analalysis of various strategies in an atempt to reason about the performance of each strategy.
The visualization and some statistics where inspired by the existing implementations of the "Seasonality" script, and the performance matrix implementations of @QuantNomad and @ZenAndTheArtOfTrading scripts.
While this library is meant to be used by my strategy framework "Template Trailing Strategy (Backtester)" script, I wrapped it in a library hoping this can be usefull for other community strategy scripts that will be released in the future.
🤔  How to Guide 
To use the functionality this library provides in your script you have to import it first!
Copy the import statement of the latest release by pressing the copy button below and then paste it into your script. Give a short name to this library so you can refer to it later on. The import statement should look like this:
 import jason5480/analytics_tables/1 as ant 
There are three types of tables provided by this library in the initial release. The stats table the metrics table and the seasonality table.
Each one shows different kinds of performance statistics.
The table UDT shall be initialized once using the `init()` method.
They can be updated using the `update()` method where the updated data UDT object shall be passed.
The data UDT can also initialized and get updated on demend depending on the use case
A code example for the StatsTable is the following:
 var ant.StatsData statsData = ant.StatsData.new()
statsData.update(SideStats.new(), SideStats.new(), 0)
if (barstate.islastconfirmedhistory or (barstate.isrealtime and barstate.isconfirmed))
        var statsTable = ant.StatsTable.new().init(ant.getTablePos('TOP', 'RIGHT'))
        statsTable.update(statsData) 
A code example for the MetricsTable is the following:
 var ant.StatsData statsData = ant.StatsData.new()
statsData.update(ant.SideStats.new(), ant.SideStats.new(), 0)
if (barstate.islastconfirmedhistory or (barstate.isrealtime and barstate.isconfirmed))
    var metricsTable = ant.MetricsTable.new().init(ant.getTablePos('BOTTOM', 'RIGHT'))
    metricsTable.update(statsData, 10) 
A code example for the SeasonalityTable is the following:
 var ant.SeasonalData seasonalData = ant.SeasonalData.new().init(Seasonality.monthOfYear)
seasonalData.update()
if (barstate.islastconfirmedhistory or (barstate.isrealtime and barstate.isconfirmed))
    var seasonalTable = ant.SeasonalTable.new().init(seasonalData, ant.getTablePos('BOTTOM', 'LEFT'))
    seasonalTable.update(seasonalData) 
🏋️♂️ Please refer to the "EXAMPLE" regions of the script for more advanced and up to date code examples!
Special thanks to @Mrcrbw for the proposal to develop this library and @DCNeu for the constructive feedback 🏆.
 getTablePos(ypos, xpos) 
  Get table position compatible string
  Parameters:
     ypos (simple string) : The position on y axise
     xpos (simple string) : The position on x axise
  Returns: The position to be passed to the table
 method init(this, pos, height, width, positiveTxtColor, negativeTxtColor, neutralTxtColor, positiveBgColor, negativeBgColor, neutralBgColor) 
  Initialize the stats table object with the given colors in the given position
  Namespace types: StatsTable
  Parameters:
     this (StatsTable) : The stats table object
     pos (simple string) : The table position string
     height (simple float) : The height of the table as a percentage of the charts height. By default, 0 auto-adjusts the height based on the text inside the cells
     width (simple float) : The width of the table as a percentage of the charts height. By default, 0 auto-adjusts the width based on the text inside the cells
     positiveTxtColor (simple color) : The text color when positive
     negativeTxtColor (simple color) : The text color when negative
     neutralTxtColor (simple color) : The text color when neutral
     positiveBgColor (simple color) : The background color with transparency when positive
     negativeBgColor (simple color) : The background color with transparency when negative
     neutralBgColor (simple color) : The background color with transparency when neutral
 method init(this, pos, height, width, neutralBgColor) 
  Initialize the metrics table object with the given colors in the given position
  Namespace types: MetricsTable
  Parameters:
     this (MetricsTable) : The metrics table object
     pos (simple string) : The table position string
     height (simple float) : The height of the table as a percentage of the charts height. By default, 0 auto-adjusts the height based on the text inside the cells
     width (simple float) : The width of the table as a percentage of the charts width. By default, 0 auto-adjusts the width based on the text inside the cells
     neutralBgColor (simple color) : The background color with transparency when neutral
 method init(this, seas) 
  Initialize the seasonal data
  Namespace types: SeasonalData
  Parameters:
     this (SeasonalData) : The seasonal data object
     seas (simple Seasonality) : The seasonality of the matrix data
 method init(this, data, pos, maxNumOfYears, height, width, extended, neutralTxtColor, neutralBgColor) 
  Initialize the seasonal table object with the given colors in the given position
  Namespace types: SeasonalTable
  Parameters:
     this (SeasonalTable) : The seasonal table object
     data (SeasonalData) : The seasonality data of the table
     pos (simple string) : The table position string
     maxNumOfYears (simple int) : The maximum number of years that fit into the table
     height (simple float) : The height of the table as a percentage of the charts height. By default, 0 auto-adjusts the height based on the text inside the cells
     width (simple float) : The width of the table as a percentage of the charts width. By default, 0 auto-adjusts the width based on the text inside the cells
     extended (simple bool) : The seasonal table with extended columns for performance
     neutralTxtColor (simple color) : The text color when neutral
     neutralBgColor (simple color) : The background color with transparency when neutral
 method update(this, wins, losses, numOfInconclusiveExits) 
  Update the strategy info data of the strategy
  Namespace types: StatsData
  Parameters:
     this (StatsData) : The strategy statistics object
     wins (SideStats) 
     losses (SideStats) 
     numOfInconclusiveExits (int) : The number of inconclusive trades
 method update(this, stats, positiveTxtColor, negativeTxtColor, negativeBgColor, neutralBgColor) 
  Update the stats table object with the given data
  Namespace types: StatsTable
  Parameters:
     this (StatsTable) : The stats table object
     stats (StatsData) : The stats data to update the table
     positiveTxtColor (simple color) : The text color when positive
     negativeTxtColor (simple color) : The text color when negative
     negativeBgColor (simple color) : The background color with transparency when negative
     neutralBgColor (simple color) : The background color with transparency when neutral
 method update(this, stats, buyAndHoldPerc, positiveTxtColor, negativeTxtColor, positiveBgColor, negativeBgColor) 
  Update the metrics table object with the given data
  Namespace types: MetricsTable
  Parameters:
     this (MetricsTable) : The metrics table object
     stats (StatsData) : The stats data to update the table
     buyAndHoldPerc (float) : The buy and hold percetage
     positiveTxtColor (simple color) : The text color when positive
     negativeTxtColor (simple color) : The text color when negative
     positiveBgColor (simple color) : The background color with transparency when positive
     negativeBgColor (simple color) : The background color with transparency when negative
 method update(this) 
  Update the seasonal data based on the season and eon timeframe
  Namespace types: SeasonalData
  Parameters:
     this (SeasonalData) : The seasonal data object
 method update(this, data, positiveTxtColor, negativeTxtColor, neutralTxtColor, positiveBgColor, negativeBgColor, neutralBgColor, timeBgColor) 
  Update the seasonal table object with the given data
  Namespace types: SeasonalTable
  Parameters:
     this (SeasonalTable) : The seasonal table object
     data (SeasonalData) : The seasonal cell data to update the table
     positiveTxtColor (simple color) : The text color when positive
     negativeTxtColor (simple color) : The text color when negative
     neutralTxtColor (simple color) : The text color when neutral
     positiveBgColor (simple color) : The background color with transparency when positive
     negativeBgColor (simple color) : The background color with transparency when negative
     neutralBgColor (simple color) : The background color with transparency when neutral
     timeBgColor (simple color) : The background color of the time gradient
 SideStats 
  Object that represents the strategy statistics data of one side win or lose
  Fields:
     numOf (series int) 
     sumFreeProfit (series float) 
     freeProfitStDev (series float) 
     sumProfit (series float) 
     profitStDev (series float) 
     sumGain (series float) 
     gainStDev (series float) 
     avgQuantityPerc (series float) 
     avgCapitalRiskPerc (series float) 
     avgTPExecutedCount (series float) 
     avgRiskRewardRatio (series float) 
     maxStreak (series int) 
 StatsTable 
  Object that represents the stats table
  Fields:
     table (series table) : The actual table
     rows (series int) : The number of rows of the table
     columns (series int) : The number of columns of the table
 StatsData 
  Object that represents the statistics data of the strategy
  Fields:
     wins (SideStats) 
     losses (SideStats) 
     numOfInconclusiveExits (series int) 
     avgFreeProfitStr (series string) 
     freeProfitStDevStr (series string) 
     lossFreeProfitStDevStr (series string) 
     avgProfitStr (series string) 
     profitStDevStr (series string) 
     lossProfitStDevStr (series string) 
     avgQuantityStr (series string) 
 MetricsTable 
  Object that represents the metrics table
  Fields:
     table (series table) : The actual table
     rows (series int) : The number of rows of the table
     columns (series int) : The number of columns of the table
 SeasonalData 
  Object that represents the seasonal table dynamic data
  Fields:
     seasonality (series Seasonality) 
     eonToMatrixRow (map) 
     numOfEons (series int) 
     mostRecentMatrixRow (series int) 
     balances (matrix) 
     returnPercs (matrix) 
     maxDDs (matrix) 
     eonReturnPercs (array) 
     eonCAGRs (array) 
     eonMaxDDs (array) 
 SeasonalTable 
  Object that represents the seasonal table
  Fields:
     table (series table) : The actual table
     headRows (series int) : The number of head rows of the table
     headColumns (series int) : The number of head columns of the table
     eonRows (series int) : The number of eon rows of the table
     seasonColumns (series int) : The number of season columns of the table
     statsRows (series int) 
     statsColumns (series int) : The number of stats columns of the table
     rows (series int) : The number of rows of the table
     columns (series int) : The number of columns of the table
     extended (series bool) : Whether the table has additional performance statistics


