Skip to main content

cfad — Characteristic Function Anomaly Detector

License: MIT CI

cfad is a research-oriented Python package for detecting changes in the distributional shape of financial returns with empirical characteristic functions (ECFs) and sequential CUSUM monitoring.

For each rolling window, CFAD compares the empirical characteristic function with the Gaussian characteristic function fitted to that window's sample mean and variance. The normalized real-frequency discrepancy is the anomaly score:

$$ D_t = \left[ \frac{1}{\xi_{\max}-\xi_{\min}} \int_{\xi_{\min}}^{\xi_{\max}} \left| \widehat\varphi_t(\xi)

\varphi_{\mathcal N(\widehat\mu_t,\widehat\sigma_t^2)}(\xi) \right|^2 ,d\xi \right]^{1/2}. $$

Because location and scale are fitted within each window, the score is aimed at higher-order shape changes such as tail and skewness changes. A two-sided Page-CUSUM then converts the score sequence into sequential alarms.

Scientific scope. The finite-sample ECF $\widehat\varphi_n(z)=n^{-1}\sum_j e^{izx_j}$ is a finite sum of entire functions and is itself entire. Therefore its exact closed-contour integral is zero. CFAD does not infer population-CF branch cuts or poles from an empirical contour residue. Complex contour integration remains available as a diagnostic helper for parametric characteristic functions evaluated at complex arguments, but it is not the empirical anomaly statistic.


Status

The repository is currently a research/development project. The codebase contains release scaffolding, documentation, benchmarks, notebooks, and a draft software paper. GitHub releases are archival research-software snapshots; no PyPI distribution is claimed unless a separate PyPI publication is explicitly performed and verified.

Current validation boundary

Two frozen validation programmes have now tested the corrected method rather than the retired contour-residue interpretation.

The v2 sequential benchmark showed that Monte Carlo calibration can control the Gaussian-null false-alarm rate, but the Gaussian-reference score was not robust to a stable Student-t in-control law and had weak first-alarm power once false alarms were controlled. The v3 score-level ablation then removed CUSUM and separated frequency scaling from reference-law choice. Standardizing each window corrected the legacy score's sensitivity to pure variance changes, and a frozen empirical in-control ECF produced strong null-law stability. However, the empirical-reference score achieved AUC 0.646 for a Gaussian-to-Student-t shape change and 0.783 for a Gaussian-to-skew change, for an average of 0.715 versus 0.738 for a simple kurtosis-distance comparator.

Accordingly, the current evidence does not establish that CFAD is a validated sequential detector or that its ECF score outperforms simpler moment summaries. The negative v2 and v3 results are retained as reproducible evidence in benchmarks/ and are treated as design constraints rather than tuned away.

Installation

From the default branch:

git clone https://github.com/DiogoRibeiro7/cfad
cd cfad
git switch main
python -m pip install -e ".[dev]" --no-build-isolation

The package includes optional Cython acceleration for rolling ECF evaluation and CUSUM updates. The statistical score itself is implemented once in NumPy, so installing the extensions changes performance rather than the definition of the statistic.

Quick start

import numpy as np
from cfad import detect

rng = np.random.default_rng(42)
returns = np.concatenate(
    [
        rng.normal(0.0, 0.01, 300),
        rng.standard_t(df=3.0, size=150) * 0.01 / np.sqrt(3.0),
    ]
)

report = detect(
    returns,
    window=60,
    xi_range=(-10.0, 10.0),
    step=1,
    calibration_frac=0.4,
    k=0.5,
    h=5.0,
)
print(report.summary())

For market data, fetch the series explicitly with the provider of your choice, then pass returns to detect. Keeping data acquisition outside the core example makes the detector reproducible without relying on network access.

Detection pipeline

returns
  │
  ├─ rolling ECF on a real-frequency grid
  │
  ├─ fitted Gaussian CF in each window
  │
  ├─ normalized ECF L2 shape distance D_t
  │
  ├─ calibration of score mean/std on an in-control prefix
  │
  └─ two-sided Page-CUSUM → alarms

Parametric CF models

CFAD also implements characteristic-function models for descriptive model comparison and goodness-of-fit work:

Model Main use
GaussianCF location/scale baseline
NIGCF semi-heavy tails and skewness
CGMYCF jump/tail-shape modelling
LevyStableCF power-law tail modelling

compare_models() compares fitted models by real-frequency ECF discrepancy and AIC. A better-fitting non-Gaussian model is evidence of distributional fit, not a direct empirical test for complex singularities.

Utilities

The repository includes:

  • rolling_gof, cf_distance, and epps_pulley_test for ECF goodness of fit;
  • WalkForwardBacktest for temporal evaluation;
  • bootstrap and score-stability diagnostics;
  • window_sensitivity, frequency_sensitivity, and threshold sensitivity;
  • multivariate and market-oriented helpers;
  • a Streamlit dashboard under apps/;
  • reproducible notebooks and benchmark scripts.

