Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
John Bogaardt committed May 24, 2024
1 parent be25774 commit 9e23666
Show file tree
Hide file tree
Showing 7 changed files with 29 additions and 59 deletions.
2 changes: 1 addition & 1 deletion chainladder/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,4 +42,4 @@ def auto_sparse(auto_sparse=True):
from chainladder.methods import * # noqa (API Import)
from chainladder.workflow import * # noqa (API Import)

__version__ = "0.8.22"
__version__ = "0.8.23"
13 changes: 3 additions & 10 deletions chainladder/core/tests/test_triangle.py
Original file line number Diff line number Diff line change
Expand Up @@ -245,16 +245,9 @@ def test_df_period_input(raa):

def test_trend_on_vector(raa):
d = raa.latest_diagonal

trend_from = datetime.strptime("12-31-1981", "%m-%d-%Y")
trend_to = datetime.strptime("12-31-1990", "%m-%d-%Y")
days_to_trend = (trend_to - trend_from).days
expected_value = np.round(
raa.latest_diagonal.to_frame().iloc[0, 0] * (1.05) ** (days_to_trend / 365.25),
0,
)

assert np.round(d.trend(0.05, axis=2).to_frame().iloc[0, 0], 0) == expected_value
assert (
d.trend(0.05, axis=2).to_frame(origin_as_datetime=False).astype(int).iloc[0, 0]
== 29217)


