xtbreak API Reference

Complete reference for the public Python API of xtbreak.

The three entry points (test, estimate, select) accept time-series or panel data with covariance options ssr, hc, hac, np, and wpn. Panel-specific options include factor controls (csa=, csanobreak=, kfactors=, nbkfactors=, csd=True). The select() function provides oracle-backed sequential break selection; it requires caller-supplied critical values rather than shipping built-in tables.

Runtime Dependencies

The package depends on Python ≥ 3.10 and NumPy at runtime. Optional:

  • scipy — Chow test p-values

  • pandas — DataFrame input/output

  • matplotlib — plotting functions

Stata is used by the test suite as a numerical parity oracle but is not a runtime dependency.

Source Authority

The API follows this authority order:

  1. Methodology paper: paper/arXiv-2211.06707v2/Multiple_Breaks_Main.tex

  2. Stata software paper: paper/arXiv-2110.14550v3/xtbreak_article.tex

  3. Stata package and fixtures: xtbreak-2.2/

  4. Tested Python public contract

Public API and Deprecation Policy

The public API is the xtbreak namespace: __all__, __version__, test, estimate, select, result classes, and exception classes. Underscored modules (_api, _result, _panel, _covariance, _benchmark, _numerics) are internal.

No deprecated aliases exist. Unsupported requests fail with XTBreakValidationError. Future deprecations must identify the deprecated symbol, its replacement, the first warning release, and the earliest removal release.

Stata Migration Boundaries

The Python API is a documented subset of Stata xtbreak, not a command-line clone. Known gaps:

  • xtbreak.test(...) does not expose Stata’s full hypothesis(), level, sequential, cvalue, or built-in critical-value table surface. Public H2 and WDmax diagnostics are available through xtbreak.select(...) only when callers provide the required critical-value inputs.

  • Stata deterministic and panel-model options such as breakconstant, noconstant, and breakfixedeffects are not public Python keyword arguments. Users who need these designs must construct the corresponding columns explicitly in x or wait for a documented public API. Note: trend and breaktrend are now supported as public keyword arguments on test(), estimate(), and select() (see New Parameters below).

  • Stata region() and date-list breakpoint parsing with index or fmt() are not public Python surfaces. Python breakpoints= values are sample-axis break indexes; callers must map calendar labels outside the package.

  • Python post-estimation exposes JSON-safe payloads, single-break SSR path data, regime_statistics, chow_tests, to_dataframe(), and break_date_labels() where available. It does not expose a public multi-break segment-SSR matrix equivalent to Stata e(SSRvmat) unless return_segment_ssr=True is passed to estimate()/select().

  • Public vce accepts only ssr, hc, hac, np, and wpn. Stata HAC routing aliases such as kw and nw are not public Python option values; use vce="hac" for HAC covariance requests.

Public Entry Points

The public API consists of the xtbreak namespace: __all__, __version__, test, estimate, select, result classes, and exception classes. Underscored modules are internal. Unsupported requests raise XTBreakValidationError. Any future deprecation must document the deprecated symbol, the replacement, the first warning release, and the earliest removal release.

xtbreak.test(...)

Tests for structural breaks in a time-series or panel design matrix.