Reproducibility

The main scientific validation target is not "does an alarm fire on one famous market event?" but how the detector behaves under controlled null and alternative data-generating processes. The benchmark layer reports false-positive behaviour, power/discrimination under prespecified shape changes, specificity to location/scale changes, and comparison against simpler baselines.

Frozen failed experiments are part of the evidence record. In particular, benchmarks/v2_failed_calibration_record.json records the failed sequential screen and benchmarks/v3_failed_score_validation_record.json records the failed score-level screen. Those failures are not retroactively reclassified after parameter or method changes.

Documentation and paper

The manuscript is a draft companion to the software. Citation metadata should only advertise a journal DOI after an actual accepted/published record exists.

Author

Diogo Ribeiro
Faculty of Media Arts and Design, Technical University of Porto
ORCID: 0009-0001-2022-7072

License

MIT

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

cfad-0.2.2.tar.gz (223.6 kB view details)

Uploaded Source

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

cfad-0.2.2-cp312-cp312-win_amd64.whl (279.5 kB view details)

Uploaded CPython 3.12Windows x86-64

cfad-0.2.2-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl (541.7 kB view details)

Uploaded CPython 3.12manylinux: glibc 2.28+ x86-64manylinux: glibc 2.5+ x86-64

cfad-0.2.2-cp312-cp312-macosx_11_0_arm64.whl (279.2 kB view details)

Uploaded CPython 3.12macOS 11.0+ ARM64

cfad-0.2.2-cp311-cp311-win_amd64.whl (276.5 kB view details)

Uploaded CPython 3.11Windows x86-64

cfad-0.2.2-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl (504.9 kB view details)

Uploaded CPython 3.11manylinux: glibc 2.28+ x86-64manylinux: glibc 2.5+ x86-64

cfad-0.2.2-cp311-cp311-macosx_11_0_arm64.whl (276.4 kB view details)

Uploaded CPython 3.11macOS 11.0+ ARM64

cfad-0.2.2-cp310-cp310-win_amd64.whl (277.4 kB view details)

Uploaded CPython 3.10Windows x86-64

cfad-0.2.2-cp310-cp310-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl (499.6 kB view details)

Uploaded CPython 3.10manylinux: glibc 2.28+ x86-64manylinux: glibc 2.5+ x86-64

cfad-0.2.2-cp310-cp310-macosx_11_0_arm64.whl (277.8 kB view details)

Uploaded CPython 3.10macOS 11.0+ ARM64

File details

Details for the file cfad-0.2.2.tar.gz.

File metadata

  • Download URL: cfad-0.2.2.tar.gz
  • Upload date:
  • Size: 223.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for cfad-0.2.2.tar.gz
Algorithm Hash digest
SHA256 d40b08f0bb1958ef7d55da4be1f71e7f14973054eecb158f777e6514e60798c6
MD5 e3be3e1355aca0e431b93b66dcdf5659
BLAKE2b-256 898644837ad7ce5c2ffa0dfb297e6e144fe96459a3f46fdb72e9bf0e3502dc08

See more details on using hashes here.

Provenance

The following attestation bundles were made for cfad-0.2.2.tar.gz:

Publisher: publish.yml on DiogoRibeiro7/cfad

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file cfad-0.2.2-cp312-cp312-win_amd64.whl.

File metadata

  • Download URL: cfad-0.2.2-cp312-cp312-win_amd64.whl
  • Upload date:
  • Size: 279.5 kB
  • Tags: CPython 3.12, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for cfad-0.2.2-cp312-cp312-win_amd64.whl
Algorithm Hash digest
SHA256 d7f7584a3953ceb8658902ea07c569ad1c486df14fcf435f3c0a73012036b2f2
MD5 17a346fd82403376ee685e282db20545
BLAKE2b-256 72b4377a2cc94fdbcba1dd7f8e54fb94eaee7641b295ab8a0af5c2d8527069c9

See more details on using hashes here.

Provenance

The following attestation bundles were made for cfad-0.2.2-cp312-cp312-win_amd64.whl:

Publisher: publish.yml on DiogoRibeiro7/cfad

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file cfad-0.2.2-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl.

File metadata

File hashes

Hashes for cfad-0.2.2-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl
Algorithm Hash digest
SHA256 596de8a6c4ca397c004d253a688097365c45341e5e02b87a39dbefffbedf43e5
MD5 cb6c78e0abdf804c82b943f687635547
BLAKE2b-256 51f3a582099492eba07053d2639dce61509b0d36cf4cf221a493ef192e3dabe2

See more details on using hashes here.

Provenance

The following attestation bundles were made for cfad-0.2.2-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl:

