-
Notifications
You must be signed in to change notification settings - Fork 106
Disposal #1039
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Disposal #1039
Changes from all commits
c6588fe
3bb4e35
4b8dea4
3726b60
0ffc46e
a232d5e
b736bc0
0c1830d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,13 +1,19 @@ | ||
| # 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/. | ||
| from __future__ import annotations | ||
|
|
||
| from chainladder.methods import Chainladder | ||
| from chainladder.methods import Chainladder, MethodBase | ||
| from chainladder.development import DevelopmentBase | ||
| import numpy as np | ||
| import copy | ||
| from chainladder.utils import TriangleWeight, concat | ||
| from chainladder import Triangle | ||
|
|
||
| from typing import TYPE_CHECKING | ||
|
|
||
| if TYPE_CHECKING: | ||
| from chainladder.core import Triangle | ||
|
|
||
|
|
||
| class DisposalRate(DevelopmentBase): | ||
| """ | ||
|
|
@@ -192,18 +198,22 @@ def fit( | |
| """ | ||
| if sample_weight is None: | ||
| raise ValueError("sample_weight is required.") | ||
| #convert to numpy | ||
| #validate dimensions of sample weight | ||
| MethodBase().validate_weight(X, sample_weight) | ||
| #set backeneds to numpy | ||
| if X.array_backend == "sparse": | ||
| X = X.set_backend("numpy").incr_to_cum() | ||
| X = X.set_backend("numpy") | ||
| else: | ||
| X = X.copy().incr_to_cum() | ||
| X = X.copy() | ||
| if sample_weight.array_backend == "sparse": | ||
| ult = sample_weight.set_backend("numpy") | ||
| else: | ||
| ult = sample_weight.copy() | ||
| #get backend | ||
| #calculate disposal rate triangle | ||
| self.xp = X.get_array_module() | ||
| self.X_ = X.sort_index() | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sorted X_ mismatches disposal triangleHigh Severity
Additional Locations (1)Reviewed by Cursor Bugbot for commit 0c1830d. Configure here. |
||
| self.disposal_rate_tri = X / ult.values | ||
| #get weights for estimation | ||
| tw = TriangleWeight( | ||
| n_periods = self.n_periods, | ||
| drop_high = self.drop_high, | ||
|
|
@@ -214,16 +224,17 @@ def fit( | |
| preserve = self.preserve, | ||
| drop = self.drop | ||
| ) | ||
| if hasattr(X, "w_"): | ||
| self.w_ = tw.fit(X=self.disposal_rate_tri * X.w_).w_.values | ||
| if hasattr(self.X_, "w_"): | ||
| self.w_ = tw.fit(X=self.disposal_rate_tri * self.X_.w_).w_.values | ||
| else: | ||
| self.w_ = tw.fit(X=self.disposal_rate_tri).w_.values | ||
| #calculate factors | ||
| super().fit(ult.values,X.values,self.w_) | ||
| super().fit(ult.values,self.X_.values,self.w_) | ||
| #keep attributes | ||
| self.disposal_ = self._param_property(self.disposal_rate_tri,self.params_.slope_[...,0][..., None, :]) | ||
| self.disposal_ = concat((self.disposal_,(X.latest_diagonal*0 + 1).iloc[:,:,0,:].rename("development", [9999])),axis=3) | ||
| self.disposal_ = concat((self.disposal_,(self.X_.latest_diagonal*0 + 1).iloc[:,:,0,:].rename("development", [9999])),axis=3) | ||
| self.disposal_.is_cumulative = True | ||
| #pattern multiples from tail and additive adds from head | ||
| self.disposal_.is_pattern = False | ||
| self.incr_disposal_ = self.disposal_.cum_to_incr() | ||
| self.incr_disposal_.is_pattern = True | ||
|
|
@@ -253,10 +264,13 @@ def transform( | |
| if sample_weight is None: | ||
| raise ValueError("sample_weight is required.") | ||
| X_new = copy.deepcopy(X) | ||
| #validate dimensions of sample weight | ||
| MethodBase().validate_weight(X, sample_weight) | ||
| #align backeneds | ||
| X_new.ultimate_ = sample_weight.set_backend(self.X_.array_backend).latest_diagonal | ||
| X_new.disposal_rate_tri = self.disposal_rate_tri | ||
| X_new.disposal_ = self.disposal_ | ||
| X_new.incr_disposal_ = self.incr_disposal_ | ||
| X_new.ultimate_ = sample_weight.latest_diagonal | ||
| ibnr_pct = 1 - X_new.disposal_.align_pattern(X_new.disposal_rate_tri) | ||
| run_off = X_new.incr_disposal_ / ibnr_pct * X_new.ibnr_ | ||
| run_off = run_off[run_off.valuation > X_new.valuation_date] | ||
|
|
||


There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removed cumulative conversion in fit
Medium Severity
fitno longer callsincr_to_cum()onXafter copying or setting the numpy backend. Disposal rates are cumulative paid (or similar) divided by ultimate; fitting on incremental values yields incorrect ratios and regression inputs for incremental triangles.Reviewed by Cursor Bugbot for commit 0c1830d. Configure here.