dfm-python 0.4.6__tar.gz → 0.4.8__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.4.6 → dfm_python-0.4.8}/PKG-INFO +9 -110
- {dfm_python-0.4.6 → dfm_python-0.4.8}/README.md +8 -109
- {dfm_python-0.4.6 → dfm_python-0.4.8}/pyproject.toml +1 -1
- {dfm_python-0.4.6 → dfm_python-0.4.8}/src/dfm_python/__init__.py +13 -25
- {dfm_python-0.4.6 → dfm_python-0.4.8}/src/dfm_python/models/base.py +0 -2
- {dfm_python-0.4.6 → dfm_python-0.4.8}/src/dfm_python/models/ddfm.py +29 -259
- {dfm_python-0.4.6 → dfm_python-0.4.8}/src/dfm_python/models/dfm.py +58 -1
- {dfm_python-0.4.6 → dfm_python-0.4.8}/src/dfm_python/ssm/em.py +165 -22
- {dfm_python-0.4.6 → dfm_python-0.4.8}/src/dfm_python/ssm/kalman.py +316 -28
- {dfm_python-0.4.6 → dfm_python-0.4.8}/src/dfm_python/ssm/utils.py +45 -0
- {dfm_python-0.4.6 → dfm_python-0.4.8}/src/dfm_python/trainer/__init__.py +10 -3
- {dfm_python-0.4.6 → dfm_python-0.4.8}/src/dfm_python/trainer/ddfm.py +5 -4
- {dfm_python-0.4.6 → dfm_python-0.4.8}/src/dfm_python/utils/__init__.py +28 -14
- dfm_python-0.4.6/src/dfm_python/nowcast/__init__.py +0 -37
- dfm_python-0.4.6/src/dfm_python/nowcast/dataview.py +0 -143
- dfm_python-0.4.6/src/dfm_python/nowcast/helpers.py +0 -356
- dfm_python-0.4.6/src/dfm_python/nowcast/nowcast.py +0 -1263
- dfm_python-0.4.6/src/dfm_python/nowcast/splitters.py +0 -441
- dfm_python-0.4.6/src/dfm_python/nowcast/transformers.py +0 -330
- dfm_python-0.4.6/src/dfm_python/nowcast/utils.py +0 -281
- {dfm_python-0.4.6 → dfm_python-0.4.8}/.git +0 -0
- {dfm_python-0.4.6 → dfm_python-0.4.8}/.gitignore +0 -0
- {dfm_python-0.4.6 → dfm_python-0.4.8}/.python-version +0 -0
- {dfm_python-0.4.6 → dfm_python-0.4.8}/LICENSE +0 -0
- {dfm_python-0.4.6 → dfm_python-0.4.8}/MANIFEST.in +0 -0
- {dfm_python-0.4.6 → dfm_python-0.4.8}/config/experiment/test_finance.yaml +0 -0
- {dfm_python-0.4.6 → dfm_python-0.4.8}/config/experiment/test_macro.yaml +0 -0
- {dfm_python-0.4.6 → dfm_python-0.4.8}/config/model/ddfm.yaml +0 -0
- {dfm_python-0.4.6 → dfm_python-0.4.8}/config/model/dfm.yaml +0 -0
- {dfm_python-0.4.6 → dfm_python-0.4.8}/config/series/KO3YEARC.yaml +0 -0
- {dfm_python-0.4.6 → dfm_python-0.4.8}/config/series/KOBFDSAAF.yaml +0 -0
- {dfm_python-0.4.6 → dfm_python-0.4.8}/config/series/KOBFINAAF.yaml +0 -0
- {dfm_python-0.4.6 → dfm_python-0.4.8}/config/series/KOBFXSAAF.yaml +0 -0
- {dfm_python-0.4.6 → dfm_python-0.4.8}/config/series/KOBSESI_R.yaml +0 -0
- {dfm_python-0.4.6 → dfm_python-0.4.8}/config/series/KOBSIBCEQ.yaml +0 -0
- {dfm_python-0.4.6 → dfm_python-0.4.8}/config/series/KOBSIBCOQ.yaml +0 -0
- {dfm_python-0.4.6 → dfm_python-0.4.8}/config/series/KOBSIBNER.yaml +0 -0
- {dfm_python-0.4.6 → dfm_python-0.4.8}/config/series/KOBSIBNMR.yaml +0 -0
- {dfm_python-0.4.6 → dfm_python-0.4.8}/config/series/KOBSIEMAR.yaml +0 -0
- {dfm_python-0.4.6 → dfm_python-0.4.8}/config/series/KOBSIHAPR.yaml +0 -0
- {dfm_python-0.4.6 → dfm_python-0.4.8}/config/series/KOBSIIMER.yaml +0 -0
- {dfm_python-0.4.6 → dfm_python-0.4.8}/config/series/KOBSIIMPR.yaml +0 -0
- {dfm_python-0.4.6 → dfm_python-0.4.8}/config/series/KOBSIXMER.yaml +0 -0
- {dfm_python-0.4.6 → dfm_python-0.4.8}/config/series/KOBUSINVR.yaml +0 -0
- {dfm_python-0.4.6 → dfm_python-0.4.8}/config/series/KOCALL_.yaml +0 -0
- {dfm_python-0.4.6 → dfm_python-0.4.8}/config/series/KOCNFBUSR.yaml +0 -0
- {dfm_python-0.4.6 → dfm_python-0.4.8}/config/series/KOCNFCONR.yaml +0 -0
- {dfm_python-0.4.6 → dfm_python-0.4.8}/config/series/KOCNGOV_D.yaml +0 -0
- {dfm_python-0.4.6 → dfm_python-0.4.8}/config/series/KOCNPER_D.yaml +0 -0
- {dfm_python-0.4.6 → dfm_python-0.4.8}/config/series/KOCOBUSIR.yaml +0 -0
- {dfm_python-0.4.6 → dfm_python-0.4.8}/config/series/KOCONPMTH.yaml +0 -0
- {dfm_python-0.4.6 → dfm_python-0.4.8}/config/series/KOCONPRCF.yaml +0 -0
- {dfm_python-0.4.6 → dfm_python-0.4.8}/config/series/KOCONSTRP.yaml +0 -0
- {dfm_python-0.4.6 → dfm_python-0.4.8}/config/series/KOCPCOREF.yaml +0 -0
- {dfm_python-0.4.6 → dfm_python-0.4.8}/config/series/KOCPEXFEF.yaml +0 -0
- {dfm_python-0.4.6 → dfm_python-0.4.8}/config/series/KOCREU__A.yaml +0 -0
- {dfm_python-0.4.6 → dfm_python-0.4.8}/config/series/KOCSECDMR.yaml +0 -0
- {dfm_python-0.4.6 → dfm_python-0.4.8}/config/series/KOCSECEMR.yaml +0 -0
- {dfm_python-0.4.6 → dfm_python-0.4.8}/config/series/KOCSEMEMR.yaml +0 -0
- {dfm_python-0.4.6 → dfm_python-0.4.8}/config/series/KOCSEOHDR.yaml +0 -0
- {dfm_python-0.4.6 → dfm_python-0.4.8}/config/series/KOCSEOHSR.yaml +0 -0
- {dfm_python-0.4.6 → dfm_python-0.4.8}/config/series/KOCSHHEMR.yaml +0 -0
- {dfm_python-0.4.6 → dfm_python-0.4.8}/config/series/KOCSHHLMR.yaml +0 -0
- {dfm_python-0.4.6 → dfm_python-0.4.8}/config/series/KOCSMTTOA.yaml +0 -0
- {dfm_python-0.4.6 → dfm_python-0.4.8}/config/series/KOCSPHIMR.yaml +0 -0
- {dfm_python-0.4.6 → dfm_python-0.4.8}/config/series/KOCSPSPMR.yaml +0 -0
- {dfm_python-0.4.6 → dfm_python-0.4.8}/config/series/KOCYLEADR.yaml +0 -0
- {dfm_python-0.4.6 → dfm_python-0.4.8}/config/series/KODBLNEQA.yaml +0 -0
- {dfm_python-0.4.6 → dfm_python-0.4.8}/config/series/KODBLNHSA.yaml +0 -0
- {dfm_python-0.4.6 → dfm_python-0.4.8}/config/series/KOEMPCONF.yaml +0 -0
- {dfm_python-0.4.6 → dfm_python-0.4.8}/config/series/KOEMPMANF.yaml +0 -0
- {dfm_python-0.4.6 → dfm_python-0.4.8}/config/series/KOEMPTOTO.yaml +0 -0
- {dfm_python-0.4.6 → dfm_python-0.4.8}/config/series/KOEMPWREP.yaml +0 -0
- {dfm_python-0.4.6 → dfm_python-0.4.8}/config/series/KOEQUIMAE.yaml +0 -0
- {dfm_python-0.4.6 → dfm_python-0.4.8}/config/series/KOEQUIPTE.yaml +0 -0
- {dfm_python-0.4.6 → dfm_python-0.4.8}/config/series/KOEQUITTE.yaml +0 -0
- {dfm_python-0.4.6 → dfm_python-0.4.8}/config/series/KOEXCHINA.yaml +0 -0
- {dfm_python-0.4.6 → dfm_python-0.4.8}/config/series/KOEXNGS_D.yaml +0 -0
- {dfm_python-0.4.6 → dfm_python-0.4.8}/config/series/KOEXPGDSA.yaml +0 -0
- {dfm_python-0.4.6 → dfm_python-0.4.8}/config/series/KOEXPPRCF.yaml +0 -0
- {dfm_python-0.4.6 → dfm_python-0.4.8}/config/series/KOGCFCNSD.yaml +0 -0
- {dfm_python-0.4.6 → dfm_python-0.4.8}/config/series/KOGCFFNVD.yaml +0 -0
- {dfm_python-0.4.6 → dfm_python-0.4.8}/config/series/KOGDP___D.yaml +0 -0
- {dfm_python-0.4.6 → dfm_python-0.4.8}/config/series/KOGFCF__D.yaml +0 -0
- {dfm_python-0.4.6 → dfm_python-0.4.8}/config/series/KOHWRWEMP.yaml +0 -0
- {dfm_python-0.4.6 → dfm_python-0.4.8}/config/series/KOIMNGS_D.yaml +0 -0
- {dfm_python-0.4.6 → dfm_python-0.4.8}/config/series/KOIMPCONA.yaml +0 -0
- {dfm_python-0.4.6 → dfm_python-0.4.8}/config/series/KOIMPGDDA.yaml +0 -0
- {dfm_python-0.4.6 → dfm_python-0.4.8}/config/series/KOIMPGDSA.yaml +0 -0
- {dfm_python-0.4.6 → dfm_python-0.4.8}/config/series/KOIMPPRCF.yaml +0 -0
- {dfm_python-0.4.6 → dfm_python-0.4.8}/config/series/KOIPALL_G.yaml +0 -0
- {dfm_python-0.4.6 → dfm_python-0.4.8}/config/series/KOIPMIMAG.yaml +0 -0
- {dfm_python-0.4.6 → dfm_python-0.4.8}/config/series/KOLRLTCO.yaml +0 -0
- {dfm_python-0.4.6 → dfm_python-0.4.8}/config/series/KOLRLTHH.yaml +0 -0
- {dfm_python-0.4.6 → dfm_python-0.4.8}/config/series/KOMPCAPGG.yaml +0 -0
- {dfm_python-0.4.6 → dfm_python-0.4.8}/config/series/KOMPCONDG.yaml +0 -0
- {dfm_python-0.4.6 → dfm_python-0.4.8}/config/series/KOMPCONGG.yaml +0 -0
- {dfm_python-0.4.6 → dfm_python-0.4.8}/config/series/KOMPCONNG.yaml +0 -0
- {dfm_python-0.4.6 → dfm_python-0.4.8}/config/series/KOMPRI30G.yaml +0 -0
- {dfm_python-0.4.6 → dfm_python-0.4.8}/config/series/KOMSCAPGG.yaml +0 -0
- {dfm_python-0.4.6 → dfm_python-0.4.8}/config/series/KOMSCONGG.yaml +0 -0
- {dfm_python-0.4.6 → dfm_python-0.4.8}/config/series/KONETTRDF.yaml +0 -0
- {dfm_python-0.4.6 → dfm_python-0.4.8}/config/series/KONEWCONA.yaml +0 -0
- {dfm_python-0.4.6 → dfm_python-0.4.8}/config/series/KOPICAPGG.yaml +0 -0
- {dfm_python-0.4.6 → dfm_python-0.4.8}/config/series/KOPICONGG.yaml +0 -0
- {dfm_python-0.4.6 → dfm_python-0.4.8}/config/series/KOPIMANUG.yaml +0 -0
- {dfm_python-0.4.6 → dfm_python-0.4.8}/config/series/KOPOPACTE.yaml +0 -0
- {dfm_python-0.4.6 → dfm_python-0.4.8}/config/series/KOPPSRM_F.yaml +0 -0
- {dfm_python-0.4.6 → dfm_python-0.4.8}/config/series/KOPROPRCF.yaml +0 -0
- {dfm_python-0.4.6 → dfm_python-0.4.8}/config/series/KOPSMANUG.yaml +0 -0
- {dfm_python-0.4.6 → dfm_python-0.4.8}/config/series/KORCNST.yaml +0 -0
- {dfm_python-0.4.6 → dfm_python-0.4.8}/config/series/KORELEC.yaml +0 -0
- {dfm_python-0.4.6 → dfm_python-0.4.8}/config/series/KORFBEV.yaml +0 -0
- {dfm_python-0.4.6 → dfm_python-0.4.8}/config/series/KORMACH.yaml +0 -0
- {dfm_python-0.4.6 → dfm_python-0.4.8}/config/series/KORMCMP.yaml +0 -0
- {dfm_python-0.4.6 → dfm_python-0.4.8}/config/series/KOROCOINF.yaml +0 -0
- {dfm_python-0.4.6 → dfm_python-0.4.8}/config/series/KORWHLS.yaml +0 -0
- {dfm_python-0.4.6 → dfm_python-0.4.8}/config/series/KOSHRPRCF.yaml +0 -0
- {dfm_python-0.4.6 → dfm_python-0.4.8}/config/series/KOSIAHOTE.yaml +0 -0
- {dfm_python-0.4.6 → dfm_python-0.4.8}/config/series/KOSIAI__E.yaml +0 -0
- {dfm_python-0.4.6 → dfm_python-0.4.8}/config/series/KOSIARRLE.yaml +0 -0
- {dfm_python-0.4.6 → dfm_python-0.4.8}/config/series/KOSIAWRTE.yaml +0 -0
- {dfm_python-0.4.6 → dfm_python-0.4.8}/config/series/KOSSBFMBE.yaml +0 -0
- {dfm_python-0.4.6 → dfm_python-0.4.8}/config/series/KOUN_TOTQ.yaml +0 -0
- {dfm_python-0.4.6 → dfm_python-0.4.8}/config/series/KOUS____.yaml +0 -0
- {dfm_python-0.4.6 → dfm_python-0.4.8}/config/series/KOVALCONA.yaml +0 -0
- {dfm_python-0.4.6 → dfm_python-0.4.8}/config/series/KOWRCCNSE.yaml +0 -0
- {dfm_python-0.4.6 → dfm_python-0.4.8}/config/series/KOWRCDURE.yaml +0 -0
- {dfm_python-0.4.6 → dfm_python-0.4.8}/config/series/KOWRCNODE.yaml +0 -0
- {dfm_python-0.4.6 → dfm_python-0.4.8}/config/series/KOWRCSEME.yaml +0 -0
- {dfm_python-0.4.6 → dfm_python-0.4.8}/data/finance.csv +0 -0
- {dfm_python-0.4.6 → dfm_python-0.4.8}/data/macro.csv +0 -0
- {dfm_python-0.4.6 → dfm_python-0.4.8}/src/dfm_python/config/__init__.py +0 -0
- {dfm_python-0.4.6 → dfm_python-0.4.8}/src/dfm_python/config/adapter.py +0 -0
- {dfm_python-0.4.6 → dfm_python-0.4.8}/src/dfm_python/config/results.py +0 -0
- {dfm_python-0.4.6 → dfm_python-0.4.8}/src/dfm_python/config/schema.py +0 -0
- {dfm_python-0.4.6 → dfm_python-0.4.8}/src/dfm_python/config/utils.py +0 -0
- {dfm_python-0.4.6 → dfm_python-0.4.8}/src/dfm_python/data/__init__.py +0 -0
- {dfm_python-0.4.6 → dfm_python-0.4.8}/src/dfm_python/data/dataloader.py +0 -0
- {dfm_python-0.4.6 → dfm_python-0.4.8}/src/dfm_python/data/dataset.py +0 -0
- {dfm_python-0.4.6 → dfm_python-0.4.8}/src/dfm_python/data/utils.py +0 -0
- {dfm_python-0.4.6 → dfm_python-0.4.8}/src/dfm_python/encoder/__init__.py +0 -0
- {dfm_python-0.4.6 → dfm_python-0.4.8}/src/dfm_python/encoder/base.py +0 -0
- {dfm_python-0.4.6 → dfm_python-0.4.8}/src/dfm_python/encoder/pca.py +0 -0
- {dfm_python-0.4.6 → dfm_python-0.4.8}/src/dfm_python/encoder/vae.py +0 -0
- {dfm_python-0.4.6 → dfm_python-0.4.8}/src/dfm_python/lightning/__init__.py +0 -0
- {dfm_python-0.4.6 → dfm_python-0.4.8}/src/dfm_python/lightning/data_module.py +0 -0
- {dfm_python-0.4.6 → dfm_python-0.4.8}/src/dfm_python/lightning/scaling.py +0 -0
- {dfm_python-0.4.6 → dfm_python-0.4.8}/src/dfm_python/logger/__init__.py +0 -0
- {dfm_python-0.4.6 → dfm_python-0.4.8}/src/dfm_python/logger/inference_logger.py +0 -0
- {dfm_python-0.4.6 → dfm_python-0.4.8}/src/dfm_python/logger/logger.py +0 -0
- {dfm_python-0.4.6 → dfm_python-0.4.8}/src/dfm_python/logger/train_logger.py +0 -0
- {dfm_python-0.4.6 → dfm_python-0.4.8}/src/dfm_python/models/__init__.py +0 -0
- {dfm_python-0.4.6 → dfm_python-0.4.8}/src/dfm_python/ssm/__init__.py +0 -0
- {dfm_python-0.4.6 → dfm_python-0.4.8}/src/dfm_python/trainer/dfm.py +0 -0
- {dfm_python-0.4.6 → dfm_python-0.4.8}/src/dfm_python/utils/data.py +0 -0
- {dfm_python-0.4.6 → dfm_python-0.4.8}/src/dfm_python/utils/diagnostics.py +0 -0
- {dfm_python-0.4.6 → dfm_python-0.4.8}/src/dfm_python/utils/helpers.py +0 -0
- {dfm_python-0.4.6 → dfm_python-0.4.8}/src/dfm_python/utils/statespace.py +0 -0
- {dfm_python-0.4.6 → dfm_python-0.4.8}/src/dfm_python/utils/time.py +0 -0
- {dfm_python-0.4.6 → dfm_python-0.4.8}/src/test/test_config.py +0 -0
- {dfm_python-0.4.6 → dfm_python-0.4.8}/src/test/test_helpers.py +0 -0
- {dfm_python-0.4.6 → dfm_python-0.4.8}/src/test/test_logger.py +0 -0
- {dfm_python-0.4.6 → dfm_python-0.4.8}/src/test/test_models.py +0 -0
- {dfm_python-0.4.6 → dfm_python-0.4.8}/src/test/test_nowcast.py +0 -0
- {dfm_python-0.4.6 → dfm_python-0.4.8}/src/test/test_sktime_integration.py +0 -0
- {dfm_python-0.4.6 → dfm_python-0.4.8}/src/test/test_ssm.py +0 -0
- {dfm_python-0.4.6 → dfm_python-0.4.8}/src/test/test_trainer.py +0 -0
- {dfm_python-0.4.6 → dfm_python-0.4.8}/src/test/test_utils.py +0 -0
- {dfm_python-0.4.6 → dfm_python-0.4.8}/uv.lock +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: dfm-python
|
|
3
|
-
Version: 0.4.
|
|
3
|
+
Version: 0.4.8
|
|
4
4
|
Summary: Dynamic Factor Model (DFM) estimation and nowcasting in Python
|
|
5
5
|
Project-URL: Homepage, https://github.com/yourusername/dfm-python
|
|
6
6
|
Project-URL: Documentation, https://github.com/yourusername/dfm-python#readme
|
|
@@ -59,7 +59,7 @@ Description-Content-Type: text/markdown
|
|
|
59
59
|
[](https://pypi.org/project/dfm-python/)
|
|
60
60
|
[](https://www.python.org/downloads/)
|
|
61
61
|
|
|
62
|
-
A comprehensive Python implementation of **Dynamic Factor Models (DFM)** for
|
|
62
|
+
A comprehensive Python implementation of **Dynamic Factor Models (DFM)** for forecasting high-dimensional time series. Built for economists, researchers, and data scientists working with mixed-frequency macroeconomic data.
|
|
63
63
|
|
|
64
64
|
## What is a Dynamic Factor Model?
|
|
65
65
|
|
|
@@ -68,7 +68,6 @@ A Dynamic Factor Model is a powerful statistical framework that:
|
|
|
68
68
|
- **Extracts common factors** from many observed time series (e.g., GDP, consumption, investment, employment)
|
|
69
69
|
- **Handles mixed frequencies** seamlessly (monthly, quarterly, annual data together)
|
|
70
70
|
- **Deals with missing data** robustly (late-arriving indicators, publication delays)
|
|
71
|
-
- **Provides nowcasts** (current-quarter GDP estimates before official release)
|
|
72
71
|
- **Forecasts** future values of both factors and observed series
|
|
73
72
|
|
|
74
73
|
**Key Innovation**: All latent factors evolve at a common "clock" frequency (configurable: `'d'`, `'w'`, `'m'`, `'q'`, `'sa'`, `'a'`), while observed series can be at different frequencies. This is achieved through deterministic tent kernel aggregation, allowing quarterly GDP to be modeled using monthly latent factors, or any slower-frequency series to be modeled using higher-frequency latent factors.
|
|
@@ -81,8 +80,7 @@ A Dynamic Factor Model is a powerful statistical framework that:
|
|
|
81
80
|
- ✅ **Block structure**: Flexible factor organization (global common factor + sector-specific factors)
|
|
82
81
|
- ✅ **Idiosyncratic components**: Per-series state augmentation for better fit (AR(1) for clock-frequency, tent-length chains for slower frequencies)
|
|
83
82
|
- ✅ **Preprocessed data**: Package expects preprocessed data from users - users handle all preprocessing (imputation, scaling, feature engineering) using sktime or other tools
|
|
84
|
-
- ✅ **
|
|
85
|
-
- ✅ **Nowcasting & Forecasting**: Generate predictions for any horizon
|
|
83
|
+
- ✅ **Forecasting**: Generate predictions for any horizon
|
|
86
84
|
- ✅ **Deep Dynamic Factor Models (DDFM)**: Nonlinear encoder with PyTorch for capturing complex factor structures (optional, requires `dfm-python[deep]`)
|
|
87
85
|
|
|
88
86
|
### Technical Features
|
|
@@ -243,7 +241,7 @@ print(f"Log-likelihood: {result.loglik:.2f}")
|
|
|
243
241
|
|
|
244
242
|
### Example 4: Fast Reuse with `load_pickle`
|
|
245
243
|
|
|
246
|
-
Once a model has been trained you can reload it instantly for forecasting
|
|
244
|
+
Once a model has been trained you can reload it instantly for forecasting without
|
|
247
245
|
re-running EM:
|
|
248
246
|
|
|
249
247
|
```python
|
|
@@ -272,15 +270,12 @@ model.load_pickle(
|
|
|
272
270
|
|
|
273
271
|
# Fast inference (milliseconds instead of minutes)
|
|
274
272
|
X_forecast, Z_forecast = model.predict(horizon=12)
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
view_date='2024-03-15'
|
|
278
|
-
)
|
|
273
|
+
# Note: Nowcasting functionality has been moved to src.nowcast
|
|
274
|
+
# Use src.nowcast.Nowcast for nowcasting operations
|
|
279
275
|
```
|
|
280
276
|
|
|
281
277
|
`DFM.load_pickle()` accepts either the auto-save payload (`{'result': ..., 'config': ...}`) or a
|
|
282
|
-
raw `DFMResult`. Provide `load_data_path` or `data`/`time_index` when you need
|
|
283
|
-
decomposition abilities (which require the data view).
|
|
278
|
+
raw `DFMResult`. Provide `load_data_path` or `data`/`time_index` when you need to access model results.
|
|
284
279
|
|
|
285
280
|
## Configuration Guide
|
|
286
281
|
|
|
@@ -510,105 +505,9 @@ idio_component = result.X_sm[:, series_idx] - series_factor_component
|
|
|
510
505
|
|
|
511
506
|
## Advanced Features
|
|
512
507
|
|
|
513
|
-
### Nowcasting
|
|
514
|
-
|
|
515
|
-
The package provides a comprehensive nowcasting API for pseudo real-time evaluation and downstream model integration:
|
|
516
|
-
|
|
517
|
-
#### Basic Nowcasting
|
|
518
|
-
|
|
519
|
-
```python
|
|
520
|
-
import dfm_python as dfm
|
|
521
|
-
from dfm_python import Nowcast
|
|
522
|
-
|
|
523
|
-
# Load config and data, train model
|
|
524
|
-
dfm.from_yaml('config/default.yaml')
|
|
525
|
-
dfm.load_data('data/data.csv')
|
|
526
|
-
dfm.train()
|
|
527
|
-
|
|
528
|
-
# Get Nowcast instance
|
|
529
|
-
model = dfm.DFM()
|
|
530
|
-
nowcast = model.nowcast # or: nowcast = Nowcast(model)
|
|
531
|
-
|
|
532
|
-
# Calculate nowcast (simple callable interface)
|
|
533
|
-
value = nowcast('gdp', view_date='2024-01-15', target_period='2024Q1')
|
|
534
|
-
print(f"Nowcast value: {value:.4f}")
|
|
535
|
-
|
|
536
|
-
# Or get full result with metadata
|
|
537
|
-
result = nowcast('gdp', view_date='2024-01-15', target_period='2024Q1', return_result=True)
|
|
538
|
-
print(f"Nowcast: {result.nowcast_value:.4f}")
|
|
539
|
-
print(f"Data availability: {result.data_availability}")
|
|
540
|
-
print(f"Factors at view: {result.factors_at_view}")
|
|
541
|
-
```
|
|
542
|
-
|
|
543
|
-
#### News Decomposition
|
|
544
|
-
|
|
545
|
-
Decompose forecast updates into contributions from individual data releases:
|
|
546
|
-
|
|
547
|
-
```python
|
|
548
|
-
# News decomposition between two data views
|
|
549
|
-
news = nowcast.decompose(
|
|
550
|
-
target_series='gdp',
|
|
551
|
-
target_period='2024Q1',
|
|
552
|
-
view_date_old='2024-01-15',
|
|
553
|
-
view_date_new='2024-02-15'
|
|
554
|
-
)
|
|
555
|
-
|
|
556
|
-
# Access results (NewsDecompResult)
|
|
557
|
-
print(f"Old forecast: {news.y_old:.4f}")
|
|
558
|
-
print(f"New forecast: {news.y_new:.4f}")
|
|
559
|
-
print(f"Change: {news.change:.4f}")
|
|
560
|
-
print(f"Top contributors: {news.top_contributors}")
|
|
561
|
-
|
|
562
|
-
# Or get dictionary format (backward compatibility)
|
|
563
|
-
news_dict = nowcast.decompose(
|
|
564
|
-
target_series='gdp',
|
|
565
|
-
target_period='2024Q1',
|
|
566
|
-
view_date_old='2024-01-15',
|
|
567
|
-
view_date_new='2024-02-15',
|
|
568
|
-
return_dict=True
|
|
569
|
-
)
|
|
570
|
-
```
|
|
571
|
-
|
|
572
|
-
#### Pseudo Real-Time Backtesting
|
|
573
|
-
|
|
574
|
-
Perform backtesting to evaluate model performance in pseudo real-time:
|
|
575
|
-
|
|
576
|
-
```python
|
|
577
|
-
from datetime import datetime
|
|
578
|
-
|
|
579
|
-
# Perform backtest
|
|
580
|
-
backtest_result = nowcast.backtest(
|
|
581
|
-
target_series='gdp',
|
|
582
|
-
target_date='2024Q4',
|
|
583
|
-
backward_steps=20, # 20 backward steps
|
|
584
|
-
higher_freq=True, # Use frequency one step faster than clock
|
|
585
|
-
include_actual=True # Compare with actual values
|
|
586
|
-
)
|
|
587
|
-
|
|
588
|
-
# Access metrics
|
|
589
|
-
print(f"Overall RMSE: {backtest_result.overall_rmse:.4f}")
|
|
590
|
-
print(f"Overall MAE: {backtest_result.overall_mae:.4f}")
|
|
591
|
-
print(f"Failed steps: {backtest_result.failed_steps}")
|
|
592
|
-
|
|
593
|
-
# Access point-wise metrics
|
|
594
|
-
print(f"RMSE per step: {backtest_result.rmse_per_step}")
|
|
595
|
-
print(f"MAE per step: {backtest_result.mae_per_step}")
|
|
596
|
-
|
|
597
|
-
# Access individual nowcast results
|
|
598
|
-
for i, nowcast_result in enumerate(backtest_result.nowcast_results):
|
|
599
|
-
print(f"Step {i}: nowcast={nowcast_result.nowcast_value:.4f}, "
|
|
600
|
-
f"view_date={nowcast_result.view_date}")
|
|
601
|
-
|
|
602
|
-
# Access news decomposition between steps
|
|
603
|
-
for i, news_result in enumerate(backtest_result.news_results):
|
|
604
|
-
if news_result is not None:
|
|
605
|
-
print(f"Step {i}: forecast change={news_result.change:.4f}")
|
|
606
|
-
|
|
607
|
-
# Visualize results
|
|
608
|
-
backtest_result.plot(save_path='backtest_results.png', show=False)
|
|
609
|
-
```
|
|
508
|
+
### Nowcasting
|
|
610
509
|
|
|
611
|
-
|
|
510
|
+
Nowcasting functionality has been moved to `src.nowcast`. Use `src.nowcast.Nowcast` for nowcasting operations, news decomposition, and backtesting.
|
|
612
511
|
|
|
613
512
|
Generate datasets for model evaluation across multiple periods:
|
|
614
513
|
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
[](https://pypi.org/project/dfm-python/)
|
|
4
4
|
[](https://www.python.org/downloads/)
|
|
5
5
|
|
|
6
|
-
A comprehensive Python implementation of **Dynamic Factor Models (DFM)** for
|
|
6
|
+
A comprehensive Python implementation of **Dynamic Factor Models (DFM)** for forecasting high-dimensional time series. Built for economists, researchers, and data scientists working with mixed-frequency macroeconomic data.
|
|
7
7
|
|
|
8
8
|
## What is a Dynamic Factor Model?
|
|
9
9
|
|
|
@@ -12,7 +12,6 @@ A Dynamic Factor Model is a powerful statistical framework that:
|
|
|
12
12
|
- **Extracts common factors** from many observed time series (e.g., GDP, consumption, investment, employment)
|
|
13
13
|
- **Handles mixed frequencies** seamlessly (monthly, quarterly, annual data together)
|
|
14
14
|
- **Deals with missing data** robustly (late-arriving indicators, publication delays)
|
|
15
|
-
- **Provides nowcasts** (current-quarter GDP estimates before official release)
|
|
16
15
|
- **Forecasts** future values of both factors and observed series
|
|
17
16
|
|
|
18
17
|
**Key Innovation**: All latent factors evolve at a common "clock" frequency (configurable: `'d'`, `'w'`, `'m'`, `'q'`, `'sa'`, `'a'`), while observed series can be at different frequencies. This is achieved through deterministic tent kernel aggregation, allowing quarterly GDP to be modeled using monthly latent factors, or any slower-frequency series to be modeled using higher-frequency latent factors.
|
|
@@ -25,8 +24,7 @@ A Dynamic Factor Model is a powerful statistical framework that:
|
|
|
25
24
|
- ✅ **Block structure**: Flexible factor organization (global common factor + sector-specific factors)
|
|
26
25
|
- ✅ **Idiosyncratic components**: Per-series state augmentation for better fit (AR(1) for clock-frequency, tent-length chains for slower frequencies)
|
|
27
26
|
- ✅ **Preprocessed data**: Package expects preprocessed data from users - users handle all preprocessing (imputation, scaling, feature engineering) using sktime or other tools
|
|
28
|
-
- ✅ **
|
|
29
|
-
- ✅ **Nowcasting & Forecasting**: Generate predictions for any horizon
|
|
27
|
+
- ✅ **Forecasting**: Generate predictions for any horizon
|
|
30
28
|
- ✅ **Deep Dynamic Factor Models (DDFM)**: Nonlinear encoder with PyTorch for capturing complex factor structures (optional, requires `dfm-python[deep]`)
|
|
31
29
|
|
|
32
30
|
### Technical Features
|
|
@@ -187,7 +185,7 @@ print(f"Log-likelihood: {result.loglik:.2f}")
|
|
|
187
185
|
|
|
188
186
|
### Example 4: Fast Reuse with `load_pickle`
|
|
189
187
|
|
|
190
|
-
Once a model has been trained you can reload it instantly for forecasting
|
|
188
|
+
Once a model has been trained you can reload it instantly for forecasting without
|
|
191
189
|
re-running EM:
|
|
192
190
|
|
|
193
191
|
```python
|
|
@@ -216,15 +214,12 @@ model.load_pickle(
|
|
|
216
214
|
|
|
217
215
|
# Fast inference (milliseconds instead of minutes)
|
|
218
216
|
X_forecast, Z_forecast = model.predict(horizon=12)
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
view_date='2024-03-15'
|
|
222
|
-
)
|
|
217
|
+
# Note: Nowcasting functionality has been moved to src.nowcast
|
|
218
|
+
# Use src.nowcast.Nowcast for nowcasting operations
|
|
223
219
|
```
|
|
224
220
|
|
|
225
221
|
`DFM.load_pickle()` accepts either the auto-save payload (`{'result': ..., 'config': ...}`) or a
|
|
226
|
-
raw `DFMResult`. Provide `load_data_path` or `data`/`time_index` when you need
|
|
227
|
-
decomposition abilities (which require the data view).
|
|
222
|
+
raw `DFMResult`. Provide `load_data_path` or `data`/`time_index` when you need to access model results.
|
|
228
223
|
|
|
229
224
|
## Configuration Guide
|
|
230
225
|
|
|
@@ -454,105 +449,9 @@ idio_component = result.X_sm[:, series_idx] - series_factor_component
|
|
|
454
449
|
|
|
455
450
|
## Advanced Features
|
|
456
451
|
|
|
457
|
-
### Nowcasting
|
|
458
|
-
|
|
459
|
-
The package provides a comprehensive nowcasting API for pseudo real-time evaluation and downstream model integration:
|
|
460
|
-
|
|
461
|
-
#### Basic Nowcasting
|
|
462
|
-
|
|
463
|
-
```python
|
|
464
|
-
import dfm_python as dfm
|
|
465
|
-
from dfm_python import Nowcast
|
|
466
|
-
|
|
467
|
-
# Load config and data, train model
|
|
468
|
-
dfm.from_yaml('config/default.yaml')
|
|
469
|
-
dfm.load_data('data/data.csv')
|
|
470
|
-
dfm.train()
|
|
471
|
-
|
|
472
|
-
# Get Nowcast instance
|
|
473
|
-
model = dfm.DFM()
|
|
474
|
-
nowcast = model.nowcast # or: nowcast = Nowcast(model)
|
|
475
|
-
|
|
476
|
-
# Calculate nowcast (simple callable interface)
|
|
477
|
-
value = nowcast('gdp', view_date='2024-01-15', target_period='2024Q1')
|
|
478
|
-
print(f"Nowcast value: {value:.4f}")
|
|
479
|
-
|
|
480
|
-
# Or get full result with metadata
|
|
481
|
-
result = nowcast('gdp', view_date='2024-01-15', target_period='2024Q1', return_result=True)
|
|
482
|
-
print(f"Nowcast: {result.nowcast_value:.4f}")
|
|
483
|
-
print(f"Data availability: {result.data_availability}")
|
|
484
|
-
print(f"Factors at view: {result.factors_at_view}")
|
|
485
|
-
```
|
|
486
|
-
|
|
487
|
-
#### News Decomposition
|
|
488
|
-
|
|
489
|
-
Decompose forecast updates into contributions from individual data releases:
|
|
490
|
-
|
|
491
|
-
```python
|
|
492
|
-
# News decomposition between two data views
|
|
493
|
-
news = nowcast.decompose(
|
|
494
|
-
target_series='gdp',
|
|
495
|
-
target_period='2024Q1',
|
|
496
|
-
view_date_old='2024-01-15',
|
|
497
|
-
view_date_new='2024-02-15'
|
|
498
|
-
)
|
|
499
|
-
|
|
500
|
-
# Access results (NewsDecompResult)
|
|
501
|
-
print(f"Old forecast: {news.y_old:.4f}")
|
|
502
|
-
print(f"New forecast: {news.y_new:.4f}")
|
|
503
|
-
print(f"Change: {news.change:.4f}")
|
|
504
|
-
print(f"Top contributors: {news.top_contributors}")
|
|
505
|
-
|
|
506
|
-
# Or get dictionary format (backward compatibility)
|
|
507
|
-
news_dict = nowcast.decompose(
|
|
508
|
-
target_series='gdp',
|
|
509
|
-
target_period='2024Q1',
|
|
510
|
-
view_date_old='2024-01-15',
|
|
511
|
-
view_date_new='2024-02-15',
|
|
512
|
-
return_dict=True
|
|
513
|
-
)
|
|
514
|
-
```
|
|
515
|
-
|
|
516
|
-
#### Pseudo Real-Time Backtesting
|
|
517
|
-
|
|
518
|
-
Perform backtesting to evaluate model performance in pseudo real-time:
|
|
519
|
-
|
|
520
|
-
```python
|
|
521
|
-
from datetime import datetime
|
|
522
|
-
|
|
523
|
-
# Perform backtest
|
|
524
|
-
backtest_result = nowcast.backtest(
|
|
525
|
-
target_series='gdp',
|
|
526
|
-
target_date='2024Q4',
|
|
527
|
-
backward_steps=20, # 20 backward steps
|
|
528
|
-
higher_freq=True, # Use frequency one step faster than clock
|
|
529
|
-
include_actual=True # Compare with actual values
|
|
530
|
-
)
|
|
531
|
-
|
|
532
|
-
# Access metrics
|
|
533
|
-
print(f"Overall RMSE: {backtest_result.overall_rmse:.4f}")
|
|
534
|
-
print(f"Overall MAE: {backtest_result.overall_mae:.4f}")
|
|
535
|
-
print(f"Failed steps: {backtest_result.failed_steps}")
|
|
536
|
-
|
|
537
|
-
# Access point-wise metrics
|
|
538
|
-
print(f"RMSE per step: {backtest_result.rmse_per_step}")
|
|
539
|
-
print(f"MAE per step: {backtest_result.mae_per_step}")
|
|
540
|
-
|
|
541
|
-
# Access individual nowcast results
|
|
542
|
-
for i, nowcast_result in enumerate(backtest_result.nowcast_results):
|
|
543
|
-
print(f"Step {i}: nowcast={nowcast_result.nowcast_value:.4f}, "
|
|
544
|
-
f"view_date={nowcast_result.view_date}")
|
|
545
|
-
|
|
546
|
-
# Access news decomposition between steps
|
|
547
|
-
for i, news_result in enumerate(backtest_result.news_results):
|
|
548
|
-
if news_result is not None:
|
|
549
|
-
print(f"Step {i}: forecast change={news_result.change:.4f}")
|
|
550
|
-
|
|
551
|
-
# Visualize results
|
|
552
|
-
backtest_result.plot(save_path='backtest_results.png', show=False)
|
|
553
|
-
```
|
|
452
|
+
### Nowcasting
|
|
554
453
|
|
|
555
|
-
|
|
454
|
+
Nowcasting functionality has been moved to `src.nowcast`. Use `src.nowcast.Nowcast` for nowcasting operations, news decomposition, and backtesting.
|
|
556
455
|
|
|
557
456
|
Generate datasets for model evaluation across multiple periods:
|
|
558
457
|
|
|
@@ -6,7 +6,6 @@ This package implements a comprehensive Dynamic Factor Model framework with supp
|
|
|
6
6
|
- Tent kernel aggregation for low-to-high frequency mapping
|
|
7
7
|
- Expectation-Maximization (EM) algorithm for parameter estimation
|
|
8
8
|
- Kalman filtering and smoothing for factor extraction
|
|
9
|
-
- News decomposition for nowcasting
|
|
10
9
|
- Deep Dynamic Factor Models (DDFM) with nonlinear encoders (requires PyTorch)
|
|
11
10
|
|
|
12
11
|
The package implements a clock-based approach to mixed-frequency DFMs, where all latent
|
|
@@ -23,7 +22,6 @@ Key Features:
|
|
|
23
22
|
- Flexible block structure for factor modeling
|
|
24
23
|
- Robust handling of missing data (internal spline interpolation)
|
|
25
24
|
- Automatic standardization and data clipping
|
|
26
|
-
- News decomposition for forecast updates
|
|
27
25
|
|
|
28
26
|
Example (Standard Lightning Pattern):
|
|
29
27
|
>>> from dfm_python import DFM, DFMDataModule, DFMTrainer
|
|
@@ -67,7 +65,7 @@ Note: DFMConfig and SeriesConfig are internal implementation details.
|
|
|
67
65
|
For detailed documentation, see the README.md file and the tutorial notebooks/scripts.
|
|
68
66
|
"""
|
|
69
67
|
|
|
70
|
-
__version__ = "0.4.
|
|
68
|
+
__version__ = "0.4.8"
|
|
71
69
|
|
|
72
70
|
# ============================================================================
|
|
73
71
|
# PUBLIC API DEFINITION
|
|
@@ -81,7 +79,7 @@ __version__ = "0.4.6"
|
|
|
81
79
|
# 2. High-level API: DFM, DDFM, module-level convenience functions
|
|
82
80
|
# 3. Core utilities: TimeIndex, diagnostics
|
|
83
81
|
# 4. Models: BaseFactorModel, DDFM (low-level)
|
|
84
|
-
# 5.
|
|
82
|
+
# 5. Data & Results: DFMResult
|
|
85
83
|
# 6. Data & Results: DFMResult
|
|
86
84
|
# ============================================================================
|
|
87
85
|
|
|
@@ -90,8 +88,9 @@ from .config import (
|
|
|
90
88
|
DEFAULT_BLOCK_NAME,
|
|
91
89
|
ConfigSource, YamlSource, DictSource, HydraSource,
|
|
92
90
|
MergedConfigSource, make_config_source,
|
|
93
|
-
DFMConfig, SeriesConfig, # Internal use - prefer Hydra YAML configs
|
|
94
91
|
)
|
|
92
|
+
# Internal imports (for backward compatibility, but not recommended)
|
|
93
|
+
from .config import DFMConfig, SeriesConfig # Internal use only
|
|
95
94
|
|
|
96
95
|
# Results
|
|
97
96
|
from .config.results import DFMResult, DDFMResult, BaseResult
|
|
@@ -101,23 +100,15 @@ from .utils.diagnostics import diagnose_series, print_series_diagnosis
|
|
|
101
100
|
from .utils.time import calculate_rmse
|
|
102
101
|
|
|
103
102
|
# PyTorch Lightning modules (mandatory dependency)
|
|
103
|
+
# Users can import these directly from dfm_python
|
|
104
104
|
from .lightning import (
|
|
105
105
|
DFMDataModule,
|
|
106
|
-
DFMDataset,
|
|
107
|
-
KalmanFilter,
|
|
108
|
-
EMAlgorithm,
|
|
106
|
+
DFMDataset, # Dataset class (usually not needed directly)
|
|
107
|
+
KalmanFilter, # Module class
|
|
108
|
+
EMAlgorithm, # Module class
|
|
109
109
|
)
|
|
110
110
|
|
|
111
|
-
# Nowcasting
|
|
112
|
-
from .nowcast import (
|
|
113
|
-
Nowcast,
|
|
114
|
-
NowcastResult,
|
|
115
|
-
)
|
|
116
|
-
from .nowcast.helpers import (
|
|
117
|
-
para_const,
|
|
118
|
-
NewsDecompResult,
|
|
119
|
-
BacktestResult,
|
|
120
|
-
)
|
|
111
|
+
# Nowcasting removed - use src.nowcast instead
|
|
121
112
|
|
|
122
113
|
# Model implementations
|
|
123
114
|
from .models.base import BaseFactorModel
|
|
@@ -128,11 +119,9 @@ from .models.ddfm import DDFM, DDFMModel
|
|
|
128
119
|
|
|
129
120
|
__all__ = [
|
|
130
121
|
# Core classes
|
|
131
|
-
'DFM',
|
|
122
|
+
'DFM',
|
|
132
123
|
# Model base and implementations
|
|
133
124
|
'BaseFactorModel',
|
|
134
|
-
# Nowcast result classes
|
|
135
|
-
'NowcastResult', 'NewsDecompResult', 'BacktestResult',
|
|
136
125
|
# Constants
|
|
137
126
|
'DEFAULT_BLOCK_NAME',
|
|
138
127
|
# Config sources
|
|
@@ -140,7 +129,6 @@ __all__ = [
|
|
|
140
129
|
'MergedConfigSource', 'make_config_source',
|
|
141
130
|
# Low-level API (functional interface - advanced usage)
|
|
142
131
|
'BaseResult', 'DFMResult', 'DDFMResult', 'calculate_rmse', 'diagnose_series', 'print_series_diagnosis',
|
|
143
|
-
'para_const',
|
|
144
132
|
]
|
|
145
133
|
|
|
146
134
|
# DDFM high-level API (PyTorch is mandatory)
|
|
@@ -152,9 +140,9 @@ __all__.extend([
|
|
|
152
140
|
# Lightning modules (mandatory dependency)
|
|
153
141
|
__all__.extend([
|
|
154
142
|
'DFMDataModule',
|
|
155
|
-
'DFMDataset',
|
|
156
|
-
'KalmanFilter',
|
|
157
|
-
'EMAlgorithm',
|
|
143
|
+
'DFMDataset', # Dataset class (usually not needed directly)
|
|
144
|
+
'KalmanFilter', # Module class
|
|
145
|
+
'EMAlgorithm', # Module class
|
|
158
146
|
])
|
|
159
147
|
|
|
160
148
|
# Trainer classes (mandatory dependency)
|
|
@@ -91,7 +91,6 @@ class BaseFactorModel(pl.LightningModule):
|
|
|
91
91
|
self._result: Optional[BaseResult] = None
|
|
92
92
|
self.training_state: Optional[Any] = None
|
|
93
93
|
self._data_module: Optional[Any] = None
|
|
94
|
-
self._nowcast: Optional[Any] = None
|
|
95
94
|
|
|
96
95
|
@property
|
|
97
96
|
def config(self) -> DFMConfig:
|
|
@@ -494,7 +493,6 @@ class BaseFactorModel(pl.LightningModule):
|
|
|
494
493
|
self._config = None
|
|
495
494
|
self._data_module = None
|
|
496
495
|
self._result = None
|
|
497
|
-
self._nowcast = None
|
|
498
496
|
if hasattr(self, 'training_state'):
|
|
499
497
|
self.training_state = None
|
|
500
498
|
return self
|