Publisher: publish.yml on DiogoRibeiro7/cfad

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file cfad-0.2.2-cp312-cp312-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for cfad-0.2.2-cp312-cp312-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 3b3eeed1c5d57f1f4b7eef61f0c1fa485edb62a055c5fc3e1797c14fdb6948eb
MD5 b80ce8d27e694305ee3aef0d2f15ee7b
BLAKE2b-256 70a8229f532d5ea15269167fea305c6321bd2f8d6a980189721f240745fae799

See more details on using hashes here.

Provenance

The following attestation bundles were made for cfad-0.2.2-cp312-cp312-macosx_11_0_arm64.whl:

Publisher: publish.yml on DiogoRibeiro7/cfad

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file cfad-0.2.2-cp311-cp311-win_amd64.whl.

File metadata

  • Download URL: cfad-0.2.2-cp311-cp311-win_amd64.whl
  • Upload date:
  • Size: 276.5 kB
  • Tags: CPython 3.11, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for cfad-0.2.2-cp311-cp311-win_amd64.whl
Algorithm Hash digest
SHA256 a750637f3980f911f4c18a7f205b3d95d4a2c8baf2999b2c1a762cb54cebacf5
MD5 50375bc9fbb2199f67d4a3847f978e7f
BLAKE2b-256 ecaa00358309cf0f1f4dceb1cc1ca7a99cf7ceb554db2b6cb085b9f1a6071f06

See more details on using hashes here.

Provenance

The following attestation bundles were made for cfad-0.2.2-cp311-cp311-win_amd64.whl:

Publisher: publish.yml on DiogoRibeiro7/cfad

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file cfad-0.2.2-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl.

File metadata

File hashes

Hashes for cfad-0.2.2-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl
Algorithm Hash digest
SHA256 5a8fb35d30a6560b0f6676fc4b24e586266d02f1bf288e1c3d3526c520a66ff2
MD5 99a4d746cba55d0abd18794ff6faea08
BLAKE2b-256 5bcfddbf23be85c986e8a0d055523a37d71da81653732cc0b774a74b2529a9c4

See more details on using hashes here.

Provenance

The following attestation bundles were made for cfad-0.2.2-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl:

Publisher: publish.yml on DiogoRibeiro7/cfad

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file cfad-0.2.2-cp311-cp311-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for cfad-0.2.2-cp311-cp311-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 41ab8f4f14a57f50788fa2f1892de779c774ca8ef7bcb979d76a4e929fc29408
MD5 9d3b279428186dfe1206bd91623b60fe
BLAKE2b-256 bf0c03e3ebe8019d12276fab33681ec8ddfb4488f2e3e7ef7ecae3399ae6612c

See more details on using hashes here.

Provenance

The following attestation bundles were made for cfad-0.2.2-cp311-cp311-macosx_11_0_arm64.whl:

Publisher: publish.yml on DiogoRibeiro7/cfad

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file cfad-0.2.2-cp310-cp310-win_amd64.whl.

File metadata

  • Download URL: cfad-0.2.2-cp310-cp310-win_amd64.whl
  • Upload date:
  • Size: 277.4 kB
  • Tags: CPython 3.10, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for cfad-0.2.2-cp310-cp310-win_amd64.whl
Algorithm Hash digest
SHA256 40b37dc533abe3c3dc95ee3c42d5532b86d72a0e67d455ae291c400eea16c8f0
MD5 40e8fdc49fcb27e9f3643ca121d1ded1
BLAKE2b-256 20f8020a0b1fcd73dca860dba9132144abc909e6b02ec740c97d5753cb2c8764

See more details on using hashes here.

Provenance

The following attestation bundles were made for cfad-0.2.2-cp310-cp310-win_amd64.whl:

Publisher: publish.yml on DiogoRibeiro7/cfad

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file cfad-0.2.2-cp310-cp310-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl.

File metadata

File hashes

Hashes for cfad-0.2.2-cp310-cp310-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl
Algorithm Hash digest
SHA256 1d92c6d7e21e0ef1b6aea7f5ddcf21016f7df59461728c130e8a5da444c2852b
MD5 e7d80c143069a21af9c5f83917cb9ce7
BLAKE2b-256 1285109251a408e8c5b142badaa5877e5d5517271965436c27322cf4d8352c1e

See more details on using hashes here.

Provenance

The following attestation bundles were made for cfad-0.2.2-cp310-cp310-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl:

Publisher: publish.yml on DiogoRibeiro7/cfad

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file cfad-0.2.2-cp310-cp310-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for cfad-0.2.2-cp310-cp310-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 2be7e46bf290a617f78b1ed42148b57bb52511c6e650c54cbbbfc10eefe3cdcc
MD5 e3c07987ec258c92f28472d874138c9d
BLAKE2b-256 98ef4408a149d4f3381e5dd55343afe65bb6984b91a6b08774fda9378373f75b

See more details on using hashes here.

Provenance

The following attestation bundles were made for cfad-0.2.2-cp310-cp310-macosx_11_0_arm64.whl:

Publisher: publish.yml on DiogoRibeiro7/cfad

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

This release

0.2.2 This release

10 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page