Current behavior:

  • requires raw y and x arrays;

  • accepts matching entity= and time= arrays for the public panel slice;

  • accepts breakpoints= for known-breakpoint vce="ssr" Chow/F tests and known-breakpoint vce="hc"/vce="hac" Wald tests, plus explicit-panel vce="np"/vce="wpn" Wald tests;

  • accepts the vce option;

  • allows ssr, hac, hc, np, and wpn;

  • raises XTBreakValidationError for unknown vce values;

  • returns XTBreakResult for vce="ssr" and robust XTBreakResult snapshots for time-series and explicit panel covariance paths;

  • records metadata["df_semantics"] so denominator_df and numerator_df are not ambiguous: SSR tests use ssr_model_degrees_of_freedom, while non-SSR Wald tests use q_normalized_wald_restriction_degrees_of_freedom;

  • raises XTBreakValidationError for time-series np/wpn because those panel covariance estimators require explicit entity= and time= arrays;

  • accepts panel csa=, csanobreak=, kfactors=, nbkfactors=, and csd=True controls, rejecting observed factors that vary across entities within a time period; SSR test(...) statistics count entity-specific common-factor nuisance loadings in the numerator and denominator degrees of freedom for the same factor surface used by the segment SSR objective;

  • accepts nobreak_x= only for the narrow known-break panel partial path test(..., nobreak_x=..., breakpoints=(single,), entity=..., time=..., vce="ssr") and the narrow single-break unknown path test(..., nobreak_x=..., entity=..., time=..., breaks=1, vce="ssr"); robust covariance is explicitly unsupported for panel partial nobreak_x and vce="hc", vce="hac", vce="np", and vce="wpn" fail fast; these paths also reject multi-break tests, factor controls including csa, csanobreak, kfactors, nbkfactors, csd, and fixed_effects=False; on balanced panels they accept reweigh=False with the same SSR/F objective as reweigh=True;

  • rejects csd=True combined with manual csa= or csanobreak= because the shortcut already defines those cross-sectional-average lists;

  • records separate breaking and non-breaking factor metadata plus source_governed_common_factor_covariance for supported robust factor paths.

xtbreak.estimate(...)

Estimates break dates by SSR-minimizing dynamic programming, for time-series or panel data (when entity= and time= arrays are supplied).

Current behavior:

  • accepts the same strict vce contract as xtbreak.test(...);

  • accepts matching entity= and time= arrays for panel raw-data SSR execution;

  • accepts nobreak_x= only for the narrow panel partial path estimate(..., nobreak_x=..., entity=..., time=..., breaks=1, vce="ssr"); this path requires balanced panels with fixed effects and currently rejects robust covariance is explicitly unsupported for panel partial nobreak_x and vce="hc", vce="hac", vce="np", and vce="wpn" fail fast; confidence-interval parity, multi-break, factor controls including csa, csanobreak, kfactors, nbkfactors, csd, and fixed_effects=False also remain unsupported; it accepts reweigh=False on balanced panels, where the reweighting factors are identical to reweigh=True; its public payload is row-order invariant and JSON-serializable through EstimateResult.to_dict(); CI bounds are nullable when ci_method="not_computed_panel_partial"; rejects time_values= because panel partial paths use time=;

  • maps panel break indexes to the common time axis, not raw observation rows;

  • records the SSR-minimizing dynamic-programming objective in metadata["break_search_objective"] and the source anchor in metadata["break_search_source"];

  • does not silently fall back to SSR for unknown covariance names;

  • returns EstimateResult for supported time-series and explicit-panel covariance paths;

  • computes homoskedastic plug-in break-date confidence intervals for supported time-series and explicit-panel samples; pass ci_level= to choose the interval level, with a degenerate fallback and ci_error metadata when the plug-in cannot be formed;

  • records non-SSR covariance metadata through metadata["covariance_estimator"], metadata["bandwidth"], and metadata["covariance"]; the covariance payload is computed on the post-break unrestricted regime-interaction design and contains coefficients, standard errors, a covariance matrix, residual SSR, residual degrees of freedom, and source-governed limitation flags where applicable;

  • records separate csa, csanobreak, kfactors, nbkfactors, and csd expansion counts and metadata["csa_covariance_status"] == "source_governed_common_factor_covariance" when supported panel factor controls are supplied on robust paths;

  • exposes metadata["solver_diagnostics"] for the break-search design so callers can audit the normalized solver name, rank, condition number, and fallback flag without changing the current estimator contract;

  • raises XTBreakValidationError for time-series np/wpn because those panel covariance estimators require explicit entity= and time= arrays.

xtbreak.select(...)

