@@ -40,6 +40,39 @@ function interpolate(x::Vector{T}, y::Vector{T}) where T <: AbstractFloat
40
40
end
41
41
end
42
42
43
+ """
44
+ _kpss_autolag(resids::Vector{T}, nobs::Int) where T <: AbstractFloat
45
+
46
+ Computes the number of lags for covariance matrix estimation in KPSS test
47
+ using method of Hobijn et al (1998). See also Andrews (1991), Newey & West
48
+ (1994), and Schwert (1989). Assumes Bartlett / Newey-West kernel.
49
+
50
+ # Arguments
51
+ - `resids::Vector{T}`: Residuals from the KPSS regression
52
+ - `nobs::Int`: Number of observations
53
+
54
+ # Returns
55
+ - `Int`: Number of lags to use in the KPSS test
56
+ """
57
+ function _kpss_autolag (resids:: Vector{T} , nobs:: Int ) where T <: AbstractFloat
58
+ covlags = Int (floor (nobs^ (2.0 / 9.0 )))
59
+ s0 = sum (resids.^ 2 ) / nobs
60
+ s0 = s0 > 0 ? s0 : 1e-5
61
+ s1 = 0.0
62
+
63
+ for i in 1 : covlags
64
+ # Calculate dot product of shifted residuals
65
+ resids_prod = dot (resids[(i+ 1 ): end ], resids[1 : (nobs- i)])
66
+ resids_prod /= nobs / 2.0
67
+ s0 += resids_prod
68
+ s1 += i * resids_prod
69
+ end
70
+
71
+ s_hat = s1 / s0
72
+ pwr = 1.0 / 3.0
73
+ gamma_hat = 1.1447 * (s_hat * s_hat)^ pwr
74
+ return max (Int (floor (gamma_hat * nobs^ pwr)),1 )
75
+ end
43
76
44
77
"""
45
78
kpss_test(y::Vector{T}; regression::Symbol=:c, nlags::Union{Symbol,Int}=:legacy) where T <: AbstractFloat
@@ -71,7 +104,7 @@ Table 1 of Kwiatkowski et al. (1992).
71
104
- Newey & West (1994). Automatic lag selection in covariance matrix estimation. Review of Economic Studies, 61: 631-653.
72
105
- Schwert (1989). Tests for unit roots: A Monte Carlo investigation. Journal of Business and Economic Statistics, 7(2): 147-159.
73
106
"""
74
- function kpss_test (y:: Vector{Fl} ; regression:: Symbol = :c , nlags:: Union{Symbol,Int} = :legacy ) where Fl
107
+ function kpss_test (y:: Vector{Fl} ; regression:: Symbol = :c , nlags:: Union{Symbol,Int} = :auto ) where Fl
75
108
nobs = length (y)
76
109
77
110
# Set critical values based on regression type
@@ -103,37 +136,42 @@ function kpss_test(y::Vector{Fl}; regression::Symbol=:c, nlags::Union{Symbol,Int
103
136
# Compute number of lags
104
137
if nlags == :legacy
105
138
nlags = min (Int (ceil (12.0 * (nobs/ 100.0 )^ 0.25 )), nobs - 1 )
139
+
140
+ elseif nlags == :auto
141
+ nlags = _kpss_autolag (residuals, nobs)
106
142
elseif isa (nlags, Integer)
107
143
if nlags >= nobs
108
144
throw (ArgumentError (" nlags must be < number of observations" ))
109
145
end
110
146
else
111
- throw (ArgumentError (" nlags must be :legacy or an integer" ))
147
+ throw (ArgumentError (" nlags must be :legacy, :auto or an integer" ))
112
148
end
113
149
114
150
# Compute KPSS test statistic
115
151
partial_sums = cumsum (residuals)
116
152
eta = sum (partial_sums.^ 2 ) / (nobs^ 2 )
117
153
118
154
# Compute s^2 using Newey-West estimator
119
- s2 = var (residuals) # Initial variance (γ₀)
155
+ s2 = sum (residuals.^ 2 ) # Initial variance (γ₀)
120
156
121
157
# Add autocovariance terms
122
158
for lag in 1 : nlags
123
159
w = 1.0 - lag/ (nlags + 1 ) # Bartlett kernel weights
124
- γₖ = sum (residuals[lag+ 1 : end ] .* residuals[1 : end - lag]) / nobs
160
+ γₖ = sum (residuals[lag+ 1 : end ] .* residuals[1 : end - lag])
125
161
s2 += 2.0 * w * γₖ
126
162
end
127
163
164
+ s2 = s2 / nobs
165
+
128
166
# Compute test statistic
129
- kpss_stat:: Float32 = eta / s2
167
+ kpss_stat:: Float64 = (s2 == 0.0 ) ? 0.0 : eta / s2
130
168
131
169
# Compute p-value using interpolation
132
- crit_vals:: Vector{Float32 } = [critical_values[0.10 ], critical_values[0.05 ], critical_values[0.025 ], critical_values[0.01 ]]
133
- pvals:: Vector{Float32 } = [0.10 , 0.05 , 0.025 , 0.01 ]
170
+ crit_vals:: Vector{Float64 } = [critical_values[0.10 ], critical_values[0.05 ], critical_values[0.025 ], critical_values[0.01 ]]
171
+ pvals:: Vector{Float64 } = [0.10 , 0.05 , 0.025 , 0.01 ]
134
172
135
173
# compute p-value as kpss_stat evaluated at the interpolation of crit_vals and pvals
136
- p_value = interpolate (crit_vals, pvals)(kpss_stat)
174
+ p_value:: Float64 = interpolate (crit_vals, pvals)(kpss_stat)
137
175
138
176
return Dict (
139
177
" test_statistic" => kpss_stat,
0 commit comments