reconnect moved files to git repo

This commit is contained in:
root
2025-08-01 04:33:03 -04:00
commit 5d3c35492d
23190 changed files with 4750716 additions and 0 deletions

View File

@ -0,0 +1,19 @@
from statsmodels.tsa.ardl.model import (
ARDL,
UECM,
ARDLOrderSelectionResults,
ARDLResults,
BoundsTestResult,
UECMResults,
ardl_select_order,
)
__all__ = [
"ARDL",
"UECM",
"ARDLResults",
"UECMResults",
"ardl_select_order",
"ARDLOrderSelectionResults",
"BoundsTestResult",
]

View File

@ -0,0 +1,168 @@
from statsmodels.compat.pandas import FUTURE_STACK
from collections import defaultdict
import glob
import os
import numpy as np
import pandas as pd
from scipy import stats
from sklearn.model_selection import KFold
if __name__ == "__main__":
from black import FileMode, TargetVersion, format_file_contents
from sklearn.linear_model import LinearRegression
from sklearn.model_selection import cross_val_score
PATH = os.environ.get("PSS_PATH", "..")
print(f"Processing {PATH}")
files = glob.glob(os.path.join(PATH, "*.npz"))
groups = defaultdict(list)
for f in files:
keys = f.split("-")
key = int(keys[2]), int(keys[4]), keys[6] == "True"
if key[0] == 0:
continue
with np.load(f) as contents:
idx = (100 * contents["percentiles"]).astype(int)
s = pd.Series(contents["q"], index=idx)
groups[key].append(s)
final = {}
quantiles = (90, 95, 99, 99.9)
crit_vals = {}
ordered_keys = sorted(groups.keys())
for key in ordered_keys:
final[key] = pd.concat(groups[key], axis=1)
cv = []
for q in quantiles:
cv.append(final[key].loc[int(100 * q)].mean())
crit_vals[key] = cv
df = pd.DataFrame(crit_vals).T
df.index.names = ("k", "case", "I1")
df.columns = quantiles
for key, row in df.iterrows():
crit_vals[key] = [round(val, 7) for val in list(row)]
def setup_regressors(df, low_pow=3, high_pow=3, cut=70, log=False):
s = df.stack(**FUTURE_STACK).reset_index()
q = s.level_0 / 10000
y = stats.norm.ppf(q)
cv = s[0]
if log:
cv = np.log(cv)
m = np.where(s.level_0 <= df.index[cut])[0].max()
reg = np.zeros((q.shape[0], 2 + low_pow + high_pow))
reg[:m, 0] = 1
for i in range(low_pow):
reg[:m, i + 1] = cv[:m] ** (i + 1)
w = 1 + low_pow
reg[m:, w] = 1
for i in range(high_pow):
reg[m:, w + i + 1] = cv[m:] ** (i + 1)
return reg, y
large_p = {}
small_p = {}
transform = {}
max_stat = {}
threshold = {}
hp = 2
for key in final:
print(key)
data = final[key]
score = {}
lr = LinearRegression(fit_intercept=False)
for lp in (2, 3):
for cut in range(40, data.shape[0] - 40):
for log in (True, False):
cv = KFold(shuffle=True, random_state=20210903)
x, y = setup_regressors(data, lp, hp, cut, log)
k = (lp, hp, cut, log)
score[k] = cross_val_score(
lr, x, y, scoring="neg_mean_absolute_error", cv=cv
).sum()
idx = pd.Series(score).idxmax()
lp, hp, cut, log = idx
assert log
x, y = setup_regressors(data, lp, hp, cut, log)
lr = lr.fit(x, y)
large = lr.coef_[: 1 + lp]
if lp == 2:
large = np.array(large.tolist() + [0.0])
large_p[key] = large.tolist()
small_p[key] = lr.coef_[1 + lp :].tolist()
transform[key] = log
max_stat[key] = np.inf
threshold[key] = data.iloc[cut].mean()
if small_p[key][2] < 0:
max_stat[key] = small_p[key][1] / (-2 * small_p[key][2])
for key in large_p:
large_p[key] = [round(val, 5) for val in large_p[key]]
small_p[key] = [round(val, 5) for val in small_p[key]]
raw_code = f"""
#!/usr/bin/env python
# coding: utf-8
\"\"\"
Critical value polynomials and related quantities for the bounds test of
Pesaran, M. H., Shin, Y., & Smith, R. J. (2001). Bounds testing approaches
to the analysis of level relationships. Journal of applied econometrics,
16(3), 289-326.
These were computed using 32,000,000 simulations for each key using the
methodology of PSS, who only used 40,000. The asymptotic P-value response
functions were computed based on the simulated value. Critical values
are the point estimates for the respective quantiles. The simulation code
is contained in pss.py. The output files from this function are then
transformed using pss-process.py.
The format of the keys are (k, case, I1) where
* k is is the number of x variables included in the model (0 is an ADF)
* case is 1, 2, 3, 4 or 5 and corresponds to the PSS paper
* I1 is True if X contains I1 variables and False if X is stationary
The parameters are for polynomials of order 3 (large) or 2 (small).
stat_star is the value where the switch between large and small occurs.
Stat values less then stat_star use large_p, while values above use
small_p. In all cases the stat is logged prior to computing the p-value
so that the p-value is
1 - Phi(c[0] + c[1] * x + c[2] * x**2 + c[3] * x**3)
where x = np.log(stat) and Phi() is the normal cdf.
When this the models, the polynomial is evaluated at the natural log of the
test statistic and then the normal CDF of this value is computed to produce
the p-value.
\"\"\"
__all__ = ["large_p", "small_p", "crit_vals", "crit_percentiles", "stat_star"]
large_p = {large_p}
small_p = {small_p}
stat_star = {threshold}
crit_percentiles = {quantiles}
crit_vals = {crit_vals}
"""
targets = {TargetVersion.PY39, TargetVersion.PY310, TargetVersion.PY311}
fm = FileMode(target_versions=targets, line_length=79)
formatted_code = format_file_contents(raw_code, fast=False, mode=fm)
with open(
"../pss_critical_values.py", "w", newline="\n", encoding="utf-8"
) as out:
out.write(formatted_code)

View File

