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.
Files changed (158) hide show
  1. {dfm_python-0.6.13 → dfm_python-0.7.0}/.gitignore +2 -1
  2. dfm_python-0.7.0/CHANGELOG.md +11 -0
  3. dfm_python-0.7.0/LICENSE +21 -0
  4. dfm_python-0.7.0/PKG-INFO +186 -0
  5. dfm_python-0.7.0/README.md +123 -0
  6. dfm_python-0.7.0/config/afm_finance.yaml +27 -0
  7. {dfm_python-0.6.13 → dfm_python-0.7.0}/config/ddfm_exchange.yaml +13 -22
  8. {dfm_python-0.6.13 → dfm_python-0.7.0}/config/ddfm_finance.yaml +12 -11
  9. dfm_python-0.7.0/config/ivdfm_exchange.yaml +39 -0
  10. dfm_python-0.7.0/config/ivdfm_finance.yaml +38 -0
  11. dfm_python-0.7.0/config/ivdfm_macro.yaml +40 -0
  12. {dfm_python-0.6.13 → dfm_python-0.7.0}/pyproject.toml +12 -8
  13. {dfm_python-0.6.13 → dfm_python-0.7.0}/src/dfm_python/__init__.py +11 -2
  14. {dfm_python-0.6.13 → dfm_python-0.7.0}/src/dfm_python/config/__init__.py +6 -6
  15. {dfm_python-0.6.13 → dfm_python-0.7.0}/src/dfm_python/config/constants.py +90 -0
  16. dfm_python-0.7.0/src/dfm_python/config/schema/__init__.py +19 -0
  17. {dfm_python-0.6.13 → dfm_python-0.7.0}/src/dfm_python/config/schema/model.py +403 -1
  18. {dfm_python-0.6.13 → dfm_python-0.7.0}/src/dfm_python/config/schema/params.py +218 -0
  19. {dfm_python-0.6.13 → dfm_python-0.7.0}/src/dfm_python/config/schema/results.py +231 -84
  20. {dfm_python-0.6.13 → dfm_python-0.7.0}/src/dfm_python/dataset/__init__.py +4 -0
  21. dfm_python-0.7.0/src/dfm_python/dataset/afm_dataset.py +119 -0
  22. {dfm_python-0.6.13 → dfm_python-0.7.0}/src/dfm_python/dataset/ddfm_dataset.py +21 -0
  23. dfm_python-0.7.0/src/dfm_python/dataset/ivdfm_dataset.py +427 -0
  24. {dfm_python-0.6.13 → dfm_python-0.7.0}/src/dfm_python/functional/krylov.py +2 -61
  25. dfm_python-0.7.0/src/dfm_python/layer/mixing.py +37 -0
  26. {dfm_python-0.6.13 → dfm_python-0.7.0}/src/dfm_python/layer/mlp.py +38 -19
  27. {dfm_python-0.6.13 → dfm_python-0.7.0}/src/dfm_python/layer/pca.py +46 -0
  28. dfm_python-0.7.0/src/dfm_python/layer/regime.py +53 -0
  29. {dfm_python-0.6.13 → dfm_python-0.7.0}/src/dfm_python/logger/__init__.py +8 -0
  30. dfm_python-0.7.0/src/dfm_python/logger/ivdfm_logger.py +92 -0
  31. {dfm_python-0.6.13 → dfm_python-0.7.0}/src/dfm_python/models/__init__.py +10 -0
  32. dfm_python-0.7.0/src/dfm_python/models/afm/__init__.py +23 -0
  33. dfm_python-0.7.0/src/dfm_python/models/afm/afm.py +385 -0
  34. dfm_python-0.7.0/src/dfm_python/models/afm/baselines.py +72 -0
  35. dfm_python-0.7.0/src/dfm_python/models/afm/factors.py +192 -0
  36. dfm_python-0.7.0/src/dfm_python/models/afm/longconv.py +97 -0
  37. {dfm_python-0.6.13 → dfm_python-0.7.0}/src/dfm_python/models/base.py +15 -0
  38. {dfm_python-0.6.13 → dfm_python-0.7.0}/src/dfm_python/models/ddfm/ddfm.py +17 -8
  39. dfm_python-0.7.0/src/dfm_python/models/ivdfm/__init__.py +18 -0
  40. dfm_python-0.7.0/src/dfm_python/models/ivdfm/decoder.py +85 -0
  41. dfm_python-0.7.0/src/dfm_python/models/ivdfm/encoder.py +198 -0
  42. dfm_python-0.7.0/src/dfm_python/models/ivdfm/ivdfm.py +1838 -0
  43. dfm_python-0.7.0/src/dfm_python/models/ivdfm/optuna.py +647 -0
  44. dfm_python-0.7.0/src/dfm_python/models/ivdfm/prior.py +633 -0
  45. {dfm_python-0.6.13 → dfm_python-0.7.0}/src/dfm_python/numeric/builder.py +247 -0
  46. {dfm_python-0.6.13 → dfm_python-0.7.0}/src/dfm_python/numeric/estimator.py +78 -9
  47. {dfm_python-0.6.13 → dfm_python-0.7.0}/src/dfm_python/numeric/validator.py +5 -0
  48. {dfm_python-0.6.13 → dfm_python-0.7.0}/src/dfm_python/ssm/__init__.py +6 -0
  49. dfm_python-0.7.0/src/dfm_python/ssm/base.py +208 -0
  50. dfm_python-0.7.0/src/dfm_python/ssm/companion.py +500 -0
  51. {dfm_python-0.6.13 → dfm_python-0.7.0}/src/dfm_python/ssm/kalman.py +100 -3
  52. dfm_python-0.7.0/src/dfm_python/utils/loss.py +324 -0
  53. dfm_python-0.7.0/src/test/dataset/test_ivdfm_dataset.py +284 -0
  54. dfm_python-0.7.0/src/test/models/test_afm.py +241 -0
  55. dfm_python-0.7.0/src/test/models/test_ivdfm.py +509 -0
  56. dfm_python-0.7.0/src/test/models/test_ivdfm_optuna.py +262 -0
  57. dfm_python-0.7.0/src/test/models/test_ivdfm_regime.py +190 -0
  58. dfm_python-0.7.0/src/test/ssm/test_companion_regime.py +133 -0
  59. dfm_python-0.7.0/tutorial/tutorial_exchange_ivdfm.py +122 -0
  60. {dfm_python-0.6.13 → dfm_python-0.7.0}/tutorial/tutorial_finance_ddfm.py +38 -14
  61. dfm_python-0.7.0/tutorial/tutorial_finance_ivdfm.py +163 -0
  62. dfm_python-0.7.0/tutorial/tutorial_macro_ivdfm.py +148 -0
  63. dfm_python-0.6.13/.cursor/agents/test-runner.md +0 -118
  64. dfm_python-0.6.13/=0.11.0 +0 -1
  65. dfm_python-0.6.13/PKG-INFO +0 -56
  66. dfm_python-0.6.13/data/exchange_rate.csv +0 -7589
  67. dfm_python-0.6.13/data/finance.csv +0 -9022
  68. dfm_python-0.6.13/data/macro.csv +0 -2539
  69. dfm_python-0.6.13/src/dfm_python/config/schema/__init__.py +0 -19
  70. dfm_python-0.6.13/src/dfm_python/functional/cauchy.py +0 -236
  71. dfm_python-0.6.13/src/dfm_python/models/ivdfm/__init__.py +0 -0
  72. dfm_python-0.6.13/src/dfm_python/models/ivdfm/decoder.py +0 -0
  73. dfm_python-0.6.13/src/dfm_python/models/ivdfm/encoder.py +0 -0
  74. dfm_python-0.6.13/src/dfm_python/models/ivdfm/ivdfm.py +0 -708
  75. dfm_python-0.6.13/src/dfm_python/utils/loss.py +0 -330
  76. dfm_python-0.6.13/uv.lock +0 -3817
  77. {dfm_python-0.6.13 → dfm_python-0.7.0}/.python-version +0 -0
  78. {dfm_python-0.6.13 → dfm_python-0.7.0}/MANIFEST.in +0 -0
  79. {dfm_python-0.6.13 → dfm_python-0.7.0}/config/ddfm_macro.yaml +0 -0
  80. {dfm_python-0.6.13 → dfm_python-0.7.0}/config/dfm_exchange.yaml +0 -0
  81. {dfm_python-0.6.13 → dfm_python-0.7.0}/config/dfm_finance.yaml +0 -0
  82. {dfm_python-0.6.13 → dfm_python-0.7.0}/config/dfm_macro.yaml +0 -0
  83. {dfm_python-0.6.13 → dfm_python-0.7.0}/src/dfm_python/config/adapter.py +0 -0
  84. {dfm_python-0.6.13 → dfm_python-0.7.0}/src/dfm_python/config/schema/block.py +0 -0
  85. {dfm_python-0.6.13 → dfm_python-0.7.0}/src/dfm_python/config/types.py +0 -0
  86. {dfm_python-0.6.13 → dfm_python-0.7.0}/src/dfm_python/dataset/dfm_dataset.py +0 -0
  87. {dfm_python-0.6.13 → dfm_python-0.7.0}/src/dfm_python/dataset/time.py +0 -0
  88. {dfm_python-0.6.13 → dfm_python-0.7.0}/src/dfm_python/functional/__init__.py +0 -0
  89. {dfm_python-0.6.13 → dfm_python-0.7.0}/src/dfm_python/functional/em.py +0 -0
  90. {dfm_python-0.6.13 → dfm_python-0.7.0}/src/dfm_python/logger/ddfm_logger.py +0 -0
  91. {dfm_python-0.6.13 → dfm_python-0.7.0}/src/dfm_python/logger/dfm_logger.py +0 -0
  92. {dfm_python-0.6.13 → dfm_python-0.7.0}/src/dfm_python/logger/inference_logger.py +0 -0
  93. {dfm_python-0.6.13 → dfm_python-0.7.0}/src/dfm_python/logger/logger.py +0 -0
  94. {dfm_python-0.6.13 → dfm_python-0.7.0}/src/dfm_python/logger/train_logger.py +0 -0
  95. {dfm_python-0.6.13 → dfm_python-0.7.0}/src/dfm_python/models/ddfm/__init__.py +0 -0
  96. {dfm_python-0.6.13 → dfm_python-0.7.0}/src/dfm_python/models/ddfm/decoder.py +0 -0
  97. {dfm_python-0.6.13 → dfm_python-0.7.0}/src/dfm_python/models/ddfm/encoder.py +0 -0
  98. {dfm_python-0.6.13 → dfm_python-0.7.0}/src/dfm_python/models/ddfm/sampling.py +0 -0
  99. {dfm_python-0.6.13 → dfm_python-0.7.0}/src/dfm_python/models/dfm/__init__.py +0 -0
  100. {dfm_python-0.6.13 → dfm_python-0.7.0}/src/dfm_python/models/dfm/dfm.py +0 -0
  101. {dfm_python-0.6.13 → dfm_python-0.7.0}/src/dfm_python/models/dfm/initialization.py +0 -0
  102. {dfm_python-0.6.13 → dfm_python-0.7.0}/src/dfm_python/models/dfm/mixed_freq.py +0 -0
  103. {dfm_python-0.6.13 → dfm_python-0.7.0}/src/dfm_python/models/dfm/tent.py +0 -0
  104. {dfm_python-0.6.13 → dfm_python-0.7.0}/src/dfm_python/numeric/stability.py +0 -0
  105. {dfm_python-0.6.13 → dfm_python-0.7.0}/src/dfm_python/numeric/statistic.py +0 -0
  106. /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
  107. {dfm_python-0.6.13 → dfm_python-0.7.0}/src/dfm_python/utils/__init__.py +0 -0
  108. {dfm_python-0.6.13 → dfm_python-0.7.0}/src/dfm_python/utils/checkpoint.py +0 -0
  109. {dfm_python-0.6.13 → dfm_python-0.7.0}/src/dfm_python/utils/errors.py +0 -0
  110. {dfm_python-0.6.13 → dfm_python-0.7.0}/src/dfm_python/utils/helper.py +0 -0
  111. {dfm_python-0.6.13 → dfm_python-0.7.0}/src/dfm_python/utils/metric.py +0 -0
  112. {dfm_python-0.6.13 → dfm_python-0.7.0}/src/dfm_python/utils/misc.py +0 -0
  113. {dfm_python-0.6.13 → dfm_python-0.7.0}/src/dfm_python/utils/validation.py +0 -0
  114. {dfm_python-0.6.13 → dfm_python-0.7.0}/src/test/__init__.py +0 -0
  115. {dfm_python-0.6.13 → dfm_python-0.7.0}/src/test/config/__init__.py +0 -0
  116. {dfm_python-0.6.13 → dfm_python-0.7.0}/src/test/config/schema/__init__.py +0 -0
  117. {dfm_python-0.6.13 → dfm_python-0.7.0}/src/test/config/schema/test_block.py +0 -0
  118. {dfm_python-0.6.13 → dfm_python-0.7.0}/src/test/config/schema/test_model.py +0 -0
  119. {dfm_python-0.6.13 → dfm_python-0.7.0}/src/test/config/schema/test_results.py +0 -0
  120. {dfm_python-0.6.13 → dfm_python-0.7.0}/src/test/config/test_adapter.py +0 -0
  121. {dfm_python-0.6.13 → dfm_python-0.7.0}/src/test/config/test_constants.py +0 -0
  122. {dfm_python-0.6.13 → dfm_python-0.7.0}/src/test/config/test_tent_weights_config.py +0 -0
  123. {dfm_python-0.6.13 → dfm_python-0.7.0}/src/test/config/test_types.py +0 -0
  124. {dfm_python-0.6.13 → dfm_python-0.7.0}/src/test/conftest.py +0 -0
  125. {dfm_python-0.6.13 → dfm_python-0.7.0}/src/test/dataset/test_ddfm_dataset.py +0 -0
  126. {dfm_python-0.6.13 → dfm_python-0.7.0}/src/test/dataset/test_dfm_dataset.py +0 -0
  127. {dfm_python-0.6.13 → dfm_python-0.7.0}/src/test/functional/__init__.py +0 -0
  128. {dfm_python-0.6.13 → dfm_python-0.7.0}/src/test/functional/test_em.py +0 -0
  129. {dfm_python-0.6.13 → dfm_python-0.7.0}/src/test/functional/test_em_correctness.py +0 -0
  130. {dfm_python-0.6.13 → dfm_python-0.7.0}/src/test/functional/test_em_properties.py +0 -0
  131. {dfm_python-0.6.13 → dfm_python-0.7.0}/src/test/logger/__init__.py +0 -0
  132. {dfm_python-0.6.13 → dfm_python-0.7.0}/src/test/logger/test_inference_logger.py +0 -0
  133. {dfm_python-0.6.13 → dfm_python-0.7.0}/src/test/logger/test_logger.py +0 -0
  134. {dfm_python-0.6.13 → dfm_python-0.7.0}/src/test/logger/test_train_logger.py +0 -0
  135. {dfm_python-0.6.13 → dfm_python-0.7.0}/src/test/models/__init__.py +0 -0
  136. {dfm_python-0.6.13 → dfm_python-0.7.0}/src/test/models/test_ddfm.py +0 -0
  137. {dfm_python-0.6.13 → dfm_python-0.7.0}/src/test/models/test_ddfm_sampling.py +0 -0
  138. {dfm_python-0.6.13 → dfm_python-0.7.0}/src/test/models/test_dfm.py +0 -0
  139. {dfm_python-0.6.13 → dfm_python-0.7.0}/src/test/numeric/__init__.py +0 -0
  140. {dfm_python-0.6.13 → dfm_python-0.7.0}/src/test/numeric/test_builder.py +0 -0
  141. {dfm_python-0.6.13 → dfm_python-0.7.0}/src/test/numeric/test_cov_rowvar_regression.py +0 -0
  142. {dfm_python-0.6.13 → dfm_python-0.7.0}/src/test/numeric/test_estimator.py +0 -0
  143. {dfm_python-0.6.13 → dfm_python-0.7.0}/src/test/numeric/test_initialization.py +0 -0
  144. {dfm_python-0.6.13 → dfm_python-0.7.0}/src/test/numeric/test_stability.py +0 -0
  145. {dfm_python-0.6.13 → dfm_python-0.7.0}/src/test/numeric/test_validator.py +0 -0
  146. {dfm_python-0.6.13 → dfm_python-0.7.0}/src/test/ssm/__init__.py +0 -0
  147. {dfm_python-0.6.13 → dfm_python-0.7.0}/src/test/ssm/test_kalman.py +0 -0
  148. {dfm_python-0.6.13 → dfm_python-0.7.0}/src/test/ssm/test_kalman_correctness.py +0 -0
  149. {dfm_python-0.6.13 → dfm_python-0.7.0}/src/test/utils/__init__.py +0 -0
  150. {dfm_python-0.6.13 → dfm_python-0.7.0}/src/test/utils/test_errors.py +0 -0
  151. {dfm_python-0.6.13 → dfm_python-0.7.0}/src/test/utils/test_helper.py +0 -0
  152. {dfm_python-0.6.13 → dfm_python-0.7.0}/src/test/utils/test_metric.py +0 -0
  153. {dfm_python-0.6.13 → dfm_python-0.7.0}/src/test/utils/test_misc.py +0 -0
  154. {dfm_python-0.6.13 → dfm_python-0.7.0}/tutorial/tutorial_exchange_ddfm.py +0 -0
  155. {dfm_python-0.6.13 → dfm_python-0.7.0}/tutorial/tutorial_exchange_dfm.py +0 -0
  156. {dfm_python-0.6.13 → dfm_python-0.7.0}/tutorial/tutorial_finance_dfm.py +0 -0
  157. {dfm_python-0.6.13 → dfm_python-0.7.0}/tutorial/tutorial_macro_ddfm.py +0 -0
  158. {dfm_python-0.6.13 → dfm_python-0.7.0}/tutorial/tutorial_macro_dfm.py +0 -0
