Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/pytest.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ jobs:
fail-fast: false
matrix:
os: ['ubuntu-latest']
python-version: ['3.10', '3.11', '3.12', '3.13', '3.14']
python-version: ['3.11', '3.12', '3.13', '3.14']
steps:
- uses: actions/checkout@v6
- name: Install uv
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/pytest_upstream_nightly.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ jobs:
fail-fast: false
matrix:
os: ['ubuntu-latest']
python-version: ['3.10', '3.11', '3.12', '3.13', '3.14']
python-version: ['3.11', '3.12', '3.13', '3.14']
steps:
- uses: actions/checkout@v6
- name: Install uv
Expand Down
4 changes: 2 additions & 2 deletions chainladder/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ class Options:
ARRAY_BACKEND = "numpy"
AUTO_SPARSE = True
ARRAY_PRIORITY = ["dask", "sparse", "cupy", "numpy"]
ULT_VAL = "2261-12-31 23:59:59.999999999"
ULT_VAL = "2261-12-31 23:59:59.999999"

@classmethod
def get_option(cls, option=None):
Expand All @@ -18,7 +18,7 @@ def reset_option(self):
self.set_option('ARRAY_BACKEND', "numpy")
self.set_option('AUTO_SPARSE', True)
self.set_option('ARRAY_PRIORITY', ["dask", "sparse", "cupy", "numpy"])
self.set_option('ULT_VAL', "2261-12-31 23:59:59.999999999")
self.set_option('ULT_VAL', "2261-12-31 23:59:59.999999")

def describe_option(self):
pass
Expand Down
4 changes: 2 additions & 2 deletions chainladder/core/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -540,12 +540,12 @@ def valuation(self):
ddim_arr = ddims - ddims[0]
origin = np.minimum(self.odims, np.datetime64(self.valuation_date))
val_array = origin.astype("datetime64[M]") + np.timedelta64(ddims[0], "M")
val_array = val_array.astype("datetime64[ns]") - np.timedelta64(1, "ns")
val_array = val_array.astype("datetime64[us]") - np.timedelta64(1, "us")
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lol, I never knew us stood for microsecond. Good stuff

