mirror of
https://github.com/mihakralj/QuanTAlib.git
synced 2026-08-04 20:17:43 +00:00
24e86d762a
- Updated BBWN, BBWP, CCV, CV, CVI, EWMA, GKV, HLV, HV, Jvolty, JVOLTYN, MASSI, NATR, RSV, RV, RVI, TR, UI, VOV, VR, YZV indicators with documentation links. - Added documentation links for Aberration, Acceleration Bands, Andrews' Pitchfork, Adaptive Price Zone, ATR Bands, Bollinger Bands, Center of Gravity, Donchian Channels, Decay Min-Max Channel, Detrended Synthetic Price, EACP, EBSW, HOMOD, Jurik Volatility Bands, Keltner Channel, MA Envelope, Min-Max Channel, Price Channel, Regression Channels, Standard Deviation Channel, Stoller Average Range Channel, Super Trend Bands, Ultimate Bands, Ultimate Channel, VWAP Bands, and VWAP with Standard Deviation Bands.
83 lines
3.6 KiB
Plaintext
83 lines
3.6 KiB
Plaintext
// The MIT License (MIT)
|
|
// © mihakralj
|
|
//@version=6
|
|
indicator("Jarque-Bera Test (JB)", "JB", overlay=false, precision=4)
|
|
|
|
// Helper function to get a window of series data into an array
|
|
_get_window_array(series float source, simple int length) =>
|
|
float[] arr = array.new_float(length)
|
|
for i = 0 to length - 1
|
|
array.set(arr, i, source[length - 1 - i]) // Oldest to newest
|
|
arr
|
|
|
|
// Helper function to calculate the k-th central moment
|
|
// m_k = sum((x_i - mean)^k) / n
|
|
_central_moment(float[] arr, int moment_order, float mean_val) =>
|
|
n = array.size(arr)
|
|
if n == 0
|
|
float(na)
|
|
else
|
|
sum_pow_diff = 0.0
|
|
for i = 0 to n - 1
|
|
sum_pow_diff += math.pow(array.get(arr, i) - mean_val, moment_order)
|
|
sum_pow_diff / n
|
|
|
|
//@function Calculates the Jarque-Bera statistic.
|
|
//@param source series float The input series.
|
|
//@param length simple int The lookback period (sample size). Min 10.
|
|
//@returns series float The Jarque-Bera statistic. Higher values suggest deviation from normality.
|
|
jb_stat(series float source, simple int length) => // Renamed function for clarity jb_stat -> jb
|
|
if length < 10 // Need sufficient sample size
|
|
float(na)
|
|
else
|
|
float[] window_arr = _get_window_array(source, length)
|
|
|
|
float mean_val = array.avg(window_arr) // Pine Script built-in array average
|
|
|
|
if na(mean_val)
|
|
float(na)
|
|
else
|
|
// Calculate variance (2nd central moment)
|
|
float m2 = _central_moment(window_arr, 2, mean_val)
|
|
|
|
if na(m2) or m2 < 1e-10 // Avoid division by zero or near-zero std dev
|
|
float(na) // Or 0 if data is truly constant, but JB is ill-defined
|
|
else
|
|
float stddev_val = math.sqrt(m2)
|
|
|
|
// Calculate 3rd central moment for skewness
|
|
float m3 = _central_moment(window_arr, 3, mean_val)
|
|
float s = m3 / math.pow(stddev_val, 3) // Skewness
|
|
|
|
// Calculate 4th central moment for kurtosis
|
|
float m4 = _central_moment(window_arr, 4, mean_val)
|
|
float k_raw = m4 / math.pow(stddev_val, 4) // Raw Kurtosis
|
|
float ek = k_raw - 3.0 // Excess Kurtosis
|
|
|
|
if na(s) or na(ek)
|
|
float(na)
|
|
else
|
|
// Jarque-Bera statistic formula: JB = (n/6) * (S^2 + (EK^2)/4)
|
|
float jb_value_calc = (length / 6.0) * (s * s + (ek * ek) / 4.0) // Renamed internal variable
|
|
jb_value_calc
|
|
|
|
// Inputs
|
|
i_source = input.source(close, title="Source")
|
|
i_length = input.int(20, title="Lookback Period (Sample Size)", minval=10, maxval=200, tooltip="Number of bars for calculation. Min 10. Max 200 due to array processing. Higher values provide more stable estimates but lag more.")
|
|
|
|
// Calculation
|
|
jb_value = jb_stat(i_source, i_length) // Call renamed function
|
|
|
|
// Plot
|
|
plot(jb_value, "Jarque-Bera Statistic", color=color.teal, linewidth=2)
|
|
|
|
// Critical values for Chi-squared distribution with 2 degrees of freedom (approximate):
|
|
// Significance Level | Critical Value
|
|
// 10% (0.10) | 4.605
|
|
// 5% (0.05) | 5.991
|
|
// 1% (0.01) | 9.210
|
|
// These lines can help interpret the JB statistic. If JB > critical value, reject null hypothesis of normality.
|
|
hline(4.605, "Critical Value (10%)", color.gray, linestyle=hline.style_dotted, linewidth=1)
|
|
hline(5.991, "Critical Value (5%)", color.orange, linestyle=hline.style_dashed, linewidth=1)
|
|
hline(9.210, "Critical Value (1%)", color.red, linestyle=hline.style_solid, linewidth=1)
|