mirror of
https://github.com/mihakralj/QuanTAlib.git
synced 2026-08-01 11:17:46 +00:00
86fe32a682
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com> Co-authored-by: aider (openrouter/anthropic/claude-sonnet-4) <aider@aider.chat> Co-authored-by: Warp <agent@warp.dev>
63 lines
2.4 KiB
Plaintext
63 lines
2.4 KiB
Plaintext
// The MIT License (MIT)
|
|
// © mihakralj
|
|
//@version=6
|
|
indicator("Standardization (Z-score)", "STANDARDIZE", overlay=false, precision=4)
|
|
|
|
//@function Calculates the Z-score of a series over a lookback period.
|
|
//@doc https://github.com/mihakralj/pinescript/blob/main/indicators/numerics/standardize.md
|
|
//@param src series float Input data series.
|
|
//@param len simple int Lookback period for calculating mean and standard deviation (must be > 1 for sample stdev).
|
|
//@returns series float The Z-score of the current data point, or na if issues like insufficient data or zero stdev for a non-mean current value.
|
|
standardize(series float src, simple int len) =>
|
|
if len <= 1
|
|
float(na)
|
|
var S1 = 0.0
|
|
var S2 = 0.0
|
|
var N = 0
|
|
var float[] window_data_vals = array.new_float(0)
|
|
var bool[] window_data_is_na = array.new_bool(0)
|
|
float x_new = src[0]
|
|
bool x_new_is_na = na(x_new)
|
|
if array.size(window_data_vals) == len
|
|
float x_old_val = array.get(window_data_vals, 0)
|
|
bool x_old_was_na = array.get(window_data_is_na, 0)
|
|
array.shift(window_data_vals)
|
|
array.shift(window_data_is_na)
|
|
if not x_old_was_na
|
|
S1 -= x_old_val
|
|
S2 -= x_old_val * x_old_val
|
|
N -= 1
|
|
array.push(window_data_vals, x_new_is_na ? 0.0 : x_new)
|
|
array.push(window_data_is_na, x_new_is_na)
|
|
if not x_new_is_na
|
|
S1 += x_new
|
|
S2 += x_new * x_new
|
|
N += 1
|
|
float z_score = na
|
|
if N < 2
|
|
z_score := na
|
|
else
|
|
float mean_val = S1 / N
|
|
float variance_pop = (S2 / N) - (mean_val * mean_val)
|
|
variance_pop := variance_pop < 1e-10 ? 0.0 : variance_pop
|
|
float variance_sample = variance_pop * N / (N - 1)
|
|
float stdev_val = math.sqrt(variance_sample)
|
|
if x_new_is_na
|
|
z_score := na
|
|
else if stdev_val > 1e-10
|
|
z_score := (x_new - mean_val) / stdev_val
|
|
else
|
|
z_score := (math.abs(x_new - mean_val) < 1e-10) ? 0.0 : na
|
|
z_score
|
|
|
|
// Inputs
|
|
i_source = input.source(close, title="Source")
|
|
i_length = input.int(20, title="Lookback Period", minval=2, tooltip="Period for mean and standard deviation. Must be at least 2 for stdev.")
|
|
|
|
// Calculation
|
|
z_score_value = standardize(i_source, i_length) // Renamed for clarity
|
|
|
|
// Plot
|
|
plot(z_score_value, "Z-score", color=color.yellow, linewidth=2)
|
|
hline(0, "Zero Line", color=color.gray, linestyle=hline.style_dashed)
|