Provides oracle-backed sequential break selection and selected break counts via caller-supplied critical values. This is not a built-in critical-value-table replacement. It:

  • accepts the same raw-data and panel axes as xtbreak.estimate(...);

  • accepts the same panel factor controls, including csd=True for all-breaking RHS cross-sectional-average expansion;

  • accepts nobreak_x= only for the narrow panel partial path select(..., nobreak_x=..., entity=..., time=..., max_breaks=1, critical_values={1: ...}); this path evaluates one caller-supplied critical-value F(1|0) step from the public unknown-break panel partial statistic and currently rejects omitted or multi-break max_breaks, including the explicit max_breaks=0 boundary, factor controls, csd, and fixed_effects=False; missing critical_values is reported before this panel partial max-breaks boundary; it accepts reweigh=False on balanced panels with zero statistic drift relative to reweigh=True and records reweigh=False on the selector metadata as well as the promoted estimate metadata; rejects time_values= because panel partial paths use time=; public selection has no vce keyword for panel partial nobreak_x and remains the single-step SSR selector; H2 diagnostic components use level_critical_values metadata when skip_h2=False, so their critical-value level, source, and rejection flag are separate from the sequential critical_values decision;

  • evaluates the sequential F(k+1|k) path up to max_breaks; selector step and H2 component payloads record df_semantics="ssr_model_degrees_of_freedom" because public selection statistics are SSR/F comparisons rather than robust Wald restrictions;

  • when max_breaks is omitted, uses the methodology-paper rule floor(1 / trimming) - 2 from paper/arXiv-2211.06707v2/Multiple_Breaks_Main.tex line 374, then applies the public guard max(1, ...) so the omitted-default path never returns a nonpositive break count. The software paper’s US example footnote uses a ceil convention; PyXTBreak follows the higher-authority methodology paper and records the source boundary in result metadata. The live Stata 18 xtbreak-2.2 probe in artifacts/verification/stata/phase40_default_maxbreaks_probe.txt records default_r_f_rows: 5 at trimming=0.15; PyXTBreak keeps the methodology-paper default of 4 and treats the Stata row count as an explicit parity boundary;

  • can optionally compute the H2 double-maximum diagnostic through wdmax; H2 diagnostic components expose critical-value level, source, rejection flag, weighted statistic, and weight from level_critical_values across raw-data, common_x, and panel partial nobreak_x selector paths; weighted H2 component rejection flags use the WDmax baseline critical value level_critical_values[1], while unweighted H2 component rejection flags use each component’s own level_critical_values[k]; H2 selected_breaks is 0 when no H2 component rejects and otherwise reports the strongest rejected H2 component count. For panel selections, sequential steps and H2/WDmax diagnostics use the same panel sample-size, fixed-effect, and common-factor nuisance degrees of freedom;

  • returns BreakSelectionResult with the evaluated steps, selected break count, selected min/max range, optional H2 payload, and optional EstimateResult for the selected count. In non-strict ambiguous ranges, selected_breaks follows the conservative lower terminal rejection used for estimate handoff while selected_min_breaks and selected_max_breaks preserve the full range. For common_x selections, nested promoted estimates match the conservative selected_breaks handoff count rather than the upper ambiguous bound, and their metadata reports the actual brute-force partial break-search algorithm. When partial structural-change confidence intervals are not computed, promoted estimates keep nullable CI bounds rather than synthetic zero-width intervals. num_fixed_regressors must match common_x.shape[1] for non-empty common_x; every common_x column enters the partial structural-change design as a non-breaking regressor and is counted in the statistic denominator degrees of freedom. A zero-column common_x matrix is invalid; omit common_x when there are no non-breaking regressors. Selector metadata records num_fixed_regressors and num_breaking_regressors, matching the non-breaking common_x columns and the breaking x columns used by the promoted estimate and sequential degrees of freedom. Common-X selections expose a dual SSR contract: selector steps and promoted estimate SSR keep the paper-style free/refit common-X objective, while EstimateResult.ssr_path, ssr_path_plot_data(), and metadata["ssr_path_objective"] expose the Stata e(SSRvec) fixed-selected-common oracle semantics used for estat ssr display. BreakSelectionResult.to_dict() preserves selection_ssr_objective and the nested estimate ssr_path_objective labels alongside the selected SSR and fixed-common SSR path values. The nested ssr_path_objective is present only for selected one-break estimates with an actual SSR path; multi-break common-X promoted estimates keep ssr_path absent and do not claim Stata estat ssr path semantics. Weighted and unweighted common-X H2 diagnostics expose ssr_objective="free_common_coefficients_candidate_refit" so diagnostic SSR values are not confused with the one-break Stata display path. Zero-break common-X selections omit promoted estimates, selected breakpoint lists, and SSR-path objective metadata, while preserving selection_ssr_objective and H2/component ssr_objective labels for evaluated diagnostics. H2 selected_breaks is diagnostic and independent of the conservative sequential selected_breaks used for promoted estimate handoff, so the two counts may differ on non-strict ambiguous selections. Strict sequential stopping does not truncate H2 diagnostics, which still evaluate the admissible hypothesis-(2) components and remain independent of promoted estimate handoff.

  • reports the narrow public panel partial estimate(..., nobreak_x=...) search as break_search_algorithm="initialized_dynamicpartial_helper_ssr", matching the initialized dynamicpartial helper-matrix SSR path rather than the generic raw-data dynamic-programming optimizer.

