dfm-python 0.1.5__tar.gz → 0.1.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.
Files changed (54) hide show
  1. {dfm_python-0.1.5 → dfm_python-0.1.8}/CHANGELOG.md +35 -0
  2. dfm_python-0.1.8/PKG-INFO +343 -0
  3. dfm_python-0.1.8/README.md +300 -0
  4. dfm_python-0.1.8/config/blocks/default.yaml +55 -0
  5. dfm_python-0.1.8/config/default.yaml +69 -0
  6. dfm_python-0.1.8/config/series/default.yaml +699 -0
  7. dfm_python-0.1.8/data/sample_data.csv +490 -0
  8. dfm_python-0.1.8/data/sample_spec.csv +85 -0
  9. {dfm_python-0.1.5 → dfm_python-0.1.8}/pyproject.toml +2 -1
  10. dfm_python-0.1.8/src/__init__.py +4 -0
  11. dfm_python-0.1.8/src/dfm_python/__init__.py +146 -0
  12. dfm_python-0.1.8/src/dfm_python/config.py +746 -0
  13. dfm_python-0.1.8/src/dfm_python/data_loader.py +836 -0
  14. dfm_python-0.1.8/src/dfm_python/dfm.py +3815 -0
  15. dfm_python-0.1.8/src/dfm_python/dfm_api.py +328 -0
  16. {dfm_python-0.1.5 → dfm_python-0.1.8}/src/dfm_python/kalman.py +0 -12
  17. {dfm_python-0.1.5 → dfm_python-0.1.8}/src/dfm_python/news.py +28 -38
  18. {dfm_python-0.1.5 → dfm_python-0.1.8}/src/dfm_python/utils/__init__.py +0 -2
  19. {dfm_python-0.1.5 → dfm_python-0.1.8}/src/dfm_python/utils/aggregation.py +4 -11
  20. {dfm_python-0.1.5 → dfm_python-0.1.8}/src/dfm_python/utils/data_utils.py +20 -8
  21. dfm_python-0.1.8/src/test/test_dfm.py +373 -0
  22. dfm_python-0.1.8/src/test/test_kalman.py +184 -0
  23. dfm_python-0.1.8/src/test/test_news.py +100 -0
  24. dfm_python-0.1.8/trash/simple_api_example.py +41 -0
  25. dfm_python-0.1.8/trash/test_dfm_edge_cases.py +552 -0
  26. dfm_python-0.1.8/trash/test_dfm_stress.py +377 -0
  27. dfm_python-0.1.8/trash/test_synthetic.py +130 -0
  28. dfm_python-0.1.8/tutorial/basic_tutorial.ipynb +577 -0
  29. dfm_python-0.1.8/tutorial/basic_tutorial.py +342 -0
  30. {dfm_python-0.1.5 → dfm_python-0.1.8}/uv.lock +323 -1
  31. dfm_python-0.1.5/PKG-INFO +0 -572
  32. dfm_python-0.1.5/README.md +0 -530
  33. dfm_python-0.1.5/config/example_config.yaml +0 -149
  34. dfm_python-0.1.5/config/example_config_macro_data.yaml +0 -214
  35. dfm_python-0.1.5/data/example_macro_data.csv +0 -18
  36. dfm_python-0.1.5/data/sample_data.csv +0 -193
  37. dfm_python-0.1.5/scripts/inference.py +0 -226
  38. dfm_python-0.1.5/scripts/train.py +0 -282
  39. dfm_python-0.1.5/spec/example_spec.csv +0 -13
  40. dfm_python-0.1.5/src/__init__.py +0 -17
  41. dfm_python-0.1.5/src/dfm_python/__init__.py +0 -60
  42. dfm_python-0.1.5/src/dfm_python/config.py +0 -556
  43. dfm_python-0.1.5/src/dfm_python/data_loader.py +0 -540
  44. dfm_python-0.1.5/src/dfm_python/dfm.py +0 -3120
  45. dfm_python-0.1.5/src/test/test_dfm.py +0 -460
  46. dfm_python-0.1.5/src/test/test_kalman.py +0 -325
  47. dfm_python-0.1.5/src/test/test_news.py +0 -229
  48. dfm_python-0.1.5/src/test/test_synthetic.py +0 -135
  49. dfm_python-0.1.5/test_comprehensive.py +0 -510
  50. {dfm_python-0.1.5 → dfm_python-0.1.8}/.gitignore +0 -0
  51. {dfm_python-0.1.5 → dfm_python-0.1.8}/.python-version +0 -0
  52. {dfm_python-0.1.5 → dfm_python-0.1.8}/LICENSE +0 -0
  53. {dfm_python-0.1.5 → dfm_python-0.1.8}/MANIFEST.in +0 -0
  54. {dfm_python-0.1.5 → dfm_python-0.1.8}/src/test/__init__.py +0 -0
@@ -1,5 +1,40 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.1.7] - 2025-01-XX
4
+
5
+ ### Changed
6
+ - **BREAKING**: Removed CSV config loading - use YAML files or create `DFMConfig` objects directly
7
+ - Made package more generic by removing application-specific dependencies
8
+ - Improved code documentation and comments throughout codebase
9
+ - Refactored variable naming for clarity and consistency
10
+ - Updated README to be more concise and focused
11
+
12
+ ### Added
13
+ - Direct `DFMConfig` object creation support in `load_config()`
14
+ - Application-specific adapter guidance for custom formats
15
+ - Database-backed data loading adapter interface documentation
16
+ - Enhanced function docstrings with detailed parameter descriptions
17
+
18
+ ### Removed
19
+ - CSV configuration file support (deprecated, use YAML or direct object creation)
20
+ - `load_config_from_csv()` function (deprecated, kept for backward compatibility with warning)
21
+ - Spec file dependencies
22
+
23
+ ### Fixed
24
+ - Improved error messages for frequency constraint violations
25
+ - Enhanced type hints and documentation
26
+
27
+ ## [0.1.6] - Previous release
28
+
29
+ ### Changed
30
+ - Frequency generalization improvements
31
+ - Code cleanup and refactoring
32
+
33
+ ## [0.1.5] - Previous release
34
+
35
+ ### Changed
36
+ - Additional improvements and bug fixes
37
+
3
38
  ## [0.1.4] - 2024-11-07
4
39
 
5
40
  ### Fixed
