Repository: JuliaStats/HypothesisTests.jl
Pull request #293 (2023-04-30 14:32:42)

Modified Jarque-Bera test (Urzua, 1996)
This commit adds the Adjusted Lagrangian Multiplier by Urzua, 1996 (as proposed [here](https://www.sciencedirect.com/science/article/abs/pii/S0165176596009238?via%3Dihub)) as a modification to the Jarque-Bera test for small and medium sample sizes.

This is an attempt to fill in one gap in issue #201 


Patch:
diff --git a/src/jarque_bera.jl b/src/jarque_bera.jl
index 42f4397..15cb5f7 100644
--- a/src/jarque_bera.jl
+++ b/src/jarque_bera.jl
@@ -32,15 +32,21 @@ struct JarqueBeraTest <: HypothesisTest
 end
 
 """
-    JarqueBeraTest(y::AbstractVector)
+    JarqueBeraTest(y::AbstractVector; adjusted::Bool=false)
 
-Compute the Jarque-Bera statistic to test the null hypothesis that a real-valued vector `y`
-is normally distributed.
+When `adjusted` is `false`, compute the Jarque-Bera statistic to test the null hypothesis
+that a real-valued vector `y` is normally distributed.
 
 Note that the approximation by the Chi-squared distribution does not work well and the
 speed of convergence is slow. In small samples, the test tends to be over-sized for
 nominal levels up to about 3% and under-sized for larger nominal levels (Mantalos, 2010).
 
+When `adjusted` is `true`, compute the Adjusted Lagrangian Multiplier statistic to test the
+null hypothesis that a real-valued vector `y` is normally distributed.
+
+Note that the use of Adjusted Lagrangian Multiplier is preferred over Jarque-Bera for small
+and medium sample sizes and it is a modification to the Jarque-Bera test (Urzua, 1996).
+
 # References
 
   * Panagiotis Mantalos, 2011, "The three different measures of the sample skewness and
@@ -48,11 +54,15 @@ nominal levels up to about 3% and under-sized for larger nominal levels (Mantalo
     of Computational Economics and Econometrics, Vol. 2, No. 1,
     [link](http://dx.doi.org/10.1504/IJCEE.2011.040576).
 
+  * Carlos M. Urzúa, "On the correct use of omnibus tests for normality", Economics Letters,
+    Volume 53, Issue 3,
+    [link](https://doi.org/10.1016/S0165-1765(96)00923-8).
+
 # External links
 
   * [Jarque-Bera test on Wikipedia](https://en.wikipedia.org/wiki/Jarque–Bera_test)
 """
-function JarqueBeraTest(y::AbstractVector{T}) where T<:Real
+function JarqueBeraTest(y::AbstractVector{T}; adjusted::Bool=false) where T<:Real
     n = length(y)
     M = Base.promote_op(/, T, typeof(n))
     m1r = m2r = m3r = m4r = zero(M)
@@ -70,7 +80,16 @@ function JarqueBeraTest(y::AbstractVector{T}) where T<:Real
     skew = m3 / m2^(3/2)
     kurt = m4 / m2^2
 
-    stat = n * skew^2 / 6 + n * (kurt - 3)^2 / 24
+    if adjusted == false
+        stat = n * skew^2 / 6 + n * (kurt - 3)^2 / 24
+    else
+        meankurt = 3 * (n-1) / (n+1)
+        varskew = 6 * (n-2) / ((n+1) * (n+3))
+        varkurt = 24 * n * (n-2) * (n-3) / ((n+1)^2 * (n+3) * (n+5))
+
+        stat = skew^2 / varskew + (kurt - meankurt)^2 / varkurt
+    end
+
     JarqueBeraTest(n, stat, skew, kurt)
 end
 


Test patch:
diff --git a/test/jarque_bera.jl b/test/jarque_bera.jl
index 4c92c7c..b31b850 100644
--- a/test/jarque_bera.jl
+++ b/test/jarque_bera.jl
@@ -41,6 +41,12 @@ t = JarqueBeraTest(sim_data_h0)
 @test default_tail(t) == :right
 show(IOBuffer(), t)
 
+t = JarqueBeraTest(sim_data_h0; adjusted=true)
+
+@test t.JB ≈ 0.9170583190120135
+@test pvalue(t) ≈ 0.6322128462414497
+show(IOBuffer(), t)
+
 sim_data_h1 = [
     0, 1, 0, 1, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1,
     0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 1, 0, 1, 0, 0,
@@ -57,4 +63,11 @@ t = JarqueBeraTest(sim_data_h1)
 @test pvalue(t) ≈ 0.00020338498134114293
 @test default_tail(t) == :right
 show(IOBuffer(), t)
+
+t = JarqueBeraTest(sim_data_h1; adjusted=true)
+
+@test t.JB ≈ 18.529299970269175
+@test pvalue(t) ≈ 9.471388144608105e-5
+show(IOBuffer(), t)
+
 end