# Time Series Chow test & Bai Perron test

I have a question about breakpoints test, that is to select which variables to put in the model ?

Example:

Y = C(constant) + Ut , Ut ~ N(0,1) ....first model

Y = C(constant) + Trend + Ut , Ut ~ N(0,1) ....second model

Y = C(constant) + AR(1) + Trend + Ut , Ut ~ N(0,1) ....third model

Y = C(constant) + AR(1) + AR(2) + Trend + Ut , Ut ~ N(0,1) ....fourth model

In the picture(1) I simulate two time series and combine them , each of them are AR(1) Model , one has trend and another no trend. Assumption I don't know components of this series , to detect break in this time series , which model should I use (1、2、3、4 model，or neither of them) ?

I know if I want to see the constant change i put C in model to detect change , want to see trend change then put C + trend in model , but I want to know a better way to select model detect break , not use eyes.

The simplest way of dealing with changepoints is to iterate through your data points (maybe like the middle 80% of them) and fit each each segment with each of your models and choose the changepoint based on whichever minimizes some criteria like rmse or something simple. Then take your residuals and do the same process again but then add your two 'rounds' of fitted values to get the new residuals. Do this again and again until you minimize a global criteria like some modified version of the AICC/BIC to take into account the number of changepoints so K + n_changepoints in the formula.

If you use python you can try out a package I am messing around with ThymeBoost:

pip install ThymeBoost


A simple example like what you have done but with a linear estimator:

from ThymeBoost import ThymeBoost as tb
boosted_model = tb.ThymeBoost(trend_estimator = 'linear',
split_cost = 'mse',
global_cost = 'maicc',
fit_type = 'local',
seasonal_period = 0,
verbose = 1)
output = boosted_model.fit(time_series)
boosted_model.plot_results()


But we really can use whatever base estimator for trend so lets use arima:

from ThymeBoost import ThymeBoost as tb
boosted_model = tb.ThymeBoost(trend_estimator = 'ar',
arima_order = (2,1,2),
split_cost = 'mse',
global_cost = 'maicc',
fit_type = 'local',
seasonal_period = 0,
verbose = 1)
output = boosted_model.fit(time_series)
boosted_model.plot_results()


Using verbose the model prints results from each round:

Round 0 cost: -1344.0438903501597
Using Split: 101
Round 1 cost: -1971.2578426717146
Using Split: 151
Round 2 cost: -1953.8696120415427
Boosting Terminated
Using round 1


So it found a changepoint at 101 where the coefficients of the arima will be different. That is close enough to the true changepoint at 100 if you ask me! Round 0 is always fit with with the median of the data since this approach is heavily influenced by gradient boosting and it has a nice interpretation of saying 'there is no trend'. Although for your case you may just want to fit all your different models globally for the first round.

Now let's try with 3 changepoints to see what happens:

from ThymeBoost import ThymeBoost as tb
boosted_model = tb.ThymeBoost(trend_estimator = 'linear',
split_cost = 'mse',
global_cost = 'maicc',
fit_type = 'local',
seasonal_period = 0,
verbose = 1)
output = boosted_model.fit(time_series)
boosted_model.plot_results()


Oof, that's pretty bad. Looks like it is a problem with how I propose the segments since I don't want to exhaustively try every data point, so let's increase the number of proposals (and you will see I commented out approximate_splits = True if set to False it will try every point):

from ThymeBoost import ThymeBoost as tb
boosted_model = tb.ThymeBoost(trend_estimator = 'linear',
split_cost = 'mse',
global_cost = 'maicc',
fit_type = 'local',
seasonal_period = 0,
#approximate_splits = True,
n_split_proposals = 25,
verbose = 1)
output = boosted_model.fit(time_series)
boosted_model.plot_results()


Looks a lot better but it is slow to react to the third changepoint at x = 200.

The only real change you would need from what is done here is that ThymeBoost won't cycle through model configurations at each segment, it will just refit for the ar coefficients or linear coefficients or whatever base trend estimator you are using. So in your loop of fitting each split you would just need to add another loop to try each model configuration. Just be careful about how different configurations effect whatever global cost you choose.

Finally, if you hadn't mentioned that you simulated trend-stationary time series with AR(1) effects my first intuition would have been that this is a non-stationary series. So I probably would have modeled the first differences $$\Delta Y$$ rather than original levels $$Y$$. Then you don't need to include the trend as a regressor. The change in slope for $$Y$$ will correspond to a change in intercept for $$\Delta Y$$.