Skip to content
69 changes: 69 additions & 0 deletions chainladder/core/tests/test_triangle.py
Original file line number Diff line number Diff line change
Expand Up @@ -1448,6 +1448,75 @@ def test_single_valuation_date_preserves_exact_date():
assert triangle.valuation_date == pd.Timestamp(val_date_exp)
assert triangle.development_grain == 'M'
assert int(triangle.valuation_date.strftime('%Y%m')) == 202510


def test_1d_annual_valuation_date() -> None:
year_data = [
[1998, 2008, 900000, 890000],
[1999, 2008, 1200000, 1170000],
[2000, 2008, 1300000, 1265000],
[2001, 2008, 1800000, 1600000],
[2002, 2008, 1450000, 1200000],
]
year_df = pd.DataFrame(
data=year_data, columns=["origin", "dev", "revenue", "expense"]
)
tri = cl.Triangle(
data=year_df,
origin="origin",
development="dev",
columns="expense",
development_format="%Y",
cumulative=True,
)
assert pd.to_datetime(tri.valuation_date).date() == pd.Timestamp("2008-12-31").date()
assert tri.development_grain == "Y"

def test_1d_monthly_valuation_date() -> None:
year_data = [
[1998, "2008-01", 900000, 890000],
[1999, "2008-01", 1200000, 1170000],
[2000, "2008-01", 1300000, 1265000],
[2001, "2008-01", 1800000, 1600000],
[2002, "2008-01", 1450000, 1200000],
]
year_df = pd.DataFrame(
data=year_data, columns=["origin", "dev", "revenue", "expense"]
)
tri = cl.Triangle(
data=year_df,
origin="origin",
development="dev",
columns="expense",
development_format="%Y-%m",
cumulative=True,
)
assert pd.to_datetime(tri.valuation_date).date() == pd.Timestamp("2008-01-31").date()
assert tri.development_grain == "M"

def test_1d_monthly_valuation_date_expanded_dev_date() -> None:
year_df = pd.DataFrame(
{
"origin": [1998, 1999, 2000, 2001, 2002],
"dev": [2008.0, 2008.0, 2008.0, 2008.0, 2008.0],
"expense": [890000, 1170000, 1265000, 1600000, 1200000],
}
)
tri = cl.Triangle(
data=year_df,
origin="origin",
development="dev",
columns="expense",
development_format="%Y",
cumulative=True,
)
assert pd.to_datetime(tri.valuation_date).date() == pd.Timestamp("2008-12-31").date()
assert tri.development_grain == "Y"

def test_friedland_gl_self_insurer_grain() -> None:
data_valuation_date = cl.load_sample('friedland_gl_self_insurer').valuation_date
assert pd.to_datetime(data_valuation_date).date() == pd.Timestamp("2008-12-31").date()

def test_OXDX_triangle():

for x in [12,6,3,1]:
Expand Down
22 changes: 17 additions & 5 deletions chainladder/core/triangle.py
Original file line number Diff line number Diff line change
Expand Up @@ -482,7 +482,18 @@ def __init__(
)

if len(development_date.unique()) == 1:
if len(data) == 1 and self.origin_grain.split("-")[0] in ["Y", "A"]:
# checks if development is not empty, and if ithas any non-yearly values
dev_has_no_month = not development or all(
pd.to_numeric(data[col], errors="coerce")
.astype("Int64")
.astype(str)
.str.fullmatch(r"\d{4}")
.all()
for col in development
)
Comment thread
cursor[bot] marked this conversation as resolved.

if len(data) == 1 or dev_has_no_month:
# if development has no monthly values, match origin
self.development_grain = self.origin_grain
else:
dev_date = pd.to_datetime(development_date.iloc[0])
Expand Down Expand Up @@ -1466,10 +1477,11 @@ def _val_dev(self, sign, inplace=False):
ddims = len(ddims.drop_duplicates())
if ddims == 1 and sign == -1:
ddims = len(obj.odims)
if obj.values.density > 0 and obj.values.coords[-1].min() < 0:
obj.values.coords[-1] = obj.values.coords[-1] - min(
obj.values.coords[-1].min(), min_slide
)
if obj.values.density > 0:
if obj.values.coords[-1].min() < 0:
obj.values.coords[-1] = obj.values.coords[-1] - min(
obj.values.coords[-1].min(), min_slide
)
ddims = np.max([np.max(obj.values.coords[-1]) + 1, ddims])
obj.values.shape = tuple(list(obj.shape[:-1]) + [ddims])
if options.AUTO_SPARSE == False or backend == "cupy":
Expand Down
1 change: 0 additions & 1 deletion chainladder/utils/data/_manifest.py
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,6 @@
"Paid Claims",
],
"cumulative": True,
"development_format": "%Y-12-31",
},
"friedland_med_mal": {
"origin": "Accident Year",
Expand Down
Loading