Skip to content

Commit

Permalink
Merge pull request #764 from bashtage/update-ci
Browse files Browse the repository at this point in the history
CI: Add Python 3.13 to run
  • Loading branch information
bashtage authored Jan 8, 2025
2 parents dbc7b99 + dd0b6d8 commit be4a5f1
Show file tree
Hide file tree
Showing 12 changed files with 50 additions and 36 deletions.
7 changes: 6 additions & 1 deletion arch/tests/unitroot/test_unitroot.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,12 @@
import scipy.stats as stats
from statsmodels.datasets import macrodata, modechoice, nile, randhie, sunspots
from statsmodels.regression.linear_model import OLS
from statsmodels.tsa.stattools import _autolag, lagmat
from statsmodels.tsa.stattools import lagmat

try:
from statsmodels.tsa.stattools import _autolag
except ImportError:
from statsmodels.tsa.stattools._stattools import _autolag

from arch.unitroot import ADF, DFGLS, KPSS, PhillipsPerron, VarianceRatio, ZivotAndrews
from arch.unitroot.critical_values.dickey_fuller import tau_2010
Expand Down
8 changes: 4 additions & 4 deletions arch/tests/univariate/test_distribution.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ def test_studentst(self, seed):
# Direct calculation of PDF, then log
constant = np.exp(gammaln(0.5 * (v + 1)) - gammaln(0.5 * v))
pdf = constant / np.sqrt(np.pi * (v - 2) * self.sigma2)
pdf *= (1 + self.resids ** 2.0 / (self.sigma2 * (v - 2))) ** (-(v + 1) / 2)
pdf *= (1 + self.resids**2.0 / (self.sigma2 * (v - 2))) ** (-(v + 1) / 2)
ll2 = np.log(pdf).sum()
assert_almost_equal(ll1, ll2)

Expand Down Expand Up @@ -87,14 +87,14 @@ def test_skewstudent(self, seed):
# Direct calculation of PDF, then log
const_c = gamma((eta + 1) / 2) / ((np.pi * (eta - 2)) ** 0.5 * gamma(eta / 2))
const_a = 4 * lam * const_c * (eta - 2) / (eta - 1)
const_b = (1 + 3 * lam ** 2 - const_a ** 2) ** 0.5
const_b = (1 + 3 * lam**2 - const_a**2) ** 0.5

