openquant.structural_breaks
Compiled from Rust (crates/pyopenquant). Signatures and types are from the shipped .pyi stubs; descriptions are the functions’ own docstrings, as help() shows them. All Python modules.
Functions
get_chow_type_stat
get_chow_type_stat(log_prices: Sequence[float], min_length: int) -> list[float]Chow-type Dickey-Fuller statistics for a single break at each candidate date.
AFML §17.3.1. For each candidate break index tau from min_length to len(log_prices) - min_length - 1, regresses the log-price change dy_t on the lagged level y_{t-1} with the regressor zeroed before tau (no intercept), and records the t-statistic beta / se(beta). Large values suggest a switch from a random walk to an explosive process at tau. A singular regression gives NaN.
Parameters
log_prices: list[float]Log prices, oldest first.
min_length: intMinimum number of observations kept on each side of a candidate break.
Returns
- list[float]
One statistic per candidate break,
len(log_prices) - 2 * min_lengthvalues; empty if the series is shorter than2 * min_length.
Raises
- ValueError
If the regression has no rows (
min_length == 0with a single price).
get_chu_stinchcombe_white_statistics
get_chu_stinchcombe_white_statistics(
log_prices: Sequence[float],
test_type: str,
) -> tuple[list[float], list[float]]Chu-Stinchcombe-White CUSUM test on levels, with its critical values.
AFML §17.3.2. For each bar t from index 2 on, sigma_t^2 is the mean of the squared one-bar changes up to t, and the statistic is S_t = max_{n < t} (y_t - y_n) / (sigma_t * sqrt(t - n)) (absolute difference for "two_sided"). The critical value is sqrt(4.6 + ln(t - n)) at the maximising n.
Parameters
log_prices: list[float]Log prices, oldest first; at least three.
test_type: str"one_sided"(tests for an upward departure) or"two_sided".
Returns
- tuple[list[float], list[float]]
(critical_value, stat), each withlen(log_prices) - 2values, for bars 2 onward. Note the critical values come first.
Raises
- ValueError
If there are fewer than three prices or
test_typeis not"one_sided"or"two_sided".
get_sadf
get_sadf(
series: Sequence[float],
model: str,
add_const: bool,
min_length: int,
lags: int,
) -> list[float]Supremum ADF and sub/super-martingale explosiveness statistics.
AFML §17.4.2-17.4.3, Snippets 17.1-17.4. Builds one regression row per bar from bar lags + 1 on, then returns, for each row from position min_length on, the supremum over every backward-expanding window of at least min_length rows ending at that row of the statistic below (t is the 0-based row position over the whole sample):
"linear":dyony_{t-1},lagslaggeddy, a constant (ifadd_const) andt; the t-statistic ofy_{t-1}."quadratic": as"linear"plust^2(Snippet 17.2ctt)."sm_poly_1":yon 1,t,t^2;|beta(t^2)| / se."sm_poly_2":log yon 1,t,t^2;|beta(t^2)| / se."sm_exp":log yon 1,t;|beta(t)| / se."sm_power":log yon 1,log(t + 1);|beta| / se.
The sm_* models ignore add_const and lags beyond setting the first row, take the absolute value because a trend of either sign is of interest, and need a positive series when they take logs. Windows whose regression is singular are skipped; a row with no usable window is -inf. Every window of every row is a separate regression, so the cost grows quickly with the series length.
Parameters
series: list[float]Log prices (or prices, for
sm_poly_1), oldest first.model: strOne of
"linear","quadratic","sm_poly_1","sm_poly_2","sm_exp","sm_power".add_const: boolWhether the ADF models include a constant.
min_length: intMinimum window length in regression rows; must be >= 1.
lags: intNumber of lagged differences in the ADF regression (lags
1..=lags).
Returns
- list[float]
One statistic per regression row from position
min_lengthon, i.e.len(series) - lags - 1 - min_lengthvalues; empty if there are no more thanmin_lengthrows.
Raises
- ValueError
If
modelis unknown, the series has fewer than two values or no more thanlags + 1, ormin_lengthis 0 (an empty window).