val_array = val_array[:, None]
s = slice(None, -1) if ddims[-1] == 9999 else slice(None, None)
val_array = (
val_array.astype("datetime64[M]") + ddim_arr[s][None, :] + 1
).astype("datetime64[ns]") - np.timedelta64(1, "ns")
).astype("datetime64[us]") - np.timedelta64(1, "us")
if ddims[-1] == 9999:
ult = np.repeat(np.datetime64(options.ULT_VAL), val_array.shape[0])[:, None]
val_array = np.concatenate(
Expand Down
2 changes: 1 addition & 1 deletion chainladder/core/pandas.py
Original file line number Diff line number Diff line change
Expand Up @@ -505,7 +505,7 @@ def agg_func(
# If axis is development, set the ddims to be the valuation date.
if axis == 3 and obj.values.shape[axis] == 1 and len(obj.ddims) > 1:
obj.ddims = pd.DatetimeIndex(
[self.valuation_date], dtype="datetime64[ns]", freq=None
[self.valuation_date], dtype="datetime64[us]", freq=None
)
obj._set_slicers()
if auto_sparse:
Expand Down
9 changes: 5 additions & 4 deletions chainladder/core/tests/test_triangle.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
import numpy as np
import pytest
import io
from datetime import datetime

from io import StringIO

try:
from IPython.core.display import HTML
Expand All @@ -13,7 +14,7 @@

def test_repr(raa):
np.testing.assert_array_equal(
pd.read_html(raa._repr_html_())[0].set_index("Unnamed: 0").values,
pd.read_html(StringIO(raa._repr_html_()))[0].set_index("Unnamed: 0").values,
raa.to_frame(origin_as_datetime=False).values,
)

Expand Down Expand Up @@ -317,7 +318,7 @@ def test_groupby_axis1(clrd, prism):
clrd = clrd.sum("origin").sum("development")
groups = [i.find("Loss") >= 0 for i in clrd.columns]
assert np.all(
clrd.to_frame(origin_as_datetime=False).groupby(groups, axis=1).sum()
clrd.to_frame(origin_as_datetime=False).T.groupby(groups).sum().T
== clrd.groupby(groups, axis=1).sum().to_frame(origin_as_datetime=False)
)
assert np.all(
Expand Down Expand Up @@ -908,7 +909,7 @@ def test_single_valuation_date_preserves_exact_date():
)

# Valuation date should be end of October 2025, not converted to a fiscal year
assert triangle.valuation_date == pd.Timestamp('2025-10-31 23:59:59.999999999')
assert triangle.valuation_date == pd.Timestamp('2025-10-31 23:59:59.999999')
assert triangle.development_grain == 'M'
assert int(triangle.valuation_date.strftime('%Y%m')) == 202510
def test_OXDX_triangle():
Expand Down
2 changes: 1 addition & 1 deletion chainladder/core/triangle.py
Original file line number Diff line number Diff line change
Expand Up @@ -577,7 +577,7 @@ def _split_ult(
if (
development
and len(development) == 1
and data[development[0]].dtype == "<M8[ns]"
and pd.api.types.is_datetime64_dtype(data[development[0]])
):
u = data[data[development[0]] == options.ULT_VAL].copy()
if len(u) > 0 and len(u) != len(data):
Expand Down
3 changes: 2 additions & 1 deletion chainladder/development/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
from chainladder.utils.utility_functions import num_to_nan
from chainladder.core.io import EstimatorIO
from chainladder.core.common import Common
from pandas.api.types import is_string_dtype


class DevelopmentBase(BaseEstimator, TransformerMixin, EstimatorIO, Common):
Expand Down Expand Up @@ -421,7 +422,7 @@ def _drop_func(self, factor):
# accommodate ldf triangle as factor, where the dimensions are '12-24'
dev_list = (
factor.development.str.split("-", expand=True)[0]
if factor.development.dtype == object
if is_string_dtype(factor.development)
else factor.development.astype("string")
)
# create ndarray of drop_list for further operation in numpy
Expand Down
2 changes: 0 additions & 2 deletions chainladder/utils/tests/test_utilities.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@

from pathlib import Path


def test_non_vertical_line():
true_olf = (
1.20
Expand Down Expand Up @@ -161,7 +160,6 @@ def test_read_csv_single(raa):
# Test the read_csv function for a single dimensional input.

# Read in the csv file.
from pathlib import Path
raa_csv_path = Path(__file__).parent.parent / "data" / "raa.csv"

assert raa == cl.read_csv(
Expand Down
4 changes: 2 additions & 2 deletions chainladder/utils/utility_functions.py
Original file line number Diff line number Diff line change
Expand Up @@ -504,7 +504,7 @@ def read_json(json_str, array_backend=None):
setattr(getattr(tri, k), "development_grain", tri.development_grain)
if "dfs" in json_dict.keys():
for k, v in json_dict["dfs"].items():
df = pd.read_json(v)
df = pd.read_json(StringIO(v))
if len(df.columns) == 1:
df = df.iloc[:, 0]
setattr(tri, k, df)
Expand Down Expand Up @@ -708,7 +708,7 @@ def concat(
if ignore_index and axis == 0:
out.key_labels = ["Index"]
out.valuation_date = pd.Series([obj.valuation_date for obj in objs]).max()
if out.ddims.dtype == "datetime64[ns]" and type(out.ddims) == np.ndarray:
if out.ddims.dtype == "datetime64[us]" and type(out.ddims) == np.ndarray:
out.ddims = pd.DatetimeIndex(out.ddims)
out._set_slicers()
if sort:
Expand Down
5 changes: 2 additions & 3 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,23 +14,22 @@ maintainers = [
description = "Chainladder Package - P&C Loss Reserving package"
readme = "README.rst"
license = {text = "MPL-2.0"}
requires-python = ">=3.10"
requires-python = ">=3.11"
classifiers = [
"Development Status :: 4 - Beta",
"Intended Audience :: Developers",
"Intended Audience :: Science/Research",
"License :: OSI Approved :: Mozilla Public License 2.0 (MPL 2.0)",
"Operating System :: OS Independent",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Programming Language :: Python :: 3.13",
"Programming Language :: Python :: 3.14",
]
keywords = ["actuarial", "reserving", "insurance", "chainladder", "IBNR"]
dependencies = [
"pandas >=2.0, <3.0",
"pandas >=3",
"scikit-learn>1.4.2",
"numba>0.54",
"sparse>=0.9",
Expand Down
Loading
Loading