resids = self.resids / self.sigma2 ** 0.5
resids = self.resids / self.sigma2**0.5
power = -(eta + 1) / 2
pdf = (
const_b
* const_c
/ self.sigma2 ** 0.5
/ self.sigma2**0.5
* (
1
+ 1
Expand Down
2 changes: 1 addition & 1 deletion arch/tests/univariate/test_mean.py
Original file line number Diff line number Diff line change
Expand Up @@ -1354,7 +1354,7 @@ def test_param_cov():
def test_plot_bad_index():
import matplotlib.pyplot as plt

idx = sorted(f"{a}{b}{c}" for a, b, c, in product(*([ascii_lowercase] * 3)))
idx = sorted(f"{a}{b}{c}" for a, b, c in product(*([ascii_lowercase] * 3)))
sp500_copy = SP500.copy()
sp500_copy.index = idx[: sp500_copy.shape[0]]
res = ConstantMean(sp500_copy).fit(disp=False)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ def dfgsl_simulation(
results = np.zeros((len(percentiles), len(T), EX_NUM))

for i in range(EX_NUM):
print(f"Experiment Number {i + 1} of {EX_NUM} " "(trend {tr})")
print(f"Experiment Number {i + 1} of {EX_NUM} (trend {tr})")
now = datetime.datetime.now()
parallel, p_func, n_jobs = parallel_func(
wrapper, n_jobs=NUM_JOBS, verbose=2
Expand Down
2 changes: 1 addition & 1 deletion arch/unitroot/unitroot.py
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@


def _is_reduced_rank(
x: Union[Float64Array, DataFrame]
x: Union[Float64Array, DataFrame],
) -> tuple[bool, Union[int, None]]:
"""
Check if a matrix has reduced rank preferring quick checks
Expand Down
7 changes: 6 additions & 1 deletion arch/univariate/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,13 @@
)
from arch.utility.testing import WaldTestStatistic

MPL_LT_310 = False
try:
from matplotlib import __version__
from matplotlib.figure import Figure
from packaging.version import Version

MPL_LT_310 = Version(__version__) < Version("3.10.0")
except ImportError:
pass

Expand Down Expand Up @@ -1642,7 +1647,7 @@ def hedgehog_plot(

fig, ax = plt.subplots(1, 1)
use_date = isinstance(self._dep_var.index, pd.DatetimeIndex)
plot_fn = ax.plot_date if use_date else ax.plot
plot_fn = ax.plot_date if use_date and MPL_LT_310 else ax.plot
x_values = np.array(self._dep_var.index)
if plot_mean:
y_values = np.asarray(self._dep_var)
Expand Down
43 changes: 22 additions & 21 deletions arch/univariate/distribution.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
Distributions to use in ARCH models. All distributions must inherit from
:class:`Distribution` and provide the same methods with the same inputs.
"""

from abc import ABCMeta, abstractmethod
from collections.abc import Sequence
from typing import Callable, Optional, Union
Expand Down Expand Up @@ -100,8 +101,8 @@ def _check_constraints(
for p, n, b in zip(params, self.name, bounds):
if not (b[0] <= p <= b[1]):
raise ValueError(
"{} does not satisfy the bounds requirement "
"of ({}, {})".format(n, *b)
f"{n} does not satisfy the bounds requirement of "
f"({b[0]}, {b[1]})"
)
return asarray(params)

Expand Down Expand Up @@ -205,7 +206,7 @@ def loglikelihood(
resids: ArrayLike,
sigma2: ArrayLike,
individual: bool = False,
) -> Union[float , Float64Array]:
) -> Union[float, Float64Array]:
"""
Loglikelihood evaluation.
Expand Down Expand Up @@ -264,7 +265,7 @@ def ppf(
self,
pits: Union[float, Sequence[float], ArrayLike1D],
parameters: Union[Sequence[float], ArrayLike1D, None] = None,
) -> Union[float , Float64Array]:
) -> Union[float, Float64Array]:
"""
Inverse cumulative density function (ICDF)
Expand Down Expand Up @@ -414,7 +415,7 @@ def loglikelihood(
resids: ArrayLike,
sigma2: ArrayLike,
individual: bool = False,
) -> Union[float , Float64Array]:
) -> Union[float, Float64Array]:
r"""Computes the log-likelihood of assuming residuals are normally
distributed, conditional on the variance
Expand Down Expand Up @@ -446,7 +447,7 @@ def loglikelihood(
+\frac{x^{2}}{\sigma^{2}}\right)
"""
lls = -0.5 * (log(2 * pi) + log(sigma2) + resids ** 2.0 / sigma2)
lls = -0.5 * (log(2 * pi) + log(sigma2) + resids**2.0 / sigma2)
if individual:
return lls
else:
Expand Down Expand Up @@ -557,7 +558,7 @@ def loglikelihood(
resids: ArrayLike,
sigma2: ArrayLike,
individual: bool = False,
) -> Union[float , Float64Array]:
) -> Union[float, Float64Array]:
r"""Computes the log-likelihood of assuming residuals are have a
standardized (to have unit variance) Student's t distribution,
conditional on the variance.
Expand Down Expand Up @@ -595,7 +596,7 @@ def loglikelihood(
nu = parameters[0]
lls = gammaln((nu + 1) / 2) - gammaln(nu / 2) - log(pi * (nu - 2)) / 2
lls -= 0.5 * (log(sigma2))
lls -= ((nu + 1) / 2) * (log(1 + (resids ** 2.0) / (sigma2 * (nu - 2))))
lls -= ((nu + 1) / 2) * (log(1 + (resids**2.0) / (sigma2 * (nu - 2))))

if individual:
return lls
Expand Down Expand Up @@ -685,7 +686,7 @@ def partial_moment(
nu = parameters[0]
var = nu / (nu - 2)
scale = 1.0 / sqrt(var)
moment = (scale ** n) * self._ord_t_partial_moment(n, z / scale, nu)
moment = (scale**n) * self._ord_t_partial_moment(n, z / scale, nu)
return moment

@staticmethod
Expand Down Expand Up @@ -729,9 +730,9 @@ def _ord_t_partial_moment(n: int, z: float, nu: float) -> float:
elif n == 1:
c = gamma(0.5 * (nu + 1)) / (sqrt(nu * pi) * gamma(0.5 * nu))
e = 0.5 * (nu + 1)
moment = (0.5 * (c * nu) / (1 - e)) * ((1 + (z ** 2) / nu) ** (1 - e))
moment = (0.5 * (c * nu) / (1 - e)) * ((1 + (z**2) / nu) ** (1 - e))
else:
t1 = (z ** (n - 1)) * (nu + z ** 2) * stats.t.pdf(z, nu)
t1 = (z ** (n - 1)) * (nu + z**2) * stats.t.pdf(z, nu)
t2 = (n - 1) * nu * StudentsT._ord_t_partial_moment(n - 2, z, nu)
moment = (1 / (n - nu)) * (t1 - t2)
return moment
Expand Down Expand Up @@ -846,7 +847,7 @@ def loglikelihood(
const_a = self.__const_a(parameters)
const_b = self.__const_b(parameters)

resids = resids / sigma2 ** 0.5
resids = resids / sigma2**0.5
lls = log(const_b) + const_c - log(sigma2) / 2
if abs(lam) >= 1.0:
lam = sign(lam) * (1.0 - 1e-6)
Expand Down Expand Up @@ -911,7 +912,7 @@ def simulate(
def parameter_names(self) -> list[str]:
return ["eta", "lambda"]

def __const_a(self, parameters: Union[Float64Array , Sequence[float]]) -> float:
def __const_a(self, parameters: Union[Float64Array, Sequence[float]]) -> float:
"""
Compute a constant.
Expand All @@ -930,7 +931,7 @@ def __const_a(self, parameters: Union[Float64Array , Sequence[float]]) -> float:
c = self.__const_c(parameters)
return float(4 * lam * exp(c) * (eta - 2) / (eta - 1))

def __const_b(self, parameters: Union[Float64Array , Sequence[float]]) -> float:
def __const_b(self, parameters: Union[Float64Array, Sequence[float]]) -> float:
"""
Compute b constant.
Expand All @@ -946,7 +947,7 @@ def __const_b(self, parameters: Union[Float64Array , Sequence[float]]) -> float:
"""
lam = float(parameters[1])
a = self.__const_a(parameters)
return (1 + 3 * lam ** 2 - a ** 2) ** 0.5
return (1 + 3 * lam**2 - a**2) ** 0.5

@staticmethod
def __const_c(parameters: Union[Float64Array, Sequence[float]]) -> float:
Expand Down Expand Up @@ -999,7 +1000,7 @@ def ppf(
self,
pits: Union[float, Sequence[float], ArrayLike1D],
parameters: Union[Sequence[float], ArrayLike1D, None] = None,
) -> Union[float , Float64Array]:
) -> Union[float, Float64Array]:
parameters = self._check_constraints(parameters)
scalar = isscalar(pits)
if scalar:
Expand Down Expand Up @@ -1052,8 +1053,8 @@ def moment(
)
l_pmom = ((-1) ** k) * r_pmom

lhs = (1 - lam) * (lscale ** k) * (loc ** (n - k)) * l_pmom
rhs = (1 + lam) * (rscale ** k) * (loc ** (n - k)) * r_pmom
lhs = (1 - lam) * (lscale**k) * (loc ** (n - k)) * l_pmom
rhs = (1 + lam) * (rscale**k) * (loc ** (n - k)) * r_pmom
moment += comb(n, k) * (lhs + rhs)

return moment
Expand Down Expand Up @@ -1083,15 +1084,15 @@ def partial_moment(
lhs = (
(1 - lam)
* (loc ** (n - k))
* (lscale ** k)
* (lscale**k)
* StudentsT._ord_t_partial_moment(k, z=(lbound - loc) / lscale, nu=eta)
)

if z > loc:
rhs = (
(1 + lam)
* (loc ** (n - k))
* (rscale ** k)
* (rscale**k)
* (
StudentsT._ord_t_partial_moment(k, z=(z - loc) / rscale, nu=eta)
- StudentsT._ord_t_partial_moment(k, z=0.0, nu=eta)
Expand Down Expand Up @@ -1285,7 +1286,7 @@ def partial_moment(
parameters = self._check_constraints(parameters)
nu = parameters[0]
scale = 1.0 / sqrt(stats.gennorm(nu).var())
moment = (scale ** n) * self._ord_gennorm_partial_moment(n, z / scale, nu)
moment = (scale**n) * self._ord_gennorm_partial_moment(n, z / scale, nu)
return moment

@staticmethod
Expand Down
2 changes: 1 addition & 1 deletion arch/univariate/mean.py
Original file line number Diff line number Diff line change
Expand Up @@ -949,7 +949,7 @@ def forecast(
"Due to backcasting and/or data availability start cannot be less "
"than the index of the largest value in the right-hand-side "
"variables used to fit the first observation. In this model, "
"this value is {}.".format(max(0, earliest - 1))
f"this value is {max(0, earliest - 1)}."
)
# Parse params
params = np.asarray(params)
Expand Down
3 changes: 1 addition & 2 deletions arch/univariate/volatility.py
Original file line number Diff line number Diff line change
Expand Up @@ -508,8 +508,7 @@ def _bootstrap_forecast(
std_resid = resids / np.sqrt(sigma2)
if start < self._min_bootstrap_obs:
raise ValueError(
"start must include more than {} "
"observations".format(self._min_bootstrap_obs)
f"start must include more than {self._min_bootstrap_obs} observations"
)
rng = BootstrapRng(std_resid, start, random_state=random_state).rng()
return self._simulation_forecast(
Expand Down
2 changes: 2 additions & 0 deletions ci/azure/azure_template_posix.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ jobs:
vmImage: ${{ parameters.vmImage }}
strategy:
matrix:
python_313:
python.version: '3.13'
python_312:
python.version: '3.12'
python_311:
Expand Down
2 changes: 2 additions & 0 deletions ci/azure/azure_template_windows.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ jobs:
python.version: '3.11'
python312_win_latest:
python.version: '3.12'
python313_win_latest:
python.version: '3.12'
maxParallel: 10

steps:
Expand Down
6 changes: 3 additions & 3 deletions requirements-dev.txt
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,12 @@ pytest-xdist
pytest-cov

# formatting
black[jupyter]~=24.8.0
isort~=5.0
black[jupyter]~=24.10.0
isort~=5.12
colorama
flake8
mypy
ruff
ruff>=0.8.6
pyupgrade>=3.4.0
jupyterlab-code-formatter

Expand Down

0 comments on commit be4a5f1

Please sign in to comment.