New Parameters (test / estimate / select)

The following parameters are available on xtbreak.test(), xtbreak.estimate(), and xtbreak.select() unless otherwise noted:

Parameter

Type

Default

Available In

Description

data

pd.DataFrame | None

None

test, estimate, select

Pandas DataFrame input. When provided, y/x/entity/time should be column name strings (or lists of strings for x).

trend

bool

False

test, estimate, select

Add a linear trend to non-breaking regressors (fixed trend across regimes).

breaktrend

bool

False

test, estimate, select

Add a linear trend to breaking regressors (trend allowed to shift at breakpoints).

n_jobs

int

1

estimate, select

Number of parallel workers. When >1, parallelizes the dynamic-programming break search.

lazy_ssr

bool | None

None

estimate, select

Memory optimization for segment SSR computation. None = auto (enabled when T > 5000), True = force lazy evaluation, False = force full matrix.

return_segment_ssr

bool

False

estimate, select

When True, includes the full segment SSR matrix in result metadata. Not available with lazy_ssr=True.

information_criterion

str | None

None

select

Information criterion for model selection. Accepted values: 'bic' or 'aic'. When set, the selector uses the specified criterion instead of the sequential F procedure.

Result Containers

xtbreak.CommandType

Literal["test", "estimate", "select"] — a type alias constraining the command field on XTBreakResult, EstimateResult, and BreakSelectionResult.

xtbreak.XTBreakResult

Immutable snapshot container for future test results. It stores command metadata, hypothesis number, break indexes, a statistic, a p-value, critical values, and arbitrary metadata. Use to_dict() for JSON-safe serialization. When metadata includes any SSR/df contract field (restricted_ssr, unrestricted_ssr, denominator_df, numerator_df, or df_semantics), it must include the complete set: SSR values must be finite and nonnegative, unrestricted SSR cannot exceed restricted SSR, degrees of freedom must be positive integers, and df_semantics must be one of the documented public semantics. This keeps xtbreak.test(...) result payloads fail-closed instead of allowing partial or ambiguous statistical metadata.

xtbreak.EstimateResult

Immutable result surface for Stata-shaped xtbreak estimate output. It supports the current parity and documentation examples and is also returned by the first raw-data estimate(...) runtime slice.

Create it with:

result = xtbreak.EstimateResult.from_break_matrices(
    command=payload["command"],
    break_matrix=payload["results"]["breaks"],
    ci_matrix=payload["results"]["ci"],
    ssr=payload["results"]["ssr"],
    metadata={"scenario_id": payload["scenario_id"]},
)