@ -0,0 +1,98 @@
#!/usr/bin/env python
from itertools import product
import os
import numpy as np
PATH = os.environ.get("PSS_PATH", "..")
def pss_block(
seed, k, case, i1, block_id, m=2_000_000, t=1_000, save=True, path="./"
):
file_name = f"pss-k-{k}-case-{case}-i1-{i1}-block-{block_id}.npz"
file_name = os.path.join(path, file_name)
if save and os.path.exists(file_name):
return
rs = np.random.default_rng(seed)
const = np.ones(t - 1)
tau = np.arange(1, t).astype(float)
f = np.empty(m)
for j in range(m):
u = rs.standard_normal((k + 1, t))
y = np.cumsum(u[0])
if i1:
x = np.cumsum(u[1:], axis=1).T
else:
x = u[1:].T
lhs = np.diff(y)
rhv = [y[:-1], x[:-1]]
if case == 2:
rhv.append(const)
elif case == 4:
rhv.append(tau)
if case >= 3:
rhv.append(const)
if case == 5:
rhv.append(tau)
rest = k + 1
if case in (2, 4):
rest += 1
rhs = np.column_stack(rhv)
b = np.linalg.lstsq(rhs, lhs, rcond=None)[0]
u = lhs - rhs @ b
s2 = u.T @ u / (u.shape[0] - rhs.shape[1])
xpx = rhs.T @ rhs
vcv = np.linalg.inv(xpx) * s2
r = np.eye(rest, rhs.shape[1])
rvcvr = r @ vcv @ r.T
rb = r @ b
f[j] = rb.T @ np.linalg.inv(rvcvr) @ rb / rest
percentiles = [0.05]
percentiles += [i / 10 for i in range(1, 10)]
percentiles += [1 + i / 2 for i in range(18)]
percentiles += [i for i in range(10, 51)]
percentiles += [100 - v for v in percentiles]
percentiles = sorted(set(percentiles))
percentiles = np.asarray(percentiles)
q = np.percentile(f, percentiles)
if save:
np.savez(file_name, q=q, percentiles=percentiles)
return q
seed = [
3957597042,
2709280948,
499296859,
1555610991,
2390531900,
2160388094,
4098495866,
47221919,
]
ss = np.random.SeedSequence(seed)
k = list(range(1, 11))
case = list(range(1, 6))
i1 = [True, False]
block_id = list(range(32))
params = list(product(k, case, i1, block_id))
seeds = ss.generate_state(8 * len(params)).reshape((-1, 8)).tolist()
configs = []
for _s, (_k, _case, _i1, _block_id) in zip(seeds, params):
configs.append(
{
"seed": _s,
"k": _k,
"case": _case,
"i1": _i1,
"block_id": _block_id,
"path": PATH,
}
)
if __name__ == "__main__":
from joblib import Parallel, delayed
Parallel(n_jobs=10)(delayed(pss_block)(**c) for c in configs)

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,452 @@
#!/usr/bin/env python
"""
Critical value polynomials and related quantities for the bounds test of
Pesaran, M. H., Shin, Y., & Smith, R. J. (2001). Bounds testing approaches
to the analysis of level relationships. Journal of applied econometrics,
16(3), 289-326.
These were computed using 32,000,000 simulations for each key using the
methodology of PSS, who only used 40,000. The asymptotic P-value response
functions were computed based on the simulated value. Critical values
are the point estimates for the respective quantiles. The simulation code
is contained in pss.py. The output files from this function are then
transformed using pss-process.py.
The format of the keys are (k, case, I1) where
* k is is the number of x variables included in the model (0 is an ADF)
* case is 1, 2, 3, 4 or 5 and corresponds to the PSS paper
* I1 is True if X contains I1 variables and False if X is stationary
The parameters are for polynomials of order 3 (large) or 2 (small).
stat_star is the value where the switch between large and small occurs.
Stat values less then stat_star use large_p, while values above use
small_p. In all cases the stat is logged prior to computing the p-value
so that the p-value is
1 - Phi(c[0] + c[1] * x + c[2] * x**2 + c[3] * x**3)
where x = np.log(stat) and Phi() is the normal cdf.
When this the models, the polynomial is evaluated at the natural log of the
test statistic and then the normal CDF of this value is computed to produce
the p-value.
"""
__all__ = ["large_p", "small_p", "crit_vals", "crit_percentiles", "stat_star"]
large_p = {
(1, 1, False): [0.2231, 0.91426, 0.10102, 0.00569],
(1, 1, True): [-0.21766, 0.85933, 0.10411, 0.00661],
(1, 2, False): [-0.60796, 1.48713, 0.15076, 0.04453],
(1, 2, True): [-0.96204, 1.52593, 0.15996, 0.04166],
(1, 3, False): [-0.62883, 0.78991, 0.1, 0.00693],
(1, 3, True): [-0.91895, 0.82086, 0.12921, 0.01076],
(1, 4, False): [-1.50546, 1.79052, 0.05488, 0.06801],
(1, 4, True): [-1.79654, 1.8048, 0.06573, 0.06768],
(1, 5, False): [-1.36367, 0.94126, 0.21556, 0.02473],
(1, 5, True): [-1.60554, 0.93305, 0.2422, 0.03241],
(2, 1, False): [0.20576, 1.18914, 0.15731, 0.01144],
(2, 1, True): [-0.49024, 1.16958, 0.20564, 0.02008],
(2, 2, False): [-0.51799, 1.6368, 0.18955, 0.04317],
(2, 2, True): [-1.13394, 1.71056, 0.20442, 0.04195],
(2, 3, False): [-0.51712, 1.12963, 0.18936, 0.01808],
(2, 3, True): [-1.07441, 1.14964, 0.26066, 0.03338],
(2, 4, False): [-1.29895, 1.88501, 0.11734, 0.06615],
(2, 4, True): [-1.82455, 1.92207, 0.13753, 0.06269],
(2, 5, False): [-1.22263, 1.23208, 0.31401, 0.04495],
(2, 5, True): [-1.67689, 1.17567, 0.33606, 0.05898],
(3, 1, False): [0.1826, 1.39275, 0.19774, 0.01647],
(3, 1, True): [-0.71889, 1.39726, 0.29712, 0.03794],
(3, 2, False): [-0.45864, 1.77632, 0.22125, 0.04372],
(3, 2, True): [-1.28619, 1.88107, 0.23969, 0.04414],
(3, 3, False): [-0.45093, 1.38824, 0.26556, 0.03063],
(3, 3, True): [-1.22712, 1.36564, 0.34942, 0.05555],
(3, 4, False): [-1.15886, 1.99182, 0.16358, 0.06392],
(3, 4, True): [-1.88388, 2.05362, 0.18349, 0.06501],
(3, 5, False): [-1.11221, 1.44327, 0.3547, 0.05263],
(3, 5, True): [-1.75354, 1.37461, 0.3882, 0.07239],
(4, 1, False): [0.16431, 1.56391, 0.22944, 0.02067],
(4, 1, True): [-0.90799, 1.56908, 0.34763, 0.04814],
(4, 2, False): [-0.41568, 1.90715, 0.24783, 0.04407],
(4, 2, True): [-1.42373, 2.03902, 0.26907, 0.04755],
(4, 3, False): [-0.41104, 1.5716, 0.3066, 0.03842],
(4, 3, True): [-1.36194, 1.54043, 0.40145, 0.06846],
(4, 4, False): [-1.05651, 2.10007, 0.20201, 0.06129],
(4, 4, True): [-1.95474, 2.18305, 0.22527, 0.06441],
(4, 5, False): [-1.02502, 1.62605, 0.38203, 0.05565],
(4, 5, True): [-1.83458, 1.555, 0.42888, 0.07459],
(5, 1, False): [0.15015, 1.71718, 0.2584, 0.02507],
(5, 1, True): [-1.0707, 1.72829, 0.39037, 0.05468],
(5, 2, False): [-0.38277, 2.02985, 0.27139, 0.04513],
(5, 2, True): [-1.54974, 2.18631, 0.29592, 0.04967],
(5, 3, False): [-0.38023, 1.72586, 0.33033, 0.04188],
(5, 3, True): [-1.48415, 1.70271, 0.44016, 0.07248],
(5, 4, False): [-0.97676, 2.20429, 0.23233, 0.06543],
(5, 4, True): [-2.03144, 2.31343, 0.25394, 0.0675],
(5, 5, False): [-0.95421, 1.78775, 0.40239, 0.05642],
(5, 5, True): [-1.91679, 1.72031, 0.46434, 0.06641],
(6, 1, False): [0.13913, 1.8581, 0.28528, 0.02931],
(6, 1, True): [-1.21438, 1.87638, 0.42416, 0.05485],
(6, 2, False): [-0.35664, 2.14606, 0.29484, 0.04728],
(6, 2, True): [-1.66532, 2.32448, 0.31723, 0.05528],
(6, 3, False): [-0.35498, 1.86634, 0.35087, 0.04455],
(6, 3, True): [-1.59785, 1.85278, 0.47304, 0.07114],
(6, 4, False): [-0.91274, 2.30752, 0.26053, 0.0644],
(6, 4, True): [-2.10956, 2.43721, 0.2852, 0.06694],
(6, 5, False): [-0.89553, 1.9318, 0.41381, 0.05292],
(6, 5, True): [-1.99931, 1.87789, 0.49842, 0.04135],
(7, 1, False): [0.12974, 1.98503, 0.30606, 0.03218],
(7, 1, True): [-1.34555, 2.01647, 0.45456, 0.05018],
(7, 2, False): [-0.33519, 2.25631, 0.31659, 0.05016],
(7, 2, True): [-1.77496, 2.45806, 0.3372, 0.05741],
(7, 3, False): [-0.33377, 1.99554, 0.36742, 0.04624],
(7, 3, True): [-1.70381, 1.99863, 0.49883, 0.05092],
(7, 4, False): [-0.8596, 2.40762, 0.28334, 0.06401],
(7, 4, True): [-2.18704, 2.55828, 0.30627, 0.07091],
(7, 5, False): [-0.84606, 2.06291, 0.42505, 0.05152],
(7, 5, True): [-2.08097, 2.02139, 0.5348, 0.02343],
(8, 1, False): [0.12244, 2.10698, 0.32849, 0.03596],
(8, 1, True): [-1.46632, 2.1505, 0.48168, 0.04116],
(8, 2, False): [-0.31707, 2.36107, 0.33198, 0.04953],
(8, 2, True): [-1.87722, 2.58105, 0.35963, 0.05848],
(8, 3, False): [-0.31629, 2.11679, 0.38514, 0.04868],
(8, 3, True): [-1.80483, 2.13412, 0.52935, 0.03618],
(8, 4, False): [-0.81509, 2.50518, 0.30456, 0.06388],
(8, 4, True): [-2.26501, 2.67227, 0.33843, 0.06554],
(8, 5, False): [-0.80333, 2.18457, 0.42995, 0.0463],
(8, 5, True): [-2.16125, 2.15208, 0.58319, 0.0],
(9, 1, False): [0.11562, 2.22037, 0.34907, 0.03968],
(9, 1, True): [-1.57878, 2.27626, 0.5124, 0.03164],
(9, 2, False): [-0.30188, 2.46235, 0.35132, 0.05209],
(9, 2, True): [-1.97465, 2.70256, 0.37466, 0.06205],
(9, 3, False): [-0.30097, 2.23118, 0.39976, 0.05001],
(9, 3, True): [-1.90164, 2.26261, 0.56431, 0.0175],
(9, 4, False): [-0.77664, 2.59712, 0.32618, 0.06452],
(9, 4, True): [-2.33996, 2.78253, 0.36072, 0.06644],
(9, 5, False): [-0.76631, 2.2987, 0.43834, 0.04274],
(9, 5, True): [-2.23753, 2.27521, 0.60763, 0.0],
(10, 1, False): [0.10995, 2.3278, 0.36567, 0.04153],
(10, 1, True): [-1.6849, 2.39419, 0.5433, 0.02457],
(10, 2, False): [-0.28847, 2.55819, 0.36959, 0.05499],
(10, 2, True): [-2.06725, 2.81756, 0.38761, 0.0676],
(10, 3, False): [-0.28748, 2.33948, 0.41398, 0.05101],
(10, 3, True): [-1.99259, 2.38061, 0.59433, 0.01114],
(10, 4, False): [-0.74317, 2.68624, 0.345, 0.07032],
(10, 4, True): [-2.41409, 2.8931, 0.37487, 0.07102],
(10, 5, False): [-0.73464, 2.40692, 0.45153, 0.0434],
(10, 5, True): [-2.31364, 2.39092, 0.64313, -0.01012],
}
small_p = {
(1, 1, False): [0.2585, 0.92944, 0.25921],
(1, 1, True): [-0.17399, 0.88425, 0.29947],
(1, 2, False): [-0.45787, 1.15813, 0.37268],
(1, 2, True): [-0.76388, 1.13438, 0.39908],
(1, 3, False): [-0.57887, 0.87657, 0.32929],
(1, 3, True): [-0.88284, 0.81513, 0.366],
(1, 4, False): [-1.1926, 1.21061, 0.40386],
(1, 4, True): [-1.42909, 1.16607, 0.42899],
(1, 5, False): [-1.34428, 0.8756, 0.37809],
(1, 5, True): [-1.56285, 0.80464, 0.40703],
(2, 1, False): [0.23004, 1.12045, 0.31791],
(2, 1, True): [-0.45371, 1.06577, 0.38144],
(2, 2, False): [-0.41191, 1.36838, 0.39668],
(2, 2, True): [-0.9488, 1.32707, 0.44808],
(2, 3, False): [-0.49166, 1.11266, 0.36824],
(2, 3, True): [-1.03636, 1.04019, 0.42589],
(2, 4, False): [-1.08188, 1.42797, 0.42653],
(2, 4, True): [-1.52152, 1.36, 0.47256],
(2, 5, False): [-1.12408, 1.0565, 0.43505],
(2, 5, True): [-1.58614, 1.01208, 0.46796],
(3, 1, False): [0.20945, 1.29304, 0.36292],
(3, 1, True): [-0.60112, 1.139, 0.47837],
(3, 2, False): [-0.37491, 1.53959, 0.42397],
(3, 2, True): [-1.11163, 1.50639, 0.48662],
(3, 3, False): [-0.41411, 1.27093, 0.41524],
(3, 3, True): [-1.14285, 1.18673, 0.4906],
(3, 4, False): [-0.9946, 1.60793, 0.44771],
(3, 4, True): [-1.62609, 1.54566, 0.50619],
(3, 5, False): [-1.04988, 1.31372, 0.44802],
(3, 5, True): [-1.68976, 1.25316, 0.49896],
(4, 1, False): [0.18839, 1.46484, 0.39125],
(4, 1, True): [-0.81822, 1.35949, 0.50619],
(4, 2, False): [-0.35123, 1.705, 0.44075],
(4, 2, True): [-1.2591, 1.67286, 0.52021],
(4, 3, False): [-0.34716, 1.39436, 0.46391],
(4, 3, True): [-1.30728, 1.41428, 0.51292],
(4, 4, False): [-0.92783, 1.77056, 0.46587],
(4, 4, True): [-1.71493, 1.69609, 0.54221],
(4, 5, False): [-0.97468, 1.50704, 0.46661],
(4, 5, True): [-1.7783, 1.4453, 0.53112],
(5, 1, False): [0.17584, 1.60806, 0.424],
(5, 1, True): [-1.00705, 1.5668, 0.52487],
(5, 2, False): [-0.32186, 1.82909, 0.47183],
(5, 2, True): [-1.39492, 1.83145, 0.54756],
(5, 3, False): [-0.32204, 1.55407, 0.4884],
(5, 3, True): [-1.43499, 1.58772, 0.54359],
(5, 4, False): [-0.87005, 1.9128, 0.48361],
(5, 4, True): [-1.81929, 1.8594, 0.56629],
(5, 5, False): [-0.91534, 1.6826, 0.47972],
(5, 5, True): [-1.86297, 1.61238, 0.56196],
(6, 1, False): [0.16642, 1.7409, 0.45235],
(6, 1, True): [-1.15641, 1.72534, 0.55469],
(6, 2, False): [-0.31023, 1.97806, 0.47892],
(6, 2, True): [-1.52248, 1.98657, 0.56855],
(6, 3, False): [-0.30333, 1.70462, 0.50703],
(6, 3, True): [-1.5521, 1.74539, 0.57191],
(6, 4, False): [-0.82345, 2.04624, 0.50026],
(6, 4, True): [-1.90659, 1.99476, 0.59394],
(6, 5, False): [-0.85675, 1.81838, 0.50387],
(6, 5, True): [-1.92708, 1.73629, 0.60069],
(7, 1, False): [0.15013, 1.88779, 0.46397],
(7, 1, True): [-1.28169, 1.85521, 0.58877],
(7, 2, False): [-0.2904, 2.09042, 0.50233],
(7, 2, True): [-1.62626, 2.10378, 0.6013],
(7, 3, False): [-0.29138, 1.8506, 0.52083],
(7, 3, True): [-1.64831, 1.87115, 0.60523],
(7, 4, False): [-0.78647, 2.1757, 0.51247],
(7, 4, True): [-1.98344, 2.10977, 0.62411],
(7, 5, False): [-0.81099, 1.95374, 0.51949],
(7, 5, True): [-1.99875, 1.86512, 0.63051],
(8, 1, False): [0.14342, 2.00691, 0.48514],
(8, 1, True): [-1.3933, 1.97361, 0.62074],
(8, 2, False): [-0.27952, 2.20983, 0.51721],
(8, 2, True): [-1.74485, 2.25435, 0.61354],
(8, 3, False): [-0.28049, 1.98611, 0.53286],
(8, 3, True): [-1.74116, 1.99245, 0.63511],
(8, 4, False): [-0.74797, 2.28202, 0.53356],
(8, 4, True): [-2.07764, 2.25027, 0.64023],
(8, 5, False): [-0.76505, 2.06317, 0.54393],
(8, 5, True): [-2.04872, 1.95334, 0.67177],
(9, 1, False): [0.13505, 2.12341, 0.50439],
(9, 1, True): [-1.49339, 2.07805, 0.65464],
(9, 2, False): [-0.26881, 2.32256, 0.53025],
(9, 2, True): [-1.82677, 2.34223, 0.65004],
(9, 3, False): [-0.26657, 2.09906, 0.55384],
(9, 3, True): [-1.80085, 2.06043, 0.68234],
(9, 4, False): [-0.71672, 2.38896, 0.54931],
(9, 4, True): [-2.17306, 2.39146, 0.65252],
(9, 5, False): [-0.70907, 2.13027, 0.58668],
(9, 5, True): [-2.14411, 2.10595, 0.68478],
(10, 1, False): [0.12664, 2.23871, 0.51771],
(10, 1, True): [-1.59784, 2.19509, 0.67874],
(10, 2, False): [-0.25969, 2.4312, 0.54096],
(10, 2, True): [-1.93843, 2.48708, 0.65741],
(10, 3, False): [-0.25694, 2.21617, 0.56619],
(10, 3, True): [-1.89772, 2.1894, 0.70143],
(10, 4, False): [-0.69126, 2.49776, 0.5583],
(10, 4, True): [-2.24685, 2.4968, 0.67598],
(10, 5, False): [-0.6971, 2.28206, 0.57816],
(10, 5, True): [-2.21015, 2.208, 0.71379],
}
stat_star = {
(1, 1, False): 0.855423425047013,
(1, 1, True): 0.9074438436193457,
(1, 2, False): 2.3148213273461034,
(1, 2, True): 2.727010046970744,
(1, 3, False): 0.846390593107207,
(1, 3, True): 1.157556027201022,
(1, 4, False): 3.220377136548005,
(1, 4, True): 3.6108265020012418,
(1, 5, False): 1.7114703606421378,
(1, 5, True): 2.066325210881278,
(2, 1, False): 1.1268996107665314,
(2, 1, True): 1.3332514927355072,
(2, 2, False): 2.0512213167246456,
(2, 2, True): 2.656191837644102,
(2, 3, False): 1.058908331354388,
(2, 3, True): 1.5313322825819844,
(2, 4, False): 2.7213091542989725,
(2, 4, True): 3.2984645209852856,
(2, 5, False): 2.6006009671146497,
(2, 5, True): 2.661856653261213,
(3, 1, False): 1.263159095916295,
(3, 1, True): 2.4151349732452863,
(3, 2, False): 1.8886043232371843,
(3, 2, True): 2.6028096820968405,
(3, 3, False): 1.4879903191884682,
(3, 3, True): 2.2926969339773926,
(3, 4, False): 2.418527659154858,
(3, 4, True): 3.1039322592065988,
(3, 5, False): 1.9523612040944802,
(3, 5, True): 2.2115727453490757,
(4, 1, False): 1.290890114741129,
(4, 1, True): 2.1296963408410905,
(4, 2, False): 1.7770902061605607,
(4, 2, True): 2.5611885327765402,
(4, 3, False): 1.9340163095801728,
(4, 3, True): 1.9141318638062572,
(4, 4, False): 2.2146739201335466,
(4, 4, True): 2.9701790485477932,
(4, 5, False): 1.7408452994169448,
(4, 5, True): 2.1047247176583914,
(5, 1, False): 1.336967174239227,
(5, 1, True): 1.9131415178585627,
(5, 2, False): 1.6953274259688569,
(5, 2, True): 2.52745981091846,
(5, 3, False): 1.8124340908468068,
(5, 3, True): 1.8520883187848405,
(5, 4, False): 2.0675009559739297,
(5, 4, True): 2.8728076833515552,
(5, 5, False): 1.5978968362839456,
(5, 5, True): 2.1017517002543418,
(6, 1, False): 1.3810422398306446,
(6, 1, True): 1.8993612909227247,
(6, 2, False): 1.6324374150719114,
(6, 2, True): 2.498801004400209,
(6, 3, False): 1.72340094901749,
(6, 3, True): 1.8586513178563737,
(6, 4, False): 1.955819927102859,
(6, 4, True): 2.797145060481245,
(6, 5, False): 1.578613967104358,
(6, 5, True): 2.356249534336445,
(7, 1, False): 1.319436681229134,
(7, 1, True): 1.9955849619883248,
(7, 2, False): 1.5822190052675569,
(7, 2, True): 2.4744987764453055,
(7, 3, False): 1.65578510076754,
(7, 3, True): 2.046536484369615,
(7, 4, False): 1.8684573094851133,
(7, 4, True): 2.737241392502754,
(7, 5, False): 1.571855677342554,
(7, 5, True): 2.6006325210258505,
(8, 1, False): 1.3413558170956845,
(8, 1, True): 2.182981174661154,
(8, 2, False): 1.5416965902808288,
(8, 2, True): 2.4538471213095594,
(8, 3, False): 1.6021238307647196,
(8, 3, True): 2.2031866832480778,
(8, 4, False): 1.797595752125897,
(8, 4, True): 2.688099837236925,
(8, 5, False): 1.6561231184668357,
(8, 5, True): 2.883361281576836,
(9, 1, False): 1.3260368480749927,
(9, 1, True): 2.359689612641543,
(9, 2, False): 1.5074890058192492,
(9, 2, True): 2.435592395931648,
(9, 3, False): 1.5584090417965821,
(9, 3, True): 2.586293446202391,
(9, 4, False): 1.7393454428092985,
(9, 4, True): 2.6470908946956655,
(9, 5, False): 1.8180517504983742,
(9, 5, True): 2.818161371392247,
(10, 1, False): 1.3126519241806318,
(10, 1, True): 2.3499432601613885,
(10, 2, False): 1.4785447632683744,
(10, 2, True): 2.4199239298786215,
(10, 3, False): 1.5219767684407846,
(10, 3, True): 2.55484741648857,
(10, 4, False): 1.6902675233415512,
(10, 4, True): 2.6119272436084637,
(10, 5, False): 1.7372865030759366,
(10, 5, True): 2.7644864472524904,
}
crit_percentiles = (90, 95, 99, 99.9)
crit_vals = {
(1, 1, False): [2.4170317, 3.119659, 4.7510799, 7.0838335],
(1, 1, True): [3.2538509, 4.0643748, 5.8825257, 8.4189144],
(1, 2, False): [3.0235968, 3.6115364, 4.9094056, 6.6859696],
(1, 2, True): [3.4943406, 4.1231394, 5.4961076, 7.3531815],
(1, 3, False): [4.044319, 4.9228967, 6.8609106, 9.5203666],
(1, 3, True): [4.7771822, 5.7217442, 7.7821227, 10.557471],
(1, 4, False): [4.0317707, 4.6921341, 6.1259225, 8.0467248],
(1, 4, True): [4.4725009, 5.169214, 6.668854, 8.6632132],
(1, 5, False): [5.5958071, 6.586727, 8.7355157, 11.6171903],
(1, 5, True): [6.2656898, 7.3133165, 9.5652229, 12.5537707],
(2, 1, False): [2.1562308, 2.6846692, 3.8773621, 5.5425892],
(2, 1, True): [3.1684785, 3.8003954, 5.177742, 7.0453814],
(2, 2, False): [2.6273503, 3.0998243, 4.1327001, 5.528847],
(2, 2, True): [3.3084134, 3.8345125, 4.9642009, 6.4657839],
(2, 3, False): [3.1741284, 3.8022629, 5.1722882, 7.0241224],
(2, 3, True): [4.108262, 4.8116858, 6.3220548, 8.322478],
(2, 4, False): [3.3668869, 3.8887628, 5.0115801, 6.5052326],
(2, 4, True): [4.0126604, 4.5835675, 5.7968684, 7.3887863],
(2, 5, False): [4.1863149, 4.8834936, 6.3813095, 8.3781415],
(2, 5, True): [5.053508, 5.8168869, 7.4384998, 9.565425],
(3, 1, False): [1.998571, 2.4316514, 3.3919322, 4.709226],
(3, 1, True): [3.0729965, 3.6016775, 4.7371358, 6.2398661],
(3, 2, False): [2.3813866, 2.7820412, 3.6486786, 4.8089784],
(3, 2, True): [3.1778198, 3.6364094, 4.6114583, 5.8888408],
(3, 3, False): [2.7295224, 3.2290217, 4.3110408, 5.7599206],
(3, 3, True): [3.7471556, 4.3222818, 5.5425521, 7.1435458],
(3, 4, False): [2.9636218, 3.4007434, 4.3358236, 5.5729155],
(3, 4, True): [3.7234883, 4.2135706, 5.247283, 6.5911207],
(3, 5, False): [3.4742551, 4.0219835, 5.1911046, 6.7348191],
(3, 5, True): [4.4323554, 5.0480574, 6.3448127, 8.0277313],
(4, 1, False): [1.8897829, 2.2616928, 3.0771215, 4.1837434],
(4, 1, True): [2.9925753, 3.4545032, 4.4326745, 5.7123835],
(4, 2, False): [2.2123295, 2.5633388, 3.3177874, 4.321218],
(4, 2, True): [3.0796353, 3.4898084, 4.3536497, 5.4747288],
(4, 3, False): [2.4565534, 2.877209, 3.7798528, 4.9852682],
(4, 3, True): [3.516144, 4.0104999, 5.0504684, 6.4022435],
(4, 4, False): [2.6902225, 3.0699099, 3.877333, 4.9405835],
(4, 4, True): [3.5231152, 3.9578931, 4.867071, 6.0403311],
(4, 5, False): [3.0443998, 3.5009718, 4.4707539, 5.7457746],
(4, 5, True): [4.0501255, 4.5739556, 5.6686684, 7.0814031],
(5, 1, False): [1.8104326, 2.1394999, 2.8541086, 3.8114409],
(5, 1, True): [2.9267613, 3.3396521, 4.2078599, 5.3342038],
(5, 2, False): [2.0879588, 2.40264, 3.0748083, 3.9596152],
(5, 2, True): [3.002768, 3.3764374, 4.1585099, 5.1657752],
(5, 3, False): [2.2702787, 2.6369717, 3.4203738, 4.4521021],
(5, 3, True): [3.3535243, 3.7914038, 4.7060983, 5.8841151],
(5, 4, False): [2.4928973, 2.831033, 3.5478855, 4.4836677],
(5, 4, True): [3.3756681, 3.7687148, 4.587147, 5.6351487],
(5, 5, False): [2.7536425, 3.149282, 3.985975, 5.0799181],
(5, 5, True): [3.7890425, 4.2501858, 5.2074857, 6.4355821],
(6, 1, False): [1.7483313, 2.0453753, 2.685931, 3.5375009],
(6, 1, True): [2.8719403, 3.2474515, 4.0322637, 5.0451946],
(6, 2, False): [1.9922451, 2.2792144, 2.8891314, 3.690865],
(6, 2, True): [2.9399824, 3.2851357, 4.0031551, 4.9247226],
(6, 3, False): [2.1343676, 2.4620175, 3.1585901, 4.0720179],
(6, 3, True): [3.2311014, 3.6271964, 4.4502999, 5.5018575],
(6, 4, False): [2.3423792, 2.6488947, 3.2947623, 4.1354724],
(6, 4, True): [3.2610813, 3.6218989, 4.3702232, 5.3232767],
(6, 5, False): [2.5446232, 2.8951601, 3.633989, 4.5935586],
(6, 5, True): [3.5984454, 4.0134462, 4.8709448, 5.9622726],
(7, 1, False): [1.6985327, 1.9707636, 2.5536649, 3.3259272],
(7, 1, True): [2.825928, 3.1725169, 3.8932738, 4.8134085],
(7, 2, False): [1.9155946, 2.1802812, 2.7408759, 3.4710326],
(7, 2, True): [2.8879427, 3.2093335, 3.8753322, 4.724748],
(7, 3, False): [2.0305429, 2.3281704, 2.9569345, 3.7788337],
(7, 3, True): [3.136325, 3.4999128, 4.2519893, 5.2075305],
(7, 4, False): [2.2246175, 2.5055486, 3.0962182, 3.86164],
(7, 4, True): [3.1695552, 3.5051856, 4.1974421, 5.073436],
(7, 5, False): [2.3861201, 2.7031072, 3.3680435, 4.2305443],
(7, 5, True): [3.4533491, 3.8323234, 4.613939, 5.6044399],
(8, 1, False): [1.6569223, 1.9092423, 2.4470718, 3.1537838],
(8, 1, True): [2.7862884, 3.1097259, 3.7785302, 4.6293176],
(8, 2, False): [1.8532862, 2.0996872, 2.6186041, 3.2930359],
(8, 2, True): [2.8435812, 3.1459955, 3.769165, 4.5623681],
(8, 3, False): [1.9480198, 2.2215083, 2.7979659, 3.54771],
(8, 3, True): [3.0595184, 3.3969531, 4.0923089, 4.9739178],
(8, 4, False): [2.1289147, 2.3893773, 2.9340882, 3.6390988],
(8, 4, True): [3.094188, 3.4085297, 4.0545165, 4.8699787],
(8, 5, False): [2.2616596, 2.5515168, 3.1586476, 3.9422645],
(8, 5, True): [3.3374076, 3.6880139, 4.407457, 5.3152095],
(9, 1, False): [1.6224492, 1.8578787, 2.3580077, 3.0112501],
(9, 1, True): [2.7520721, 3.0557346, 3.6811682, 4.4739536],
(9, 2, False): [1.8008993, 2.0320841, 2.5170871, 3.1451424],
(9, 2, True): [2.8053707, 3.091422, 3.6784683, 4.4205306],
(9, 3, False): [1.8811231, 2.1353897, 2.6683796, 3.358463],
(9, 3, True): [2.9957112, 3.3114482, 3.9596061, 4.7754473],
(9, 4, False): [2.0498497, 2.2930641, 2.8018384, 3.4543646],
(9, 4, True): [3.0308611, 3.3269185, 3.9347618, 4.6993614],
(9, 5, False): [2.1610306, 2.4296727, 2.98963, 3.7067719],
(9, 5, True): [3.2429533, 3.5699095, 4.2401975, 5.0823119],
(10, 1, False): [1.5927907, 1.8145253, 2.2828013, 2.8927966],
(10, 1, True): [2.7222721, 3.009471, 3.5990544, 4.3432975],
(10, 2, False): [1.756145, 1.9744492, 2.4313123, 3.0218681],
(10, 2, True): [2.7724339, 3.0440412, 3.6004793, 4.3015151],
(10, 3, False): [1.8248841, 2.0628201, 2.5606728, 3.2029316],
(10, 3, True): [2.9416094, 3.239357, 3.8484916, 4.6144906],
(10, 4, False): [1.9833587, 2.2124939, 2.690228, 3.3020807],
(10, 4, True): [2.9767752, 3.2574924, 3.8317161, 4.5512138],
(10, 5, False): [2.0779589, 2.3285481, 2.8499681, 3.5195753],
(10, 5, True): [3.1649384, 3.4725945, 4.1003673, 4.8879723],
}

