Collection Functions Reference
Reference for array.*, map.*, and matrix.* namespaces in ATK PyneScript V6 — rolling buffers, keyed runtime bundles, and 2D numeric grids.
array.* Namespace#
The array namespace provides a Pine-style list container. Beyond the core mutation helpers (push, pop, get, set, size), it includes aggregate and reorder methods for summarizing or reshaping stored lists.
Aggregate Methods#
| Method | Returns | Use it when |
|---|---|---|
array.first(handle) | First element, or None | You want the oldest element without popping it. |
array.last(handle) | Last element, or None | You want the most-recent element without a full slice. |
array.sum(handle) | float | Rolling sum of a numeric buffer. |
array.avg(handle) | float | Average of a numeric buffer; NaN values are excluded. |
array.min(handle) | float | Minimum over all elements; NaN-safe. |
array.max(handle) | float | Maximum over all elements; NaN-safe. |
array.sort(handle, order="asc") | None (in-place) | Sort the buffer before reading a ranked value. |
array.reverse(handle) | None (in-place) | Reverse the current order. |
array.fill(handle, value, index_from=0, index_to=None) | None (in-place) | Reset a range of elements to a constant without rebuilding the array. |
Rolling Buffer with Aggregate Reads#
from source import array, indicator, ta
indicator("Rolling Buffer Demo", overlay=False)
buf = array.new_float(0)
def build_indicator_frame(df, params=None):
frame = df.copy().reset_index(drop=True)
for val in frame["close"].tolist():
array.push(buf, float(val))
if array.size(buf) > 20:
array.shift(buf) # keep last 20 values
frame["buf_avg"] = array.avg(buf)
frame["buf_min"] = array.min(buf)
frame["buf_max"] = array.max(buf)
frame["buf_sum"] = array.sum(buf)
frame["buf_first"] = array.first(buf)
frame["buf_last"] = array.last(buf)
return frameSort, Reverse, and Fill#
# Sort ascending then read the median element.
scores = array.from_([5.0, 1.0, 3.0, 4.0, 2.0])
array.sort(scores, order="asc")
median_value = array.get(scores, array.size(scores) // 2)
# Fill a buffer with zeros to reset it.
data = array.new_float(10, 0.0)
array.fill(data, 0.0)map.* Namespace#
The map namespace provides a string-keyed dictionary container with a stable Pine-style API. Use it when you need to store script-scoped key-value metadata alongside a frame, pass named parameters between helpers, or record per-run configuration in frame.attrs.
| Method | Returns | Notes |
|---|---|---|
map.new() | map handle {} | Create an empty map. Usually assigned to a module-level variable. |
map.put(handle, key, value) | None | Insert or overwrite a key. |
map.get(handle, key, default=None) | stored value or default | Safe read; returns default when the key is absent. |
map.keys(handle) | list[str] | All current keys. Useful for iteration or introspection. |
map.values(handle) | list | All current values in insertion order. |
map.size(handle) | int | Number of entries. |
map.contains(handle, key) | bool | Check whether a key exists before calling get. |
map.remove(handle, key) | None | Remove a key if present. |
map.clear(handle) | None | Delete all entries. |
map.copy(handle) | new map handle | Shallow copy. Good for snapshotting before mutation. |
map.to_array_keys(handle) | list[str] | Independent copy of all keys as a plain list. |
map.to_array_values(handle) | list | Independent copy of all values as a plain list. |
map.* in a Frame Builder#
from source import indicator, input, map, ta
indicator("Map Runtime Demo", overlay=False)
fast_length = input.int(8, title="Fast", key="fast_length")
slow_length = input.int(21, title="Slow", key="slow_length")
def build_indicator_frame(df, params=None):
frame = df.copy().reset_index(drop=True)
merged = {"fast_length": int(fast_length), "slow_length": int(slow_length)} | dict(params or {})
fast = max(int(merged.get("fast_length", 8) or 8), 1)
slow = max(int(merged.get("slow_length", 21) or 21), 1)
frame["ema_fast"] = ta.ema(frame["close"], fast)
frame["ema_slow"] = ta.ema(frame["close"], slow)
frame["spread_value"] = (frame["ema_fast"] - frame["ema_slow"]).fillna(0.0)
cfg = map.new()
map.put(cfg, "fast_length", fast)
map.put(cfg, "slow_length", slow)
trend = "bullish" if float(frame["spread_value"].iloc[-1] or 0.0) >= 0.0 else "bearish"
map.put(cfg, "trend_bias", trend)
frame.attrs["map_keys"] = map.keys(cfg)
frame.attrs["map_size"] = map.size(cfg)
frame.attrs["trend_bias"] = map.get(cfg, "trend_bias", "neutral")
return frameWhen to use map vs dict: use map.* when authoring in the PyneScript style and the map will be passed to other PyneScript helpers. Use plain Python dict when the data stays internal to a single function and never crosses the Pine-style API boundary.
matrix.* Namespace#
The matrix namespace models a 2-D numeric grid. Use it when you need to store a window of multi-column bar data, compute a rolling covariance surface, or pass structured numeric payloads between stages.
| Method | Returns | Notes |
|---|---|---|
matrix.new(rows, cols, fill=0.0) | matrix handle | Create a rows×cols grid pre-filled with fill. |
matrix.set(handle, row, col, value) | None | Write a single cell. |
matrix.get(handle, row, col) | float | Read a single cell. |
matrix.rows(handle) | int | Current row count. |
matrix.columns(handle) | int | Current column count. |
matrix.row(handle, row_index) | list[float] | All values in a specific row. |
matrix.col(handle, col_index) | list[float] | All values in a specific column. |
matrix.add_row(handle, row_index, values) | None | Insert a new row at a position. |
matrix.add_col(handle, values) | None | Append a new column. |
matrix.remove_row(handle, row_index) | None | Delete a row. |
matrix.submatrix(handle, from_row, to_row, from_col, to_col) | new matrix handle | Extract a rectangular slice into a new matrix. |
matrix.sum(handle) | float | Sum of all non-NaN elements. |
matrix.avg(handle) | float | Average of all non-NaN elements. |
matrix.min(handle) | float | Minimum element (NaN-safe). |
matrix.max(handle) | float | Maximum element (NaN-safe). |
matrix.copy(handle) | new matrix handle | Deep copy. Safe to mutate independently. |
OHLC Window Example#
from source import indicator, input, matrix
indicator("Matrix Runtime Demo", overlay=False)
window = input.int(3, title="Window", key="window", minval=1)
def build_indicator_frame(df, params=None):
frame = df.copy().reset_index(drop=True)
merged = {"window": int(window)} | dict(params or {})
win = max(int(merged.get("window", 3) or 3), 1)
tail = frame.tail(win).reset_index(drop=True)
grid = matrix.new(len(tail), 2, 0.0)
for i, row in tail.iterrows():
matrix.set(grid, i, 0, float(row["open"]))
matrix.set(grid, i, 1, float(row["close"]))
# Append a computed column: high-low range.
matrix.add_col(grid, values=(tail["high"] - tail["low"]).astype(float).tolist())
frame["open_sum"] = float(sum(matrix.col(grid, 0))) if matrix.rows(grid) > 0 else 0.0
frame["close_sum"] = float(sum(matrix.col(grid, 1))) if matrix.rows(grid) > 0 else 0.0
frame["range_sum"] = float(sum(matrix.col(grid, 2))) if matrix.rows(grid) > 0 else 0.0
frame["grid_total_sum"] = matrix.sum(grid)
frame["grid_avg"] = matrix.avg(grid)
frame.attrs["matrix_shape"] = {"rows": matrix.rows(grid), "columns": matrix.columns(grid)}
frame.attrs["last_row"] = matrix.row(grid, matrix.rows(grid) - 1) if matrix.rows(grid) > 0 else []
return frameSubmatrix Extraction#
# Extract top-left 2×2 sub-grid from a 4×4 matrix.
full = matrix.new(4, 4, 1.0)
sub = matrix.submatrix(full, from_row=0, to_row=2, from_col=0, to_col=2)
print(matrix.rows(sub), matrix.columns(sub)) # 2, 2Download matrix runtime example
See also: