mfe-toolbox 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.
Files changed (116) hide show
  1. mfe_toolbox-0.1.0/.github/workflows/docs.yml +18 -0
  2. mfe_toolbox-0.1.0/.github/workflows/publish.yml +55 -0
  3. mfe_toolbox-0.1.0/.gitignore +75 -0
  4. mfe_toolbox-0.1.0/PKG-INFO +84 -0
  5. mfe_toolbox-0.1.0/README.md +70 -0
  6. mfe_toolbox-0.1.0/dev/benchmarks/bench_realized.py +78 -0
  7. mfe_toolbox-0.1.0/docs/api/bootstrap.md +5 -0
  8. mfe_toolbox-0.1.0/docs/api/crosssection.md +5 -0
  9. mfe_toolbox-0.1.0/docs/api/distributions.md +5 -0
  10. mfe_toolbox-0.1.0/docs/api/multivariate.md +5 -0
  11. mfe_toolbox-0.1.0/docs/api/realized.md +5 -0
  12. mfe_toolbox-0.1.0/docs/api/tests_stat.md +5 -0
  13. mfe_toolbox-0.1.0/docs/api/timeseries.md +5 -0
  14. mfe_toolbox-0.1.0/docs/api/univariate.md +5 -0
  15. mfe_toolbox-0.1.0/docs/api/utils.md +5 -0
  16. mfe_toolbox-0.1.0/docs/changelog.md +74 -0
  17. mfe_toolbox-0.1.0/docs/guide/bootstrap.md +34 -0
  18. mfe_toolbox-0.1.0/docs/guide/comparison.md +77 -0
  19. mfe_toolbox-0.1.0/docs/guide/crosssection.md +41 -0
  20. mfe_toolbox-0.1.0/docs/guide/distributions.md +40 -0
  21. mfe_toolbox-0.1.0/docs/guide/installation.md +62 -0
  22. mfe_toolbox-0.1.0/docs/guide/multivariate.md +57 -0
  23. mfe_toolbox-0.1.0/docs/guide/quickstart.md +161 -0
  24. mfe_toolbox-0.1.0/docs/guide/realized.md +75 -0
  25. mfe_toolbox-0.1.0/docs/guide/timeseries.md +40 -0
  26. mfe_toolbox-0.1.0/docs/guide/univariate.md +38 -0
  27. mfe_toolbox-0.1.0/docs/index.md +141 -0
  28. mfe_toolbox-0.1.0/mkdocs.yml +98 -0
  29. mfe_toolbox-0.1.0/pyproject.toml +57 -0
  30. mfe_toolbox-0.1.0/setup_cython.py +61 -0
  31. mfe_toolbox-0.1.0/src/mfe/__init__.py +18 -0
  32. mfe_toolbox-0.1.0/src/mfe/bootstrap/__init__.py +18 -0
  33. mfe_toolbox-0.1.0/src/mfe/bootstrap/spa.py +217 -0
  34. mfe_toolbox-0.1.0/src/mfe/bootstrap/stepM.py +210 -0
  35. mfe_toolbox-0.1.0/src/mfe/bootstrap/wild.py +169 -0
  36. mfe_toolbox-0.1.0/src/mfe/crosssection/__init__.py +15 -0
  37. mfe_toolbox-0.1.0/src/mfe/crosssection/fm.py +171 -0
  38. mfe_toolbox-0.1.0/src/mfe/crosssection/ols.py +176 -0
  39. mfe_toolbox-0.1.0/src/mfe/crosssection/pca.py +143 -0
  40. mfe_toolbox-0.1.0/src/mfe/distributions/__init__.py +21 -0
  41. mfe_toolbox-0.1.0/src/mfe/distributions/ged.py +85 -0
  42. mfe_toolbox-0.1.0/src/mfe/distributions/mvnorm.py +166 -0
  43. mfe_toolbox-0.1.0/src/mfe/distributions/skewt.py +140 -0
  44. mfe_toolbox-0.1.0/src/mfe/multivariate/__init__.py +22 -0
  45. mfe_toolbox-0.1.0/src/mfe/multivariate/_core.html +2944 -0
  46. mfe_toolbox-0.1.0/src/mfe/multivariate/_core.pyx +303 -0
  47. mfe_toolbox-0.1.0/src/mfe/multivariate/base.py +193 -0
  48. mfe_toolbox-0.1.0/src/mfe/multivariate/bekk.py +415 -0
  49. mfe_toolbox-0.1.0/src/mfe/multivariate/ccc.py +84 -0
  50. mfe_toolbox-0.1.0/src/mfe/multivariate/dcc.py +244 -0
  51. mfe_toolbox-0.1.0/src/mfe/multivariate/gogarch.py +581 -0
  52. mfe_toolbox-0.1.0/src/mfe/multivariate/rcc.py +330 -0
  53. mfe_toolbox-0.1.0/src/mfe/realized/__init__.py +39 -0
  54. mfe_toolbox-0.1.0/src/mfe/realized/_core.html +3075 -0
  55. mfe_toolbox-0.1.0/src/mfe/realized/_core.pyx +225 -0
  56. mfe_toolbox-0.1.0/src/mfe/realized/_core_fallback.py +26 -0
  57. mfe_toolbox-0.1.0/src/mfe/realized/_types.py +73 -0
  58. mfe_toolbox-0.1.0/src/mfe/realized/covariance.py +217 -0
  59. mfe_toolbox-0.1.0/src/mfe/realized/jumps.py +76 -0
  60. mfe_toolbox-0.1.0/src/mfe/realized/kernel.py +208 -0
  61. mfe_toolbox-0.1.0/src/mfe/realized/multivariate_kernel.py +133 -0
  62. mfe_toolbox-0.1.0/src/mfe/realized/noise.py +67 -0
  63. mfe_toolbox-0.1.0/src/mfe/realized/quantile_var.py +123 -0
  64. mfe_toolbox-0.1.0/src/mfe/realized/quarticity.py +44 -0
  65. mfe_toolbox-0.1.0/src/mfe/realized/range_.py +131 -0
  66. mfe_toolbox-0.1.0/src/mfe/realized/sampling.py +205 -0
  67. mfe_toolbox-0.1.0/src/mfe/realized/tsrv.py +178 -0
  68. mfe_toolbox-0.1.0/src/mfe/realized/variance.py +256 -0
  69. mfe_toolbox-0.1.0/src/mfe/tests_stat/__init__.py +24 -0
  70. mfe_toolbox-0.1.0/src/mfe/tests_stat/arch_lm.py +95 -0
  71. mfe_toolbox-0.1.0/src/mfe/tests_stat/forecast_eval.py +186 -0
  72. mfe_toolbox-0.1.0/src/mfe/tests_stat/serial.py +150 -0
  73. mfe_toolbox-0.1.0/src/mfe/timeseries/__init__.py +18 -0
  74. mfe_toolbox-0.1.0/src/mfe/timeseries/beveridge_nelson.py +289 -0
  75. mfe_toolbox-0.1.0/src/mfe/timeseries/var.py +599 -0
  76. mfe_toolbox-0.1.0/src/mfe/univariate/__init__.py +15 -0
  77. mfe_toolbox-0.1.0/src/mfe/univariate/har.py +225 -0
  78. mfe_toolbox-0.1.0/src/mfe/univariate/heavy.py +332 -0
  79. mfe_toolbox-0.1.0/src/mfe/utils/__init__.py +16 -0
  80. mfe_toolbox-0.1.0/src/mfe/utils/lags.py +96 -0
  81. mfe_toolbox-0.1.0/src/mfe/utils/typing.py +27 -0
  82. mfe_toolbox-0.1.0/src/mfe/utils/vcv.py +73 -0
  83. mfe_toolbox-0.1.0/tests/__init__.py +0 -0
  84. mfe_toolbox-0.1.0/tests/conftest.py +62 -0
  85. mfe_toolbox-0.1.0/tests/test_bootstrap/__init__.py +0 -0
  86. mfe_toolbox-0.1.0/tests/test_bootstrap/test_spa.py +58 -0
  87. mfe_toolbox-0.1.0/tests/test_bootstrap/test_stepm.py +56 -0
  88. mfe_toolbox-0.1.0/tests/test_bootstrap/test_wild.py +49 -0
  89. mfe_toolbox-0.1.0/tests/test_crosssection/__init__.py +0 -0
  90. mfe_toolbox-0.1.0/tests/test_crosssection/test_fm.py +44 -0
  91. mfe_toolbox-0.1.0/tests/test_crosssection/test_ols.py +96 -0
  92. mfe_toolbox-0.1.0/tests/test_crosssection/test_pca.py +67 -0
  93. mfe_toolbox-0.1.0/tests/test_distributions/__init__.py +0 -0
  94. mfe_toolbox-0.1.0/tests/test_distributions/test_mvnorm.py +85 -0
  95. mfe_toolbox-0.1.0/tests/test_multivariate/__init__.py +0 -0
  96. mfe_toolbox-0.1.0/tests/test_multivariate/test_bekk.py +43 -0
  97. mfe_toolbox-0.1.0/tests/test_multivariate/test_gogarch.py +268 -0
  98. mfe_toolbox-0.1.0/tests/test_multivariate/test_rcc.py +112 -0
  99. mfe_toolbox-0.1.0/tests/test_realized/__init__.py +0 -0
  100. mfe_toolbox-0.1.0/tests/test_realized/test_covariance.py +80 -0
  101. mfe_toolbox-0.1.0/tests/test_realized/test_cython_parity.py +155 -0
  102. mfe_toolbox-0.1.0/tests/test_realized/test_kernel.py +62 -0
  103. mfe_toolbox-0.1.0/tests/test_realized/test_range.py +56 -0
  104. mfe_toolbox-0.1.0/tests/test_realized/test_tsrv_qrv_mk.py +152 -0
  105. mfe_toolbox-0.1.0/tests/test_realized/test_variance.py +80 -0
  106. mfe_toolbox-0.1.0/tests/test_tests_stat/__init__.py +0 -0
  107. mfe_toolbox-0.1.0/tests/test_tests_stat/test_arch_lm.py +43 -0
  108. mfe_toolbox-0.1.0/tests/test_tests_stat/test_serial.py +68 -0
  109. mfe_toolbox-0.1.0/tests/test_timeseries/__init__.py +0 -0
  110. mfe_toolbox-0.1.0/tests/test_timeseries/test_beveridge_nelson.py +85 -0
  111. mfe_toolbox-0.1.0/tests/test_timeseries/test_var.py +142 -0
  112. mfe_toolbox-0.1.0/tests/test_univariate/__init__.py +0 -0
  113. mfe_toolbox-0.1.0/tests/test_univariate/test_har.py +35 -0
  114. mfe_toolbox-0.1.0/tests/test_univariate/test_har_extended.py +86 -0
  115. mfe_toolbox-0.1.0/tests/test_univariate/test_heavy.py +63 -0
  116. mfe_toolbox-0.1.0/uv.lock +2671 -0