View File

@ -0,0 +1,850 @@
from typing import NamedTuple
import numpy as np
from numpy.testing import assert_allclose
import pandas as pd
from pandas.testing import assert_index_equal
import pytest
from statsmodels.datasets import danish_data
from statsmodels.iolib.summary import Summary
from statsmodels.tools.sm_exceptions import SpecificationWarning
from statsmodels.tsa.ar_model import AutoReg
from statsmodels.tsa.ardl.model import (
ARDL,
UECM,
ARDLResults,
ardl_select_order,
)
from statsmodels.tsa.deterministic import DeterministicProcess
dane_data = danish_data.load_pandas().data
class Dataset(NamedTuple):
y: pd.Series
x: pd.DataFrame
@pytest.fixture(scope="module", params=[None, 0, 3, [1, 2, 4]])
def lags(request):
return request.param
@pytest.fixture(
scope="module",
params=[
2,
[1, 3, 5],
{"lry": 3, "ibo": 2, "ide": 1},
{"lry": 3, "ibo": [2], "ide": [1, 3]},
],
)
def order(request):
return request.param
@pytest.fixture(
scope="module",
params=[
2,
{"lry": 3, "ibo": 2, "ide": 1},
],
)
def uecm_order(request):
return request.param
@pytest.fixture(scope="module", params=[None, 3])
def uecm_lags(request):
return request.param
@pytest.fixture(scope="module", params=["n", "c", "ct"])
def trend(request):
return request.param
@pytest.fixture(scope="module", params=[True, False])
def causal(request):
return request.param
@pytest.fixture(scope="module", params=[0, 3])
def maxlag(request):
return request.param
@pytest.fixture(scope="module", params=[2, {"lry": 3, "ibo": 2, "ide": 1}])
def maxorder(request):
return request.param
@pytest.fixture(scope="module", params=[True, False])
def seasonal(request):
return request.param
@pytest.fixture(scope="module", params=[True, False])
def use_numpy(request):
return request.param
@pytest.fixture(scope="module", params=[None, 10])
def hold_back(request):
return request.param
@pytest.fixture(scope="module")
def data():
y = dane_data.lrm
x = dane_data[["lry", "ibo", "ide"]]
return Dataset(y, x)
@pytest.fixture(scope="module", params=[None, 2])
def fixed(request):
if request.param is None:
return None
index = dane_data.lrm.index
gen = np.random.default_rng(0)
return pd.DataFrame(
gen.standard_t(10, (dane_data.lrm.shape[0], 2)),
index=index,
columns=["z0", "z1"],
)
def check_results(res: ARDLResults):
model: ARDL = res.model
n, k = model._x.shape
assert model.score(res.params).shape == (k,)
assert model.hessian(res.params).shape == (k, k)
assert isinstance(model.loglike(res.params), float)
assert model.information(res.params).shape == (k, k)
assert isinstance(model.exog_names, list)
assert model.ar_lags is None or isinstance(model.ar_lags, list)
assert isinstance(model.seasonal, bool)
assert isinstance(model.hold_back, int)
assert isinstance(model.ardl_order, tuple)
assert isinstance(model.df_model, int)
assert isinstance(model.nobs, int)
assert isinstance(model.endog_names, str)
assert isinstance(model.k_constant, int)
res.summary()
res.test_heteroskedasticity()
res.diagnostic_summary()
assert res.ar_lags is None or isinstance(res.ar_lags, list)
assert res.df_resid == (res.nobs - res.df_model)
assert res.scale == res.sigma2
assert isinstance(res.fpe, float)
def _convert_to_numpy(data, fixed, order, seasonal, use_numpy):
y = data.y
x = data.x
z = fixed
period = None
if use_numpy:
y = np.asarray(y)
x = np.asarray(x)
if isinstance(order, dict):
order = {i: v for i, v in enumerate(order.values())}
if fixed is not None:
z = np.asarray(fixed)
period = 4 if seasonal else None
return y, x, z, order, period
def test_model_init(
data: Dataset, lags, order, trend, causal, fixed, use_numpy, seasonal
):
y, x, z, order, period = _convert_to_numpy(
data, fixed, order, seasonal, use_numpy
)
mod = ARDL(
y,
lags,
x,
order,
trend,
causal=causal,
fixed=z,
seasonal=seasonal,
period=period,
)
res = mod.fit()
check_results(res)
res.predict()
fixed_oos = None
if z is not None:
fixed_oos = np.array(z)[:12]
if isinstance(z, pd.DataFrame):
fixed_oos = pd.DataFrame(fixed_oos, columns=z.columns)
exog_oos = None
if x is not None:
exog_oos = np.array(x)[:12]
if isinstance(x, pd.DataFrame):
exog_oos = pd.DataFrame(exog_oos, columns=x.columns)
res.forecast(12, exog=exog_oos, fixed=fixed_oos)
def test_ardl_order_exceptions(data):
with pytest.raises(ValueError, match="lags must be a non-negative"):
ARDL(data.y, -1)
with pytest.raises(
ValueError, match="All values in lags must be positive"
):
ARDL(data.y, [-1, 0, 2])
with pytest.raises(ValueError, match="integer orders must be at least"):
ARDL(data.y, 2, data.x, order=0, causal=True)
with pytest.raises(ValueError, match="integer orders must be at least"):
ARDL(data.y, 2, data.x, -1, causal=False)
with pytest.raises(
ValueError, match="sequence orders must be strictly positive"
):
ARDL(
data.y, 2, data.x, {"lry": [0, 1], "ibo": 3, "ide": 0}, causal=True
)
with pytest.raises(
TypeError, match="sequence orders must contain non-negative"
):
ARDL(
data.y,
2,
data.x,
{"lry": [1, "apple"], "ibo": 3, "ide": 1},
causal=True,
)
with pytest.raises(
ValueError, match="sequence orders must contain distinct"
):
ARDL(
data.y,
2,
data.x,
{"lry": [1, 1, 2, 3], "ibo": 3, "ide": [1, 1, 1]},
causal=True,
)
with pytest.raises(
ValueError, match="sequence orders must be strictly positive"
):
ARDL(data.y, 2, data.x, [0, 1, 2], causal=True)
def test_ardl_order_keys_exceptions(data):
with pytest.raises(
ValueError, match="order dictionary contains keys for exogenous"
):
ARDL(
data.y,
2,
data.x,
{"lry": [1, 2], "ibo": 3, "other": 4},
causal=False,
)
with pytest.warns(
SpecificationWarning, match="exog contains variables that"
):
ARDL(data.y, 2, data.x, {"lry": [1, 2]}, causal=False)
def test_ardl_deterministic_exceptions(data):
with pytest.raises(TypeError):
ARDL(data.y, 2, data.x, 2, deterministic="seasonal")
with pytest.warns(
SpecificationWarning, match="When using deterministic, trend"
):
deterministic = DeterministicProcess(
data.y.index, constant=True, order=1
)
ARDL(data.y, 2, data.x, 2, deterministic=deterministic, trend="ct")
def test_ardl_holdback_exceptions(data):
with pytest.raises(ValueError, match="hold_back must be >="):
ARDL(data.y, 2, data.x, 2, hold_back=1)
def test_ardl_fixed_exceptions(data):
fixed = np.random.standard_normal((2, 200))
with pytest.raises(ValueError, match="fixed must be an"):
ARDL(data.y, 2, data.x, 2, fixed=fixed)
fixed = np.random.standard_normal((dane_data.lrm.shape[0], 2))
fixed[20, 0] = -np.inf
with pytest.raises(ValueError, match="fixed must be an"):
ARDL(data.y, 2, data.x, 2, fixed=fixed)
def test_ardl_select_order(
data: Dataset,
maxlag,
maxorder,
trend,
causal,
fixed,
use_numpy,
seasonal,
hold_back,
):
y, x, z, maxorder, period = _convert_to_numpy(
data, fixed, maxorder, seasonal, use_numpy
)
res = ardl_select_order(
y,
maxlag,
x,
maxorder,
trend,
fixed=fixed,
causal=causal,
hold_back=hold_back,
period=period,
seasonal=seasonal,
glob=seasonal,
)
assert isinstance(res.model, ARDL)
assert isinstance(res.aic, pd.Series)
assert isinstance(res.bic, pd.Series)
assert isinstance(res.hqic, pd.Series)
assert res.period == period
assert res.trend == trend
assert res.seasonal == seasonal
assert isinstance(res.dl_lags, dict)
assert res.ar_lags is None or isinstance(res.ar_lags, list)
def test_ardl_no_regressors(data):
res = ARDL(
data.y,
None,
data.x,
{"lry": None, "ibo": None, "ide": None},
trend="n",
).fit()
assert res.params.shape[0] == 0
check_results(res)
def test_ardl_only_y_lag(data):
res = ARDL(data.y, 3, data.x, None, trend="n").fit()
assert res.params.shape[0] == 3
check_results(res)
def test_ardl_only_x(data):
res = ARDL(
data.y, None, data.x, {"lry": 1, "ibo": 2, "ide": 3}, trend="n"
).fit()
assert res.params.shape[0] == 9
res = ARDL(
data.y,
None,
data.x,
{"lry": 1, "ibo": 2, "ide": 3},
trend="n",
causal=True,
).fit()
assert res.params.shape[0] == 6
check_results(res)
def test_ardl_only_trend(data):
res = ARDL(data.y, None, data.x, None, trend="c").fit()
assert res.params.shape[0] == 1
check_results(res)
def test_ardl_only_seasonal(data):
res = ARDL(data.y, None, data.x, None, trend="n", seasonal=True).fit()
assert res.params.shape[0] == 4
check_results(res)
def test_ardl_only_deterministic(data):
deterministic = DeterministicProcess(data.y.index, constant=True, order=3)
res = ARDL(
data.y, None, data.x, None, trend="n", deterministic=deterministic
).fit()
assert res.params.shape[0] == 4
check_results(res)
def test_ardl_no_endog_exog(data):
res = ARDL(data.y, None, data.x, None, trend="ct", seasonal=True).fit()
assert res.params.shape[0] == 5
check_results(res)
def test_ardl_no_exog(data):
res = ARDL(data.y, [1, 4], data.x, None, trend="ct", seasonal=True).fit()
assert res.params.shape[0] == 7
check_results(res)
def test_ardl_parameter_names(data):
mod = ARDL(data.y, 2, data.x, 2, causal=True, trend="c")
expected = [
"const",
"lrm.L1",
"lrm.L2",
"lry.L1",
"lry.L2",
"ibo.L1",
"ibo.L2",
"ide.L1",
"ide.L2",
]
assert mod.exog_names == expected
mod = ARDL(
np.asarray(data.y), 2, np.asarray(data.x), 2, causal=False, trend="ct"
)
expected = [
"const",
"trend",
"y.L1",
"y.L2",
"x0.L0",
"x0.L1",
"x0.L2",
"x1.L0",
"x1.L1",
"x1.L2",
"x2.L0",
"x2.L1",
"x2.L2",
]
assert mod.exog_names == expected
mod = ARDL(
np.asarray(data.y),
[2],
np.asarray(data.x),
None,
causal=False,
trend="n",
seasonal=True,
period=4,
)
expected = ["s(1,4)", "s(2,4)", "s(3,4)", "s(4,4)", "y.L2"]
assert mod.exog_names == expected
@pytest.mark.matplotlib
def test_diagnostics_plot(data, close_figures):
import matplotlib.figure
res = ARDL(
data.y,
2,
data.x,
{"lry": 3, "ibo": 2, "ide": [1, 3]},
trend="ct",
seasonal=True,
).fit()
fig = res.plot_diagnostics()
assert isinstance(fig, matplotlib.figure.Figure)
def test_against_autoreg(data, trend, seasonal):
ar = AutoReg(data.y, 3, trend=trend, seasonal=seasonal)
ardl = ARDL(data.y, 3, trend=trend, seasonal=seasonal)
ar_res = ar.fit()
ardl_res = ardl.fit()
assert_allclose(ar_res.params, ardl_res.params)
assert ar_res.ar_lags == ardl_res.ar_lags
assert ar.trend == ardl.trend
assert ar.seasonal == ardl.seasonal
ar_fcast = ar_res.forecast(12)
ardl_fcast = ardl_res.forecast(12)
assert_allclose(ar_fcast, ardl_fcast)
assert_index_equal(ar_fcast.index, ardl_fcast.index)
ar_fcast = ar_res.predict()
ardl_fcast = ardl_res.predict()
assert_allclose(ar_fcast, ardl_fcast)
assert_index_equal(ar_fcast.index, ardl_fcast.index)
@pytest.mark.parametrize("start", [None, 0, 2, 4])
@pytest.mark.parametrize("end", [None, 20])
@pytest.mark.parametrize("dynamic", [20, True])
def test_against_autoreg_predict_start_end(
data, trend, seasonal, start, end, dynamic
):
ar = AutoReg(data.y, 3, trend=trend, seasonal=seasonal)
ardl = ARDL(data.y, 3, trend=trend, seasonal=seasonal)
ar_res = ar.fit()
ardl_res = ardl.fit()
ar_fcast = ar_res.predict(start=start, end=end, dynamic=dynamic)
ardl_fcast = ardl_res.predict(start=start, end=end, dynamic=dynamic)
assert_index_equal(ar_fcast.index, ardl_fcast.index)
assert_allclose(ar_fcast, ardl_fcast)
def test_invalid_init(data):
with pytest.raises(ValueError, match="lags must be a non-negative"):
ARDL(data.y, -1)
with pytest.raises(
ValueError, match="All values in lags must be positive"
):
ARDL(data.y, [-1, 1, 2])
with pytest.raises(
ValueError, match="All values in lags must be positive"
):
ARDL(data.y, [1, 2, 2, 3])
with pytest.raises(ValueError, match="hold_back must be "):
ARDL(data.y, 3, data.x, 4, hold_back=3)
def test_prediction_oos_no_new_data(data):
res = ARDL(data.y, 2, data.x, 3, causal=True).fit()
val = res.forecast(1)
assert val.shape[0] == 1
res = ARDL(data.y, [3], data.x, [3]).fit()
val = res.forecast(3)
assert val.shape[0] == 3
def test_prediction_exceptions(data, fixed, use_numpy):
y, x, z, order, _ = _convert_to_numpy(data, None, 3, False, use_numpy)
res = ARDL(y, 2, x, 3, causal=False).fit()
with pytest.raises(ValueError, match="exog_oos must be"):
res.forecast(1)
if isinstance(x, pd.DataFrame):
exog_oos = np.asarray(data.x)[:12]
with pytest.raises(
TypeError, match="exog_oos must be a DataFrame when"
):
res.forecast(12, exog=exog_oos)
with pytest.raises(ValueError, match="must have the same columns"):
res.forecast(12, exog=data.x.iloc[:12, :1])
def test_prediction_replacements(data, fixed):
res = ARDL(data.y, 4, data.x, [1, 3]).fit()
direct = res.predict()
alt = res.predict(exog=data.x)
assert_allclose(direct, alt)
assert_index_equal(direct.index, alt.index)
res = ARDL(data.y, 4, data.x, [1, 3], fixed=fixed).fit()
direct = res.predict()
alt = res.predict(fixed=fixed)
assert_allclose(direct, alt)
assert_index_equal(direct.index, alt.index)
def test_prediction_wrong_shape(data):
x = np.asarray(data.x)
res = ARDL(data.y, 4, x, [1, 3]).fit()
with pytest.raises(ValueError, match="exog must have the same number"):
res.predict(exog=np.asarray(data.x)[:, :1])
with pytest.raises(
ValueError, match="exog must have the same number of rows"
):
res.predict(exog=np.asarray(data.x)[:-2])
res = ARDL(data.y, 4, data.x, [1, 3]).fit()
with pytest.raises(ValueError, match="exog must have the same columns"):
res.predict(exog=data.x.iloc[:, :1])
with pytest.raises(
ValueError, match="exog must have the same number of rows"
):
res.predict(exog=data.x.iloc[:-2])
def test_prediction_wrong_shape_fixed(data):
x = np.asarray(data.x)
res = ARDL(data.y, 4, fixed=x).fit()
with pytest.raises(ValueError, match="fixed must have the same number"):
res.predict(fixed=np.asarray(data.x)[:, :1])
with pytest.raises(
ValueError, match="fixed must have the same number of rows"
):
res.predict(fixed=np.asarray(data.x)[:-2])
res = ARDL(data.y, 4, fixed=data.x).fit()
with pytest.raises(ValueError, match="fixed must have the same number"):
res.predict(fixed=data.x.iloc[:, :1])
with pytest.raises(
ValueError, match="fixed must have the same number of rows"
):
res.predict(fixed=data.x.iloc[:-2])
def test_insuficient_oos(data):
x = np.asarray(data.x)
res = ARDL(data.y, 4, fixed=x).fit()
with pytest.raises(ValueError, match="fixed_oos must be provided"):
res.forecast(12)
with pytest.raises(ValueError, match="fixed_oos must have at least"):
res.forecast(12, fixed=x[:11])
res = ARDL(data.y, 4, data.x, 3, causal=True).fit()
with pytest.raises(ValueError, match="exog_oos must be provided"):
res.forecast(12)
with pytest.raises(ValueError, match="exog_oos must have at least"):
res.forecast(12, exog=data.x.iloc[-10:])
def test_insuficient_data(data):
with pytest.raises(ValueError, match=r"The number of regressors \(36\)"):
ARDL(data.y, 20, data.x, 4)
def test_forecast_date(data):
res = ARDL(data.y, 3).fit()
numeric = res.forecast(12)
date = res.forecast("1990-07-01")
assert_allclose(numeric, date)
assert_index_equal(numeric.index, date.index)
def test_get_prediction(data):
res = ARDL(data.y, 3).fit()
ar_res = AutoReg(data.y, 3).fit()
pred = res.get_prediction(end="2020-01-01")
ar_pred = ar_res.get_prediction(end="2020-01-01")
assert_allclose(pred.predicted_mean, ar_pred.predicted_mean)
assert_allclose(pred.var_pred_mean, ar_pred.var_pred_mean)
@pytest.mark.matplotlib
@pytest.mark.smoke
@pytest.mark.parametrize("trend", ["n", "c", "ct"])
@pytest.mark.parametrize("seasonal", [True, False])
def test_ardl_smoke_plots(data, seasonal, trend, close_figures):
from matplotlib.figure import Figure
mod = ARDL(
data.y,
3,
trend=trend,
seasonal=seasonal,
)
res = mod.fit()
fig = res.plot_diagnostics()
assert isinstance(fig, Figure)
fig = res.plot_predict(end=100)
assert isinstance(fig, Figure)
fig = res.plot_predict(end=75, alpha=None, in_sample=False)
assert isinstance(fig, Figure)
assert isinstance(res.summary(), Summary)
def test_uecm_model_init(
data: Dataset,
uecm_lags,
uecm_order,
trend,
causal,
fixed,
use_numpy,
seasonal,
):
y, x, z, uecm_order, period = _convert_to_numpy(
data, fixed, uecm_order, seasonal, use_numpy
)
mod = UECM(
y,
uecm_lags,
x,
uecm_order,
trend,
causal=causal,
fixed=z,
seasonal=seasonal,
period=period,
)
res = mod.fit()
check_results(res)
res.predict()
ardl = ARDL(
y,
uecm_lags,
x,
uecm_order,
trend,
causal=causal,
fixed=z,
seasonal=seasonal,
period=period,
)
uecm = UECM.from_ardl(ardl)
uecm_res = uecm.fit()
check_results(uecm_res)
uecm_res.predict()
def test_from_ardl_none(data):
with pytest.warns(SpecificationWarning):
mod = UECM.from_ardl(
ARDL(data.y, 2, data.x, {"lry": 2, "ide": 2, "ibo": None})
)
assert mod.ardl_order == (2, 2, 2)
def test_uecm_model_formula(
data: Dataset,
uecm_lags,
uecm_order,
trend,
causal,
fixed,
seasonal,
):
fmla = "lrm ~ lry + ibo + ide"
df = pd.concat([data.y, data.x], axis=1)
if fixed is not None:
fmla += " | " + " + ".join(fixed.columns)
df = pd.concat([df, fixed], axis=1)
mod = UECM.from_formula(
fmla,
df,
uecm_lags,
uecm_order,
trend,
causal=causal,
seasonal=seasonal,
)
res = mod.fit()
check_results(res)
res.predict()
def test_uecm_errors(data):
with pytest.raises(TypeError, match="order must be None"):
UECM(data.y, 2, data.x, [0, 1, 2])
with pytest.raises(TypeError, match="lags must be an"):
UECM(data.y, [1, 2], data.x, 2)
with pytest.raises(TypeError, match="order values must be positive"):
UECM(data.y, 2, data.x, {"ibo": [1, 2]})
with pytest.raises(ValueError, match="Model must contain"):
UECM(data.y, 2, data.x, None)
with pytest.raises(ValueError, match="All included exog"):
UECM(data.y, 2, data.x, {"lry": 2, "ide": 2, "ibo": 0})
with pytest.raises(ValueError, match="hold_back must be"):
UECM(data.y, 3, data.x, 5, hold_back=4)
with pytest.raises(ValueError, match="The number of"):
UECM(data.y, 20, data.x, 4)
ardl = ARDL(data.y, 2, data.x, {"lry": [1, 2], "ide": 2, "ibo": 2})
with pytest.raises(ValueError, match="UECM can only be created from"):
UECM.from_ardl(ardl)
ardl = ARDL(data.y, 2, data.x, {"lry": [0, 2], "ide": 2, "ibo": 2})
with pytest.raises(ValueError, match="UECM can only be created from"):
UECM.from_ardl(ardl)
ardl = ARDL(data.y, [1, 3], data.x, 2)
with pytest.raises(ValueError, match="UECM can only be created from"):
UECM.from_ardl(ardl)
res = UECM(data.y, 2, data.x, 2).fit()
with pytest.raises(NotImplementedError):
res.predict(end=100)
with pytest.raises(NotImplementedError):
res.predict(dynamic=True)
with pytest.raises(NotImplementedError):
res.predict(dynamic=25)
@pytest.mark.parametrize("use_numpy", [True, False])
@pytest.mark.parametrize("use_t", [True, False])
def test_uecm_ci_repr(use_numpy, use_t):
y = dane_data.lrm
x = dane_data[["lry", "ibo", "ide"]]
if use_numpy:
y = np.asarray(y)
x = np.asarray(x)
mod = UECM(y, 3, x, 3)
res = mod.fit(use_t=use_t)
if use_numpy:
ci_params = res.params[:5].copy()
ci_params /= ci_params[1]
else:
ci_params = res.params.iloc[:5].copy()
ci_params /= ci_params["lrm.L1"]
assert_allclose(res.ci_params, ci_params)
assert res.ci_bse.shape == (5,)
assert res.ci_tvalues.shape == (5,)
assert res.ci_pvalues.shape == (5,)
assert "Cointegrating Vector" in str(res.ci_summary())
assert res.ci_conf_int().shape == (5, 2)
assert res.ci_cov_params().shape == (5, 5)
assert res.ci_resids.shape == dane_data.lrm.shape
@pytest.mark.parametrize("case", [1, 2, 3, 4, 5])
def test_bounds_test(case):
mod = UECM(
dane_data.lrm,
3,
dane_data[["lry", "ibo", "ide"]],
{"lry": 1, "ibo": 3, "ide": 2},
)
res = mod.fit()
expected = {
1: 0.7109023,
2: 5.116768,
3: 6.205875,
4: 5.430622,
5: 6.785325,
}
bounds_result = res.bounds_test(case)
assert_allclose(bounds_result.stat, expected[case])
assert "BoundsTestResult" in str(bounds_result)
@pytest.mark.parametrize("case", [1, 2, 3, 4, 5])
def test_bounds_test_simulation(case):
mod = UECM(
dane_data.lrm,
3,
dane_data[["lry", "ibo", "ide"]],
{"lry": 1, "ibo": 3, "ide": 2},
)
res = mod.fit()
bounds_result = res.bounds_test(
case=case, asymptotic=False, seed=[1, 2, 3, 4], nsim=10_000
)
assert (bounds_result.p_values >= 0.0).all()
assert (bounds_result.p_values <= 1.0).all()
assert (bounds_result.crit_vals > 0.0).all().all()
@pytest.mark.parametrize(
"seed",
[None, np.random.RandomState(0), 0, [1, 2], np.random.default_rng([1, 2])],
)
def test_bounds_test_seed(seed):
mod = UECM(
dane_data.lrm,
3,
dane_data[["lry", "ibo", "ide"]],
{"lry": 1, "ibo": 3, "ide": 2},
)
res = mod.fit()
bounds_result = res.bounds_test(
case=3, asymptotic=False, seed=seed, nsim=10_000
)
assert (bounds_result.p_values >= 0.0).all()
assert (bounds_result.p_values <= 1.0).all()
assert (bounds_result.crit_vals > 0.0).all().all()
def test_bounds_test_simulate_order():
mod = UECM(
dane_data.lrm,
3,
dane_data[["lry", "ibo", "ide"]],
{"lry": 1, "ibo": 3, "ide": 2},
)
res = mod.fit()
bounds_result = res.bounds_test(3)
assert "BoundsTestResult" in str(bounds_result)
bounds_result_sim = res.bounds_test(
3, asymptotic=False, nsim=10_000, seed=[1, 2, 3]
)
assert_allclose(bounds_result.stat, bounds_result_sim.stat)
assert (bounds_result_sim.p_values > bounds_result.p_values).all()