def test_latest_diagonal_val_to_dev(raa):
Expand Down
50 changes: 13 additions & 37 deletions chainladder/core/triangle.py
Original file line number Diff line number Diff line change
Expand Up @@ -346,7 +346,7 @@ def origin(self):
def origin(self, value):
self._len_check(self.origin, value)
freq = {
"Y": "Y" if float(".".join(pd.__version__.split(".")[:-1])) < 2.2 else "A",
"Y": "A" if float(".".join(pd.__version__.split(".")[:-1])) < 2.2 else "Y",
"S": "2Q",
}.get(self.origin_grain, self.origin_grain)
freq = freq if freq == "M" else freq + "-" + self.origin_close
Expand Down Expand Up @@ -772,15 +772,15 @@ def trend(
Parameters
----------
trend : float
The annual amount of the trend. Use 1/(1+trend)-1 to de-trend.
The annual amount of the trend. Use 1/(1+trend)-1 to detrend.
axis : str (options: ['origin', 'valuation'])
The axis on which to apply the trend
start: date
The start date from which trend should be calculated. If none is
provided, then the earliest date of the triangle is used.
provided then the latest date of the triangle is used.
end: date
The end date to which the trend should be calculated. If none is
provided, then the valuation date of the triangle is used.
provided then the earliest period of the triangle is used.
ultimate_lag : int
If ultimate valuations are in the triangle, optionally set the overall
age (in months) of the ultimate to be some lag from the latest non-Ultimate
Expand All @@ -795,59 +795,35 @@ def trend(
raise ValueError(
"Only origin and valuation axes are supported for trending"
)

# print("====== BEGIN ======")
xp = self.get_array_module()

start = pd.to_datetime(start) if type(start) is str else start
start = self.origin[0].to_timestamp() if start is None else start
# print("start", start)

start = self.valuation_date if start is None else start
end = pd.to_datetime(end) if type(end) is str else end
end = self.valuation_date if end is None else end
# print("end", end)

end = self.origin[0].to_timestamp() if end is None else end
if axis in ["origin", 2, -2]:
vector = pd.DatetimeIndex(
np.tile(
self.origin.to_timestamp(how="e").date, self.shape[-1]
self.origin.to_timestamp(how="e").values, self.shape[-1]
).flatten()
)
else:
vector = self.valuation
# print("vector\n", vector)

upper, lower = (end, start) if end > start else (start, end)
# print("lower", lower)
# print("upper", upper)

lower, upper = (end, start) if end > start else (start, end)
vector = pd.DatetimeIndex(
np.maximum(
np.minimum(np.datetime64(upper), vector.values), np.datetime64(lower)
np.minimum(np.datetime64(lower), vector.values), np.datetime64(upper)
)
)
# print("vector\n", vector)
# print("vector\n", vector)
# vector = (
# (end.year - vector.year) * 12 + (end.month - vector.month)
# ).values.reshape(self.shape[-2:], order="f")
# print("vector\n", vector)

vector = ((end - vector).days).values.reshape(self.shape[-2:], order="f")
# print("days to trend\n", vector)

vector = (
(start.year - vector.year) * 12 + (start.month - vector.month)
).values.reshape(self.shape[-2:], order="f")
if self.is_ultimate and ultimate_lag is not None and vector.shape[-1] > 1:
vector[:, -1] = vector[:, -2] + ultimate_lag

trend = (
xp.array((1 + trend) ** (vector / 365.25))[None, None, ...]
* self.nan_triangle
xp.array((1 + trend) ** (vector / 12))[None, None, ...] * self.nan_triangle
)
# print("trend\n", trend)

obj = self.copy()
obj.values = obj.values * trend

return obj

def broadcast_axis(self, axis, value):
Expand Down
2 changes: 1 addition & 1 deletion chainladder/development/development.py
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,7 @@ def transform(self, X):
"w_v2_",
]
for item in triangles:
setattr(X_new, item, getattr(self, item))
setattr(X_new, item, getattr(self, item), None)

X_new._set_slicers()

Expand Down
14 changes: 7 additions & 7 deletions chainladder/development/tests/test_development.py
Original file line number Diff line number Diff line change
Expand Up @@ -197,21 +197,21 @@ def test_hilo_multiple_indices(clrd):
def test_new_drop_1(clrd):
clrd = clrd.groupby("LOB")[["IncurLoss", "CumPaidLoss"]].sum()
# n_periods
return compare_new_drop(cl.Development(n_periods=4).fit(clrd), clrd)
compare_new_drop(cl.Development(n_periods=4).fit(clrd), clrd)


def test_new_drop_2(clrd):
clrd = clrd.groupby("LOB")[["IncurLoss", "CumPaidLoss"]].sum()
# single drop and drop_valuation
return compare_new_drop(
compare_new_drop(
cl.Development(drop=("1992", 12), drop_valuation=1993).fit(clrd), clrd
)


def test_new_drop_3(clrd):
clrd = clrd.groupby("LOB")[["IncurLoss", "CumPaidLoss"]].sum()
# multiple drop and drop_valuation
return compare_new_drop(
compare_new_drop(
cl.Development(
drop=[("1992", 12), ("1996", 24)], drop_valuation=[1993, 1995]
).fit(clrd),
Expand All @@ -222,13 +222,13 @@ def test_new_drop_3(clrd):
def test_new_drop_4(clrd):
clrd = clrd.groupby("LOB")[["IncurLoss", "CumPaidLoss"]].sum()
# drop_hi/low without preserve
return compare_new_drop(cl.Development(drop_high=1, drop_low=1).fit(clrd), clrd)
compare_new_drop(cl.Development(drop_high=1, drop_low=1).fit(clrd), clrd)


def test_new_drop_5(clrd):
clrd = clrd.groupby("LOB")[["IncurLoss", "CumPaidLoss"]].sum()
# drop_hi/low without preserve
return compare_new_drop(
compare_new_drop(
cl.Development(drop_high=1, drop_low=1, preserve=3).fit(clrd), clrd
)

Expand All @@ -254,15 +254,15 @@ def test_new_drop_5a(clrd):
def test_new_drop_6(clrd):
clrd = clrd.groupby("LOB")[["IncurLoss", "CumPaidLoss"]].sum()
# drop_above/below without preserve
return compare_new_drop(
compare_new_drop(
cl.Development(drop_above=1.01, drop_below=0.95).fit(clrd), clrd
)


def test_new_drop_7(clrd):
clrd = clrd.groupby("LOB")[["IncurLoss", "CumPaidLoss"]].sum()
# drop_above/below with preserve
return compare_new_drop(
compare_new_drop(
cl.Development(drop_above=1.01, drop_below=0.95, preserve=3).fit(clrd), clrd
)

Expand Down
5 changes: 3 additions & 2 deletions chainladder/utils/utility_functions.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
from patsy import dmatrix
from sklearn.base import BaseEstimator, TransformerMixin
from typing import Iterable, Union
from io import StringIO


def load_sample(key: str, *args, **kwargs):
Expand Down Expand Up @@ -110,7 +111,7 @@ def read_json(json_str, array_backend=None):
)
elif "metadata" in json_dict.keys():
j = json.loads(json_str)
y = pd.read_json(j["data"], orient="split", date_unit="ns")
y = pd.read_json(StringIO(j["data"]), orient="split", date_unit="ns")
y["origin"] = pd.to_datetime(y["origin"])
y.columns = [c if c != "valuation" else "development" for c in y.columns]
y["development"] = pd.to_datetime(y["development"])
Expand Down Expand Up @@ -185,7 +186,7 @@ def parallelogram_olf(

cum_rate_changes = np.cumprod(1 + rate_changes.values)
cum_rate_changes = pd.Series(cum_rate_changes, rate_changes.index)
crl = cum_rate_changes[-1]
crl = cum_rate_changes.iloc[-1]

cum_avg_rate_non_leaps = cum_rate_changes
cum_avg_rate_leaps = cum_rate_changes
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
descr = "Chainladder Package - P&C Loss Reserving package "
name = 'chainladder'
url = 'https://github.com/casact/chainladder-python'
version='0.8.22' # Put this in __init__.py
version='0.8.23' # Put this in __init__.py

data_path = ''
setup(
Expand Down

0 comments on commit 9e23666

Please sign in to comment.