Pass sample_time_values=... when an oracle or runtime result carries the full time axis. The result validates that every break index points to the same time value recorded in the Stata-shaped break matrix. For single-break estat ssr payloads, pass both ssr_path and sample_time_values. Phase 140 locks EstimateResult break-index order validation: break estimate indexes must be strictly increasing even when no sample_time_values axis is attached. Duplicate or decreasing indexes fail with break estimate indexes must be strictly increasing. rather than being serialized into impossible break tables or post-estimation regimes. Phase 141 locks EstimateResult time-axis validation: sample_time_values and FittedSample.time_axis entries must be strictly increasing. Duplicate or decreasing time axes fail with sample_time_values entries must be strictly increasing. or time_axis entries must be strictly increasing. so regime boundaries and ssr_path_plot_data() cannot contradict the ordered t=1..T sample index. Phase 142 locks EstimateResult terminal-break validation when a sample axis is attached: a break index must be smaller than len(sample_time_values) so the post-break regime is non-empty. Terminal sample-axis breaks fail with break estimate index must leave a non-empty post-break regime. Phase 143 locks EstimateResult CI-axis validation when a sample axis is attached: non-null confidence-interval index bounds must be positive, and confidence-interval time bounds must equal sample_time_values when the CI index falls on the attached axis. Positive CI bounds outside a candidate SSR axis remain allowed for source oracles whose confidence interval extends beyond that display axis. Mismatches fail with break estimate ci_index must align with sample_time_values. or break estimate ci_time_value must align with sample_time_values. Phase 144 locks EstimateResult SSR-path selected-value validation: single-break ssr_path payloads must have a finite value at the selected break index, and that value must match EstimateResult.ssr within machine precision. Missing or contradictory selected path values fail with selected ssr_path value must match ssr. Phase 145 locks FittedSample row-id validation: fitted-sample row IDs must be unique and hashable at construction time, because post-estimation indicator, split, and scatter payloads use them as observation identity keys. Invalid row IDs fail with row_ids entries must be unique. or row_ids entries must be hashable. Phase 146 locks FittedSample variable-name validation: fitted-sample regressor_names and break_variable_names must each be unique, because post-estimation split and scatter payloads resolve fitted columns by name. Duplicate names fail with regressor_names entries must be unique. or break_variable_names entries must be unique.

Available fields:

  • regime_statistics: tuple[RegimeStatistics, ...] — per-regime OLS statistics (coefficients, standard errors, t-statistics, R², adjusted R², SSR) computed from the estimated break partition. Empty when regime statistics are not computed.

  • chow_tests: tuple[ChowTestResult, ...] — between-regime Chow F test results for coefficient equality across each pair of adjacent regimes. Empty when Chow tests are not computed.

Available methods:

  • to_dataframe() -> pd.DataFrame converts regime statistics to a tidy DataFrame with one row per variable per regime, containing columns: regime, variable_index, coefficient, std_error, t_statistic, regime_start, regime_end, n_obs, r_squared, adjusted_r_squared, ssr. Raises ImportError if pandas is not installed. Returns an empty DataFrame when regime_statistics is empty.

  • break_date_labels(time_labels=None) -> tuple[str, ...] maps break indices to human-readable date labels. If time_labels (a sequence of strings matching each time period) is provided, uses those; otherwise falls back to time_value from each EstimateBreak, or formats as "t={index}".

  • break_table() returns one row per break with index, time value, and confidence-interval bounds.

  • plot_data() returns breakpoint, confidence-interval, and optional sample-axis payloads for downstream plotting.

  • regime_indicators() returns a JSON-safe command="indicator" payload with Stata-style regime labels, row IDs, time values, optional entity values, and an explicit outside-sample policy.

  • split_design() returns a JSON-safe command="split" payload with regime-specific columns for fitted variables listed in fitted_sample.break_variable_names and any requested breaking constant; non-breaking fitted regressors are retained in the fitted sample but are not eligible for regime splitting.

  • scatter_plot_data() returns a JSON-safe command="scatter" payload with row-level points, regime-grouped traces, break lines, confidence intervals, legend labels, and source anchors. For common-X promoted estimates, scatter_plot_data() only accepts breaking variables as the x-axis variable, matching Stata estat scatter; non-breaking common-X regressors remain inspectable through FittedSample but are not valid scatter x variables.

  • summary() returns a compact text summary.

  • ssr_path_plot_data() returns a JSON-safe command="ssr" payload when ssr_path and sample_time_values were supplied for a single-break result.

The post-estimation helpers return data only. They do not require matplotlib, plotly, or any plotting backend; callers pass the returned payloads into their own plotting or reporting tools.

For promoted estimates from select(..., common_x=..., num_fixed_regressors=common_x.shape[1]), the fitted sample metadata distinguishes breaking x columns from non-breaking common_x columns. Default split_design() uses only the breaking x columns, and explicit requests for non-breaking common_x columns fail clearly instead of creating incoherent regime-specific common-X columns. scatter_plot_data() has the same boundary: scatter_plot_data("common_x*") fails because Stata estat scatter is defined for a variable with breaks on the x-axis. Historical non-common-X fitted-sample scatter payloads keep their existing compatibility.

xtbreak.BreakSelectionResult

Immutable automatic-selection payload. It stores the sequential evidence, selected break counts, optional H2 diagnostic, optional EstimateResult, and selection metadata. selected_breaks is the estimate-handoff count; in non-strict ambiguous ranges the full span remains available as selected_min_breaks and selected_max_breaks. Use to_dict() for JSON-safe serialization. For common_x selectors, nested promoted estimates match selected_breaks, metadata reports the actual brute-force partial break-search algorithm, and promoted estimates use nullable CI bounds when partial structural-change confidence intervals are not computed. num_fixed_regressors must match the number of common_x columns, and zero-column common_x designs are rejected. Top-level metadata records both BreakSelectionResult.metadata["num_fixed_regressors"] and BreakSelectionResult.metadata["num_breaking_regressors"] so serialized payloads carry the denominator and numerator regressor counts used by the selection statistics. Optional H2/WDmax diagnostic selected_breaks can differ from the conservative sequential BreakSelectionResult.selected_breaks used for promoted estimates. Strict sequential stopping does not truncate H2 diagnostics; nested H2 components continue to represent the independent hypothesis-(2) diagnostic surface. Raw-data, common_x, and panel partial selectors use the same public separation between sequential estimate handoff and H2 diagnostics. Strict sequential stopping can return selected_breaks == 0 and omit a promoted estimate while the nested H2 payload still reports its independently evaluated diagnostic components. Raw-data H2 diagnostics report ssr_objective="standard_segment_ssr_candidate_refit"; panel partial nobreak_x diagnostics report ssr_objective="initialized_dynamicpartial_helper_ssr". Count metadata keeps the same distinction: selection_steps_evaluated records returned sequential steps, selection_statistics_computed records evaluated selection statistics, and h2_components_evaluated records evaluated H2 components.

Manually constructed BreakSelectionResult objects validate their public payloads at construction time. Break-count fields must be non-bool integers in their admissible ranges, max_breaks must be at least one, and selected ranges must either be zero or refer to returned sequential steps. Critical-value levels must be finite probabilities with real boolean exact-match flags, and reserved metadata mirrors such as requested_cvalue, requested_level, and max_breaks must match the canonical top-level fields. Positive selections may omit a promoted estimate, but a supplied estimate must be an EstimateResult whose num_breaks equals top-level selected_breaks.

Sequential steps are SSR/F payloads. Each step must be a mapping with finite nonnegative SSR values, positive integer numerator and denominator degrees of freedom, df_semantics="ssr_model_degrees_of_freedom", finite nonnegative statistic, positive finite critical_value, and a boolean rejected field that matches statistic > critical_value. The returned step family must be the contiguous sequence 1..len(steps), and selected_min_breaks / selected_max_breaks must match the step decisions under strict or non-strict selection.

When present, h2 must be a mapping, must be omitted when skip_h2=True, and must carry a real boolean weighted flag matching wdmax. H2 payloads include selected_breaks with selected_breaks_role="h2_diagnostic_not_estimate_handoff", a finite top-level statistic, a non-empty ordered component family, and a top-level ssr_objective shared by all components. H2 selected-break counts are diagnostic counts: they must be nonnegative integers no larger than max_breaks, and they aggregate the strongest rejected component rather than overwriting the top-level estimate handoff.

Each H2 component must include finite statistic and weighted_statistic fields, an integer breaks value in the contiguous sequence 1..len(components), positive finite critical_value and weight, a boolean rejected decision, finite nonnegative restricted and unrestricted SSR values, positive integer numerator and denominator degrees of freedom, and df_semantics="ssr_model_degrees_of_freedom". Component algebra is checked: unrestricted SSR cannot exceed restricted SSR, weighted_statistic must equal statistic * weight, rejected must match the H2/WDmax decision rule, and the top-level H2 statistic and selected-break count must match the component evidence.

