From 433f940111ae4e9501d2501d9d836fde464116a5 Mon Sep 17 00:00:00 2001 From: Gene Dan Date: Sat, 20 Jun 2026 12:30:16 -0500 Subject: [PATCH 1/3] TEST: Add test for Triangle.to_pickle(). --- chainladder/core/io.py | 9 ++++-- chainladder/utils/tests/test_utilities.py | 36 +++++++++++++++++++++++ 2 files changed, 42 insertions(+), 3 deletions(-) diff --git a/chainladder/core/io.py b/chainladder/core/io.py index 127c1f77..b72f0d1b 100644 --- a/chainladder/core/io.py +++ b/chainladder/core/io.py @@ -1,11 +1,14 @@ +""" +Support Triangle I/O capabilities. +""" # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at https://mozilla.org/MPL/2.0/. +import dill +import json import pandas as pd + from sklearn.base import BaseEstimator -import json -import joblib -import dill class TriangleIO: diff --git a/chainladder/utils/tests/test_utilities.py b/chainladder/utils/tests/test_utilities.py index c296507e..9c4615b2 100644 --- a/chainladder/utils/tests/test_utilities.py +++ b/chainladder/utils/tests/test_utilities.py @@ -420,6 +420,42 @@ def test_read_pickle_triangle(raa: Triangle, tmp_path: Path) -> None: assert cl.read_pickle(str(pkl_path)) == raa +def test_triangle_to_pickle( + raa: Triangle, + clrd: Triangle, + tmp_path: Path +) -> None: + """ + Dump a pickle of a triangle and read it back in. The read-in triangle should + equal the one that was dumped. + + Parameters + ---------- + raa: Triangle + The raa sample data set Triangle. + clrd: Triangle + The clrd sample data set Triangle. + tmp_path: Path + The builtin pytest tmp_path fixture, provides a temporary path to dump the pickle to. + + Returns + ------- + None + + """ + # Single-dimension case. + raa_path = tmp_path / "raa.pkl" + raa.to_pickle(str(raa_path)) + assert raa_path.is_file() + assert cl.read_pickle(str(raa_path)) == raa + + # Multidimensional case. + clrd_path = tmp_path / "clrd.pkl" + clrd.to_pickle(str(clrd_path)) + assert clrd_path.is_file() + assert cl.read_pickle(str(clrd_path)) == clrd + + def test_read_pickle_estimator(raa: Triangle, tmp_path: Path) -> None: """ Create an estimator, dump a pickle of it, and then read it back in. The ingested pickle should result From daea7402c976499a04031e77b80a55b9c4eee3d5 Mon Sep 17 00:00:00 2001 From: "henrydingliu@gmail.com" Date: Fri, 19 Jun 2026 01:44:25 +0000 Subject: [PATCH 2/3] promoting _param_property --- chainladder/development/base.py | 48 ++++++++++++++++++++++---- chainladder/development/incremental.py | 16 +-------- 2 files changed, 43 insertions(+), 21 deletions(-) diff --git a/chainladder/development/base.py b/chainladder/development/base.py index 47c13081..7e34fd7f 100644 --- a/chainladder/development/base.py +++ b/chainladder/development/base.py @@ -21,7 +21,7 @@ from typing import TYPE_CHECKING if TYPE_CHECKING: - from chainladder.core.typing import TriangleLike + from chainladder.core import Triangle class DevelopmentBase( @@ -45,18 +45,18 @@ def fit(self, X, y=None, sample_weight=None): def _set_fit_groups( self, - X: TriangleLike - ) -> TriangleLike: + X: Triangle + ) -> Triangle: """ Used for assigning group_index in fit. Parameters ---------- - X: TriangleLike + X: Triangle Returns ------- - TriangleLike, after performing the groupby on it. + Triangle, after performing the groupby on it. """ backend = "numpy" if X.array_backend in ["sparse", "numpy"] else "cupy" @@ -383,4 +383,40 @@ def _drop(self, X): np.where(X.origin == item[0])[0][0], np.where(X.development == item[1])[0][0], ] = 0 - return arr[:, :-1] \ No newline at end of file + return arr[:, :-1] + + @staticmethod + def _param_property( + self, + X: Triangle, + params: np.ndarray + ) -> Triangle: + """ + Wrap an array of estimated parameters in a Triangle + + Parameters + ---------- + X: Triangle + The Triangle to wrap the parameters with + + params: np.ndarray + The parameters to be wrapped + + Returns + ------- + Triangle + The wrapped parameters + + """ + from chainladder import options + + obj: Triangle = X[X.origin == X.origin.min()] + xp = X.get_array_module() + obj.values = params + obj.valuation_date = pd.to_datetime(options.ULT_VAL) + obj.is_pattern = True + obj.is_additive = True + obj.is_cumulative = False + obj.virtual_columns.columns = {} + obj._set_slicers() + return obj diff --git a/chainladder/development/incremental.py b/chainladder/development/incremental.py index a79df253..90e80777 100644 --- a/chainladder/development/incremental.py +++ b/chainladder/development/incremental.py @@ -294,18 +294,4 @@ def transform(self, X): X_new = X.copy() for item in ["ldf_", "w_", "zeta_", "incremental_", "tri_zeta", "fit_zeta_", "sample_weight"]: X_new.__dict__[item] = self.__dict__[item] - return X_new - - def _param_property(self, factor, params): - from chainladder import options - - obj = factor[factor.origin == factor.origin.min()] - xp = factor.get_array_module() - obj.values = params - obj.valuation_date = pd.to_datetime(options.ULT_VAL) - obj.is_pattern = True - obj.is_additive = True - obj.is_cumulative = False - obj.virtual_columns.columns = {} - obj._set_slicers() - return obj + return X_new \ No newline at end of file From a4d913bc1f8119365dee54380ca9317305672627 Mon Sep 17 00:00:00 2001 From: "henrydingliu@gmail.com" Date: Fri, 19 Jun 2026 01:58:09 +0000 Subject: [PATCH 3/3] fixing bug --- chainladder/development/base.py | 1 - 1 file changed, 1 deletion(-) diff --git a/chainladder/development/base.py b/chainladder/development/base.py index 7e34fd7f..49c1192e 100644 --- a/chainladder/development/base.py +++ b/chainladder/development/base.py @@ -387,7 +387,6 @@ def _drop(self, X): @staticmethod def _param_property( - self, X: Triangle, params: np.ndarray ) -> Triangle: