-
Notifications
You must be signed in to change notification settings - Fork 92
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
Reactions are currently unavailable
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).