xtbreak.EstimateBreak

Represents one estimated break date. It stores the break number, one-based break index, time-axis value, confidence interval in indexes, and confidence interval in time values. Public constructors require positive one-based break numbers and indexes, ordered nullable confidence-interval bounds, and matching nullable index/time confidence-interval shape. Inside EstimateResult, break entries must be EstimateBreak objects with contiguous break_number == 1..num_breaks, and SSR plus SSR-path values must be nonnegative.

xtbreak.FittedSample

Immutable fitted-sample metadata used by EstimateResult post-estimation helpers. Runtime estimate(...) results populate it when fitted row IDs, time values, optional entity values, dependent values, regressor values, regressor names, break-variable names, and the aligned time axis are available. Users normally consume this through regime_indicators(), split_design(), and scatter_plot_data() rather than constructing it directly. Direct construction validates that row_ids are non-empty, unique, and hashable before serialization or post-estimation mapping. It also validates that regressor_names and break_variable_names are unique, so split and scatter helpers do not silently choose the first of multiple same-named fitted columns.

xtbreak.RegimeStatistics

Frozen dataclass holding per-regime OLS regression statistics computed from the estimated break partition. One instance per regime (0-based indexing). Fields:

  • regime_index: int — regime number (0-based).

  • start_index: int — first observation index in this regime.

  • end_index: int — end observation index (exclusive).

  • n_observations: int — number of observations in this regime.

  • coefficients: tuple[float, ...] — OLS coefficient estimates β̂_j.

  • standard_errors: tuple[float, ...] — standard errors SE(β̂_j).

  • t_statistics: tuple[float, ...] — t-statistics for each coefficient.

  • r_squared: float — R² for this regime.

  • adjusted_r_squared: float — adjusted R² for this regime.

  • ssr: float — regime-specific residual sum of squares.

xtbreak.ChowTestResult

Frozen dataclass holding the result of a between-regime Chow F test for coefficient equality across adjacent regimes. Fields:

  • regime_j: int — index of the first regime in the pair.

  • regime_j_plus_1: int — index of the second regime in the pair.

  • f_statistic: float — the Chow F statistic.

  • p_value: float | None — p-value from the F distribution (None if scipy unavailable).

  • degrees_of_freedom: tuple[int, int](numerator_df, denominator_df).

xtbreak.LazySegmentSSR

Lazy SSR matrix that computes segment-level OLS residual sums of squares on demand with caching. For large T, avoids precomputing the full T×T matrix. Only segments that are actually requested are computed. Instances behave like a 2-D array (shape (T, T+1), ndim == 2) and support [i, j] indexing.

from xtbreak import LazySegmentSSR
import numpy as np

y = np.random.randn(200)
x = np.ones((200, 1))
ssr_matrix = LazySegmentSSR(y, x, min_segment=10)
print(ssr_matrix[0, 100])  # SSR for segment [0, 100)

Plotting Functions

All plotting functions require matplotlib as an optional dependency.

xtbreak.plot_breaks

plot_breaks(y, *, break_indices, time_values=None, ci_indices=None,
            title="Structural Breaks", figsize=(12, 5), ax=None)

Plot a time series with vertical lines at estimated break dates and optional confidence-interval shading. Returns the matplotlib Figure.

xtbreak.plot_regime_fit

plot_regime_fit(y, x, *, break_indices, time_values=None,
                title="Regime-Specific Fitted Values", figsize=(12, 5), ax=None)

Plot raw data with per-regime OLS fitted values (different colors per regime). Returns the matplotlib Figure.

xtbreak.plot_ssr_path

plot_ssr_path(ssr_path, *, time_values=None, break_index=None,
              title="SSR Path (Single Break)", figsize=(10, 5), ax=None)

Plot the SSR path for single-break estimation, showing SSR as a function of candidate break position with a vertical line at the optimal break. Returns the matplotlib Figure.

Utility Functions

xtbreak.get_blas_info

get_blas_info() -> dict[str, str]

