Remove Monthly/Quarterly Cost Patterns—Isolate True Trend from Predictable Calendar Effects
python# Seasonal Adjustment Framework monthly_seasonal_factors = { 'January': 1.12, # Deductible reset, elective procedures scheduled 'February': 1.08, # Continued deductible optimization 'March': 1.05, # Deductible satisfied, utilization normalizing 'April': 0.98, # Spring lull 'May': 0.95, # Pre-summer drop 'June': 0.94, # Summer vacation begins 'July': 0.92, # Peak vacation season 'August': 0.91, # Continued summer lull 'September': 1.02, # Back-to-school checkups 'October': 1.04, # Flu season begins 'November': 0.97, # Holiday deferrals begin 'December': 0.93 # Year-end holidays, elective procedures deferred } def seasonally_adjust_costs(monthly_claims): """ Remove seasonal patterns to expose true underlying trend """ adjusted_claims = [] for month_data in monthly_claims: month_name = month_data.month actual_pmpm = month_data.total_claims / month_data.member_months # Remove seasonal effect seasonal_factor = monthly_seasonal_factors[month_name] adjusted_pmpm = actual_pmpm / seasonal_factor adjusted_claims.append({ 'month': month_name, 'actual_pmpm': actual_pmpm, 'seasonal_factor': seasonal_factor, 'seasonally_adjusted_pmpm': adjusted_pmpm }) return adjusted_claims def calculate_deseasonalized_trend(current_period, prior_period): """ Compare same months year-over-year OR use seasonally-adjusted values """ # Method 1: Year-over-year (natural deseasonalization) yoy_trend = (current_period.pmpm / prior_period.pmpm) - 1 # Method 2: Seasonally-adjusted month-to-month current_adjusted = current_period.pmpm / monthly_seasonal_factors[current_period.month] prior_adjusted = prior_period.pmpm / monthly_seasonal_factors[prior_period.month] mom_trend = (current_adjusted / prior_adjusted) - 1 return { 'yoy_trend': yoy_trend, 'mom_seasonally_adjusted': mom_trend } # Example: Q1 vs. Q3 Comparison # Q1 Actual: $1,085 PMPM (Jan 1.12x, Feb 1.08x, Mar 1.05x avg = 1.083x) # Q1 Adjusted: $1,002 ($1,085 / 1.083) # # Q3 Actual: $945 PMPM (Jul 0.92x, Aug 0.91x, Sep 1.02x avg = 0.950x) # Q3 Adjusted: $995 ($945 / 0.950) # # Without adjustment: looks like 14.8% decline (panic!) # With adjustment: actually 0.7% improvement (normal variance)
Adjust for predictable monthly patterns. Compare apples-to-apples across quarters. Budget with seasonal intelligence.
Deseasonalize Costs→