API Reference¶
This page combines a short API map with generated reference documentation from the package docstrings.
Which API Should I Use?¶
| Workflow | API |
|---|---|
| Standard one-shot detection | cfad.detect |
| Custom rolling detector configuration | cfad.detection.RollingDetector |
| Online updates | cfad.detection.StreamDetector |
| Train/test temporal evaluation | cfad.backtest.WalkForwardBacktest |
| ECF model comparison | cfad.compare_models |
| ECF goodness-of-fit tests and distances | cfad.gof |
| Parameter sweeps | cfad.sensitivity |
| Plotting diagnostics | cfad.viz |
Return Objects¶
detect() and RollingDetector.fit_transform() return an AnomalyReport.
The most important fields are scores, cusum_pos, cusum_neg,
alarm_indices, window_end_indices, mu0, sigma0, and threshold.
WalkForwardBacktest.run() returns a BacktestResult, which can be summarized
with summary() or converted to a fold-concatenated DataFrame with
to_dataframe().
High-Level API¶
Public API entry points for common CFAD workflows.
AnomalyReport
dataclass
¶
AnomalyReport(scores: NDArray[float64], cusum_pos: NDArray[float64], cusum_neg: NDArray[float64], alarm_indices: NDArray[int64], window_end_indices: NDArray[int64], dates: Optional[DatetimeIndex] = None, mu0: float = 0.0, sigma0: float = 1.0, threshold: float = 5.0)
Container for detector output.
alarm_dates
property
¶
Return dates corresponding to alarm-window endpoints.
window_end_indices use Python's half-open convention and therefore
point one position beyond the final observation in each rolling window.
summary ¶
Return a compact human-readable report summary.
Source code in cfad/detection.py
RollingDetector ¶
RollingDetector(window: int = 60, xi_min: float = -10.0, xi_max: float = 10.0, n_xi: int = 128, step: int = 1, calibration_frac: float = 0.3, k: float = 0.5, h: float = 5.0)
Rolling ECF shape detector followed by a two-sided Page-CUSUM.
Source code in cfad/detection.py
score_windows ¶
Compute rolling ECF-shape scores without fitting CUSUM calibration.
This separation is useful for walk-forward evaluation: a test fold can be scored without estimating any in-control parameter from the test data.
Source code in cfad/detection.py
apply_calibration ¶
apply_calibration(scores: NDArray[float64], mu0: float, sigma0: float) -> tuple[NDArray[np.float64], NDArray[np.float64], NDArray[np.int64]]
Apply this detector's CUSUM settings to externally calibrated scores.
Source code in cfad/detection.py
fit_transform ¶
Score windows, estimate in-control moments, and apply CUSUM.
Source code in cfad/detection.py
detect ¶
detect(returns: Union[NDArray, Series], window: int = 60, xi_range: tuple[float, float] = (-10.0, 10.0), n_xi: int = 128, step: int = 1, calibration_frac: float = 0.3, k: float = 0.5, h: float = 5.0, *, height: float | None = None) -> AnomalyReport
Detect distributional-shape changes in a financial return series.
Each rolling empirical characteristic function is compared with the Gaussian characteristic function fitted to the same window. The resulting real-frequency L2 distance is monitored with a two-sided Page-CUSUM.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
returns
|
array - like or Series
|
One-dimensional return series. |
required |
window
|
int
|
Rolling window size for ECF estimation. |
60
|
xi_range
|
tuple[float, float]
|
Real-frequency grid bounds. |
(-10, 10)
|
n_xi
|
int
|
Number of frequency grid points. |
128
|
step
|
int
|
Rolling step. |
1
|
calibration_frac
|
float
|
Fraction of score windows used to estimate the in-control score mean and standard deviation. |
0.3
|
k
|
float
|
Dimensionless Page-CUSUM reference value on standardized scores. |
0.5
|
h
|
float
|
CUSUM decision threshold. |
5.0
|
height
|
(float or None, keyword - only)
|
Deprecated compatibility argument from the former empirical-contour implementation. It is ignored by the corrected real-frequency score and will be removed in a future breaking release. |
None
|
Returns:
| Type | Description |
|---|---|
AnomalyReport
|
Scores, CUSUM statistics, alarm indices, and optional dates. |
Source code in cfad/api.py
compare_models ¶
compare_models(returns: NDArray[float64], xi: Optional[NDArray[float64]] = None) -> dict[str, object]
Fit Gaussian and NIG models and compare real-frequency ECF distance.
This model comparison is descriptive evidence about distributional fit. It must not be interpreted as a test for branch cuts or population-CF singularities from a finite-sample empirical characteristic function.
Source code in cfad/api.py
Detection Objects¶
Rolling ECF shape detector followed by a two-sided Page-CUSUM.
Source code in cfad/detection.py
score_windows ¶
Compute rolling ECF-shape scores without fitting CUSUM calibration.
This separation is useful for walk-forward evaluation: a test fold can be scored without estimating any in-control parameter from the test data.
Source code in cfad/detection.py
apply_calibration ¶
apply_calibration(scores: NDArray[float64], mu0: float, sigma0: float) -> tuple[NDArray[np.float64], NDArray[np.float64], NDArray[np.int64]]
Apply this detector's CUSUM settings to externally calibrated scores.
Source code in cfad/detection.py
fit_transform ¶
Score windows, estimate in-control moments, and apply CUSUM.
Source code in cfad/detection.py
Online detector using the same ECF-shape score as RollingDetector.
Source code in cfad/detection.py
_make_output ¶
Create the public result object for one streamed observation.
Source code in cfad/detection.py
_calibrate_if_ready ¶
Estimate in-control score moments once enough score windows exist.
Source code in cfad/detection.py
update ¶
Ingest one return observation and update the sequential detector.
Source code in cfad/detection.py
update_batch ¶
Process a one-dimensional array through :meth:update.
Source code in cfad/detection.py
reset ¶
Reset buffer, CUSUM state, and score calibration.
Source code in cfad/detection.py
Container for detector output.
alarm_dates
property
¶
Return dates corresponding to alarm-window endpoints.
window_end_indices use Python's half-open convention and therefore
point one position beyond the final observation in each rolling window.
summary ¶
Return a compact human-readable report summary.
Source code in cfad/detection.py
Backtesting¶
Walk-forward evaluation with train-only score calibration.
Source code in cfad/backtest.py
_split_folds ¶
Create non-overlapping test folds as half-open index intervals.
Source code in cfad/backtest.py
_sanitize_sigma
staticmethod
¶
Ensure a strictly positive finite calibration scale.
run ¶
Execute a leakage-free walk-forward evaluation.
Each fold estimates mu0 and sigma0 only from training-window
scores. Test-window ECF scores are produced by score_windows and the
frozen training calibration is then applied via apply_calibration.
No test-fold statistic is used to fit the sequential decision rule.
Source code in cfad/backtest.py
166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 | |
score_alarms ¶
score_alarms(result: BacktestResult, known_breaks: list, tolerance_windows: int = 10) -> dict[str, float | int]
Score alarms against known break dates or integer indices.
Source code in cfad/backtest.py
272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 | |
Container for walk-forward backtest output.
_global_dates
class-attribute
instance-attribute
¶
summary ¶
Return a concise textual summary of backtest outcomes.
Source code in cfad/backtest.py
to_dataframe ¶
Return fold-concatenated score diagnostics as a DataFrame.
Source code in cfad/backtest.py
ECF and Scoring Functions¶
Empirical CF at frequency grid xi from a single sample of returns.
phi_n(xi) = (1/n) sum_j exp(i xi r_j)
Uses Cython extension when available (typically 20-50x faster than the NumPy broadcasting version for large n).
Source code in cfad/empirical_cf.py
Sliding-window ECF.
Returns:
| Name | Type | Description |
|---|---|---|
ecf_mat |
complex ndarray of shape (n_windows, m)
|
|
end_indices |
int ndarray of shape (n_windows,)
|
|
Source code in cfad/empirical_cf.py
Compute normalized L2 distance from each ECF to its fitted Gaussian CF.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
ecf_windows
|
complex ndarray of shape (n_windows, n_xi)
|
Empirical characteristic-function values for each rolling window. |
required |
xi_grid
|
float ndarray of shape (n_xi,)
|
Real frequency grid used for the ECF. |
required |
means
|
float ndarray of shape (n_windows,)
|
Sample mean for each rolling window. |
required |
stds
|
float ndarray of shape (n_windows,)
|
Sample standard deviation for each rolling window. |
required |
Returns:
| Name | Type | Description |
|---|---|---|
scores |
float ndarray of shape (n_windows,)
|
Square root of the frequency-averaged integrated squared distance between the ECF and the Gaussian CF fitted to the same window. |
Source code in cfad/contour.py
Deprecated legacy name for the former empirical-residue proxy.
Source code in cfad/contour.py
Build a counter-clockwise rectangular contour in the complex plane.
Source code in cfad/contour.py
Normalise a raw anomaly score series to a common scale.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
scores
|
float ndarray of shape (T,)
|
|
required |
method
|
"zscore" -> (scores - mean) / std
|
|
'zscore'
|
Returns:
| Name | Type | Description |
|---|---|---|
normalised |
float ndarray of shape (T,)
|
|
Source code in cfad/residue_score.py
Pointwise p-value of each score under the in-control distribution
estimated from a rolling past window of length window.
For each index t, fit the in-control distribution to scores[max(0, t-window):t], then return P(S >= scores[t]) under that fit.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
scores
|
float ndarray of shape (T,)
|
|
required |
window
|
int
|
Lookback for in-control estimation. |
required |
dist
|
'normal' or 'empirical'
|
In-control distribution family. |
'empirical'
|
Returns:
| Name | Type | Description |
|---|---|---|
pvalues |
float ndarray of shape (T,), values in [0, 1]
|
NaN for the first |
Source code in cfad/residue_score.py
Return the score threshold that achieves a given false-positive rate on the calibration (in-control) score distribution.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
scores
|
float ndarray of shape (T,)
|
Full score series (unused, kept for API symmetry). |
required |
calibration_scores
|
float ndarray of shape (T_cal,)
|
In-control score series used to set the threshold. If omitted,
|
None
|
fpr
|
float
|
Desired false-positive rate (default 0.01 = 1%). |
0.01
|
Returns:
| Name | Type | Description |
|---|---|---|
threshold |
float
|
The (1-fpr) quantile of calibration_scores. |
Source code in cfad/residue_score.py
Goodness of Fit¶
Distance between empirical CF and parametric CF.
L2: sqrt( integral |phi_hat - phi_theta|^2 dxi ) L1: integral |phi_hat - phi_theta| dxi Sup: max |phi_hat(xi) - phi_theta(xi)|
All integrals via numpy.trapezoid on uniform xi grid.
Source code in cfad/gof.py
Epps-Pulley (1983) ECF-based goodness-of-fit test.
Test statistic: T_n = n * integral_{-xi_max}^{xi_max} |phi_hat_n(xi) - phi_theta(xi)|^2 w(xi) dxi
where w(xi) = exp(-xi^2) (Gaussian weight, standard in ECF tests). phi_theta is the fitted model's CF.
Under H0 (data ~ model), T_n is asymptotically chi-squared. Use a simulation-based p-value: simulate B samples of size n from the fitted model, compute T_n for each, p-value = fraction >= observed T_n.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
returns
|
float ndarray of shape (n,)
|
|
required |
model
|
CFModel
|
Fitted CFModel instance. |
required |
xi_max
|
float
|
Frequency cutoff. |
3.0
|
n_xi
|
int
|
Number of grid points. |
50
|
B
|
int
|
Number of simulation replicates for p-value estimation. |
999
|
Returns:
| Name | Type | Description |
|---|---|---|
result |
dict
|
Dictionary with keys: "statistic", "pvalue", "n", "model", "reject_5pct". |
Source code in cfad/gof.py
106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 | |
Fit all provided CF models and return an AIC comparison table.
Default models if None: [GaussianCF(), NIGCF(), CGMYCF(), LevyStableCF()]
Returns pd.DataFrame with columns: model, is_analytic, n_params, aic, ecf_l2, winner (bool) Sorted by aic ascending.
Source code in cfad/gof.py
Rolling window goodness-of-fit distance (L2) between empirical CF and a freshly fitted parametric model on each window.
Used to track how well the null model fits over time — a sustained increase in distance signals model inadequacy (structural break).
Returns float ndarray of shape (n_windows,).
Source code in cfad/gof.py
Sensitivity¶
Evaluate detector sensitivity to rolling-window length.
Source code in cfad/sensitivity.py
Evaluate sensitivity to the symmetric real-frequency cutoff.
The corrected detector operates entirely on the real frequency axis. The
relevant geometric tuning parameter is therefore the frequency range
[-xi_max, xi_max], not a complex contour height.
Source code in cfad/sensitivity.py
Evaluate alarm-rate sensitivity to the CUSUM decision threshold.
Source code in cfad/sensitivity.py
Recommend a conservative detector configuration from sensitivity sweeps.
This routine is heuristic. It is intended for exploratory configuration, not as a substitute for out-of-sample calibration against an application- specific false-alarm objective.
Source code in cfad/sensitivity.py
Model Classes¶
Bases: CFModel
Normal-distribution characteristic-function model.
Source code in cfad/models/gaussian.py
cf ¶
Evaluate the characteristic function on the supplied frequency grid.
log_cf ¶
fit ¶
Fit mean and sample standard deviation by their usual estimators.
Source code in cfad/models/gaussian.py
Bases: CFModel
NIG characteristic function model (non-analytic).
Source code in cfad/models/nig.py
cf ¶
log_cf ¶
fit ¶
MLE via scipy minimize (L-BFGS-B).
Source code in cfad/models/nig.py
Bases: CFModel
CGMY characteristic-function model (non-analytic).
Source code in cfad/models/cgmy.py
log_cf ¶
Evaluate the CGMY log characteristic function.
At Y=1 the standard expression has the removable singularity
Gamma(-1) * 0. Taking the limit in Y gives
C * [(M-i*xi) log(M-i*xi) - M log(M)
+ (G+i*xi) log(G+i*xi) - G log(G)].
The characteristic-function normalization log(phi(0)) = 0 is
imposed exactly after evaluation. This avoids cancellation error near
Y=1 without perturbing the model at nonzero frequencies.
Source code in cfad/models/cgmy.py
cf ¶
fit ¶
ECF minimum-distance estimation via Nelder-Mead.
Source code in cfad/models/cgmy.py
Bases: CFModel
Lévy-stable characteristic function model (non-analytic for alpha<2).
Source code in cfad/models/levy_stable.py
log_cf ¶
Source code in cfad/models/levy_stable.py
cf ¶
fit ¶
Maximum likelihood estimation via scipy.stats.levy_stable.fit.