@@ -0,0 +1,18 @@
1
+ name: Deploy docs
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+
7
+ jobs:
8
+ deploy:
9
+ runs-on: ubuntu-latest
10
+ permissions:
11
+ contents: write
12
+ steps:
13
+ - uses: actions/checkout@v4
14
+ - uses: actions/setup-python@v5
15
+ with:
16
+ python-version: "3.12"
17
+ - run: pip install mkdocs-material mkdocstrings[python]
18
+ - run: mkdocs gh-deploy --force
@@ -0,0 +1,55 @@
1
+ name: Publish to PyPI
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - "v*"
7
+
8
+ jobs:
9
+ build:
10
+ runs-on: ubuntu-latest
11
+ steps:
12
+ - uses: actions/checkout@v4
13
+
14
+ - uses: actions/setup-python@v5
15
+ with:
16
+ python-version: "3.12"
17
+
18
+ - run: pip install uv
19
+ - run: uv sync --all-groups
20
+ - run: uv build
21
+
22
+ - uses: actions/upload-artifact@v4
23
+ with:
24
+ name: dist
25
+ path: dist/
26
+
27
+ publish-testpypi:
28
+ needs: build
29
+ runs-on: ubuntu-latest
30
+ environment: testpypi
31
+ permissions:
32
+ id-token: write
33
+ steps:
34
+ - uses: actions/download-artifact@v4
35
+ with:
36
+ name: dist
37
+ path: dist/
38
+
39
+ - uses: pypa/gh-action-pypi-publish@release/v1
40
+ with:
41
+ repository-url: https://test.pypi.org/legacy/
42
+
43
+ publish-pypi:
44
+ needs: publish-testpypi
45
+ runs-on: ubuntu-latest
46
+ environment: pypi
47
+ permissions:
48
+ id-token: write
49
+ steps:
50
+ - uses: actions/download-artifact@v4
51
+ with:
52
+ name: dist
53
+ path: dist/
54
+
55
+ - uses: pypa/gh-action-pypi-publish@release/v1
@@ -0,0 +1,75 @@
1
+ # Python
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+ *.pyo
6
+ .Python
7
+
8
+ # Virtual environments
9
+ .venv/
10
+ venv/
11
+ env/
12
+
13
+ # uv
14
+ .uv/
15
+
16
+ # Distribution / packaging
17
+ dist/
18
+ build/
19
+ *.egg-info/
20
+ *.egg
21
+ MANIFEST
22
+
23
+ # Cython compiled files
24
+ *.c
25
+ *.cpp
26
+ *.so
27
+ *.pyd
28
+ *.html # Cython annotation files (from annotate=True)
29
+
30
+ # Cython build artifacts
31
+ src/mfe/realized/_core.cpython-*.so
32
+ src/mfe/multivariate/_core.cpython-*.so
33
+
34
+ # setuptools build directories
35
+ build/
36
+ lib.*/
37
+ temp.*/
38
+
39
+ # pytest
40
+ .pytest_cache/
41
+ .cache/
42
+ htmlcov/
43
+ .coverage
44
+ coverage.xml
45
+ *.cover
46
+
47
+ # mypy
48
+ .mypy_cache/
49
+ .dmypy.json
50
+
51
+ # ruff
52
+ .ruff_cache/
53
+
54
+ # MkDocs
55
+ site/
56
+
57
+ # Jupyter
58
+ .ipynb_checkpoints/
59
+ *.ipynb
60
+
61
+ # IDE
62
+ .idea/
63
+ .vscode/
64
+ *.swp
65
+ *.swo
66
+ *~
67
+ .DS_Store
68
+
69
+ # Profiling
70
+ *.prof
71
+ *.lprof
72
+
73
+ # Local dev
74
+ .env
75
+ *.local
@@ -0,0 +1,84 @@
1
+ Metadata-Version: 2.5
2
+ Name: mfe-toolbox
3
+ Version: 0.1.0
4
+ Summary: Python port of the MFE Toolbox — financial econometrics for HFT data
5
+ Author: Gabin Taibi
6
+ License-Expression: MIT
7
+ Requires-Python: >=3.11
8
+ Requires-Dist: arch>=6.2
9
+ Requires-Dist: numpy>=1.26
10
+ Requires-Dist: pandas>=2.1
11
+ Requires-Dist: scipy>=1.11
12
+ Requires-Dist: statsmodels>=0.14
13
+ Description-Content-Type: text/markdown
14
+
15
+ # mfe — Financial Econometrics for Python
16
+
17
+ Python port of Kevin Sheppard's Oxford MFE Toolbox, optimised for HFT data.
18
+ Complements [`arch`](https://arch.readthedocs.io) — covering everything `arch` is missing.
19
+
20
+ ## What's inside
21
+
22
+ | Module | Contents |
23
+ |--------|----------|
24
+ | `mfe.realized` | RV, BPV, MedRV, realized kernel, TSRV, MSRV, Hayashi-Yoshida, multivariate kernel, BNS jump test |
25
+ | `mfe.multivariate` | DCC, CCC, BEKK, O-GARCH, GO-GARCH, RCC |
26
+ | `mfe.univariate` | HAR-RV (standard / MODIFIED / matrix intervals / HAR-J), HEAVY |
27
+ | `mfe.timeseries` | VAR (4 VCV options), Granger causality, IRF, Beveridge-Nelson |
28
+ | `mfe.bootstrap` | Wild bootstrap, SPA test (Hansen 2005), StepM (Romano-Wolf 2005) |
29
+ | `mfe.crosssection` | Fama-MacBeth, OLS/OLSNW, PCA |
30
+ | `mfe.tests_stat` | ARCH-LM, Ljung-Box, HAC LM, Diebold-Mariano, Mincer-Zarnowitz |
31
+ | `mfe.distributions` | Skew-t (analytic score), GED, multivariate normal log-likelihood |
32
+
33
+ ## Installation
34
+
35
+ ```bash
36
+ pip install mfe
37
+ ```
38
+
39
+ ## Cython extensions (optional, recommended for production)
40
+
41
+ Cython compilation gives 10–800× speedups on hot paths (realized kernel inner
42
+ loop, Hayashi-Yoshida sweep, DCC/BEKK recursions):
43
+
44
+ ```bash
45
+ pip install cython numpy setuptools
46
+ python setup_cython.py build_ext --inplace
47
+ ```
48
+
49
+ ## Quick start
50
+
51
+ ```python
52
+ from mfe.realized import price_filter, returns_from_prices, realized_kernel, bns_jump_test
53
+ from mfe.realized._types import SamplingType
54
+
55
+ prices_5m, times_5m = price_filter(
56
+ tick_prices, tick_times,
57
+ sampling_type=SamplingType.CALENDAR_TIME,
58
+ sampling_interval=300,
59
+ )
60
+ r = returns_from_prices(prices_5m)
61
+ rk = realized_kernel(r)
62
+ jmp = bns_jump_test(r)
63
+
64
+ from mfe.multivariate import DCC, RCC
65
+ dcc = DCC().fit(returns) # (T, K) → (T, K, K) sigma_t
66
+ rcc = RCC().fit(returns) # covariance targeting by construction
67
+
68
+ from mfe.univariate import HEAVY
69
+ heavy = HEAVY().fit(daily_returns, realized_variances)
70
+ ```
71
+
72
+ ## Development
73
+
74
+ ```bash
75
+ uv sync --all-groups
76
+ PYTHONPATH=src pytest tests/ # 246 tests
77
+ mkdocs serve # documentation
78
+ ```
79
+
80
+ ## Relationship to MATLAB MFE Toolbox
81
+
82
+ This package ports [bashtage/mfe-toolbox](https://github.com/bashtage/mfe-toolbox)
83
+ to Python, fixing several bugs present in the MATLAB source (memory leaks, silent
84
+ non-convergence, O(N²) algorithms replaced with O(N log N) Cython implementations).
@@ -0,0 +1,70 @@
1
+ # mfe — Financial Econometrics for Python
2
+
3
+ Python port of Kevin Sheppard's Oxford MFE Toolbox, optimised for HFT data.
4
+ Complements [`arch`](https://arch.readthedocs.io) — covering everything `arch` is missing.
5
+
6
+ ## What's inside
7
+
8
+ | Module | Contents |
9
+ |--------|----------|
10
+ | `mfe.realized` | RV, BPV, MedRV, realized kernel, TSRV, MSRV, Hayashi-Yoshida, multivariate kernel, BNS jump test |
11
+ | `mfe.multivariate` | DCC, CCC, BEKK, O-GARCH, GO-GARCH, RCC |
12
+ | `mfe.univariate` | HAR-RV (standard / MODIFIED / matrix intervals / HAR-J), HEAVY |
13
+ | `mfe.timeseries` | VAR (4 VCV options), Granger causality, IRF, Beveridge-Nelson |
14
+ | `mfe.bootstrap` | Wild bootstrap, SPA test (Hansen 2005), StepM (Romano-Wolf 2005) |
15
+ | `mfe.crosssection` | Fama-MacBeth, OLS/OLSNW, PCA |
16
+ | `mfe.tests_stat` | ARCH-LM, Ljung-Box, HAC LM, Diebold-Mariano, Mincer-Zarnowitz |
17
+ | `mfe.distributions` | Skew-t (analytic score), GED, multivariate normal log-likelihood |
18
+
19
+ ## Installation
20
+
21
+ ```bash
22
+ pip install mfe
23
+ ```
24
+
25
+ ## Cython extensions (optional, recommended for production)
26
+
27
+ Cython compilation gives 10–800× speedups on hot paths (realized kernel inner
28
+ loop, Hayashi-Yoshida sweep, DCC/BEKK recursions):
29
+
30
+ ```bash
31
+ pip install cython numpy setuptools
32
+ python setup_cython.py build_ext --inplace
33
+ ```
34
+
35
+ ## Quick start
36
+
37
+ ```python
38
+ from mfe.realized import price_filter, returns_from_prices, realized_kernel, bns_jump_test
39
+ from mfe.realized._types import SamplingType
40
+
41
+ prices_5m, times_5m = price_filter(
42
+ tick_prices, tick_times,
43
+ sampling_type=SamplingType.CALENDAR_TIME,
44
+ sampling_interval=300,
45
+ )
46
+ r = returns_from_prices(prices_5m)
47
+ rk = realized_kernel(r)
48
+ jmp = bns_jump_test(r)
49
+
50
+ from mfe.multivariate import DCC, RCC
51
+ dcc = DCC().fit(returns) # (T, K) → (T, K, K) sigma_t
52
+ rcc = RCC().fit(returns) # covariance targeting by construction
53
+
54
+ from mfe.univariate import HEAVY
55
+ heavy = HEAVY().fit(daily_returns, realized_variances)
56
+ ```
57
+
58
+ ## Development
59
+
60
+ ```bash
61
+ uv sync --all-groups
62
+ PYTHONPATH=src pytest tests/ # 246 tests
63
+ mkdocs serve # documentation
64
+ ```
65
+
66
+ ## Relationship to MATLAB MFE Toolbox
67
+
68
+ This package ports [bashtage/mfe-toolbox](https://github.com/bashtage/mfe-toolbox)
69
+ to Python, fixing several bugs present in the MATLAB source (memory leaks, silent
70
+ non-convergence, O(N²) algorithms replaced with O(N log N) Cython implementations).
@@ -0,0 +1,78 @@
1
+ """
2
+ Performance benchmarks for mfe.realized on HFT-scale data.
3
+
4
+ Run with:
5
+ cd repo_root
6
+ PYTHONPATH=src python dev/benchmarks/bench_realized.py
7
+
8
+ Or with pytest-benchmark:
9
+ PYTHONPATH=src pytest dev/benchmarks/bench_realized.py --benchmark-only
10
+
11
+ Target: all operations on T=1_000_000 ticks should complete in < 5s
12
+ on a modern CPU without Cython (pure numpy). With Cython, kernel inner
13
+ loop should be ~10x faster.
14
+ """
15
+
16
+ import time
17
+
18
+ import numpy as np
19
+
20
+ from mfe.realized import (
21
+ realized_variance,
22
+ realized_bipower_variation,
23
+ realized_med_variance,
24
+ realized_kernel,
25
+ bns_jump_test,
26
+ )
27
+ from mfe.realized.covariance import realized_hayashi_yoshida
28
+
29
+
30
+ def _make_returns(T: int, seed: int = 0) -> np.ndarray:
31
+ rng = np.random.default_rng(seed)
32
+ return rng.standard_normal(T) * 0.001
33
+
34
+
35
+ def _make_tick_prices(T: int, seed: int = 0):
36
+ rng = np.random.default_rng(seed)
37
+ price = np.exp(np.cumsum(rng.standard_normal(T) * 0.001))
38
+ time_ = np.sort(rng.uniform(0, 23400, T))
39
+ return price, time_
40
+
41
+
42
+ def bench(label: str, fn, *args, n_runs: int = 3):
43
+ times = []
44
+ for _ in range(n_runs):
45
+ t0 = time.perf_counter()
46
+ fn(*args)
47
+ times.append(time.perf_counter() - t0)
48
+ mean_ms = np.mean(times) * 1000
49
+ print(f" {label:<40s} {mean_ms:8.1f} ms (n={n_runs})")
50
+
51
+
52
+ if __name__ == "__main__":
53
+ print("=" * 60)
54
+ print("mfe.realized benchmarks")
55
+ print("=" * 60)
56
+
57
+ for T in [10_000, 100_000, 500_000]:
58
+ print(f"\nT = {T:,} returns")
59
+ r = _make_returns(T)
60
+
61
+ bench("realized_variance", realized_variance, r)
62
+ bench("realized_bipower_variation (skip=0)", realized_bipower_variation, r, 0)
63
+ bench("realized_bipower_variation (skip=1)", realized_bipower_variation, r, 1)
64
+ bench("realized_med_variance", realized_med_variance, r)
65
+ bench("realized_kernel (auto bandwidth)", realized_kernel, r)
66
+ bench("bns_jump_test", bns_jump_test, r)
67
+
68
+ print(f"\nHayashi-Yoshida bivariate (non-synchronous)")
69
+ for T in [1_000, 5_000, 10_000]:
70
+ p1, t1 = _make_tick_prices(T, seed=0)
71
+ p2, t2 = _make_tick_prices(T, seed=1)
72
+ # HY is O(N1 * N2) in worst case with the current numpy impl
73
+ bench(f" HY T={T:,}", realized_hayashi_yoshida, [p1, p2], [t1, t2], n_runs=2)
74
+
75
+ print()
76
+ print("NOTE: Cython uses event-sweep with swap-remove open-list.")
77
+ print(" Complexity: O((N1+N2)*log(N1+N2)) sort + O((N1+N2)*k) sweep")
78
+ print(" where k = avg simultaneous open intervals (typically O(1) for HFT data).")
@@ -0,0 +1,5 @@
1
+ # mfe.bootstrap
2
+
3
+ ::: mfe.bootstrap
4
+ options:
5
+ show_submodules: true
@@ -0,0 +1,5 @@
1
+ # mfe.crosssection
2
+
3
+ ::: mfe.crosssection
4
+ options:
5
+ show_submodules: true
@@ -0,0 +1,5 @@
1
+ # mfe.distributions
2
+
3
+ ::: mfe.distributions
4
+ options:
5
+ show_submodules: true
@@ -0,0 +1,5 @@
1
+ # mfe.multivariate
2
+
3
+ ::: mfe.multivariate
4
+ options:
5
+ show_submodules: true
@@ -0,0 +1,5 @@
1
+ # mfe.realized
2
+
3
+ ::: mfe.realized
4
+ options:
5
+ show_submodules: true
@@ -0,0 +1,5 @@
1
+ # mfe.tests_stat
2
+
3
+ ::: mfe.tests_stat
4
+ options:
5
+ show_submodules: true
@@ -0,0 +1,5 @@
1
+ # mfe.timeseries
2
+
3
+ ::: mfe.timeseries
4
+ options:
5
+ show_submodules: true
@@ -0,0 +1,5 @@
1
+ # mfe.univariate
2
+
3
+ ::: mfe.univariate
4
+ options:
5
+ show_submodules: true
@@ -0,0 +1,5 @@
1
+ # mfe.utils
2
+
3
+ ::: mfe.utils
4
+ options:
5
+ show_submodules: true
@@ -0,0 +1,74 @@
1
+ # Changelog
2
+
3
+ ## 0.1.0 (2026-09)
4
+
5
+ Initial release — Python port of the Oxford MFE Toolbox.
6
+
7
+ ### mfe.realized
8
+ - `realized_variance`, `realized_bipower_variation` (skip-k), `realized_med_variance`, `realized_min_variance`, `realized_preaveraged_variance`, `realized_semivariance`, `realized_quantile_variance`
9
+ - `realized_kernel` (Parzen/Bartlett/Tukey-Hanning/Cubic/Epanechnikov/FlatTop, auto-bandwidth)
10
+ - `tsrv`, `msrv` — Two-Scale and Multi-Scale Realized Variance
11
+ - `realized_covariance`, `realized_correlation`, `realized_hayashi_yoshida`, `realized_covariance_refresh_time`
12
+ - `realized_multivariate_kernel` — PSD-guaranteed (K,K) multivariate realized kernel
13
+ - `realized_range`, `realized_range_from_ticks`
14
+ - `bns_jump_test`, `estimate_noise_variance`, `realized_quarticity`, `realized_tripower_quarticity`
15
+ - `price_filter`, `returns_from_prices`, `refresh_time`
16
+ - Cython extensions: `_autocovariance_sum`, `_bpv_sum`, `_medvar_triplets`, `_hy_sweep`, `_refresh_time_indices`
17
+
18
+ ### mfe.multivariate
19
+ - `DCC` (Engle 2002) with cDCC and DECO variants
20
+ - `CCC` (Bollerslev 1990)
21
+ - `BEKK` scalar and diagonal (Engle & Kroner 1995)
22
+ - `OGARCH` (Alexander 2001)
23
+ - `GOGARCH` ICA and moments rotation (van der Weide 2002)
24
+ - `RCC` symmetric and Cholesky rotation (Noureldin, Shephard & Sheppard 2014)
25
+ - Cython extensions: `_dcc_q_recursion`, `_dcc_corr_loglik`, `_bekk_scalar_recursion`, `_bekk_diagonal_recursion`
26
+
27
+ ### mfe.univariate
28
+ - `har_rv` — standard, MODIFIED spec, matrix intervals
29
+ - `har_rv_j` — jump-augmented HAR
30
+ - `har_forecast` — multi-step forecasting
31
+ - `HEAVY` — joint model of returns + realized variance (Shephard & Sheppard 2010)
32
+
33
+ ### mfe.timeseries
34
+ - `vectorar` — VAR(P) with 4 VCV options (homo/het × corr/uncorr)
35
+ - `grangercause` — Granger causality LR/LM/Wald with robust VCV
36
+ - `impulse_response` — IRF with delta-method standard errors
37
+ - `beveridge_nelson` — AR and state-space methods, auto order selection
38
+
39
+ ### mfe.bootstrap
40
+ - `wild_bootstrap_rv`, `wild_bootstrap_test` — Rademacher/Mammen/Normal multipliers
41
+ - `spa_test` — Hansen (2005) SPA: consistent, upper (Reality Check), lower p-values
42
+ - `step_m` — Romano & Wolf (2005) stepdown FWER control
43
+
44
+ ### mfe.crosssection
45
+ - `ols`, `olsnw` — OLS with White / Newey-West SEs
46
+ - `fama_macbeth` — Fama-MacBeth with Shanken correction
47
+ - `rolling_betas`, `pca`
48
+
49
+ ### mfe.tests_stat
50
+ - `ljung_box` — Ljung-Box Q statistic
51
+ - `lm_test` — HAC-robust LM serial correlation test (MFE lmtest1.m)
52
+ - `arch_lm` — Engle (1982) ARCH-LM test (LM form + F form)
53
+ - `mincer_zarnowitz` — MZ regression forecast evaluation
54
+ - `diebold_mariano` — DM test (MSE/MAE/QLIKE loss)
55
+
56
+ ### mfe.distributions
57
+ - `skewt_logpdf`, `skewt_ppf`, `skewt_score` — Hansen (1994) Skew-t with analytic gradient
58
+ - `ged_logpdf`, `ged_ppf`, `ged_score` — Generalized Error Distribution
59
+ - `mvnorm_loglik`, `mvnorm_loglik_t`, `mahalanobis`, `standardize_mvn`
60
+
61
+ ### mfe.utils
62
+ - `lag_matrix`, `har_lag_matrix`
63
+ - `sandwich`, `newey_west`
64
+ - Type aliases: `FloatArray`, `IntArray`, etc.
65
+
66
+ ### Bugs fixed vs. MATLAB source
67
+ - `gogarch.m`: memory leak via closure over `volData` inside `fmincon` loop → eliminated
68
+ - All univariate estimators: `MFEToolbox:Convergence` silently used bad params → `ConvergenceWarning`
69
+ - `realized_kernel.m`: parameter validation mixed into hot path → separated
70
+ - `realized_bipower_variation.m`: inconsistent `skip` default → standardised to 0
71
+ - `dcc.m`: `Q_bar` recomputed inside likelihood → pre-computed
72
+ - No sandwich VCV in MATLAB multivariate → standard in all `mfe` estimators
73
+ - `realized_hayashi_yoshida.m` TODO for K>2 → implemented for general K
74
+ - HY Cython: `sort_key = time * 4 + type` loses bits for large timestamps → `np.lexsort`
@@ -0,0 +1,34 @@
1
+ # Bootstrap & Multiple Testing
2
+
3
+ ## Wild bootstrap (realized volatility)
4
+
5
+ ```python
6
+ from mfe.bootstrap import wild_bootstrap_rv, wild_bootstrap_test
7
+
8
+ # 95% CI for a realized volatility statistic
9
+ result = wild_bootstrap_rv(r, n_replications=999, multiplier="rademacher")
10
+ print(f"Statistic: {result.statistic:.6f}")
11
+ print(f"95% CI: [{result.ci_lower:.6f}, {result.ci_upper:.6f}]")
12
+ ```
13
+
14
+ ## SPA test (Superior Predictive Ability)
15
+
16
+ ```python
17
+ from mfe.bootstrap import spa_test
18
+
19
+ # loss_benchmark: (T,) loss for benchmark model
20
+ # loss_models: (T, M) losses for M alternatives (lower = better)
21
+ res = spa_test(loss_benchmark, loss_models, n_bootstrap=999)
22
+ print(f"SPA p-value (consistent): {res.p_value_consistent:.3f}")
23
+ print(f"Reality Check p-value: {res.p_value_upper:.3f}")
24
+ ```
25
+
26
+ ## StepM (Romano-Wolf FWER control)
27
+
28
+ ```python
29
+ from mfe.bootstrap import step_m
30
+
31
+ res = step_m(loss_benchmark, loss_models, alpha=0.05, n_bootstrap=999)
32
+ print(f"Models beating benchmark: {res.rejected}") # indices, 0-based
33
+ print(f"FWER-adjusted p-values: {res.p_values_adjusted.round(3)}")
34
+ ```
@@ -0,0 +1,77 @@
1
+ # mfe vs. arch vs. statsmodels
2
+
3
+ ## Decision guide
4
+
5
+ | Task | Use |
6
+ |---|---|
7
+ | GARCH / EGARCH / TARCH / APARCH estimation | [`arch`](https://arch.readthedocs.io) |
8
+ | FIGARCH, HARCH, MIDAS-GARCH | `arch` |
9
+ | Unit root tests (ADF, PP, KPSS, DFGLS) | `arch.unitroot` |
10
+ | Cointegration (Johansen, Engle-Granger) | `statsmodels` |
11
+ | ARMA/ARMAX estimation | `statsmodels` |
12
+ | VAR with robust VCV options | **`mfe`** |
13
+ | Granger causality with heteroskedastic VCV | **`mfe`** |
14
+ | Impulse response functions under heteroskedasticity | **`mfe`** |
15
+ | Realized variance / BPV / MedRV | **`mfe`** |
16
+ | Realized kernel (noise-robust) | **`mfe`** |
17
+ | TSRV / MSRV (two-scale noise correction) | **`mfe`** |
18
+ | Hayashi-Yoshida non-synchronous covariance | **`mfe`** |
19
+ | Multivariate realized kernel (PSD guaranteed) | **`mfe`** |
20
+ | DCC-GARCH | **`mfe`** |
21
+ | BEKK-GARCH | **`mfe`** |
22
+ | CCC-GARCH | **`mfe`** |
23
+ | GO-GARCH / O-GARCH | **`mfe`** |
24
+ | RCC (Rotated Conditional Correlation) | **`mfe`** |
25
+ | HAR-RV model | **`mfe`** |
26
+ | HEAVY model (realized variance in mean equation) | **`mfe`** |
27
+ | Beveridge-Nelson decomposition | **`mfe`** |
28
+ | SPA test / StepM FWER | **`mfe`** |
29
+ | Wild bootstrap for realized volatility | **`mfe`** |
30
+ | Fama-MacBeth regression | **`mfe`** |
31
+ | OLS with White / Newey-West SEs | **`mfe`** (thin wrapper) or `statsmodels` |
32
+ | PCA with financial conventions | **`mfe`** |
33
+ | Hansen Skew-t / GED distributions (standalone) | **`mfe`** |
34
+
35
+ ## Key API differences
36
+
37
+ ### arch (univariate, correct home for GARCH)
38
+
39
+ ```python
40
+ from arch import arch_model
41
+ am = arch_model(returns, vol="Garch", p=1, q=1)
42
+ res = am.fit()
43
+ ```
44
+
45
+ ### mfe (multivariate, realized, everything arch doesn't cover)
46
+
47
+ ```python
48
+ from mfe.multivariate import DCC
49
+ from mfe.realized import realized_kernel
50
+
51
+ dcc = DCC().fit(returns) # (T, K) → (T, K, K) sigma_t
52
+ rk = realized_kernel(r) # noise-robust RV
53
+ ```
54
+
55
+ ### statsmodels (ARIMA, VAR basic, cointegration)
56
+
57
+ ```python
58
+ from statsmodels.tsa.api import VAR
59
+ mod = VAR(data)
60
+ res = mod.fit(maxlags=2)
61
+ # → no robust VCV, no GC test with het-robust options
62
+ ```
63
+
64
+ ```python
65
+ from mfe.timeseries import vectorar, grangercause
66
+ res = vectorar(data, lags=2, het=True) # White-robust VCV
67
+ gc = grangercause(data, lags=2, method="wald") # Wald test with robust VCV
68
+ ```
69
+
70
+ ## What mfe does NOT replace
71
+
72
+ - `arch` for any univariate GARCH estimation — we use `arch` internally for
73
+ the first step of DCC/RCC/CCC.
74
+ - `statsmodels` for ARIMA, SARIMA, SARIMAX estimation.
75
+ - `scipy.signal` for filtering.
76
+ - `sklearn.decomposition.PCA` for general-purpose PCA (our PCA is tailored to
77
+ financial returns with covariance convention and factor interpretation tools).
@@ -0,0 +1,41 @@
1
+ # Cross-Section
2
+
3
+ ## OLS and OLSNW
4
+
5
+ ```python
6
+ from mfe.crosssection import ols, olsnw
7
+
8
+ # Y = alpha + X beta + eps
9
+ res = ols(y, X) # White-robust SEs
10
+ res_nw = olsnw(y, X, nw_lags=6) # Newey-West HAC SEs
11
+
12
+ print(res.params, res.std_errors, res.r_squared)
13
+ ```
14
+
15
+ ## Fama-MacBeth
16
+
17
+ ```python
18
+ from mfe.crosssection import fama_macbeth, rolling_betas
19
+
20
+ # Pass 1: rolling betas
21
+ betas = rolling_betas(returns, factors, window=60) # (N, K)
22
+
23
+ # Pass 2: FM
24
+ fm = fama_macbeth(returns, betas, include_intercept=True, shanken_correction=True)
25
+ print(fm.lambda_mean) # (K+1,) mean risk premia
26
+ print(fm.t_stats_shanken) # Shanken-corrected t-stats
27
+ print(fm.r_squared_mean) # mean cross-sectional R²
28
+ ```
29
+
30
+ ## PCA
31
+
32
+ ```python
33
+ from mfe.crosssection import pca
34
+
35
+ res = pca(returns, n_components=3)
36
+ print(res.explained_variance) # proportion per component
37
+ print(res.cumulative_variance) # cumulative
38
+ factors = res.factors # (T, 3) principal components
39
+ loadings = res.loadings # (K, 3) factor loadings
40
+ recon = res.reconstruct(k_c=3) # (T, K) reconstruction from 3 PCs
41
+ ```