import numpy as np, pandas as pd, sys, os sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..")) from econometrics.structural_change import its_fit, placebo_breaks, bai_perron, pelt, bocpd rng = np.random.default_rng(1) dates = pd.date_range("2018-01-01", "2026-06-01", freq="MS") t = np.arange(len(dates)); ev = np.searchsorted(dates, pd.Timestamp("2022-12-01")) y = np.exp(5 + 0.01 * t + 0.4 * (t >= ev) + 0.02 * np.maximum(t - ev, 0) + 0.05 * rng.standard_normal(len(t))) def test_its_recovers_break(): o, _ = its_fit(y, dates, "2022-12-01") assert abs(o["level_change"] - 0.4) < 0.1 and abs(o["slope_change"] - 0.02) < 0.01 and o["level_p"] < 0.01 def test_placebo_rank_true_event_is_extreme(): o, df = placebo_breaks(y, dates, "2022-12-01") assert o["level_t_placebo_p"] <= 0.1 def test_bai_perron_finds_break_near_event(): r = bai_perron(np.log(y), dates, max_breaks=2) assert r["m_bic"] >= 1 and min(abs(b - ev) for b in r["breaks_bic"]) <= 3 def test_pelt_and_bocpd_flag_event(): cps = pelt(np.log(y)); assert any(abs(c - ev) <= 3 for c in cps) _, cp, map_rl = bocpd(np.log(y)) assert map_rl[ev - 1] > 20 and map_rl[ev + 3] <= 6 and cp[ev:ev + 4].max() > 0.3