onlevel factors not matching CAS example #497
-
I am testing the ParallelogramOLF feature in this python package. I have the code to replicate p. 75-76 of the following: https://www.casact.org/sites/default/files/2021-03/5_Werner_Modlin.pdf I would expect the onlevel factor produced by this package for CY2011 to = 1.0431. But I am getting 1.0462. Am I missing something?
Output: |
Beta Was this translation helpful? Give feedback.
Replies: 3 comments 15 replies
-
Hi @vdunaway, This is because the Let's look at the parallelogram chart at the top of page 76 of the text, we see that Werner and Modlin assumes area 1 has an area of 0.125 for year 2011, however, this is actually not exactly true, it is only approximately true assuming all months have an equal number of days. 0.125 = 0.5 ^ 2 * 0.5 Since the effective date of the 5% rate change is from 7/1/2010, Area 1 is actually [181/365] ^2 / 2, which is ~0.12295 instead of 0.1250. (181 is the number of days between 1/1/2011 to 6/30/2011, basically the height, and length, of area 1's triangle). Area 3 has an area of 365/365 ^2 *0.5 = 0.5 (same as in the text). Area 2 would be 1 - 0.500 - 0.12295 = 0.37705. I didn't spend the time to verify the rest of the calculation, but this should hopefully be convincing enough that the Werner and Modlin's version of OLF is understated. Note that Does this help? |
Beta Was this translation helpful? Give feedback.
-
These two blocks of code should work correctly now. Monthly approximation scenario: rate_history = pd.DataFrame(
{
"EffDate": ["2010-07-01", "2011-01-01", "2012-07-01", "2013-04-01"],
"RateChange": [0.035, 0.05, 0.10, -0.01],
}
)
rate_history
data = pd.DataFrame({"Year": list(range(2006, 2016)), "EarnedPremium": [10_000] * 10})
prem_tri = cl.Triangle(data, origin="Year", columns="EarnedPremium", cumulative=True)
prem_tri = cl.ParallelogramOLF(
rate_history,
change_col="RateChange",
date_col="EffDate",
approximation_grain="M",
vertical_line=False,
).fit_transform(prem_tri)
(
np.round(prem_tri.olf_.to_frame().values, 6).flatten()
== [
1.183471,
1.183471,
1.183471,
1.183471,
1.178316,
1.120181,
1.075556,
1.004236,
0.999684,
1.000000,
]
).all() And daily approximation scenario, includes consideration of leap years: rate_history = pd.DataFrame(
{
"EffDate": ["2010-07-01", "2011-01-01", "2012-07-01", "2013-04-01"],
"RateChange": [0.035, 0.05, 0.10, -0.01],
}
)
rate_history
data = pd.DataFrame({"Year": list(range(2006, 2016)), "EarnedPremium": [10_000] * 10})
prem_tri = cl.Triangle(data, origin="Year", columns="EarnedPremium", cumulative=True)
prem_tri = cl.ParallelogramOLF(
rate_history,
change_col="RateChange",
date_col="EffDate",
approximation_grain="D",
vertical_line=False,
).fit_transform(prem_tri)
(
np.round(prem_tri.olf_.to_frame().values, 6).flatten()
== [
1.183471,
1.183471,
1.183471,
1.183471,
1.178231,
1.120105,
1.075410,
1.004073,
0.999693,
1.000000,
]
).all() Now, I think we just have one final decision to make. As you can see above, I will be introducing a new parameter, named I think the default value should be What are your thoughts? |
Beta Was this translation helpful? Give feedback.
-
@jbogaardt, there's a calculation error with one of the test cases in chainladder/utils/tests/test_utilities.py::test_non_vertical_line. In this example, the rate change is effective 7/1/2017 and we want the on-level factor for 2017, I propose that the OLF should be calculated as:
or, with everything chained together (no rounding):
Basically, the last line should replace line 8. In addition, we can now use @jbogaardt, do you agree? Perhaps @vdunaway can peer-review this? Since we are trying to pass a unit test case by modifying the unit test. |
Beta Was this translation helpful? Give feedback.
These two blocks of code should work correctly now.
Monthly approximation scenario: