dfm-python 0.6.13__tar.gz → 0.7.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.
- {dfm_python-0.6.13 → dfm_python-0.7.0}/.gitignore +2 -1
- dfm_python-0.7.0/CHANGELOG.md +11 -0
- dfm_python-0.7.0/LICENSE +21 -0
- dfm_python-0.7.0/PKG-INFO +186 -0
- dfm_python-0.7.0/README.md +123 -0
- dfm_python-0.7.0/config/afm_finance.yaml +27 -0
- {dfm_python-0.6.13 → dfm_python-0.7.0}/config/ddfm_exchange.yaml +13 -22
- {dfm_python-0.6.13 → dfm_python-0.7.0}/config/ddfm_finance.yaml +12 -11
- dfm_python-0.7.0/config/ivdfm_exchange.yaml +39 -0
- dfm_python-0.7.0/config/ivdfm_finance.yaml +38 -0
- dfm_python-0.7.0/config/ivdfm_macro.yaml +40 -0
- {dfm_python-0.6.13 → dfm_python-0.7.0}/pyproject.toml +12 -8
- {dfm_python-0.6.13 → dfm_python-0.7.0}/src/dfm_python/__init__.py +11 -2
- {dfm_python-0.6.13 → dfm_python-0.7.0}/src/dfm_python/config/__init__.py +6 -6
- {dfm_python-0.6.13 → dfm_python-0.7.0}/src/dfm_python/config/constants.py +90 -0
- dfm_python-0.7.0/src/dfm_python/config/schema/__init__.py +19 -0
- {dfm_python-0.6.13 → dfm_python-0.7.0}/src/dfm_python/config/schema/model.py +403 -1
- {dfm_python-0.6.13 → dfm_python-0.7.0}/src/dfm_python/config/schema/params.py +218 -0
- {dfm_python-0.6.13 → dfm_python-0.7.0}/src/dfm_python/config/schema/results.py +231 -84
- {dfm_python-0.6.13 → dfm_python-0.7.0}/src/dfm_python/dataset/__init__.py +4 -0
- dfm_python-0.7.0/src/dfm_python/dataset/afm_dataset.py +119 -0
- {dfm_python-0.6.13 → dfm_python-0.7.0}/src/dfm_python/dataset/ddfm_dataset.py +21 -0
- dfm_python-0.7.0/src/dfm_python/dataset/ivdfm_dataset.py +427 -0
- {dfm_python-0.6.13 → dfm_python-0.7.0}/src/dfm_python/functional/krylov.py +2 -61
- dfm_python-0.7.0/src/dfm_python/layer/mixing.py +37 -0
- {dfm_python-0.6.13 → dfm_python-0.7.0}/src/dfm_python/layer/mlp.py +38 -19
- {dfm_python-0.6.13 → dfm_python-0.7.0}/src/dfm_python/layer/pca.py +46 -0
- dfm_python-0.7.0/src/dfm_python/layer/regime.py +53 -0
- {dfm_python-0.6.13 → dfm_python-0.7.0}/src/dfm_python/logger/__init__.py +8 -0
- dfm_python-0.7.0/src/dfm_python/logger/ivdfm_logger.py +92 -0
- {dfm_python-0.6.13 → dfm_python-0.7.0}/src/dfm_python/models/__init__.py +10 -0
- dfm_python-0.7.0/src/dfm_python/models/afm/__init__.py +23 -0
- dfm_python-0.7.0/src/dfm_python/models/afm/afm.py +385 -0
- dfm_python-0.7.0/src/dfm_python/models/afm/baselines.py +72 -0
- dfm_python-0.7.0/src/dfm_python/models/afm/factors.py +192 -0
- dfm_python-0.7.0/src/dfm_python/models/afm/longconv.py +97 -0
- {dfm_python-0.6.13 → dfm_python-0.7.0}/src/dfm_python/models/base.py +15 -0
- {dfm_python-0.6.13 → dfm_python-0.7.0}/src/dfm_python/models/ddfm/ddfm.py +17 -8
- dfm_python-0.7.0/src/dfm_python/models/ivdfm/__init__.py +18 -0
- dfm_python-0.7.0/src/dfm_python/models/ivdfm/decoder.py +85 -0
- dfm_python-0.7.0/src/dfm_python/models/ivdfm/encoder.py +198 -0
- dfm_python-0.7.0/src/dfm_python/models/ivdfm/ivdfm.py +1838 -0
- dfm_python-0.7.0/src/dfm_python/models/ivdfm/optuna.py +647 -0
- dfm_python-0.7.0/src/dfm_python/models/ivdfm/prior.py +633 -0
- {dfm_python-0.6.13 → dfm_python-0.7.0}/src/dfm_python/numeric/builder.py +247 -0
- {dfm_python-0.6.13 → dfm_python-0.7.0}/src/dfm_python/numeric/estimator.py +78 -9
- {dfm_python-0.6.13 → dfm_python-0.7.0}/src/dfm_python/numeric/validator.py +5 -0
- {dfm_python-0.6.13 → dfm_python-0.7.0}/src/dfm_python/ssm/__init__.py +6 -0
- dfm_python-0.7.0/src/dfm_python/ssm/base.py +208 -0
- dfm_python-0.7.0/src/dfm_python/ssm/companion.py +500 -0
- {dfm_python-0.6.13 → dfm_python-0.7.0}/src/dfm_python/ssm/kalman.py +100 -3
- dfm_python-0.7.0/src/dfm_python/utils/loss.py +324 -0
- dfm_python-0.7.0/src/test/dataset/test_ivdfm_dataset.py +284 -0
- dfm_python-0.7.0/src/test/models/test_afm.py +241 -0
- dfm_python-0.7.0/src/test/models/test_ivdfm.py +509 -0
- dfm_python-0.7.0/src/test/models/test_ivdfm_optuna.py +262 -0
- dfm_python-0.7.0/src/test/models/test_ivdfm_regime.py +190 -0
- dfm_python-0.7.0/src/test/ssm/test_companion_regime.py +133 -0
- dfm_python-0.7.0/tutorial/tutorial_exchange_ivdfm.py +122 -0
- {dfm_python-0.6.13 → dfm_python-0.7.0}/tutorial/tutorial_finance_ddfm.py +38 -14
- dfm_python-0.7.0/tutorial/tutorial_finance_ivdfm.py +163 -0
- dfm_python-0.7.0/tutorial/tutorial_macro_ivdfm.py +148 -0
- dfm_python-0.6.13/.cursor/agents/test-runner.md +0 -118
- dfm_python-0.6.13/=0.11.0 +0 -1
- dfm_python-0.6.13/PKG-INFO +0 -56
- dfm_python-0.6.13/data/exchange_rate.csv +0 -7589
- dfm_python-0.6.13/data/finance.csv +0 -9022
- dfm_python-0.6.13/data/macro.csv +0 -2539
- dfm_python-0.6.13/src/dfm_python/config/schema/__init__.py +0 -19
- dfm_python-0.6.13/src/dfm_python/functional/cauchy.py +0 -236
- dfm_python-0.6.13/src/dfm_python/models/ivdfm/__init__.py +0 -0
- dfm_python-0.6.13/src/dfm_python/models/ivdfm/decoder.py +0 -0
- dfm_python-0.6.13/src/dfm_python/models/ivdfm/encoder.py +0 -0
- dfm_python-0.6.13/src/dfm_python/models/ivdfm/ivdfm.py +0 -708
- dfm_python-0.6.13/src/dfm_python/utils/loss.py +0 -330
- dfm_python-0.6.13/uv.lock +0 -3817
- {dfm_python-0.6.13 → dfm_python-0.7.0}/.python-version +0 -0
- {dfm_python-0.6.13 → dfm_python-0.7.0}/MANIFEST.in +0 -0
- {dfm_python-0.6.13 → dfm_python-0.7.0}/config/ddfm_macro.yaml +0 -0
- {dfm_python-0.6.13 → dfm_python-0.7.0}/config/dfm_exchange.yaml +0 -0
- {dfm_python-0.6.13 → dfm_python-0.7.0}/config/dfm_finance.yaml +0 -0
- {dfm_python-0.6.13 → dfm_python-0.7.0}/config/dfm_macro.yaml +0 -0
- {dfm_python-0.6.13 → dfm_python-0.7.0}/src/dfm_python/config/adapter.py +0 -0
- {dfm_python-0.6.13 → dfm_python-0.7.0}/src/dfm_python/config/schema/block.py +0 -0
- {dfm_python-0.6.13 → dfm_python-0.7.0}/src/dfm_python/config/types.py +0 -0
- {dfm_python-0.6.13 → dfm_python-0.7.0}/src/dfm_python/dataset/dfm_dataset.py +0 -0
- {dfm_python-0.6.13 → dfm_python-0.7.0}/src/dfm_python/dataset/time.py +0 -0
- {dfm_python-0.6.13 → dfm_python-0.7.0}/src/dfm_python/functional/__init__.py +0 -0
- {dfm_python-0.6.13 → dfm_python-0.7.0}/src/dfm_python/functional/em.py +0 -0
- {dfm_python-0.6.13 → dfm_python-0.7.0}/src/dfm_python/logger/ddfm_logger.py +0 -0
- {dfm_python-0.6.13 → dfm_python-0.7.0}/src/dfm_python/logger/dfm_logger.py +0 -0
- {dfm_python-0.6.13 → dfm_python-0.7.0}/src/dfm_python/logger/inference_logger.py +0 -0
- {dfm_python-0.6.13 → dfm_python-0.7.0}/src/dfm_python/logger/logger.py +0 -0
- {dfm_python-0.6.13 → dfm_python-0.7.0}/src/dfm_python/logger/train_logger.py +0 -0
- {dfm_python-0.6.13 → dfm_python-0.7.0}/src/dfm_python/models/ddfm/__init__.py +0 -0
- {dfm_python-0.6.13 → dfm_python-0.7.0}/src/dfm_python/models/ddfm/decoder.py +0 -0
- {dfm_python-0.6.13 → dfm_python-0.7.0}/src/dfm_python/models/ddfm/encoder.py +0 -0
- {dfm_python-0.6.13 → dfm_python-0.7.0}/src/dfm_python/models/ddfm/sampling.py +0 -0
- {dfm_python-0.6.13 → dfm_python-0.7.0}/src/dfm_python/models/dfm/__init__.py +0 -0
- {dfm_python-0.6.13 → dfm_python-0.7.0}/src/dfm_python/models/dfm/dfm.py +0 -0
- {dfm_python-0.6.13 → dfm_python-0.7.0}/src/dfm_python/models/dfm/initialization.py +0 -0
- {dfm_python-0.6.13 → dfm_python-0.7.0}/src/dfm_python/models/dfm/mixed_freq.py +0 -0
- {dfm_python-0.6.13 → dfm_python-0.7.0}/src/dfm_python/models/dfm/tent.py +0 -0
- {dfm_python-0.6.13 → dfm_python-0.7.0}/src/dfm_python/numeric/stability.py +0 -0
- {dfm_python-0.6.13 → dfm_python-0.7.0}/src/dfm_python/numeric/statistic.py +0 -0
- /dfm_python-0.6.13/src/dfm_python/logger/ivdfm_logger.py → /dfm_python-0.7.0/src/dfm_python/ssm/residual.py +0 -0
- {dfm_python-0.6.13 → dfm_python-0.7.0}/src/dfm_python/utils/__init__.py +0 -0
- {dfm_python-0.6.13 → dfm_python-0.7.0}/src/dfm_python/utils/checkpoint.py +0 -0
- {dfm_python-0.6.13 → dfm_python-0.7.0}/src/dfm_python/utils/errors.py +0 -0
- {dfm_python-0.6.13 → dfm_python-0.7.0}/src/dfm_python/utils/helper.py +0 -0
- {dfm_python-0.6.13 → dfm_python-0.7.0}/src/dfm_python/utils/metric.py +0 -0
- {dfm_python-0.6.13 → dfm_python-0.7.0}/src/dfm_python/utils/misc.py +0 -0
- {dfm_python-0.6.13 → dfm_python-0.7.0}/src/dfm_python/utils/validation.py +0 -0
- {dfm_python-0.6.13 → dfm_python-0.7.0}/src/test/__init__.py +0 -0
- {dfm_python-0.6.13 → dfm_python-0.7.0}/src/test/config/__init__.py +0 -0
- {dfm_python-0.6.13 → dfm_python-0.7.0}/src/test/config/schema/__init__.py +0 -0
- {dfm_python-0.6.13 → dfm_python-0.7.0}/src/test/config/schema/test_block.py +0 -0
- {dfm_python-0.6.13 → dfm_python-0.7.0}/src/test/config/schema/test_model.py +0 -0
- {dfm_python-0.6.13 → dfm_python-0.7.0}/src/test/config/schema/test_results.py +0 -0
- {dfm_python-0.6.13 → dfm_python-0.7.0}/src/test/config/test_adapter.py +0 -0
- {dfm_python-0.6.13 → dfm_python-0.7.0}/src/test/config/test_constants.py +0 -0
- {dfm_python-0.6.13 → dfm_python-0.7.0}/src/test/config/test_tent_weights_config.py +0 -0
- {dfm_python-0.6.13 → dfm_python-0.7.0}/src/test/config/test_types.py +0 -0
- {dfm_python-0.6.13 → dfm_python-0.7.0}/src/test/conftest.py +0 -0
- {dfm_python-0.6.13 → dfm_python-0.7.0}/src/test/dataset/test_ddfm_dataset.py +0 -0
- {dfm_python-0.6.13 → dfm_python-0.7.0}/src/test/dataset/test_dfm_dataset.py +0 -0
- {dfm_python-0.6.13 → dfm_python-0.7.0}/src/test/functional/__init__.py +0 -0
- {dfm_python-0.6.13 → dfm_python-0.7.0}/src/test/functional/test_em.py +0 -0
- {dfm_python-0.6.13 → dfm_python-0.7.0}/src/test/functional/test_em_correctness.py +0 -0
- {dfm_python-0.6.13 → dfm_python-0.7.0}/src/test/functional/test_em_properties.py +0 -0
- {dfm_python-0.6.13 → dfm_python-0.7.0}/src/test/logger/__init__.py +0 -0
- {dfm_python-0.6.13 → dfm_python-0.7.0}/src/test/logger/test_inference_logger.py +0 -0
- {dfm_python-0.6.13 → dfm_python-0.7.0}/src/test/logger/test_logger.py +0 -0
- {dfm_python-0.6.13 → dfm_python-0.7.0}/src/test/logger/test_train_logger.py +0 -0
- {dfm_python-0.6.13 → dfm_python-0.7.0}/src/test/models/__init__.py +0 -0
- {dfm_python-0.6.13 → dfm_python-0.7.0}/src/test/models/test_ddfm.py +0 -0
- {dfm_python-0.6.13 → dfm_python-0.7.0}/src/test/models/test_ddfm_sampling.py +0 -0
- {dfm_python-0.6.13 → dfm_python-0.7.0}/src/test/models/test_dfm.py +0 -0
- {dfm_python-0.6.13 → dfm_python-0.7.0}/src/test/numeric/__init__.py +0 -0
- {dfm_python-0.6.13 → dfm_python-0.7.0}/src/test/numeric/test_builder.py +0 -0
- {dfm_python-0.6.13 → dfm_python-0.7.0}/src/test/numeric/test_cov_rowvar_regression.py +0 -0
- {dfm_python-0.6.13 → dfm_python-0.7.0}/src/test/numeric/test_estimator.py +0 -0
- {dfm_python-0.6.13 → dfm_python-0.7.0}/src/test/numeric/test_initialization.py +0 -0
- {dfm_python-0.6.13 → dfm_python-0.7.0}/src/test/numeric/test_stability.py +0 -0
- {dfm_python-0.6.13 → dfm_python-0.7.0}/src/test/numeric/test_validator.py +0 -0
- {dfm_python-0.6.13 → dfm_python-0.7.0}/src/test/ssm/__init__.py +0 -0
- {dfm_python-0.6.13 → dfm_python-0.7.0}/src/test/ssm/test_kalman.py +0 -0
- {dfm_python-0.6.13 → dfm_python-0.7.0}/src/test/ssm/test_kalman_correctness.py +0 -0
- {dfm_python-0.6.13 → dfm_python-0.7.0}/src/test/utils/__init__.py +0 -0
- {dfm_python-0.6.13 → dfm_python-0.7.0}/src/test/utils/test_errors.py +0 -0
- {dfm_python-0.6.13 → dfm_python-0.7.0}/src/test/utils/test_helper.py +0 -0
- {dfm_python-0.6.13 → dfm_python-0.7.0}/src/test/utils/test_metric.py +0 -0
- {dfm_python-0.6.13 → dfm_python-0.7.0}/src/test/utils/test_misc.py +0 -0
- {dfm_python-0.6.13 → dfm_python-0.7.0}/tutorial/tutorial_exchange_ddfm.py +0 -0
- {dfm_python-0.6.13 → dfm_python-0.7.0}/tutorial/tutorial_exchange_dfm.py +0 -0
- {dfm_python-0.6.13 → dfm_python-0.7.0}/tutorial/tutorial_finance_dfm.py +0 -0
- {dfm_python-0.6.13 → dfm_python-0.7.0}/tutorial/tutorial_macro_ddfm.py +0 -0
- {dfm_python-0.6.13 → dfm_python-0.7.0}/tutorial/tutorial_macro_dfm.py +0 -0
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## 0.7.0
|
|
4
|
+
|
|
5
|
+
- The Attention Factor Model (`dfm_python.models.afm`: `AFM`, attention and PCA
|
|
6
|
+
factors, LongConv filter, Avellaneda-Lee baseline) now ships in the
|
|
7
|
+
distribution; the 0.6.14 wheel on PyPI did not include it.
|
|
8
|
+
- README added and used as the package long description.
|
|
9
|
+
- Metadata: project URLs point to `github.com/minkeymouse/dfm-python`.
|
|
10
|
+
- `build` and `twine` moved from runtime dependencies to the `dev` extra.
|
|
11
|
+
- `__version__` now matches the release; the sdist no longer bundles the example CSVs or the lock file.
|
dfm_python-0.7.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Minkey Chang
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: dfm-python
|
|
3
|
+
Version: 0.7.0
|
|
4
|
+
Summary: Dynamic Factor Model (DFM) estimation and forecasting in Python
|
|
5
|
+
Project-URL: Homepage, https://github.com/minkeymouse/dfm-python
|
|
6
|
+
Project-URL: Documentation, https://github.com/minkeymouse/dfm-python#readme
|
|
7
|
+
Project-URL: Repository, https://github.com/minkeymouse/dfm-python
|
|
8
|
+
Project-URL: Issues, https://github.com/minkeymouse/dfm-python/issues
|
|
9
|
+
Author: Minkey Chang
|
|
10
|
+
License: MIT
|
|
11
|
+
License-File: LICENSE
|
|
12
|
+
Keywords: dfm,dynamic-factor-model,econometrics,forecasting,time-series
|
|
13
|
+
Classifier: Development Status :: 4 - Beta
|
|
14
|
+
Classifier: Intended Audience :: Science/Research
|
|
15
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
16
|
+
Classifier: Programming Language :: Python :: 3
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
21
|
+
Classifier: Topic :: Scientific/Engineering
|
|
22
|
+
Requires-Python: >=3.10
|
|
23
|
+
Requires-Dist: einops>=0.8.1
|
|
24
|
+
Requires-Dist: hydra-core>=1.3.2
|
|
25
|
+
Requires-Dist: matplotlib>=3.5.0
|
|
26
|
+
Requires-Dist: numpy>=1.24.0
|
|
27
|
+
Requires-Dist: optuna>=4.7.0
|
|
28
|
+
Requires-Dist: pandas>=2.0.0
|
|
29
|
+
Requires-Dist: pyarrow>=22.0.0
|
|
30
|
+
Requires-Dist: pykalman>=0.11.0
|
|
31
|
+
Requires-Dist: pytorch-lightning>=2.0.0
|
|
32
|
+
Requires-Dist: scikit-learn>=1.7.2
|
|
33
|
+
Requires-Dist: scipy>=1.10.0
|
|
34
|
+
Requires-Dist: sktime>=0.40.1
|
|
35
|
+
Requires-Dist: torch>=2.0.0
|
|
36
|
+
Provides-Extra: all
|
|
37
|
+
Requires-Dist: build>=1.4.0; extra == 'all'
|
|
38
|
+
Requires-Dist: hydra-core>=1.3.0; extra == 'all'
|
|
39
|
+
Requires-Dist: omegaconf>=2.3.0; extra == 'all'
|
|
40
|
+
Requires-Dist: pytest-cov>=4.0.0; extra == 'all'
|
|
41
|
+
Requires-Dist: pytest>=7.0.0; extra == 'all'
|
|
42
|
+
Requires-Dist: scikit-learn>=1.0.0; extra == 'all'
|
|
43
|
+
Requires-Dist: sktime>=0.27.0; extra == 'all'
|
|
44
|
+
Requires-Dist: sqlalchemy>=2.0.0; extra == 'all'
|
|
45
|
+
Requires-Dist: twine>=6.2.0; extra == 'all'
|
|
46
|
+
Provides-Extra: db
|
|
47
|
+
Requires-Dist: sqlalchemy>=2.0.0; extra == 'db'
|
|
48
|
+
Provides-Extra: deep
|
|
49
|
+
Provides-Extra: dev
|
|
50
|
+
Requires-Dist: build>=1.4.0; extra == 'dev'
|
|
51
|
+
Requires-Dist: pytest-cov>=4.0.0; extra == 'dev'
|
|
52
|
+
Requires-Dist: pytest>=7.0.0; extra == 'dev'
|
|
53
|
+
Requires-Dist: scikit-learn>=1.0.0; extra == 'dev'
|
|
54
|
+
Requires-Dist: twine>=6.2.0; extra == 'dev'
|
|
55
|
+
Provides-Extra: forecasting
|
|
56
|
+
Requires-Dist: sktime[forecasting]>=0.40.1; extra == 'forecasting'
|
|
57
|
+
Provides-Extra: hydra
|
|
58
|
+
Requires-Dist: hydra-core>=1.3.0; extra == 'hydra'
|
|
59
|
+
Requires-Dist: omegaconf>=2.3.0; extra == 'hydra'
|
|
60
|
+
Provides-Extra: transform
|
|
61
|
+
Requires-Dist: sktime>=0.27.0; extra == 'transform'
|
|
62
|
+
Description-Content-Type: text/markdown
|
|
63
|
+
|
|
64
|
+
# dfm-python
|
|
65
|
+
|
|
66
|
+
Dynamic factor models in Python.
|
|
67
|
+
|
|
68
|
+
- **DFM**: linear, mixed-frequency Dynamic Factor Model estimated by EM with
|
|
69
|
+
Kalman filtering and smoothing.
|
|
70
|
+
- **DDFM**: Deep Dynamic Factor Model with a nonlinear (PyTorch) encoder.
|
|
71
|
+
- **iVDFM**: Identifiable Variational Dynamic Factor Model.
|
|
72
|
+
- **AFM**: the Attention Factor Model of Epstein, Wang, Choi and Pelger (2025),
|
|
73
|
+
a cross-sectional conditional factor model whose residuals are traded
|
|
74
|
+
portfolios, with PCA and Avellaneda-Lee benchmarks.
|
|
75
|
+
|
|
76
|
+
Mixed frequencies are handled with a clock: latent factors evolve at one
|
|
77
|
+
frequency (for example monthly) and lower-frequency series load on them through
|
|
78
|
+
tent-kernel aggregation in the observation equation. Series faster than the
|
|
79
|
+
clock are not supported.
|
|
80
|
+
|
|
81
|
+
## Install
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
pip install dfm-python # or: uv add dfm-python
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
Requires Python 3.10 or later; PyTorch is a required dependency.
|
|
88
|
+
|
|
89
|
+
## DFM
|
|
90
|
+
|
|
91
|
+
Pass preprocessed data; the model standardizes it internally.
|
|
92
|
+
|
|
93
|
+
```python
|
|
94
|
+
import numpy as np
|
|
95
|
+
import pandas as pd
|
|
96
|
+
from dfm_python import DFM, DFMDataset
|
|
97
|
+
from dfm_python.config import DFMConfig
|
|
98
|
+
|
|
99
|
+
rng = np.random.default_rng(0)
|
|
100
|
+
cols = ["s0", "s1", "s2", "s3"]
|
|
101
|
+
df = pd.DataFrame(rng.standard_normal((120, 4)), columns=cols)
|
|
102
|
+
df["date"] = pd.date_range("2010-01-31", periods=120, freq="ME")
|
|
103
|
+
|
|
104
|
+
config = DFMConfig(
|
|
105
|
+
blocks={"global": {"num_factors": 1, "series": cols}},
|
|
106
|
+
frequency={c: "m" for c in cols},
|
|
107
|
+
clock="m",
|
|
108
|
+
max_iter=50,
|
|
109
|
+
)
|
|
110
|
+
dataset = DFMDataset(config=config, data=df, time_index="date")
|
|
111
|
+
model = DFM(dataset=dataset, config=config)
|
|
112
|
+
model.fit() # EM + Kalman smoother
|
|
113
|
+
X_forecast, Z_forecast = model.predict(horizon=6)
|
|
114
|
+
print(X_forecast.shape, Z_forecast.shape) # (6, 4) series, (6, state dim)
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
`DDFM` (`from dfm_python import DDFM, DDFMDataset`) and `iVDFM`
|
|
118
|
+
(`from dfm_python.models.ivdfm import iVDFM`) follow the same
|
|
119
|
+
dataset-then-model pattern. Hydra YAML configurations for each model are in
|
|
120
|
+
[`config/`](https://github.com/minkeymouse/dfm-python/tree/main/config) and
|
|
121
|
+
end-to-end scripts in
|
|
122
|
+
[`tutorial/`](https://github.com/minkeymouse/dfm-python/tree/main/tutorial).
|
|
123
|
+
|
|
124
|
+
## AFM
|
|
125
|
+
|
|
126
|
+
AFM takes a returns panel `(T, N)` and, for learned attention factors, firm
|
|
127
|
+
characteristics `(T, N, M)`. It is trained on an after-cost Sharpe ratio plus an
|
|
128
|
+
explained-variance term (`lambda_var`).
|
|
129
|
+
|
|
130
|
+
```python
|
|
131
|
+
import numpy as np
|
|
132
|
+
import torch
|
|
133
|
+
from dfm_python import AFM, AFMDataset
|
|
134
|
+
from dfm_python.models.afm.factors import residuals
|
|
135
|
+
|
|
136
|
+
rng = np.random.default_rng(0)
|
|
137
|
+
T, N, M = 120, 20, 8 # dates, assets, characteristics
|
|
138
|
+
returns = 0.01 * rng.standard_normal((T, N))
|
|
139
|
+
characteristics = rng.standard_normal((T, N, M))
|
|
140
|
+
|
|
141
|
+
ds = AFMDataset(returns=returns, characteristics=characteristics)
|
|
142
|
+
model = AFM(dataset=ds, n_factors=3, hist_len=20, max_epochs=20, seed=0)
|
|
143
|
+
model.fit()
|
|
144
|
+
|
|
145
|
+
out = model.predict()
|
|
146
|
+
out["residuals"].shape # (1, T, N) residual returns
|
|
147
|
+
out["weights"].shape # (1, T - hist_len, N) portfolio weights
|
|
148
|
+
out["book_returns"].shape # (1, T - hist_len) after-cost returns
|
|
149
|
+
result = model.get_result()
|
|
150
|
+
print(result.sharpe, result.explained_variance)
|
|
151
|
+
|
|
152
|
+
# Residuals from the fitted factor block directly
|
|
153
|
+
R, X = ds.get_tensors(model.device)
|
|
154
|
+
with torch.no_grad():
|
|
155
|
+
omega_f, beta_t = model.factor_block(X) # (T, K, N), (T, N, K)
|
|
156
|
+
eps = residuals(omega_f, beta_t, R) # (T, N)
|
|
157
|
+
|
|
158
|
+
# Benchmarks: PCA factors need no characteristics
|
|
159
|
+
pca = AFM(dataset=AFMDataset(returns=returns), n_factors=3, hist_len=20,
|
|
160
|
+
factor_model="pca", trading="ou") # or trading="longconv"
|
|
161
|
+
pca.fit()
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
## Layout
|
|
165
|
+
|
|
166
|
+
```
|
|
167
|
+
src/dfm_python/
|
|
168
|
+
models/ dfm/, ddfm/, ivdfm/, afm/ model classes
|
|
169
|
+
dataset/ DFMDataset, DDFMDataset, iVDFMDataset, AFMDataset
|
|
170
|
+
config/ model configs (DFMConfig, ..., AFMConfig), YAML adapter, results
|
|
171
|
+
ssm/ state-space form and Kalman filtering
|
|
172
|
+
functional/ EM algorithm
|
|
173
|
+
numeric/, layer/, utils/, logger/ shared numerics, network layers, helpers
|
|
174
|
+
src/test/ pytest suite
|
|
175
|
+
config/ example Hydra YAML configurations
|
|
176
|
+
tutorial/ end-to-end scripts per model and dataset
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
Tests, from a clone: `uv sync --group dev && uv run pytest src/test -q`.
|
|
180
|
+
|
|
181
|
+
The paper repository [minkeymouse/nfe](https://github.com/minkeymouse/nfe) uses
|
|
182
|
+
AFM as a baseline.
|
|
183
|
+
|
|
184
|
+
## License
|
|
185
|
+
|
|
186
|
+
MIT. See [LICENSE](https://github.com/minkeymouse/dfm-python/blob/main/LICENSE).
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
# dfm-python
|
|
2
|
+
|
|
3
|
+
Dynamic factor models in Python.
|
|
4
|
+
|
|
5
|
+
- **DFM**: linear, mixed-frequency Dynamic Factor Model estimated by EM with
|
|
6
|
+
Kalman filtering and smoothing.
|
|
7
|
+
- **DDFM**: Deep Dynamic Factor Model with a nonlinear (PyTorch) encoder.
|
|
8
|
+
- **iVDFM**: Identifiable Variational Dynamic Factor Model.
|
|
9
|
+
- **AFM**: the Attention Factor Model of Epstein, Wang, Choi and Pelger (2025),
|
|
10
|
+
a cross-sectional conditional factor model whose residuals are traded
|
|
11
|
+
portfolios, with PCA and Avellaneda-Lee benchmarks.
|
|
12
|
+
|
|
13
|
+
Mixed frequencies are handled with a clock: latent factors evolve at one
|
|
14
|
+
frequency (for example monthly) and lower-frequency series load on them through
|
|
15
|
+
tent-kernel aggregation in the observation equation. Series faster than the
|
|
16
|
+
clock are not supported.
|
|
17
|
+
|
|
18
|
+
## Install
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
pip install dfm-python # or: uv add dfm-python
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
Requires Python 3.10 or later; PyTorch is a required dependency.
|
|
25
|
+
|
|
26
|
+
## DFM
|
|
27
|
+
|
|
28
|
+
Pass preprocessed data; the model standardizes it internally.
|
|
29
|
+
|
|
30
|
+
```python
|
|
31
|
+
import numpy as np
|
|
32
|
+
import pandas as pd
|
|
33
|
+
from dfm_python import DFM, DFMDataset
|
|
34
|
+
from dfm_python.config import DFMConfig
|
|
35
|
+
|
|
36
|
+
rng = np.random.default_rng(0)
|
|
37
|
+
cols = ["s0", "s1", "s2", "s3"]
|
|
38
|
+
df = pd.DataFrame(rng.standard_normal((120, 4)), columns=cols)
|
|
39
|
+
df["date"] = pd.date_range("2010-01-31", periods=120, freq="ME")
|
|
40
|
+
|
|
41
|
+
config = DFMConfig(
|
|
42
|
+
blocks={"global": {"num_factors": 1, "series": cols}},
|
|
43
|
+
frequency={c: "m" for c in cols},
|
|
44
|
+
clock="m",
|
|
45
|
+
max_iter=50,
|
|
46
|
+
)
|
|
47
|
+
dataset = DFMDataset(config=config, data=df, time_index="date")
|
|
48
|
+
model = DFM(dataset=dataset, config=config)
|
|
49
|
+
model.fit() # EM + Kalman smoother
|
|
50
|
+
X_forecast, Z_forecast = model.predict(horizon=6)
|
|
51
|
+
print(X_forecast.shape, Z_forecast.shape) # (6, 4) series, (6, state dim)
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
`DDFM` (`from dfm_python import DDFM, DDFMDataset`) and `iVDFM`
|
|
55
|
+
(`from dfm_python.models.ivdfm import iVDFM`) follow the same
|
|
56
|
+
dataset-then-model pattern. Hydra YAML configurations for each model are in
|
|
57
|
+
[`config/`](https://github.com/minkeymouse/dfm-python/tree/main/config) and
|
|
58
|
+
end-to-end scripts in
|
|
59
|
+
[`tutorial/`](https://github.com/minkeymouse/dfm-python/tree/main/tutorial).
|
|
60
|
+
|
|
61
|
+
## AFM
|
|
62
|
+
|
|
63
|
+
AFM takes a returns panel `(T, N)` and, for learned attention factors, firm
|
|
64
|
+
characteristics `(T, N, M)`. It is trained on an after-cost Sharpe ratio plus an
|
|
65
|
+
explained-variance term (`lambda_var`).
|
|
66
|
+
|
|
67
|
+
```python
|
|
68
|
+
import numpy as np
|
|
69
|
+
import torch
|
|
70
|
+
from dfm_python import AFM, AFMDataset
|
|
71
|
+
from dfm_python.models.afm.factors import residuals
|
|
72
|
+
|
|
73
|
+
rng = np.random.default_rng(0)
|
|
74
|
+
T, N, M = 120, 20, 8 # dates, assets, characteristics
|
|
75
|
+
returns = 0.01 * rng.standard_normal((T, N))
|
|
76
|
+
characteristics = rng.standard_normal((T, N, M))
|
|
77
|
+
|
|
78
|
+
ds = AFMDataset(returns=returns, characteristics=characteristics)
|
|
79
|
+
model = AFM(dataset=ds, n_factors=3, hist_len=20, max_epochs=20, seed=0)
|
|
80
|
+
model.fit()
|
|
81
|
+
|
|
82
|
+
out = model.predict()
|
|
83
|
+
out["residuals"].shape # (1, T, N) residual returns
|
|
84
|
+
out["weights"].shape # (1, T - hist_len, N) portfolio weights
|
|
85
|
+
out["book_returns"].shape # (1, T - hist_len) after-cost returns
|
|
86
|
+
result = model.get_result()
|
|
87
|
+
print(result.sharpe, result.explained_variance)
|
|
88
|
+
|
|
89
|
+
# Residuals from the fitted factor block directly
|
|
90
|
+
R, X = ds.get_tensors(model.device)
|
|
91
|
+
with torch.no_grad():
|
|
92
|
+
omega_f, beta_t = model.factor_block(X) # (T, K, N), (T, N, K)
|
|
93
|
+
eps = residuals(omega_f, beta_t, R) # (T, N)
|
|
94
|
+
|
|
95
|
+
# Benchmarks: PCA factors need no characteristics
|
|
96
|
+
pca = AFM(dataset=AFMDataset(returns=returns), n_factors=3, hist_len=20,
|
|
97
|
+
factor_model="pca", trading="ou") # or trading="longconv"
|
|
98
|
+
pca.fit()
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
## Layout
|
|
102
|
+
|
|
103
|
+
```
|
|
104
|
+
src/dfm_python/
|
|
105
|
+
models/ dfm/, ddfm/, ivdfm/, afm/ model classes
|
|
106
|
+
dataset/ DFMDataset, DDFMDataset, iVDFMDataset, AFMDataset
|
|
107
|
+
config/ model configs (DFMConfig, ..., AFMConfig), YAML adapter, results
|
|
108
|
+
ssm/ state-space form and Kalman filtering
|
|
109
|
+
functional/ EM algorithm
|
|
110
|
+
numeric/, layer/, utils/, logger/ shared numerics, network layers, helpers
|
|
111
|
+
src/test/ pytest suite
|
|
112
|
+
config/ example Hydra YAML configurations
|
|
113
|
+
tutorial/ end-to-end scripts per model and dataset
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
Tests, from a clone: `uv sync --group dev && uv run pytest src/test -q`.
|
|
117
|
+
|
|
118
|
+
The paper repository [minkeymouse/nfe](https://github.com/minkeymouse/nfe) uses
|
|
119
|
+
AFM as a baseline.
|
|
120
|
+
|
|
121
|
+
## License
|
|
122
|
+
|
|
123
|
+
MIT. See [LICENSE](https://github.com/minkeymouse/dfm-python/blob/main/LICENSE).
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# Attention Factor Model (Epstein et al., 2025) — finance / statistical arbitrage.
|
|
2
|
+
# Flat AFMConfig keys; loaded via AFMConfig.from_dict(OmegaConf.to_container(cfg)).
|
|
3
|
+
clock: d
|
|
4
|
+
scaler: null
|
|
5
|
+
|
|
6
|
+
# Factor / trading structure
|
|
7
|
+
num_factors: 5
|
|
8
|
+
factor_model: attention # 'attention' (learned) | 'pca' (benchmark)
|
|
9
|
+
trading: longconv # 'longconv' (learned) | 'ou' (Avellaneda-Lee)
|
|
10
|
+
|
|
11
|
+
# Architecture
|
|
12
|
+
embed_dim: 32 # characteristic embedding dimension d
|
|
13
|
+
hist_len: 20 # residual-history length s for the trading filter
|
|
14
|
+
n_kernels: 32 # number of long convolutions
|
|
15
|
+
ridge: 0.01 # ridge penalty for the closed-form loadings
|
|
16
|
+
|
|
17
|
+
# Objective and costs (paper values: 5bps turnover, 1bp shorting)
|
|
18
|
+
lambda_var: 0.1
|
|
19
|
+
turnover_cost: 0.0005
|
|
20
|
+
short_cost: 0.0001
|
|
21
|
+
risk_free: 0.0
|
|
22
|
+
|
|
23
|
+
# Training
|
|
24
|
+
learning_rate: 0.001
|
|
25
|
+
max_epochs: 50
|
|
26
|
+
patience: 10
|
|
27
|
+
seed: 0
|
|
@@ -9,16 +9,20 @@ encoder_layers: [16, 4] # Hidden layers: [16] -> latent: 4 (matching original s
|
|
|
9
9
|
activation: relu # Matching original link='relu'
|
|
10
10
|
use_batch_norm: true # Matching original batch_norm=True
|
|
11
11
|
|
|
12
|
-
# Training Parameters
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
12
|
+
# Training Parameters
|
|
13
|
+
# NOTE: for fair comparison with iVDFM exchange tutorial/config, we align the
|
|
14
|
+
# effective window length and training budget (see ivdfm_exchange.yaml).
|
|
15
|
+
learning_rate: 0.005
|
|
16
|
+
n_mc_samples: 10
|
|
17
|
+
window_size: 200 # Align with iVDFM sequence_length=200
|
|
16
18
|
|
|
17
|
-
# MCMC/Iterative Parameters
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
19
|
+
# MCMC/Iterative Parameters
|
|
20
|
+
# NOTE: DDFM uses max_epoch as an iteration budget; iVDFM uses max_epochs.
|
|
21
|
+
# We set this to 10 here to make the tutorials comparable in runtime budget.
|
|
22
|
+
max_epoch: 10
|
|
23
|
+
tolerance: 0.0005
|
|
24
|
+
disp: 10
|
|
25
|
+
seed: 3
|
|
22
26
|
|
|
23
27
|
# Interpolation Parameters
|
|
24
28
|
interpolation_method: linear # Interpolation method for missing values
|
|
@@ -28,16 +32,3 @@ interpolation_limit_direction: both # Direction to fill ('forward', 'backward',
|
|
|
28
32
|
# Data Handling (used by Dataset, not Model)
|
|
29
33
|
clock: d # Daily clock frequency (all series are daily)
|
|
30
34
|
scaler: null # No scaler - data should be pre-scaled before passing to Dataset
|
|
31
|
-
|
|
32
|
-
# Frequency mapping (all series are daily)
|
|
33
|
-
# If not specified, all series use clock frequency (d)
|
|
34
|
-
# Format: {"series_name": "frequency_code"}
|
|
35
|
-
# frequency:
|
|
36
|
-
# AUD_USD: d
|
|
37
|
-
# GBP_USD: d
|
|
38
|
-
# CAD_USD: d
|
|
39
|
-
# CHF_USD: d
|
|
40
|
-
# CNY_USD: d
|
|
41
|
-
# JPY_USD: d
|
|
42
|
-
# SGD_USD: d
|
|
43
|
-
# NZD_USD: d
|
|
@@ -3,17 +3,24 @@
|
|
|
3
3
|
# Clock: Monthly (m) - all series are monthly frequency
|
|
4
4
|
|
|
5
5
|
# Neural Network Architecture
|
|
6
|
-
|
|
6
|
+
# Match iVDFM depth/width more closely: 3 hidden layers of size ~200
|
|
7
|
+
encoder_layers: [64, 32, 5] # Hidden layers: [200, 200] -> latent: 5 factors (match iVDFM capacity)
|
|
7
8
|
activation: relu # Activation function: 'tanh', 'relu', 'sigmoid'
|
|
8
9
|
use_batch_norm: true # Use batch normalization
|
|
10
|
+
decoder_type: mlp # Use non-linear (MLP) decoder instead of linear
|
|
11
|
+
|
|
12
|
+
# Target/covariate split
|
|
13
|
+
# For DDFM finance: covariates are ALL columns except the target.
|
|
14
|
+
target_col: market_forward_excess_returns
|
|
15
|
+
covariates: all_except_target
|
|
9
16
|
|
|
10
17
|
# Training Parameters
|
|
11
18
|
learning_rate: 0.001 # Learning rate for optimizer
|
|
12
|
-
n_mc_samples:
|
|
13
|
-
window_size:
|
|
19
|
+
n_mc_samples: 10 # Number of MC samples per MCMC iteration
|
|
20
|
+
window_size: 200 # Align with iVDFM sequence_length=200
|
|
14
21
|
|
|
15
22
|
# MCMC/Iterative Parameters
|
|
16
|
-
max_epoch:
|
|
23
|
+
max_epoch: 10 # Align with iVDFM max_epochs=10
|
|
17
24
|
tolerance: 0.0005 # Convergence tolerance
|
|
18
25
|
disp: 10 # Display frequency for training progress
|
|
19
26
|
seed: null # Random seed (None uses default)
|
|
@@ -27,10 +34,4 @@ interpolation_limit_direction: both # Direction to fill ('forward', 'backward',
|
|
|
27
34
|
clock: m # Monthly clock frequency
|
|
28
35
|
scaler: standard # Scaler for target series: 'standard', 'robust', 'minmax', 'maxabs', 'quantile', or null
|
|
29
36
|
|
|
30
|
-
|
|
31
|
-
# If not specified, all series use clock frequency
|
|
32
|
-
# Format: {"series_name": "frequency_code"}
|
|
33
|
-
# frequency:
|
|
34
|
-
# gdp: q
|
|
35
|
-
# unemployment: m
|
|
36
|
-
# interest_rate: m
|
|
37
|
+
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# iVDFM Configuration for Exchange Rate Dataset
|
|
2
|
+
# Data: 8 exchange rate series (AUD_USD, GBP_USD, CAD_USD, CHF_USD, CNY_USD, JPY_USD, SGD_USD, NZD_USD)
|
|
3
|
+
# Clock: Daily (d) - all series are daily frequency
|
|
4
|
+
# Date range: 1990-01-01 to 2010-10-10
|
|
5
|
+
|
|
6
|
+
# ===== Model Structure =====
|
|
7
|
+
# Latent dimension
|
|
8
|
+
num_factors: 2
|
|
9
|
+
sequence_length: 200 # Sequence length for sliding windows
|
|
10
|
+
context: null # Column names (DataFrame) or indices (array) for context variables. If None, time-based context is generated.
|
|
11
|
+
context_dim: 1 # Dimension of context. Used when context is None (generates time-based context) or when context is multivariate.
|
|
12
|
+
|
|
13
|
+
# ===== Neural Network Architecture =====
|
|
14
|
+
encoder_hidden_dim: 200 # Encoder hidden dimension
|
|
15
|
+
encoder_n_layers: 3 # Number of encoder layers
|
|
16
|
+
decoder_hidden_dim: 200 # Decoder hidden dimension
|
|
17
|
+
decoder_n_layers: 3 # Number of decoder layers
|
|
18
|
+
prior_hidden_dim: 100 # Prior network hidden dimension
|
|
19
|
+
prior_n_layers: 2 # Number of prior network layers
|
|
20
|
+
activation: lrelu # Activation function: 'relu', 'lrelu', 'tanh', 'sigmoid'
|
|
21
|
+
slope: 0.1 # Leaky ReLU slope
|
|
22
|
+
|
|
23
|
+
# ===== Dynamics and Distribution Parameters =====
|
|
24
|
+
factor_order: 1 # AR order for factors (p in AR(p))
|
|
25
|
+
innovation_distribution: laplace # Innovation distribution: 'laplace', 'gaussian', 'student_t'
|
|
26
|
+
decoder_var: 0.01 # Decoder variance (observation noise)
|
|
27
|
+
|
|
28
|
+
# ===== Training Parameters =====
|
|
29
|
+
learning_rate: 0.001 # Learning rate for optimizer
|
|
30
|
+
optimizer: Adam # Optimizer type: 'Adam', 'AdamW', 'SGD'
|
|
31
|
+
batch_size: 256 # Batch size for training (larger to reduce #batches/epoch)
|
|
32
|
+
max_epochs: 10 # Maximum training epochs
|
|
33
|
+
tolerance: 1.0e-5 # Convergence tolerance
|
|
34
|
+
seed: null # Random seed (None uses default)
|
|
35
|
+
|
|
36
|
+
# ===== Base Model Config (inherited) =====
|
|
37
|
+
frequency: null # iVDFM doesn't use mixed-frequency structure
|
|
38
|
+
clock: d # Daily clock frequency (all series are daily)
|
|
39
|
+
scaler: null # Scaler for targets: 'standard', 'robust', 'minmax', 'maxabs', 'quantile', or null. Applied to targets only (not context/auxiliary variables)
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# iVDFM Configuration for Finance Dataset
|
|
2
|
+
# Data: Finance data with market_forward_excess_returns as target variable
|
|
3
|
+
# Clock: Monthly (m) - all series are monthly frequency
|
|
4
|
+
|
|
5
|
+
# ===== Model Structure =====
|
|
6
|
+
# Latent dimension
|
|
7
|
+
num_factors: 5
|
|
8
|
+
sequence_length: 200 # Sequence length for sliding windows
|
|
9
|
+
context: null # Column names (DataFrame) or indices (array) for context variables. If None, time-based context is generated.
|
|
10
|
+
context_dim: 1 # Dimension of context. Used when context is None (generates time-based context) or when context is multivariate.
|
|
11
|
+
|
|
12
|
+
# ===== Neural Network Architecture =====
|
|
13
|
+
encoder_hidden_dim: 50 # Encoder hidden dimension
|
|
14
|
+
encoder_n_layers: 2 # Number of encoder layers
|
|
15
|
+
decoder_hidden_dim: 50 # Decoder hidden dimension
|
|
16
|
+
decoder_n_layers: 2 # Number of decoder layers
|
|
17
|
+
prior_hidden_dim: 100 # Prior network hidden dimension
|
|
18
|
+
prior_n_layers: 2 # Number of prior network layers
|
|
19
|
+
activation: lrelu # Activation function: 'relu', 'lrelu', 'tanh', 'sigmoid'
|
|
20
|
+
slope: 0.1 # Leaky ReLU slope
|
|
21
|
+
|
|
22
|
+
# ===== Dynamics and Distribution Parameters =====
|
|
23
|
+
factor_order: 2 # AR order for factors (p in AR(p))
|
|
24
|
+
innovation_distribution: laplace # Innovation distribution: 'laplace', 'gaussian', 'student_t'
|
|
25
|
+
decoder_var: 0.01 # Decoder variance (observation noise)
|
|
26
|
+
|
|
27
|
+
# ===== Training Parameters =====
|
|
28
|
+
learning_rate: 0.001 # Learning rate for optimizer
|
|
29
|
+
optimizer: Adam # Optimizer type: 'Adam', 'AdamW', 'SGD'
|
|
30
|
+
batch_size: 128 # Batch size for training (larger to reduce #batches/epoch)
|
|
31
|
+
max_epochs: 10 # Maximum training epochs
|
|
32
|
+
tolerance: 1.0e-5 # Convergence tolerance
|
|
33
|
+
seed: null # Random seed (None uses default)
|
|
34
|
+
|
|
35
|
+
# ===== Base Model Config (inherited) =====
|
|
36
|
+
frequency: null # iVDFM doesn't use mixed-frequency structure
|
|
37
|
+
clock: m # Monthly clock frequency
|
|
38
|
+
scaler: standard # Scaler for targets: 'standard', 'robust', 'minmax', 'maxabs', 'quantile', or null. Applied to targets only (not context/auxiliary variables)
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# iVDFM Configuration for Macroeconomic Datasets
|
|
2
|
+
# Based on Korean economic indicators (KO* series)
|
|
3
|
+
# Data: 101 series, mixed weekly/monthly frequency (1985-04-05 to 2025-11-21)
|
|
4
|
+
# Clock: Weekly (w) - base frequency for latent factors
|
|
5
|
+
# Target: KOEQUIPTE (Investment, Equipment, Estimation, SA)
|
|
6
|
+
|
|
7
|
+
# ===== Model Structure =====
|
|
8
|
+
# Latent dimension
|
|
9
|
+
num_factors: 5
|
|
10
|
+
sequence_length: 200 # Sequence length for sliding windows
|
|
11
|
+
context: null # Column names (DataFrame) or indices (array) for context variables. If None, time-based context is generated.
|
|
12
|
+
context_dim: 1 # Dimension of context. Used when context is None (generates time-based context) or when context is multivariate.
|
|
13
|
+
|
|
14
|
+
# ===== Neural Network Architecture =====
|
|
15
|
+
encoder_hidden_dim: 200 # Encoder hidden dimension
|
|
16
|
+
encoder_n_layers: 3 # Number of encoder layers
|
|
17
|
+
decoder_hidden_dim: 200 # Decoder hidden dimension
|
|
18
|
+
decoder_n_layers: 3 # Number of decoder layers
|
|
19
|
+
prior_hidden_dim: 100 # Prior network hidden dimension
|
|
20
|
+
prior_n_layers: 2 # Number of prior network layers
|
|
21
|
+
activation: lrelu # Activation function: 'relu', 'lrelu', 'tanh', 'sigmoid'
|
|
22
|
+
slope: 0.1 # Leaky ReLU slope
|
|
23
|
+
|
|
24
|
+
# ===== Dynamics and Distribution Parameters =====
|
|
25
|
+
factor_order: 3 # AR order for factors (p in AR(p))
|
|
26
|
+
innovation_distribution: laplace # Innovation distribution: 'laplace', 'gaussian', 'student_t'
|
|
27
|
+
decoder_var: 0.01 # Decoder variance (observation noise)
|
|
28
|
+
|
|
29
|
+
# ===== Training Parameters =====
|
|
30
|
+
learning_rate: 0.001 # Learning rate for optimizer
|
|
31
|
+
optimizer: Adam # Optimizer type: 'Adam', 'AdamW', 'SGD'
|
|
32
|
+
batch_size: 256 # Batch size for training (larger to reduce #batches/epoch)
|
|
33
|
+
max_epochs: 10 # Maximum training epochs
|
|
34
|
+
tolerance: 1.0e-5 # Convergence tolerance
|
|
35
|
+
seed: null # Random seed (None uses default)
|
|
36
|
+
|
|
37
|
+
# ===== Base Model Config (inherited) =====
|
|
38
|
+
frequency: null # iVDFM doesn't use mixed-frequency structure
|
|
39
|
+
clock: w # Weekly clock frequency (base frequency for latent factors)
|
|
40
|
+
scaler: standard # Scaler for targets: 'standard', 'robust', 'minmax', 'maxabs', 'quantile', or null. Applied to targets only (not context/auxiliary variables)
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "dfm-python"
|
|
3
|
-
version = "0.
|
|
3
|
+
version = "0.7.0"
|
|
4
4
|
description = "Dynamic Factor Model (DFM) estimation and forecasting in Python"
|
|
5
|
+
readme = "README.md"
|
|
5
6
|
requires-python = ">=3.10"
|
|
6
7
|
license = {text = "MIT"}
|
|
7
8
|
authors = [
|
|
@@ -16,14 +17,15 @@ classifiers = [
|
|
|
16
17
|
"Programming Language :: Python :: 3.10",
|
|
17
18
|
"Programming Language :: Python :: 3.11",
|
|
18
19
|
"Programming Language :: Python :: 3.12",
|
|
20
|
+
"Programming Language :: Python :: 3.13",
|
|
19
21
|
"Topic :: Scientific/Engineering",
|
|
20
22
|
]
|
|
21
23
|
dependencies = [
|
|
22
|
-
"build>=1.4.0",
|
|
23
24
|
"einops>=0.8.1",
|
|
24
25
|
"hydra-core>=1.3.2",
|
|
25
26
|
"matplotlib>=3.5.0",
|
|
26
27
|
"numpy>=1.24.0",
|
|
28
|
+
"optuna>=4.7.0",
|
|
27
29
|
"pandas>=2.0.0",
|
|
28
30
|
"pyarrow>=22.0.0",
|
|
29
31
|
"pykalman>=0.11.0",
|
|
@@ -32,7 +34,6 @@ dependencies = [
|
|
|
32
34
|
"scipy>=1.10.0",
|
|
33
35
|
"sktime>=0.40.1",
|
|
34
36
|
"torch>=2.0.0",
|
|
35
|
-
"twine>=6.2.0",
|
|
36
37
|
]
|
|
37
38
|
|
|
38
39
|
[project.optional-dependencies]
|
|
@@ -58,6 +59,8 @@ dev = [
|
|
|
58
59
|
"pytest>=7.0.0",
|
|
59
60
|
"pytest-cov>=4.0.0",
|
|
60
61
|
"scikit-learn>=1.0.0",
|
|
62
|
+
"build>=1.4.0",
|
|
63
|
+
"twine>=6.2.0",
|
|
61
64
|
]
|
|
62
65
|
all = [
|
|
63
66
|
"dfm-python[hydra,db,dev,deep,transform]",
|
|
@@ -83,7 +86,8 @@ packages = [
|
|
|
83
86
|
exclude = [
|
|
84
87
|
"test_venv",
|
|
85
88
|
"test_venv/**",
|
|
86
|
-
"
|
|
89
|
+
"data/**",
|
|
90
|
+
"uv.lock",
|
|
87
91
|
]
|
|
88
92
|
|
|
89
93
|
[dependency-groups]
|
|
@@ -92,7 +96,7 @@ dev = [
|
|
|
92
96
|
]
|
|
93
97
|
|
|
94
98
|
[project.urls]
|
|
95
|
-
Homepage = "https://github.com/
|
|
96
|
-
Documentation = "https://github.com/
|
|
97
|
-
Repository = "https://github.com/
|
|
98
|
-
Issues = "https://github.com/
|
|
99
|
+
Homepage = "https://github.com/minkeymouse/dfm-python"
|
|
100
|
+
Documentation = "https://github.com/minkeymouse/dfm-python#readme"
|
|
101
|
+
Repository = "https://github.com/minkeymouse/dfm-python"
|
|
102
|
+
Issues = "https://github.com/minkeymouse/dfm-python/issues"
|