[BUG] Incorrect origin periods in non-standard Quarterly Triangles
Describe the bug The origin periods are incorrect when creating a quarterly triangle object with non-standard Quarter periods (Feb-Apr, May-Jul, Aug-Oct, Nov-Jan). IN my example below, I have non-standard quarter periods and when I try to create a Triangle object from the data, I get incorrect origin periods. The amounts seem to lagging. Compare the below image with the pandas dataframe.
To Reproduce Steps to reproduce the behavior. Code should be self-contained and runnable against publicly available data. For example:
import chainladder as cl
import pandas as pd
data= pd.DataFrame([
["5/1/2023", 12, '4/30/2024', 100],
["8/1/2023", 9, "4/30/2024", 130],
["11/1/2023", 6, "4/30/2024", 160],
["2/1/2024", 3, "4/30/2024", 140]],
columns = ['origin', 'development', 'valuation', 'EarnedPremium'])
triangle = cl.Triangle(
data, origin='origin', origin_format='%Y-%m-%d', development='valuation', columns='EarnedPremium', trailing=True, cumulative=True
)
data_from_tri = triangle.to_frame(origin_as_datetime=True)
Expected behavior:
The periods seem to not match with the original data. The expected result should look something like this:
Desktop (please complete the following information):
- Numpy Version 1.26.4
- Pandas Version 2.2.2
- Chainladder Version 0.8.20
Fantastic bug report! Thanks for finding this. Will fix in next release.
If it helps - I notice this occurs frequently when changing the grain to quarterly with the grain method, with trailing=True. Also the valuations are potentially off as shown below. Sometimes this only occurs when the triangle HTML is displayed but the underlying dataframe is correct. Though in this example, both are incorrect:
import chainladder as cl
import pandas as pd
monthly_triangle = cl.load_sample('prism')['Incurred'].sum()
monthly_triangle = monthly_triangle[monthly_triangle.valuation<pd.to_datetime('2009-06-01')]
print( 'Monthly Triangle')
display(monthly_triangle)
print( 'Quarterly Triangle displayed as triangle object')
quarterly_triangle = monthly_triangle.grain('OQDQ',trailing=True)
display(quarterly_triangle)
display(quarterly_triangle.valuation.unique())
print( 'Quarterly Triangle displayed as dataframe')
display(quarterly_triangle.to_frame())
not reopening due to age of issue. here is a screenshot showing the assertions holding with the fix. also added as test_odd_quarter_end under test_triangle