Detect the BLAS library backing NumPy operations. Returns a dict with keys 'library' (mkl, openblas, accelerate, blas, or unknown), 'version', and 'threading'.

xtbreak.recommend_blas_optimization

recommend_blas_optimization() -> str | None

Return an optimization recommendation string if a suboptimal BLAS is detected. Returns None when an optimized BLAS (MKL, OpenBLAS, Accelerate) is already in use.

xtbreak.LazySegmentSSR

Lazy SSR matrix that computes segment-level OLS residual sums of squares on demand with caching. For large T, avoids precomputing the full T×T matrix. Only segments that are actually requested are computed. Instances behave like a 2-D array (shape (T, T+1), ndim == 2) and support [i, j] indexing.

from xtbreak import LazySegmentSSR
import numpy as np

y = np.random.randn(200)
x = np.ones((200, 1))
ssr_matrix = LazySegmentSSR(y, x, min_segment=10)
print(ssr_matrix[0, 100])  # SSR for segment [0, 100)

Plotting Functions

All plotting functions require matplotlib as an optional dependency.

xtbreak.plot_breaks

plot_breaks(y, *, break_indices, time_values=None, ci_indices=None,
            title="Structural Breaks", figsize=(12, 5), ax=None)

Plot a time series with vertical lines at estimated break dates and optional confidence-interval shading. Returns the matplotlib Figure.

xtbreak.plot_regime_fit

plot_regime_fit(y, x, *, break_indices, time_values=None,
                title="Regime-Specific Fitted Values", figsize=(12, 5), ax=None)

Plot raw data with per-regime OLS fitted values (different colors per regime). Returns the matplotlib Figure.

xtbreak.plot_ssr_path

plot_ssr_path(ssr_path, *, time_values=None, break_index=None,
              title="SSR Path (Single Break)", figsize=(10, 5), ax=None)

Plot the SSR path for single-break estimation, showing SSR as a function of candidate break position with a vertical line at the optimal break. Returns the matplotlib Figure.

Utility Functions

xtbreak.get_blas_info

get_blas_info() -> dict[str, str]

Detect the BLAS library backing NumPy operations. Returns a dict with keys 'library' (mkl, openblas, accelerate, blas, or unknown), 'version', and 'threading'.

xtbreak.recommend_blas_optimization

recommend_blas_optimization() -> str | None

Return an optimization recommendation string if a suboptimal BLAS is detected. Returns None when an optimized BLAS (MKL, OpenBLAS, Accelerate) is already in use.

Exceptions

xtbreak.XTBreakError

Base package exception.

xtbreak.XTBreakValidationError

Raised for invalid user-facing options or malformed matrix-shaped result payloads.

Internal Modules

The following modules are internal. They appear here only for auditability:

  • xtbreak._segments: segment-level OLS SSR and SSR matrices.

  • xtbreak._breakpoints: trimming-aware breakpoint enumeration.

  • xtbreak._dynamic: dynamic-programming break search and brute-force oracles.

  • xtbreak._statistics: SSR-based known-break F, supF, double-maximum, and additional-break statistics.

  • xtbreak._critical: critical-value records and sequential decision helpers.

  • xtbreak._result: result containers and Stata-shaped estimate hydration.

  • xtbreak._confidence: homoskedastic plug-in break-date confidence intervals for the current time-series and explicit-panel raw-data estimate slices.

  • xtbreak._panel: panel indexing, fixed-effect transforms, cross-section averages, panel segment SSR, and panel covariance grids.

  • xtbreak._covariance: SSR, HC0, Bartlett HAC OLS covariance helpers, plus explicit-panel np and wpn covariance helpers.

  • xtbreak._partial: partial structural-change search where selected regressors break and common regressors do not.

Outside the narrow single-break balanced-panel fixed-effects vce="ssr" nobreak_x slice, panel raw-data partial structural-change requests that require Stata nobreakvariables(...) semantics remain a public validation boundary. The Phase 45 crosswalk at .planning/phases/45-panel-partial-structural-change-crosswalk/45-CONTEXT.md records the methodology-paper x/w split, Stata dynamicpartial handoff, and future oracle prerequisites.

Internal module names and signatures can still change before a public release.