-
Notifications
You must be signed in to change notification settings - Fork 91
Open
Labels
Effort > Moderate 🐕Mid-sized tasks estimated to take a few days to a few weeks.Mid-sized tasks estimated to take a few days to a few weeks.Great First Contribution! 🌱Beginner friendly tickets with narrow scope and huge impact. Perfect to join our community!Beginner friendly tickets with narrow scope and huge impact. Perfect to join our community!Impact > Moderate 🔶User-visible but non-breaking change. Treated like a minor version bump (e.g., 0.6.5 → 0.7.0).User-visible but non-breaking change. Treated like a minor version bump (e.g., 0.6.5 → 0.7.0).
Description
Description
Hi, I would like to propose and discuss the inclusion of my current age-to-age factor smoothing implementation into the chainladder-python codebase.
Summary
Add age-to-age factor smoothing capability to the Development class, allowing to smooth erratic development patterns in specific origins using linear interpolation of cumulative loss values.
Use Cases
- Smoothing accident years with unusual patterns due to abnormal claims movements
- Addressing low-volume specialty lines with erratic development
- Removing data quality issues in specific cells
- Creating more stable reserve estimates for volatile lines
Proposed API
Find a more detailed example here.
import chainladder as cl
# Load triangle data
tri = cl.load_sample('quarterly')['incurred']
# Smooth specific origin and development range
dev = cl.Development(
smooth=[('2002', 18, 30)] # (origin, start_age, end_age) - both INCLUSIVE
).fit(tri)
# Multiple origins with different ranges
dev = cl.Development(
smooth=[
('2002', 18, 30), # Smooths LDFs starting at ages 18, 21, 24, 27, 30
('2003', 9, 12), # Smooths LDFs starting at ages 9, 12 (minimum: 2 LDFs)
]
).fit(tri)
# Combine with other Development parameters
dev = cl.Development(
smooth=[('2002', 18, 30)],
n_periods=10,
drop=[('2001', 12)]
).fit(tri)Algorithm
Linear Interpolation of Cumulative Values:
- Extract cumulative loss values at the start and end boundaries of the smoothed block
- Linearly interpolate intermediate cumulative values:
C_i = C_start + w_i × (C_end - C_start) - Recalculate age-to-age factors from interpolated cumulatives:
LDF_j = C_{j+1} / C_j
Properties:
- Preserves boundary values exactly
- Produces smoothly declining factors
- No parametric assumptions required
- Simple, transparent calculation
Implementation Details
New Parameter:
smooth: tuple or list of tuples specifying(origin, start_age, end_age)- Both
start_ageandend_ageare inclusive (starting ages of first and last LDFs to smooth) - Minimum requirement: 2 link ratios (3 cumulative values) needed for interpolation
- Applied to specific origins before averaging across all origins
Workflow Position:
Development.fit() pipeline:
1. Convert to cumulative and development mode
2. Get triangle arrays
3. → Apply smoothing (modifies specific origins)
4. Apply drop adjustments (sets weights for exclusion)
5. Run weighted regression (averages across origins)
6. Calculate LDFs, CDFs, sigmas, etc.
Important: If you smooth AND drop the same cell:
- The smoothed value is calculated but then excluded from the weighted average
- Best practice: Use smooth OR drop for a given cell, not both
Display Mechanism:
- Smoothed values visible in triangle.link_ratio heatmaps
- Uses
smooth_weights_attribute to scale displayed values - Existing triangle.py code applies these weights automatically
Implementation Status
- Add
smoothparameter to Development class with inclusiveend_agebehavior - Implement
_smooth()method with linear interpolation - Add
smooth_weights_for heatmap display - Write tests for new feature
- Update Development docstring
- Create minimal example notebook demonstrating functionality
- Verify integration with existing methods
- Ensure backend compatibility (numpy, sparse)
Files Changed
Modified:
chainladder/development/development.py- Updated docstring with smooth parameterchainladder/development/base.py- Added_smooth()method with inclusive end_age behaviorchainladder/development/tests/test_smoothing.py- New test file (31 tests, all updated for inclusive API)
Tests
Current tests are covering:
- Basic functionality (single/multiple tuples)
- Error handling (invalid inputs, minimum periods)
- Integration with other Development parameters (including
drop) - Edge cases (first/last origins, boundary preservation)
- Backend compatibility (numpy, sparse)
- No unintended cascade beyond specified range
Is your feature request at odds with the scope of the package?
- Yes, absolutely!
- No, but it's still worth discussing.
- N/A (this request is not a codebase enhancement).
Describe the solution you'd like, or your current workaround.
No response
Do you have any additional supporting notes?
No response
Metadata
Metadata
Assignees
Labels
Effort > Moderate 🐕Mid-sized tasks estimated to take a few days to a few weeks.Mid-sized tasks estimated to take a few days to a few weeks.Great First Contribution! 🌱Beginner friendly tickets with narrow scope and huge impact. Perfect to join our community!Beginner friendly tickets with narrow scope and huge impact. Perfect to join our community!Impact > Moderate 🔶User-visible but non-breaking change. Treated like a minor version bump (e.g., 0.6.5 → 0.7.0).User-visible but non-breaking change. Treated like a minor version bump (e.g., 0.6.5 → 0.7.0).