pycointbreak 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 Dr. Merwan Roudane
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,10 @@
1
+ include README.md
2
+ include LICENSE
3
+ include pyproject.toml
4
+ recursive-include pycointbreak *.py
5
+ recursive-exclude tests *
6
+ recursive-exclude examples *
7
+ global-exclude __pycache__
8
+ global-exclude *.pyc
9
+ global-exclude *.pyo
10
+ global-exclude .DS_Store
@@ -0,0 +1,316 @@
1
+ Metadata-Version: 2.4
2
+ Name: pycointbreak
3
+ Version: 0.1.0
4
+ Summary: Tests for breaks in fractional cointegration (Hassler & Breitung 2006; Rodrigues, Sibbertsen & Voges 2019).
5
+ Home-page: https://github.com/merwanroudane/pycointbreak
6
+ Author: Dr. Merwan Roudane
7
+ Author-email: "Dr. Merwan Roudane" <merwanroudane920@gmail.com>
8
+ Maintainer-email: "Dr. Merwan Roudane" <merwanroudane920@gmail.com>
9
+ License: MIT
10
+ Project-URL: Homepage, https://github.com/merwanroudane/pycointbreak
11
+ Project-URL: Repository, https://github.com/merwanroudane/pycointbreak
12
+ Project-URL: Bug Tracker, https://github.com/merwanroudane/pycointbreak/issues
13
+ Keywords: econometrics,fractional cointegration,structural breaks,time series,Hassler-Breitung,Rodrigues-Sibbertsen-Voges,long memory,LM test
14
+ Classifier: Development Status :: 4 - Beta
15
+ Classifier: Intended Audience :: Science/Research
16
+ Classifier: License :: OSI Approved :: MIT License
17
+ Classifier: Operating System :: OS Independent
18
+ Classifier: Programming Language :: Python :: 3
19
+ Classifier: Programming Language :: Python :: 3.10
20
+ Classifier: Programming Language :: Python :: 3.11
21
+ Classifier: Programming Language :: Python :: 3.12
22
+ Classifier: Topic :: Scientific/Engineering :: Mathematics
23
+ Classifier: Topic :: Scientific/Engineering :: Information Analysis
24
+ Requires-Python: >=3.10
25
+ Description-Content-Type: text/markdown
26
+ License-File: LICENSE
27
+ Requires-Dist: numpy>=1.22
28
+ Requires-Dist: pandas>=1.4
29
+ Requires-Dist: scipy>=1.8
30
+ Requires-Dist: statsmodels>=0.13
31
+ Requires-Dist: matplotlib>=3.5
32
+ Requires-Dist: seaborn>=0.12
33
+ Provides-Extra: examples
34
+ Requires-Dist: yfinance>=0.2; extra == "examples"
35
+ Provides-Extra: dev
36
+ Requires-Dist: pytest>=7.0; extra == "dev"
37
+ Requires-Dist: pytest-cov>=4.0; extra == "dev"
38
+ Requires-Dist: build; extra == "dev"
39
+ Requires-Dist: twine; extra == "dev"
40
+ Dynamic: author
41
+ Dynamic: home-page
42
+ Dynamic: license-file
43
+ Dynamic: requires-python
44
+
45
+ # pycointbreak
46
+
47
+ > **Tests for breaks in fractional cointegration** — a Python
48
+ > implementation of the Hassler & Breitung (2006) residual-based LM
49
+ > test and the Rodrigues, Sibbertsen & Voges (2019) supremum tests
50
+ > for breaks in the cointegrating relationship.
51
+
52
+ [![python](https://img.shields.io/badge/python-3.10%2B-blue)]()
53
+ [![status](https://img.shields.io/badge/status-research%20release-orange)]()
54
+ [![license](https://img.shields.io/badge/license-MIT-green)]()
55
+
56
+ ---
57
+
58
+ ## Author
59
+
60
+ **Dr. Merwan Roudane**
61
+ Email: [merwanroudane920@gmail.com](mailto:merwanroudane920@gmail.com)
62
+ GitHub: <https://github.com/merwanroudane/pycointbreak>
63
+
64
+ If you use this library in academic work, please cite both the
65
+ underlying papers and this package — see `pycointbreak.cite()` for
66
+ ready-made BibTeX entries.
67
+
68
+ ---
69
+
70
+ ## What does it do?
71
+
72
+ Given a scalar series `y` and a (possibly multivariate) series `x`,
73
+ each integrated of order `d`, `pycointbreak` lets you test whether
74
+
75
+ ```
76
+ y_t = β' x_t + z_t, z_t ~ I(d − b), b ≥ 0,
77
+ ```
78
+
79
+ is
80
+
81
+ 1. **Cointegrated at all** (`b > 0`) — using the Hassler & Breitung
82
+ (2006) LM-type test.
83
+ 2. **Cointegrated only on part of the sample** (segmented fractional
84
+ cointegration) — using the Rodrigues, Sibbertsen & Voges (2019)
85
+ sup-tests over split, forward incremental, backward incremental,
86
+ and rolling sub-samples.
87
+
88
+ When the answer is "yes, breaks", the library can also estimate the
89
+ **break date** via the consistent estimator of RSV (2019, eq. 19).
90
+
91
+ ---
92
+
93
+ ## Installation
94
+
95
+ ```bash
96
+ git clone https://github.com/merwanroudane/pycointbreak.git
97
+ cd pycointbreak
98
+ pip install -e .
99
+ ```
100
+
101
+ Dependencies: `numpy`, `pandas`, `scipy`, `statsmodels`,
102
+ `matplotlib`, `seaborn`. Optional: `yfinance` (for the real-data
103
+ example).
104
+
105
+ ---
106
+
107
+ ## Quick start
108
+
109
+ ```python
110
+ import pycointbreak as pcb
111
+
112
+ # 1. Generate (or load) two I(d) series.
113
+ y, x = pcb.simulate_segmented_cointegration(
114
+ T=500, d=1.0, b=0.4, break_frac=0.5,
115
+ regime="coint_then_spurious", seed=2024,
116
+ )
117
+
118
+ # 2. Full-sample Hassler-Breitung test.
119
+ hb = pcb.hassler_breitung_test(y, x, d=1.0, p=0)
120
+ print(hb.summary())
121
+
122
+ # 3. RSV (2019) sup-test battery.
123
+ battery = pcb.rsv_battery(y, x, d=1.0, lam0=0.5, n_grid=120)
124
+ for k, r in battery.items():
125
+ print(r.summary())
126
+
127
+ # 4. Estimate the break date.
128
+ bp = pcb.estimate_break_point(y, x, d=1.0, direction="auto")
129
+ print(bp.summary())
130
+
131
+ # 5. Paper-style summary table.
132
+ df = pcb.battery_to_dataframe(battery, hb=hb, label="my pair")
133
+ print(pcb.render_table(df, fmt="text",
134
+ title="Tests for segmented cointegration"))
135
+
136
+ # 6. Plots.
137
+ import matplotlib.pyplot as plt
138
+ pcb.plot_series_with_breaks({"y": y, "x": x}, {"break": bp.obs})
139
+ pcb.plot_rsv_battery(battery)
140
+ pcb.plot_breakpoint_objective(bp)
141
+ plt.show()
142
+ ```
143
+
144
+ ---
145
+
146
+ ## Mathematical compatibility with the papers
147
+
148
+ The implementation follows the papers' notation closely. The key
149
+ ingredients are exposed as building blocks:
150
+
151
+ | Symbol | Function |
152
+ | ------------------------------------------------------------------ | ----------------------------------------- |
153
+ | `Δ⁺ᵈ x_t` — truncated (Type II) fractional difference | `pcb.fdiff(x, d)` |
154
+ | `π_j(d)` — coefficients of `(1−L)^d` | `pcb.frac_coefs(d, n)` |
155
+ | `x*_{t−1} = Σ_{j=1}^{t−1} x_{t−j}/j` — harmonic-weighted sum (HB eq. 3) | `pcb.harmonic_running_sum(x)` |
156
+ | `(1−L)^{−d} x_t` — fractional integration | `pcb.frac_integrate(x, d)` |
157
+ | Geweke & Porter-Hudak `d̂` | `pcb.gph(x)` |
158
+ | HB test (eqs. 12–14, iid case) | `pcb.hassler_breitung_test(..., p=0)` |
159
+ | HB test with AR(p) augmentation (eqs. 17–18) | `pcb.hassler_breitung_test(..., p=p)` |
160
+ | RSV sub-sample t-stat (eq. 5) | internal `_hb_subsample_tstat` |
161
+ | Sup-statistics 𝒯_S, 𝒯_S*, 𝒯_If, 𝒯_Ib, 𝒯_R (eqs. 10–15) | `pcb.rsv_sup_test(..., kind=...)` |
162
+ | RSV break-point estimator (eq. 19) | `pcb.estimate_break_point(...)` |
163
+ | Critical values from Table 1 of RSV2019 | `pcb.rsv_critical_value(test, T, alpha)` |
164
+
165
+ ### On the eq.-(5) `√n` factor
166
+
167
+ Equation (5) of RSV (2019) literally reads
168
+
169
+ ```
170
+ t(ê(λ₁,λ₂)) = √(⌊λ₂T⌋ − ⌊λ₁T⌋) · Σ ê_t · ê*_{t−1}
171
+ / [√Σ ê*²_{t−1} · √((T−1)⁻¹ · Σ ê²_t)]
172
+ ```
173
+
174
+ With the full-sample variance `1/(T−1)` and the extra `√n` factor,
175
+ under H0 this statistic is `O_p(√T)` rather than asymptotically
176
+ N(0,1), which would contradict Theorem 2 (`sup χ²₁` limit) and the
177
+ critical values of Table 1 (5%-cv ≈ 4–6 for `T = 500`). We
178
+ therefore interpret the formula as the standard HB statistic
179
+ (eq. 14 of HB2006) applied to the **sub-sample**, with sub-sample
180
+ variance `1/(n−1)` — the same convention used by Davidson &
181
+ Monticini (2010). This yields `t → N(0, 1)` per Proposition 3 of
182
+ HB2006 and `T_K → sup χ²₁` consistent with Theorem 2 of RSV2019.
183
+
184
+ ### On the critical values
185
+
186
+ The tabulated critical values in `pcb.RSV_TABLE1` reproduce Table 1
187
+ of RSV (2019) for `T = 250` and `T = 500` with `λ₀ = 0.5`. They are
188
+ the result of a Monte Carlo simulation in the paper averaged over
189
+ several values of `d`. For configurations far from
190
+ `(T ∈ {250, 500}, λ₀ = 0.5, d ≈ 1)`, use the bootstrap helper
191
+
192
+ ```python
193
+ cv = pcb.bootstrap_rsv_cv(
194
+ T=1000, d=1.0, kind="T_If", n_sim=2000,
195
+ )
196
+ print(cv) # {0.10: ..., 0.05: ..., 0.01: ...}
197
+ ```
198
+
199
+ which returns critical values calibrated to your exact sample size,
200
+ grid, and `d`.
201
+
202
+ ---
203
+
204
+ ## Modules
205
+
206
+ | Module | Contents |
207
+ | ------------------------------- | ------------------------------------------------------ |
208
+ | `pycointbreak.fracdiff` | Truncated (Type II) fractional difference operators |
209
+ | `pycointbreak.gph` | GPH log-periodogram estimator of `d` |
210
+ | `pycointbreak.hassler_breitung` | HB (2006) LM-type test |
211
+ | `pycointbreak.rsv_tests` | RSV (2019) sup-tests for breaks |
212
+ | `pycointbreak.breakpoint` | Break-fraction estimator (RSV eq. 19) |
213
+ | `pycointbreak.critical_values` | Tabulated and bootstrap critical values |
214
+ | `pycointbreak.simulate` | DGPs from HB2006 §5 and RSV2019 §4 (Experiments 1–3) |
215
+ | `pycointbreak.reporting` | Paper-style tables (text/markdown/LaTeX/HTML) |
216
+ | `pycointbreak.plots` | Publication-quality figures (matplotlib + seaborn) |
217
+
218
+ ---
219
+
220
+ ## API at a glance
221
+
222
+ ### Tests
223
+
224
+ ```python
225
+ hassler_breitung_test(y1, y2, d=1.0, p=0, include_const=True)
226
+ → HBResult(t_stat, p_value, reject, ...)
227
+
228
+ rsv_sup_test(y1, y2, d=1.0, kind="T_If", lam0=0.5, n_grid=200, ...)
229
+ → RSVResult(statistic, argmax, t2_path, ...)
230
+
231
+ rsv_battery(y1, y2, d=1.0, tests=("T_S_star", "T_If", "T_Ib", "T_R"), ...)
232
+ → dict[str, RSVResult]
233
+
234
+ estimate_break_point(y1, y2, d=1.0, delta=0.05, direction="auto", ...)
235
+ → BreakPointResult(tau_hat, obs, date, objective, ...)
236
+ ```
237
+
238
+ ### Reporting
239
+
240
+ ```python
241
+ df = battery_to_dataframe(battery, hb=hb, label="series")
242
+ print(render_table(df, fmt="text")) # ASCII
243
+ print(render_table(df, fmt="markdown")) # for GitHub / Jupyter
244
+ print(render_table(df, fmt="latex")) # for papers
245
+ print(render_table(df, fmt="html")) # for web
246
+ ```
247
+
248
+ ### Plots
249
+
250
+ ```python
251
+ plot_series_with_breaks(series_dict, breaks_dict)
252
+ plot_rsv_profile(rsv_result) # one sup-test
253
+ plot_rsv_battery(battery_dict) # 2×2 panel of all four
254
+ plot_breakpoint_objective(bp_result)
255
+ plot_residual_diagnostics(residuals)
256
+ plot_split_heatmap(y, x, d=1.0, ...) # 2-D (λ₁, λ₂) heatmap
257
+ ```
258
+
259
+ ### Simulation
260
+
261
+ ```python
262
+ simulate_rsv_dgp(T=500, d=1.0, b=0.0)
263
+ # Experiment 1 — constant cointegration over the whole sample
264
+
265
+ simulate_segmented_cointegration(
266
+ T=500, d=1.0, b=0.4, break_frac=0.5,
267
+ regime="coint_then_spurious",
268
+ )
269
+ # Experiments 2 & 3 — one break in the cointegrating relationship
270
+ ```
271
+
272
+ ---
273
+
274
+ ## Examples
275
+
276
+ The `examples/` folder contains three runnable scripts:
277
+
278
+ * `example_basic.py` — minimal end-to-end demo on simulated data.
279
+ * `example_real_data.py` — applies the full pipeline to real stock
280
+ prices (Coca-Cola / Pepsi by default via `yfinance`; falls back to
281
+ simulated data when the network is unavailable).
282
+ * `example_simulation_study.py` — small Monte Carlo reproducing a
283
+ slice of Table 2 of RSV (2019).
284
+
285
+ ---
286
+
287
+ ## References
288
+
289
+ * Hassler, U. and Breitung, J. (2006). *A Residual-Based LM Type
290
+ Test Against Fractional Cointegration*. **Econometric Theory**,
291
+ 22(6), 1091–1111.
292
+ * Rodrigues, P. M. M., Sibbertsen, P. and Voges, M. (2019).
293
+ *Testing for breaks in the cointegrating relationship: On the
294
+ stability of government bond markets' equilibrium*. Discussion
295
+ Paper 656.
296
+ * Davidson, J. and Monticini, A. (2010). *Tests for cointegration
297
+ with structural breaks based on subsamples*.
298
+ **Computational Statistics & Data Analysis**, 54(11), 2498–2511.
299
+ * Robinson, P. M. (1991). *Testing for strong serial correlation and
300
+ dynamic conditional heteroskedasticity in multiple regression*.
301
+ **Journal of Econometrics**, 47, 67–84.
302
+ * Breitung, J. and Hassler, U. (2002). *Inference on the cointegration
303
+ rank in fractionally integrated processes*. **Journal of
304
+ Econometrics**, 110, 167–185.
305
+ * Demetrescu, M., Kuzin, V. and Hassler, U. (2008). *Long memory
306
+ testing in the time domain*. **Econometric Theory**, 24(1),
307
+ 176–215.
308
+ * Geweke, J. and Porter-Hudak, S. (1983). *The Estimation and
309
+ Application of Long Memory Time Series Models*. **Journal of Time
310
+ Series Analysis**, 4, 221–238.
311
+
312
+ ---
313
+
314
+ ## License
315
+
316
+ MIT
@@ -0,0 +1,272 @@
1
+ # pycointbreak
2
+
3
+ > **Tests for breaks in fractional cointegration** — a Python
4
+ > implementation of the Hassler & Breitung (2006) residual-based LM
5
+ > test and the Rodrigues, Sibbertsen & Voges (2019) supremum tests
6
+ > for breaks in the cointegrating relationship.
7
+
8
+ [![python](https://img.shields.io/badge/python-3.10%2B-blue)]()
9
+ [![status](https://img.shields.io/badge/status-research%20release-orange)]()
10
+ [![license](https://img.shields.io/badge/license-MIT-green)]()
11
+
12
+ ---
13
+
14
+ ## Author
15
+
16
+ **Dr. Merwan Roudane**
17
+ Email: [merwanroudane920@gmail.com](mailto:merwanroudane920@gmail.com)
18
+ GitHub: <https://github.com/merwanroudane/pycointbreak>
19
+
20
+ If you use this library in academic work, please cite both the
21
+ underlying papers and this package — see `pycointbreak.cite()` for
22
+ ready-made BibTeX entries.
23
+
24
+ ---
25
+
26
+ ## What does it do?
27
+
28
+ Given a scalar series `y` and a (possibly multivariate) series `x`,
29
+ each integrated of order `d`, `pycointbreak` lets you test whether
30
+
31
+ ```
32
+ y_t = β' x_t + z_t, z_t ~ I(d − b), b ≥ 0,
33
+ ```
34
+
35
+ is
36
+
37
+ 1. **Cointegrated at all** (`b > 0`) — using the Hassler & Breitung
38
+ (2006) LM-type test.
39
+ 2. **Cointegrated only on part of the sample** (segmented fractional
40
+ cointegration) — using the Rodrigues, Sibbertsen & Voges (2019)
41
+ sup-tests over split, forward incremental, backward incremental,
42
+ and rolling sub-samples.
43
+
44
+ When the answer is "yes, breaks", the library can also estimate the
45
+ **break date** via the consistent estimator of RSV (2019, eq. 19).
46
+
47
+ ---
48
+
49
+ ## Installation
50
+
51
+ ```bash
52
+ git clone https://github.com/merwanroudane/pycointbreak.git
53
+ cd pycointbreak
54
+ pip install -e .
55
+ ```
56
+
57
+ Dependencies: `numpy`, `pandas`, `scipy`, `statsmodels`,
58
+ `matplotlib`, `seaborn`. Optional: `yfinance` (for the real-data
59
+ example).
60
+
61
+ ---
62
+
63
+ ## Quick start
64
+
65
+ ```python
66
+ import pycointbreak as pcb
67
+
68
+ # 1. Generate (or load) two I(d) series.
69
+ y, x = pcb.simulate_segmented_cointegration(
70
+ T=500, d=1.0, b=0.4, break_frac=0.5,
71
+ regime="coint_then_spurious", seed=2024,
72
+ )
73
+
74
+ # 2. Full-sample Hassler-Breitung test.
75
+ hb = pcb.hassler_breitung_test(y, x, d=1.0, p=0)
76
+ print(hb.summary())
77
+
78
+ # 3. RSV (2019) sup-test battery.
79
+ battery = pcb.rsv_battery(y, x, d=1.0, lam0=0.5, n_grid=120)
80
+ for k, r in battery.items():
81
+ print(r.summary())
82
+
83
+ # 4. Estimate the break date.
84
+ bp = pcb.estimate_break_point(y, x, d=1.0, direction="auto")
85
+ print(bp.summary())
86
+
87
+ # 5. Paper-style summary table.
88
+ df = pcb.battery_to_dataframe(battery, hb=hb, label="my pair")
89
+ print(pcb.render_table(df, fmt="text",
90
+ title="Tests for segmented cointegration"))
91
+
92
+ # 6. Plots.
93
+ import matplotlib.pyplot as plt
94
+ pcb.plot_series_with_breaks({"y": y, "x": x}, {"break": bp.obs})
95
+ pcb.plot_rsv_battery(battery)
96
+ pcb.plot_breakpoint_objective(bp)
97
+ plt.show()
98
+ ```
99
+
100
+ ---
101
+
102
+ ## Mathematical compatibility with the papers
103
+
104
+ The implementation follows the papers' notation closely. The key
105
+ ingredients are exposed as building blocks:
106
+
107
+ | Symbol | Function |
108
+ | ------------------------------------------------------------------ | ----------------------------------------- |
109
+ | `Δ⁺ᵈ x_t` — truncated (Type II) fractional difference | `pcb.fdiff(x, d)` |
110
+ | `π_j(d)` — coefficients of `(1−L)^d` | `pcb.frac_coefs(d, n)` |
111
+ | `x*_{t−1} = Σ_{j=1}^{t−1} x_{t−j}/j` — harmonic-weighted sum (HB eq. 3) | `pcb.harmonic_running_sum(x)` |
112
+ | `(1−L)^{−d} x_t` — fractional integration | `pcb.frac_integrate(x, d)` |
113
+ | Geweke & Porter-Hudak `d̂` | `pcb.gph(x)` |
114
+ | HB test (eqs. 12–14, iid case) | `pcb.hassler_breitung_test(..., p=0)` |
115
+ | HB test with AR(p) augmentation (eqs. 17–18) | `pcb.hassler_breitung_test(..., p=p)` |
116
+ | RSV sub-sample t-stat (eq. 5) | internal `_hb_subsample_tstat` |
117
+ | Sup-statistics 𝒯_S, 𝒯_S*, 𝒯_If, 𝒯_Ib, 𝒯_R (eqs. 10–15) | `pcb.rsv_sup_test(..., kind=...)` |
118
+ | RSV break-point estimator (eq. 19) | `pcb.estimate_break_point(...)` |
119
+ | Critical values from Table 1 of RSV2019 | `pcb.rsv_critical_value(test, T, alpha)` |
120
+
121
+ ### On the eq.-(5) `√n` factor
122
+
123
+ Equation (5) of RSV (2019) literally reads
124
+
125
+ ```
126
+ t(ê(λ₁,λ₂)) = √(⌊λ₂T⌋ − ⌊λ₁T⌋) · Σ ê_t · ê*_{t−1}
127
+ / [√Σ ê*²_{t−1} · √((T−1)⁻¹ · Σ ê²_t)]
128
+ ```
129
+
130
+ With the full-sample variance `1/(T−1)` and the extra `√n` factor,
131
+ under H0 this statistic is `O_p(√T)` rather than asymptotically
132
+ N(0,1), which would contradict Theorem 2 (`sup χ²₁` limit) and the
133
+ critical values of Table 1 (5%-cv ≈ 4–6 for `T = 500`). We
134
+ therefore interpret the formula as the standard HB statistic
135
+ (eq. 14 of HB2006) applied to the **sub-sample**, with sub-sample
136
+ variance `1/(n−1)` — the same convention used by Davidson &
137
+ Monticini (2010). This yields `t → N(0, 1)` per Proposition 3 of
138
+ HB2006 and `T_K → sup χ²₁` consistent with Theorem 2 of RSV2019.
139
+
140
+ ### On the critical values
141
+
142
+ The tabulated critical values in `pcb.RSV_TABLE1` reproduce Table 1
143
+ of RSV (2019) for `T = 250` and `T = 500` with `λ₀ = 0.5`. They are
144
+ the result of a Monte Carlo simulation in the paper averaged over
145
+ several values of `d`. For configurations far from
146
+ `(T ∈ {250, 500}, λ₀ = 0.5, d ≈ 1)`, use the bootstrap helper
147
+
148
+ ```python
149
+ cv = pcb.bootstrap_rsv_cv(
150
+ T=1000, d=1.0, kind="T_If", n_sim=2000,
151
+ )
152
+ print(cv) # {0.10: ..., 0.05: ..., 0.01: ...}
153
+ ```
154
+
155
+ which returns critical values calibrated to your exact sample size,
156
+ grid, and `d`.
157
+
158
+ ---
159
+
160
+ ## Modules
161
+
162
+ | Module | Contents |
163
+ | ------------------------------- | ------------------------------------------------------ |
164
+ | `pycointbreak.fracdiff` | Truncated (Type II) fractional difference operators |
165
+ | `pycointbreak.gph` | GPH log-periodogram estimator of `d` |
166
+ | `pycointbreak.hassler_breitung` | HB (2006) LM-type test |
167
+ | `pycointbreak.rsv_tests` | RSV (2019) sup-tests for breaks |
168
+ | `pycointbreak.breakpoint` | Break-fraction estimator (RSV eq. 19) |
169
+ | `pycointbreak.critical_values` | Tabulated and bootstrap critical values |
170
+ | `pycointbreak.simulate` | DGPs from HB2006 §5 and RSV2019 §4 (Experiments 1–3) |
171
+ | `pycointbreak.reporting` | Paper-style tables (text/markdown/LaTeX/HTML) |
172
+ | `pycointbreak.plots` | Publication-quality figures (matplotlib + seaborn) |
173
+
174
+ ---
175
+
176
+ ## API at a glance
177
+
178
+ ### Tests
179
+
180
+ ```python
181
+ hassler_breitung_test(y1, y2, d=1.0, p=0, include_const=True)
182
+ → HBResult(t_stat, p_value, reject, ...)
183
+
184
+ rsv_sup_test(y1, y2, d=1.0, kind="T_If", lam0=0.5, n_grid=200, ...)
185
+ → RSVResult(statistic, argmax, t2_path, ...)
186
+
187
+ rsv_battery(y1, y2, d=1.0, tests=("T_S_star", "T_If", "T_Ib", "T_R"), ...)
188
+ → dict[str, RSVResult]
189
+
190
+ estimate_break_point(y1, y2, d=1.0, delta=0.05, direction="auto", ...)
191
+ → BreakPointResult(tau_hat, obs, date, objective, ...)
192
+ ```
193
+
194
+ ### Reporting
195
+
196
+ ```python
197
+ df = battery_to_dataframe(battery, hb=hb, label="series")
198
+ print(render_table(df, fmt="text")) # ASCII
199
+ print(render_table(df, fmt="markdown")) # for GitHub / Jupyter
200
+ print(render_table(df, fmt="latex")) # for papers
201
+ print(render_table(df, fmt="html")) # for web
202
+ ```
203
+
204
+ ### Plots
205
+
206
+ ```python
207
+ plot_series_with_breaks(series_dict, breaks_dict)
208
+ plot_rsv_profile(rsv_result) # one sup-test
209
+ plot_rsv_battery(battery_dict) # 2×2 panel of all four
210
+ plot_breakpoint_objective(bp_result)
211
+ plot_residual_diagnostics(residuals)
212
+ plot_split_heatmap(y, x, d=1.0, ...) # 2-D (λ₁, λ₂) heatmap
213
+ ```
214
+
215
+ ### Simulation
216
+
217
+ ```python
218
+ simulate_rsv_dgp(T=500, d=1.0, b=0.0)
219
+ # Experiment 1 — constant cointegration over the whole sample
220
+
221
+ simulate_segmented_cointegration(
222
+ T=500, d=1.0, b=0.4, break_frac=0.5,
223
+ regime="coint_then_spurious",
224
+ )
225
+ # Experiments 2 & 3 — one break in the cointegrating relationship
226
+ ```
227
+
228
+ ---
229
+
230
+ ## Examples
231
+
232
+ The `examples/` folder contains three runnable scripts:
233
+
234
+ * `example_basic.py` — minimal end-to-end demo on simulated data.
235
+ * `example_real_data.py` — applies the full pipeline to real stock
236
+ prices (Coca-Cola / Pepsi by default via `yfinance`; falls back to
237
+ simulated data when the network is unavailable).
238
+ * `example_simulation_study.py` — small Monte Carlo reproducing a
239
+ slice of Table 2 of RSV (2019).
240
+
241
+ ---
242
+
243
+ ## References
244
+
245
+ * Hassler, U. and Breitung, J. (2006). *A Residual-Based LM Type
246
+ Test Against Fractional Cointegration*. **Econometric Theory**,
247
+ 22(6), 1091–1111.
248
+ * Rodrigues, P. M. M., Sibbertsen, P. and Voges, M. (2019).
249
+ *Testing for breaks in the cointegrating relationship: On the
250
+ stability of government bond markets' equilibrium*. Discussion
251
+ Paper 656.
252
+ * Davidson, J. and Monticini, A. (2010). *Tests for cointegration
253
+ with structural breaks based on subsamples*.
254
+ **Computational Statistics & Data Analysis**, 54(11), 2498–2511.
255
+ * Robinson, P. M. (1991). *Testing for strong serial correlation and
256
+ dynamic conditional heteroskedasticity in multiple regression*.
257
+ **Journal of Econometrics**, 47, 67–84.
258
+ * Breitung, J. and Hassler, U. (2002). *Inference on the cointegration
259
+ rank in fractionally integrated processes*. **Journal of
260
+ Econometrics**, 110, 167–185.
261
+ * Demetrescu, M., Kuzin, V. and Hassler, U. (2008). *Long memory
262
+ testing in the time domain*. **Econometric Theory**, 24(1),
263
+ 176–215.
264
+ * Geweke, J. and Porter-Hudak, S. (1983). *The Estimation and
265
+ Application of Long Memory Time Series Models*. **Journal of Time
266
+ Series Analysis**, 4, 221–238.
267
+
268
+ ---
269
+
270
+ ## License
271
+
272
+ MIT