@@ -0,0 +1,343 @@
1
+ Metadata-Version: 2.4
2
+ Name: dfm-python
3
+ Version: 0.1.8
4
+ Summary: Dynamic Factor Model (DFM) estimation and nowcasting in Python
5
+ Project-URL: Homepage, https://github.com/yourusername/dfm-python
6
+ Project-URL: Documentation, https://github.com/yourusername/dfm-python#readme
7
+ Project-URL: Repository, https://github.com/yourusername/dfm-python
8
+ Project-URL: Issues, https://github.com/yourusername/dfm-python/issues
9
+ Author: DFM Python Contributors
10
+ License: MIT
11
+ License-File: LICENSE
12
+ Keywords: dfm,dynamic-factor-model,econometrics,forecasting,nowcasting,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.12
18
+ Classifier: Topic :: Scientific/Engineering
19
+ Requires-Python: >=3.12
20
+ Requires-Dist: matplotlib>=3.10.7
21
+ Requires-Dist: numpy>=1.24.0
22
+ Requires-Dist: pandas>=2.0.0
23
+ Requires-Dist: scipy>=1.10.0
24
+ Provides-Extra: all
25
+ Requires-Dist: httpx>=0.24.0; extra == 'all'
26
+ Requires-Dist: hydra-core>=1.3.0; extra == 'all'
27
+ Requires-Dist: omegaconf>=2.3.0; extra == 'all'
28
+ Requires-Dist: psycopg2-binary>=2.9.0; extra == 'all'
29
+ Requires-Dist: pydantic-settings>=2.11.0; extra == 'all'
30
+ Requires-Dist: pytest>=7.0.0; extra == 'all'
31
+ Requires-Dist: supabase>=2.0.0; extra == 'all'
32
+ Provides-Extra: database
33
+ Requires-Dist: httpx>=0.24.0; extra == 'database'
34
+ Requires-Dist: psycopg2-binary>=2.9.0; extra == 'database'
35
+ Requires-Dist: pydantic-settings>=2.11.0; extra == 'database'
36
+ Requires-Dist: supabase>=2.0.0; extra == 'database'
37
+ Provides-Extra: dev
38
+ Requires-Dist: pytest>=7.0.0; extra == 'dev'
39
+ Provides-Extra: hydra
40
+ Requires-Dist: hydra-core>=1.3.0; extra == 'hydra'
41
+ Requires-Dist: omegaconf>=2.3.0; extra == 'hydra'
42
+ Description-Content-Type: text/markdown
43
+
44
+ # dfm-python: Dynamic Factor Models for Python
45
+
46
+ [![PyPI version](https://img.shields.io/pypi/v/dfm-python.svg)](https://pypi.org/project/dfm-python/)
47
+ [![Python 3.12+](https://img.shields.io/badge/python-3.12+-blue.svg)](https://www.python.org/downloads/)
48
+
49
+ A Python implementation of **Dynamic Factor Models (DFM)** for nowcasting and forecasting high-dimensional time series. Implements clock-based synchronization and tent kernel aggregation for mixed-frequency data.
50
+
51
+ ## Features
52
+
53
+ - **Mixed-frequency data**: Monthly, quarterly, semi-annual, annual (no daily/weekly)
54
+ - **Clock-based framework**: All factors evolve at a common clock frequency
55
+ - **Block structure**: Flexible factor organization (global, sector-specific)
56
+ - **Robust missing data**: Spline interpolation and Kalman filter handling
57
+ - **News decomposition**: Attribute forecast changes to data releases
58
+ - **Generic design**: YAML configs or direct object creation, extensible via adapters
59
+
60
+ ## Installation
61
+
62
+ ```bash
63
+ pip install dfm-python
64
+ ```
65
+
66
+ **Requirements**: Python >= 3.12, numpy >= 1.24.0, pandas >= 2.0.0, scipy >= 1.10.0
67
+
68
+ ## Quick Start
69
+
70
+ ### Option 1: YAML Configuration
71
+
72
+ ```python
73
+ from dfm_python import load_config, load_data, dfm
74
+
75
+ # Load configuration from YAML
76
+ config = load_config('config.yaml')
77
+ X, Time, _ = load_data('data.csv', config)
78
+
79
+ # Estimate model
80
+ result = dfm(X, config)
81
+
82
+ # Access results
83
+ factors = result.Z # (T × m) Smoothed factors
84
+ loadings = result.C # (N × m) Factor loadings
85
+ smoothed = result.X_sm # (T × N) Smoothed data
86
+ ```
87
+
88
+ ### Option 2: Direct Configuration
89
+
90
+ ```python
91
+ from dfm_python import DFMConfig, SeriesConfig, load_data, dfm
92
+
93
+ # Create configuration programmatically
94
+ config = DFMConfig(
95
+ series=[
96
+ SeriesConfig(
97
+ series_id='gdp_real',
98
+ series_name='Real GDP',
99
+ frequency='q',
100
+ transformation='pca',
101
+ category='National Accounts',
102
+ units='Index',
103
+ blocks=[1] # Loads on first block (global)
104
+ ),
105
+ SeriesConfig(
106
+ series_id='consumption',
107
+ series_name='Consumption',
108
+ frequency='m',
109
+ transformation='pch',
110
+ category='Consumption',
111
+ units='Index',
112
+ blocks=[1]
113
+ )
114
+ ],
115
+ block_names=['Global'],
116
+ clock='m',
117
+ threshold=1e-5,
118
+ max_iter=5000
119
+ )
120
+
121
+ # Load data and estimate
122
+ X, Time, _ = load_data('data.csv', config)
123
+ result = dfm(X, config)
124
+ ```
125
+
126
+ ## Configuration
127
+
128
+ ### YAML Format
129
+
130
+ ```yaml
131
+ dfm:
132
+ clock: "m" # Clock frequency (base for all factors)
133
+ threshold: 1e-5 # EM convergence threshold
134
+ max_iter: 5000 # Maximum EM iterations
135
+ ar_lag: 1 # AR lag for factors
136
+
137
+ series:
138
+ gdp_real:
139
+ series_name: "Real GDP"
140
+ frequency: "q"
141
+ transformation: "pca"
142
+ category: "National Accounts"
143
+ units: "Index"
144
+ blocks: [Global]
145
+
146
+ consumption:
147
+ series_name: "Consumption"
148
+ frequency: "m"
149
+ transformation: "pch"
150
+ category: "Consumption"
151
+ units: "Index"
152
+ blocks: [Global]
153
+ ```
154
+
155
+ ### Key Parameters
156
+
157
+ - **clock**: Base frequency for latent factors (typically "m" for monthly)
158
+ - **threshold**: EM convergence criterion (default: 1e-5)
159
+ - **max_iter**: Maximum EM iterations (default: 5000)
160
+ - **ar_lag**: Autoregressive lag for factors (default: 1)
161
+
162
+ ### Numerical Stability
163
+
164
+ All numerical stability techniques are configurable and transparent:
165
+
166
+ ```yaml
167
+ dfm:
168
+ clip_ar_coefficients: true # Ensure stationarity
169
+ clip_data_values: true # Clip extreme outliers
170
+ use_regularization: true # Prevent ill-conditioned matrices
171
+ use_damped_updates: true # Prevent likelihood decreases
172
+ ```
173
+
174
+ Warnings are logged when techniques are applied. All parameters can be disabled for research purposes.
175
+
176
+ ## Data Format
177
+
178
+ ### File-Based (CSV)
179
+
180
+ Data file with series as columns and dates as rows:
181
+
182
+ ```csv
183
+ Date,gdp_real,consumption,investment
184
+ 2000-01-01,,98.5,95.0
185
+ 2000-02-01,,98.7,95.2
186
+ 2000-03-01,100.5,99.0,95.5
187
+ ```
188
+
189
+ **Requirements**:
190
+ - First column: `Date` (YYYY-MM-DD format)
191
+ - Column names: Must match `series_id` in configuration
192
+ - Missing values: Empty cells or NaN
193
+ - Mixed frequencies: Quarterly series only at quarter-end months
194
+
195
+ **Frequency Support**:
196
+ - **Supported**: Monthly (m), Quarterly (q), Semi-annual (sa), Annual (a)
197
+ - **Not supported**: Daily (d), Weekly (w) - raises ValueError
198
+ - All series must have frequency ≤ clock frequency
199
+
200
+ ### Database-Backed
201
+
202
+ For production applications, implement adapters that return:
203
+ - `X`: Transformed data matrix (T × N)
204
+ - `Time`: Time index (pandas DatetimeIndex)
205
+ - `Z`: Original untransformed data (T × N)
206
+
207
+ ## Usage Examples
208
+
209
+ ### Basic Estimation
210
+
211
+ ```python
212
+ from dfm_python import load_config, load_data, dfm
213
+
214
+ config = load_config('config.yaml')
215
+ X, Time, _ = load_data('data.csv', config)
216
+ result = dfm(X, config)
217
+
218
+ # Extract common factor
219
+ common_factor = result.Z[:, 0]
220
+
221
+ # Model fit
222
+ rmse = result.rmse
223
+ ```
224
+
225
+ ### News Decomposition
226
+
227
+ ```python
228
+ from dfm_python import news_dfm
229
+
230
+ # Estimate on old and new data
231
+ result_old = dfm(X_old, config)
232
+ result_new = dfm(X_new, config)
233
+
234
+ # Decompose news
235
+ y_old, y_new, singlenews, actual, forecast, weight, t_miss, v_miss, innov = news_dfm(
236
+ X_old, result_old, t_fcst=100, v_news=0
237
+ )
238
+
239
+ # Forecast update
240
+ forecast_update = y_new - y_old
241
+ ```
242
+
243
+ ## API Reference
244
+
245
+ ### `load_config(configfile) -> DFMConfig`
246
+
247
+ Load configuration from YAML file or return existing DFMConfig object.
248
+
249
+ **Parameters**:
250
+ - `configfile`: Path to YAML file (.yaml, .yml) or `DFMConfig` object
251
+
252
+ **Returns**: `DFMConfig` object
253
+
254
+ ### `load_data(datafile, config, sample_start=None) -> Tuple[np.ndarray, pd.DatetimeIndex, np.ndarray]`
255
+
256
+ Load and transform time series data.
257
+
258
+ **Parameters**:
259
+ - `datafile`: Path to data file (CSV supported)
260
+ - `config`: `DFMConfig` object
261
+ - `sample_start`: Optional start date (YYYY-MM-DD) to filter data
262
+
263
+ **Returns**: `(X, Time, Z)` where:
264
+ - `X`: Transformed data matrix (T × N)
265
+ - `Time`: Time index (DatetimeIndex)
266
+ - `Z`: Original untransformed data (T × N)
267
+
268
+ ### `dfm(X, config, threshold=None, max_iter=None) -> DFMResult`
269
+
270
+ Estimate Dynamic Factor Model using EM algorithm.
271
+
272
+ **Parameters**:
273
+ - `X`: Data matrix (T × N) with possible missing values
274
+ - `config`: `DFMConfig` object
275
+ - `threshold`: Convergence threshold (default: from config)
276
+ - `max_iter`: Maximum iterations (default: from config)
277
+
278
+ **Returns**: `DFMResult` object
279
+
280
+ ### `DFMResult` Object
281
+
282
+ Contains all estimation outputs:
283
+
284
+ - **Factors**: `Z` (T × m), `C` (N × m)
285
+ - **Parameters**: `A` (m × m), `Q` (m × m), `R` (N × N)
286
+ - **Smoothed Data**: `X_sm` (T × N), `x_sm` (T × N)
287
+ - **Initial Conditions**: `Z_0` (m,), `V_0` (m × m)
288
+ - **Standardization**: `Mx` (N,), `Wx` (N,)
289
+ - **Convergence**: `converged`, `num_iter`, `loglik`
290
+ - **Model Fit**: `rmse`, `rmse_per_series`
291
+
292
+ ## Architecture
293
+
294
+ **Core Modules**:
295
+ - `config.py`: Configuration management
296
+ - `data_loader.py`: Data loading and transformation
297
+ - `dfm.py`: Core estimation (EM algorithm)
298
+ - `kalman.py`: Kalman filter and smoother
299
+ - `news.py`: News decomposition
300
+
301
+ **Design Principles**:
302
+ - Generic core (no application-specific code)
303
+ - Flexible configuration (YAML or direct object creation)
304
+ - Extensible via application-specific adapters
305
+ - Robust error handling and numerical stability
306
+
307
+ ## Troubleshooting
308
+
309
+ **Convergence Issues**:
310
+ - Increase `max_iter` (try 10000)
311
+ - Relax `threshold` (try 1e-3)
312
+ - Check data quality and missing data patterns
313
+
314
+ **Dimension Mismatch**:
315
+ - Ensure `series_id` in config matches data column names
316
+ - Verify block structure consistency
317
+ - Check frequency codes are valid
318
+
319
+ **Numerical Instability**:
320
+ - Monitor warnings for stability techniques
321
+ - Adjust thresholds based on data characteristics
322
+ - Investigate data quality if techniques frequently needed
323
+
324
+ ## License
325
+
326
+ MIT License
327
+
328
+ ## Citation
329
+
330
+ ```bibtex
331
+ @software{dfm-python,
332
+ title = {dfm-python: Dynamic Factor Models for Nowcasting and Forecasting},
333
+ author = {DFM Python Contributors},
334
+ year = {2025},
335
+ url = {https://pypi.org/project/dfm-python/}
336
+ }
337
+ ```
338
+
339
+ ---
340
+
341
+ **Package Status**: Stable
342
+ **PyPI**: https://pypi.org/project/dfm-python/
343
+ **Python**: 3.12+
@@ -0,0 +1,300 @@
1
+ # dfm-python: Dynamic Factor Models for Python
2
+
3
+ [![PyPI version](https://img.shields.io/pypi/v/dfm-python.svg)](https://pypi.org/project/dfm-python/)
4
+ [![Python 3.12+](https://img.shields.io/badge/python-3.12+-blue.svg)](https://www.python.org/downloads/)
5
+
6
+ A Python implementation of **Dynamic Factor Models (DFM)** for nowcasting and forecasting high-dimensional time series. Implements clock-based synchronization and tent kernel aggregation for mixed-frequency data.
7
+
8
+ ## Features
9
+
10
+ - **Mixed-frequency data**: Monthly, quarterly, semi-annual, annual (no daily/weekly)
11
+ - **Clock-based framework**: All factors evolve at a common clock frequency
12
+ - **Block structure**: Flexible factor organization (global, sector-specific)
13
+ - **Robust missing data**: Spline interpolation and Kalman filter handling
14
+ - **News decomposition**: Attribute forecast changes to data releases
15
+ - **Generic design**: YAML configs or direct object creation, extensible via adapters
16
+
17
+ ## Installation
18
+
19
+ ```bash
20
+ pip install dfm-python
21
+ ```
22
+
23
+ **Requirements**: Python >= 3.12, numpy >= 1.24.0, pandas >= 2.0.0, scipy >= 1.10.0
24
+
25
+ ## Quick Start
26
+
27
+ ### Option 1: YAML Configuration
28
+
29
+ ```python
30
+ from dfm_python import load_config, load_data, dfm
31
+
32
+ # Load configuration from YAML
33
+ config = load_config('config.yaml')
34
+ X, Time, _ = load_data('data.csv', config)
35
+
36
+ # Estimate model
37
+ result = dfm(X, config)
38
+
39
+ # Access results
40
+ factors = result.Z # (T × m) Smoothed factors
41
+ loadings = result.C # (N × m) Factor loadings
42
+ smoothed = result.X_sm # (T × N) Smoothed data
43
+ ```
44
+
45
+ ### Option 2: Direct Configuration
46
+
47
+ ```python
48
+ from dfm_python import DFMConfig, SeriesConfig, load_data, dfm
49
+
50
+ # Create configuration programmatically
51
+ config = DFMConfig(
52
+ series=[
53
+ SeriesConfig(
54
+ series_id='gdp_real',
55
+ series_name='Real GDP',
56
+ frequency='q',
57
+ transformation='pca',
58
+ category='National Accounts',
59
+ units='Index',
60
+ blocks=[1] # Loads on first block (global)
61
+ ),
62
+ SeriesConfig(
63
+ series_id='consumption',
64
+ series_name='Consumption',
65
+ frequency='m',
66
+ transformation='pch',
67
+ category='Consumption',
68
+ units='Index',
69
+ blocks=[1]
70
+ )
71
+ ],
72
+ block_names=['Global'],
73
+ clock='m',
74
+ threshold=1e-5,
75
+ max_iter=5000
76
+ )
77
+
78
+ # Load data and estimate
79
+ X, Time, _ = load_data('data.csv', config)
80
+ result = dfm(X, config)
81
+ ```
82
+
83
+ ## Configuration
84
+
85
+ ### YAML Format
86
+
87
+ ```yaml
88
+ dfm:
89
+ clock: "m" # Clock frequency (base for all factors)
90
+ threshold: 1e-5 # EM convergence threshold
91
+ max_iter: 5000 # Maximum EM iterations
92
+ ar_lag: 1 # AR lag for factors
93
+
94
+ series:
95
+ gdp_real:
96
+ series_name: "Real GDP"
97
+ frequency: "q"
98
+ transformation: "pca"
99
+ category: "National Accounts"
100
+ units: "Index"
101
+ blocks: [Global]
102
+
103
+ consumption:
104
+ series_name: "Consumption"
105
+ frequency: "m"
106
+ transformation: "pch"
107
+ category: "Consumption"
108
+ units: "Index"
109
+ blocks: [Global]
110
+ ```
111
+
112
+ ### Key Parameters
113
+
114
+ - **clock**: Base frequency for latent factors (typically "m" for monthly)
115
+ - **threshold**: EM convergence criterion (default: 1e-5)
116
+ - **max_iter**: Maximum EM iterations (default: 5000)
117
+ - **ar_lag**: Autoregressive lag for factors (default: 1)
118
+
119
+ ### Numerical Stability
120
+
121
+ All numerical stability techniques are configurable and transparent:
122
+
123
+ ```yaml
124
+ dfm:
125
+ clip_ar_coefficients: true # Ensure stationarity
126
+ clip_data_values: true # Clip extreme outliers
127
+ use_regularization: true # Prevent ill-conditioned matrices
128
+ use_damped_updates: true # Prevent likelihood decreases
129
+ ```
130
+
131
+ Warnings are logged when techniques are applied. All parameters can be disabled for research purposes.
132
+
133
+ ## Data Format
134
+
135
+ ### File-Based (CSV)
136
+
137
+ Data file with series as columns and dates as rows:
138
+
139
+ ```csv
140
+ Date,gdp_real,consumption,investment
141
+ 2000-01-01,,98.5,95.0
142
+ 2000-02-01,,98.7,95.2
143
+ 2000-03-01,100.5,99.0,95.5
144
+ ```
145
+
146
+ **Requirements**:
147
+ - First column: `Date` (YYYY-MM-DD format)
148
+ - Column names: Must match `series_id` in configuration
149
+ - Missing values: Empty cells or NaN
150
+ - Mixed frequencies: Quarterly series only at quarter-end months
151
+
152
+ **Frequency Support**:
153
+ - **Supported**: Monthly (m), Quarterly (q), Semi-annual (sa), Annual (a)
154
+ - **Not supported**: Daily (d), Weekly (w) - raises ValueError
155
+ - All series must have frequency ≤ clock frequency
156
+
157
+ ### Database-Backed
158
+
159
+ For production applications, implement adapters that return:
160
+ - `X`: Transformed data matrix (T × N)
161
+ - `Time`: Time index (pandas DatetimeIndex)
162
+ - `Z`: Original untransformed data (T × N)
163
+
164
+ ## Usage Examples
165
+
166
+ ### Basic Estimation
167
+
168
+ ```python
169
+ from dfm_python import load_config, load_data, dfm
170
+
171
+ config = load_config('config.yaml')
172
+ X, Time, _ = load_data('data.csv', config)
173
+ result = dfm(X, config)
174
+
175
+ # Extract common factor
176
+ common_factor = result.Z[:, 0]
177
+
178
+ # Model fit
179
+ rmse = result.rmse
180
+ ```
181
+
182
+ ### News Decomposition
183
+
184
+ ```python
185
+ from dfm_python import news_dfm
186
+
187
+ # Estimate on old and new data
188
+ result_old = dfm(X_old, config)
189
+ result_new = dfm(X_new, config)
190
+
191
+ # Decompose news
192
+ y_old, y_new, singlenews, actual, forecast, weight, t_miss, v_miss, innov = news_dfm(
193
+ X_old, result_old, t_fcst=100, v_news=0
194
+ )
195
+
196
+ # Forecast update
197
+ forecast_update = y_new - y_old
198
+ ```
199
+
200
+ ## API Reference
201
+
202
+ ### `load_config(configfile) -> DFMConfig`
203
+
204
+ Load configuration from YAML file or return existing DFMConfig object.
205
+
206
+ **Parameters**:
207
+ - `configfile`: Path to YAML file (.yaml, .yml) or `DFMConfig` object
208
+
209
+ **Returns**: `DFMConfig` object
210
+
211
+ ### `load_data(datafile, config, sample_start=None) -> Tuple[np.ndarray, pd.DatetimeIndex, np.ndarray]`
212
+
213
+ Load and transform time series data.
214
+
215
+ **Parameters**:
216
+ - `datafile`: Path to data file (CSV supported)
217
+ - `config`: `DFMConfig` object
218
+ - `sample_start`: Optional start date (YYYY-MM-DD) to filter data
219
+
220
+ **Returns**: `(X, Time, Z)` where:
221
+ - `X`: Transformed data matrix (T × N)
222
+ - `Time`: Time index (DatetimeIndex)
223
+ - `Z`: Original untransformed data (T × N)
224
+
225
+ ### `dfm(X, config, threshold=None, max_iter=None) -> DFMResult`
226
+
227
+ Estimate Dynamic Factor Model using EM algorithm.
228
+
229
+ **Parameters**:
230
+ - `X`: Data matrix (T × N) with possible missing values
231
+ - `config`: `DFMConfig` object
232
+ - `threshold`: Convergence threshold (default: from config)
233
+ - `max_iter`: Maximum iterations (default: from config)
234
+
235
+ **Returns**: `DFMResult` object
236
+
237
+ ### `DFMResult` Object
238
+
239
+ Contains all estimation outputs:
240
+
241
+ - **Factors**: `Z` (T × m), `C` (N × m)
242
+ - **Parameters**: `A` (m × m), `Q` (m × m), `R` (N × N)
243
+ - **Smoothed Data**: `X_sm` (T × N), `x_sm` (T × N)
244
+ - **Initial Conditions**: `Z_0` (m,), `V_0` (m × m)
245
+ - **Standardization**: `Mx` (N,), `Wx` (N,)
246
+ - **Convergence**: `converged`, `num_iter`, `loglik`
247
+ - **Model Fit**: `rmse`, `rmse_per_series`
248
+
249
+ ## Architecture
250
+
251
+ **Core Modules**:
252
+ - `config.py`: Configuration management
253
+ - `data_loader.py`: Data loading and transformation
254
+ - `dfm.py`: Core estimation (EM algorithm)
255
+ - `kalman.py`: Kalman filter and smoother
256
+ - `news.py`: News decomposition
257
+
258
+ **Design Principles**:
259
+ - Generic core (no application-specific code)
260
+ - Flexible configuration (YAML or direct object creation)
261
+ - Extensible via application-specific adapters
262
+ - Robust error handling and numerical stability
263
+
264
+ ## Troubleshooting
265
+
266
+ **Convergence Issues**:
267
+ - Increase `max_iter` (try 10000)
268
+ - Relax `threshold` (try 1e-3)
269
+ - Check data quality and missing data patterns
270
+
271
+ **Dimension Mismatch**:
272
+ - Ensure `series_id` in config matches data column names
273
+ - Verify block structure consistency
274
+ - Check frequency codes are valid
275
+
276
+ **Numerical Instability**:
277
+ - Monitor warnings for stability techniques
278
+ - Adjust thresholds based on data characteristics
279
+ - Investigate data quality if techniques frequently needed
280
+
281
+ ## License
282
+
283
+ MIT License
284
+
285
+ ## Citation
286
+
287
+ ```bibtex
288
+ @software{dfm-python,
289
+ title = {dfm-python: Dynamic Factor Models for Nowcasting and Forecasting},
290
+ author = {DFM Python Contributors},
291
+ year = {2025},
292
+ url = {https://pypi.org/project/dfm-python/}
293
+ }
294
+ ```
295
+
296
+ ---
297
+
298
+ **Package Status**: Stable
299
+ **PyPI**: https://pypi.org/project/dfm-python/
300
+ **Python**: 3.12+