mirror of
https://github.com/mihakralj/QuanTAlib.git
synced 2026-07-27 17:27:43 +00:00
84 lines
2.8 KiB
Plaintext
84 lines
2.8 KiB
Plaintext
// Licensed under the Apache License, Version 2.0
|
|
// © mihakralj
|
|
//@version=6
|
|
indicator("Skewness (SKEW)", "SKEW", overlay=false, precision=6)
|
|
|
|
//@function Calculates the skewness of a source series over a specified period.
|
|
// Skewness is a measure of the asymmetry of the probability distribution of a real-valued random variable about its mean.
|
|
// This implementation calculates the population skewness (Fisher-Pearson coefficient g1).
|
|
//@param src The source series.
|
|
//@param len The lookback period. Must be > 2.
|
|
//@returns The skewness value.
|
|
//@optimized Uses efficient rolling calculations for mean, variance, and the third central moment.
|
|
skew(series float src, simple int len) =>
|
|
if len <= 2
|
|
runtime.error("Length must be greater than 2 for Skewness calculation.")
|
|
var float sum_m = 0.0
|
|
var array<float> buffer_m = array.new_float(len)
|
|
var int head_m = 0
|
|
if bar_index >= len
|
|
sum_m -= array.get(buffer_m, head_m)
|
|
float current_src_nz = nz(src)
|
|
sum_m += current_src_nz
|
|
array.set(buffer_m, head_m, current_src_nz)
|
|
head_m := (head_m + 1) % len
|
|
|
|
float mean_val = na
|
|
if bar_index >= len - 1
|
|
mean_val := sum_m / len
|
|
else
|
|
mean_val := sum_m / (bar_index + 1)
|
|
float dev = src - mean_val
|
|
var float sum_v = 0.0
|
|
var array<float> buffer_v = array.new_float(len)
|
|
var int head_v = 0
|
|
float dev_sq_nz = nz(math.pow(dev, 2))
|
|
if bar_index >= len
|
|
sum_v -= array.get(buffer_v, head_v)
|
|
sum_v += dev_sq_nz
|
|
array.set(buffer_v, head_v, dev_sq_nz)
|
|
head_v := (head_v + 1) % len
|
|
float variance_val = na
|
|
if bar_index >= len - 1
|
|
variance_val := sum_v / len
|
|
else
|
|
variance_val := sum_v / (bar_index + 1)
|
|
float stddev_val = variance_val > 1e-9 ? math.sqrt(variance_val) : 0.0
|
|
var float sum_s3 = 0.0
|
|
var array<float> buffer_s3 = array.new_float(len)
|
|
var int head_s3 = 0
|
|
float dev_cubed_nz = nz(math.pow(dev, 3))
|
|
if bar_index >= len
|
|
sum_s3 -= array.get(buffer_s3, head_s3)
|
|
sum_s3 += dev_cubed_nz
|
|
array.set(buffer_s3, head_s3, dev_cubed_nz)
|
|
head_s3 := (head_s3 + 1) % len
|
|
float m3 = na
|
|
if bar_index >= len - 1
|
|
m3 := sum_s3 / len
|
|
else
|
|
m3 := sum_s3 / (bar_index + 1)
|
|
float skew_val = na
|
|
if not na(m3) and not na(stddev_val)
|
|
if stddev_val > 1e-9
|
|
float stddev_cubed = math.pow(stddev_val, 3)
|
|
if stddev_cubed != 0
|
|
skew_val := m3 / stddev_cubed
|
|
else
|
|
skew_val := 0.0
|
|
else
|
|
skew_val := 0.0
|
|
skew_val
|
|
|
|
// ---------- Main loop ----------
|
|
|
|
// Inputs
|
|
i_source = input.source(close, "Source")
|
|
i_length = input.int(20, "Length", minval=3) // Minval 3 for skewness
|
|
|
|
// Calculation
|
|
skewValue = skew(i_source, i_length)
|
|
|
|
// Plot
|
|
plot(skewValue, "Skewness", color=color.yellow, linewidth=2)
|