@@ -215,4 +215,5 @@ Nowcasting/
215
215
  agent/
216
216
 
217
217
  *.db
218
- *.pkl
218
+ *.pkl
219
+ *.pt
@@ -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.
@@ -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 (matching original TensorFlow DDFM)
13
- learning_rate: 0.005 # Matching original learning_rate=0.005
14
- n_mc_samples: 10 # Number of MC samples per MCMC iteration (matching original epochs=10)
15
- window_size: 100 # Time-step batch size for training (matching original batch_size=100)
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 (matching original TensorFlow DDFM)
18
- max_epoch: 200 # Maximum MCMC iterations (matching original max_iter=200)
19
- tolerance: 0.0005 # Convergence tolerance (matching original tolerance=0.0005)
20
- disp: 10 # Display frequency for training progress (matching original disp=10)
21
- seed: 3 # Random seed (matching original seed=3)
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
- encoder_layers: [64, 32, 2] # Hidden layers: [64, 32] -> latent: 2 factors
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: 1 # Number of MC samples per MCMC iteration (reduced for faster execution)
13
- window_size: 100 # Time-step batch size for training
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: 200 # Maximum MCMC iterations
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
- # Frequency mapping (optional)
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.6.13"
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
- "LICENSE",
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/yourusername/dfm-python"
96
- Documentation = "https://github.com/yourusername/dfm-python#readme"
97
- Repository = "https://github.com/yourusername/dfm-python"
98
- Issues = "https://github.com/yourusername/dfm-python/issues"
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"