Approach (brief): use segmented (piecewise) regression to estimate immediate (level) and gradual (slope) changes after the redesign date. Model time trend, binary intervention indicator, and interaction for post-intervention slope; check and account for autocorrelation and seasonality.Statistical model (segmented regression)Y_t = β0 + β1 * time_t + β2 * intervention_t + β3 * post_time_t + ε_t- time_t: continuous time index (1,2,...)- intervention_t: 0 before, 1 after (including day of deployment)- post_time_t: 0 before, (time_t - time_of_intervention +1) afterInterpretation:- β2 tests immediate level change- β3 tests change in slope (trend)Diagnostics- Plot series + fitted lines- Residual ACF/PACF plots; Durbin-Watson; Ljung-Box for autocorrelation- Seasonal decomposition (STL) or include seasonal dummies (day-of-week, month)- Check heteroskedasticity (Breusch-Pagan)Adjustment strategies- If autocorrelation: fit GLSAR or use OLS with HAC (Newey-West) SEs; or ARIMA with regressors (SARIMAX)- If seasonality: include seasonal dummies or Fourier terms, or model with SARIMAXPython/statsmodels implementation (example using OLS + Newey-West and GLSAR)python
import pandas as pd
import numpy as np
import statsmodels.api as sm
from statsmodels.stats.diagnostic import acorr_ljungbox
from statsmodels.graphics.tsaplots import plot_acf
# assume df with 'date' and 'y'
df = df.sort_values('date').reset_index(drop=True)
df['time'] = np.arange(1, len(df)+1)
intervention_date = pd.to_datetime("2024-06-01")
df['intervention'] = (df['date'] >= intervention_date).astype(int)
df['post_time'] = df['time'] - df.loc[df['date']>=intervention_date,'time'].min() + 1
df.loc[df['intervention']==0,'post_time'] = 0
# design
X = sm.add_constant(df[['time','intervention','post_time']])
ols = sm.OLS(df['y'], X).fit()
print(ols.summary())
# diagnostics
plot_acf(ols.resid)
print('Ljung-Box:', acorr_ljungbox(ols.resid, lags=[12]))
# robust SEs (Newey-West) for autocorrelation up to lag L
nw = ols.get_robustcov_results(cov_type='HAC', maxlags=7)
print(nw.summary())
# alternative: GLSAR to model AR(1)
from statsmodels.regression.linear_model import GLSAR
glsar = GLSAR(df['y'], X, rho=1)
res_glsar = glsar.iterative_fit(10)
print(res_glsar.summary())
Testing sustained change- Immediate level: H0: β2 = 0 (use t-test from model)- Slope change: H0: β3 = 0- Joint tests: F-test on β2 and β3 simultaneously- Use HAC SEs or GLSAR estimates for correct inference if autocorrelation presentPractical notes- Visualize counterfactual (predict using pre-intervention β0+β1*time)- Check sensitivity (vary intervention date, include covariates)- Report effect sizes with CI and discuss practical significance, not only p-values.