dfm-python 0.1.0__tar.gz → 0.1.1__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.1.1/.gitignore +207 -0
- dfm_python-0.1.1/LICENSE +21 -0
- {dfm_python-0.1.0 → dfm_python-0.1.1}/PKG-INFO +141 -17
- {dfm_python-0.1.0 → dfm_python-0.1.1}/README.md +139 -16
- dfm_python-0.1.1/config/example_config.yaml +119 -0
- dfm_python-0.1.1/data/sample_data.csv +133 -0
- {dfm_python-0.1.0 → dfm_python-0.1.1}/pyproject.toml +1 -1
- dfm_python-0.1.1/spec/example_spec.csv +13 -0
- dfm_python-0.1.1/src/__init__.py +17 -0
- {dfm_python-0.1.0 → dfm_python-0.1.1}/src/dfm_python/data_loader.py +31 -131
- {dfm_python-0.1.0 → dfm_python-0.1.1}/src/dfm_python/dfm.py +84 -35
- {dfm_python-0.1.0 → dfm_python-0.1.1}/src/dfm_python/news.py +230 -77
- {dfm_python-0.1.0 → dfm_python-0.1.1}/src/test/test_dfm.py +6 -4
- {dfm_python-0.1.0 → dfm_python-0.1.1}/src/test/test_kalman.py +5 -1
- {dfm_python-0.1.0 → dfm_python-0.1.1}/src/test/test_news.py +5 -1
- dfm_python-0.1.1/src/test/test_synthetic.py +135 -0
- {dfm_python-0.1.0 → dfm_python-0.1.1}/src/utils/data_utils.py +10 -3
- dfm_python-0.1.0/.cursor/worktrees.json +0 -7
- dfm_python-0.1.0/.github/workflows/database.yaml +0 -67
- dfm_python-0.1.0/.github/workflows/nowcast.yaml +0 -69
- dfm_python-0.1.0/.github/workflows/train.yaml +0 -78
- dfm_python-0.1.0/.gitignore +0 -33
- dfm_python-0.1.0/adapters/__init__.py +0 -30
- dfm_python-0.1.0/adapters/adapter_database.py +0 -1280
- dfm_python-0.1.0/assets/initialization.py +0 -319
- dfm_python-0.1.0/assets/test_initialization.py +0 -404
- dfm_python-0.1.0/config/default.yaml +0 -33
- dfm_python-0.1.0/config/series/default.yaml +0 -133
- dfm_python-0.1.0/config/series/test_series.yaml +0 -134
- dfm_python-0.1.0/config/test.yaml +0 -33
- dfm_python-0.1.0/database/__init__.py +0 -113
- dfm_python-0.1.0/database/client.py +0 -80
- dfm_python-0.1.0/database/db_utils.py +0 -633
- dfm_python-0.1.0/database/helpers.py +0 -599
- dfm_python-0.1.0/database/models.py +0 -133
- dfm_python-0.1.0/database/operations.py +0 -1728
- dfm_python-0.1.0/database/series.py +0 -172
- dfm_python-0.1.0/database/settings.py +0 -324
- dfm_python-0.1.0/database/spec_manager.py +0 -323
- dfm_python-0.1.0/migrations/001_initial_schema.sql +0 -509
- dfm_python-0.1.0/migrations/002_add_blocks.sql +0 -179
- dfm_python-0.1.0/scripts/__init__.py +0 -2
- dfm_python-0.1.0/scripts/ingest_api.py +0 -659
- dfm_python-0.1.0/scripts/nowcast_dfm.py +0 -354
- dfm_python-0.1.0/scripts/train_dfm.py +0 -348
- dfm_python-0.1.0/scripts/utils.py +0 -194
- dfm_python-0.1.0/services/__init__.py +0 -20
- dfm_python-0.1.0/services/api/__init__.py +0 -15
- dfm_python-0.1.0/services/api/base.py +0 -99
- dfm_python-0.1.0/services/api/bok_client.py +0 -317
- dfm_python-0.1.0/services/api/kosis_client.py +0 -368
- dfm_python-0.1.0/services/ingestion/__init__.py +0 -14
- dfm_python-0.1.0/services/ingestion/base.py +0 -389
- dfm_python-0.1.0/services/ingestion/bok.py +0 -297
- dfm_python-0.1.0/services/ingestion/kosis.py +0 -298
- dfm_python-0.1.0/services/ingestion/orchestrator.py +0 -526
- dfm_python-0.1.0/src/__init__.py +0 -43
- dfm_python-0.1.0/tests/__init__.py +0 -0
- dfm_python-0.1.0/tests/test_adapters_database.py +0 -184
- dfm_python-0.1.0/tests/test_database_connection.py +0 -213
- dfm_python-0.1.0/tests/test_database_ingestion.py +0 -508
- dfm_python-0.1.0/tests/test_full_workflow.py +0 -248
- dfm_python-0.1.0/tests/test_nowcast_dfm.py +0 -230
- dfm_python-0.1.0/tests/test_nowcasting_dfm.py +0 -148
- dfm_python-0.1.0/tests/test_train_dfm.py +0 -251
- {dfm_python-0.1.0 → dfm_python-0.1.1}/.python-version +0 -0
- {dfm_python-0.1.0 → dfm_python-0.1.1}/MANIFEST.in +0 -0
- {dfm_python-0.1.0 → dfm_python-0.1.1}/src/dfm_python/__init__.py +0 -0
- {dfm_python-0.1.0 → dfm_python-0.1.1}/src/dfm_python/config.py +0 -0
- {dfm_python-0.1.0 → dfm_python-0.1.1}/src/dfm_python/kalman.py +0 -0
- {dfm_python-0.1.0 → dfm_python-0.1.1}/src/test/__init__.py +0 -0
- {dfm_python-0.1.0 → dfm_python-0.1.1}/src/utils/__init__.py +0 -0
- {dfm_python-0.1.0 → dfm_python-0.1.1}/uv.lock +0 -0
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
# Byte-compiled / optimized / DLL files
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[codz]
|
|
4
|
+
*$py.class
|
|
5
|
+
|
|
6
|
+
# C extensions
|
|
7
|
+
*.so
|
|
8
|
+
|
|
9
|
+
# Distribution / packaging
|
|
10
|
+
.Python
|
|
11
|
+
build/
|
|
12
|
+
develop-eggs/
|
|
13
|
+
dist/
|
|
14
|
+
downloads/
|
|
15
|
+
eggs/
|
|
16
|
+
.eggs/
|
|
17
|
+
lib/
|
|
18
|
+
lib64/
|
|
19
|
+
parts/
|
|
20
|
+
sdist/
|
|
21
|
+
var/
|
|
22
|
+
wheels/
|
|
23
|
+
share/python-wheels/
|
|
24
|
+
*.egg-info/
|
|
25
|
+
.installed.cfg
|
|
26
|
+
*.egg
|
|
27
|
+
MANIFEST
|
|
28
|
+
|
|
29
|
+
# PyInstaller
|
|
30
|
+
# Usually these files are written by a python script from a template
|
|
31
|
+
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
|
32
|
+
*.manifest
|
|
33
|
+
*.spec
|
|
34
|
+
|
|
35
|
+
# Installer logs
|
|
36
|
+
pip-log.txt
|
|
37
|
+
pip-delete-this-directory.txt
|
|
38
|
+
|
|
39
|
+
# Unit test / coverage reports
|
|
40
|
+
htmlcov/
|
|
41
|
+
.tox/
|
|
42
|
+
.nox/
|
|
43
|
+
.coverage
|
|
44
|
+
.coverage.*
|
|
45
|
+
.cache
|
|
46
|
+
nosetests.xml
|
|
47
|
+
coverage.xml
|
|
48
|
+
*.cover
|
|
49
|
+
*.py.cover
|
|
50
|
+
.hypothesis/
|
|
51
|
+
.pytest_cache/
|
|
52
|
+
cover/
|
|
53
|
+
|
|
54
|
+
# Translations
|
|
55
|
+
*.mo
|
|
56
|
+
*.pot
|
|
57
|
+
|
|
58
|
+
# Django stuff:
|
|
59
|
+
*.log
|
|
60
|
+
local_settings.py
|
|
61
|
+
db.sqlite3
|
|
62
|
+
db.sqlite3-journal
|
|
63
|
+
|
|
64
|
+
# Flask stuff:
|
|
65
|
+
instance/
|
|
66
|
+
.webassets-cache
|
|
67
|
+
|
|
68
|
+
# Scrapy stuff:
|
|
69
|
+
.scrapy
|
|
70
|
+
|
|
71
|
+
# Sphinx documentation
|
|
72
|
+
docs/_build/
|
|
73
|
+
|
|
74
|
+
# PyBuilder
|
|
75
|
+
.pybuilder/
|
|
76
|
+
target/
|
|
77
|
+
|
|
78
|
+
# Jupyter Notebook
|
|
79
|
+
.ipynb_checkpoints
|
|
80
|
+
|
|
81
|
+
# IPython
|
|
82
|
+
profile_default/
|
|
83
|
+
ipython_config.py
|
|
84
|
+
|
|
85
|
+
# pyenv
|
|
86
|
+
# For a library or package, you might want to ignore these files since the code is
|
|
87
|
+
# intended to run in multiple environments; otherwise, check them in:
|
|
88
|
+
# .python-version
|
|
89
|
+
|
|
90
|
+
# pipenv
|
|
91
|
+
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
|
92
|
+
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
|
93
|
+
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
|
94
|
+
# install all needed dependencies.
|
|
95
|
+
#Pipfile.lock
|
|
96
|
+
|
|
97
|
+
# UV
|
|
98
|
+
# Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control.
|
|
99
|
+
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
|
100
|
+
# commonly ignored for libraries.
|
|
101
|
+
#uv.lock
|
|
102
|
+
|
|
103
|
+
# poetry
|
|
104
|
+
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
|
|
105
|
+
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
|
106
|
+
# commonly ignored for libraries.
|
|
107
|
+
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
|
|
108
|
+
#poetry.lock
|
|
109
|
+
#poetry.toml
|
|
110
|
+
|
|
111
|
+
# pdm
|
|
112
|
+
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
|
|
113
|
+
# pdm recommends including project-wide configuration in pdm.toml, but excluding .pdm-python.
|
|
114
|
+
# https://pdm-project.org/en/latest/usage/project/#working-with-version-control
|
|
115
|
+
#pdm.lock
|
|
116
|
+
#pdm.toml
|
|
117
|
+
.pdm-python
|
|
118
|
+
.pdm-build/
|
|
119
|
+
|
|
120
|
+
# pixi
|
|
121
|
+
# Similar to Pipfile.lock, it is generally recommended to include pixi.lock in version control.
|
|
122
|
+
#pixi.lock
|
|
123
|
+
# Pixi creates a virtual environment in the .pixi directory, just like venv module creates one
|
|
124
|
+
# in the .venv directory. It is recommended not to include this directory in version control.
|
|
125
|
+
.pixi
|
|
126
|
+
|
|
127
|
+
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
|
|
128
|
+
__pypackages__/
|
|
129
|
+
|
|
130
|
+
# Celery stuff
|
|
131
|
+
celerybeat-schedule
|
|
132
|
+
celerybeat.pid
|
|
133
|
+
|
|
134
|
+
# SageMath parsed files
|
|
135
|
+
*.sage.py
|
|
136
|
+
|
|
137
|
+
# Environments
|
|
138
|
+
.env
|
|
139
|
+
.envrc
|
|
140
|
+
.venv
|
|
141
|
+
env/
|
|
142
|
+
venv/
|
|
143
|
+
ENV/
|
|
144
|
+
env.bak/
|
|
145
|
+
venv.bak/
|
|
146
|
+
|
|
147
|
+
# Spyder project settings
|
|
148
|
+
.spyderproject
|
|
149
|
+
.spyproject
|
|
150
|
+
|
|
151
|
+
# Rope project settings
|
|
152
|
+
.ropeproject
|
|
153
|
+
|
|
154
|
+
# mkdocs documentation
|
|
155
|
+
/site
|
|
156
|
+
|
|
157
|
+
# mypy
|
|
158
|
+
.mypy_cache/
|
|
159
|
+
.dmypy.json
|
|
160
|
+
dmypy.json
|
|
161
|
+
|
|
162
|
+
# Pyre type checker
|
|
163
|
+
.pyre/
|
|
164
|
+
|
|
165
|
+
# pytype static type analyzer
|
|
166
|
+
.pytype/
|
|
167
|
+
|
|
168
|
+
# Cython debug symbols
|
|
169
|
+
cython_debug/
|
|
170
|
+
|
|
171
|
+
# PyCharm
|
|
172
|
+
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
|
|
173
|
+
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
|
|
174
|
+
# and can be added to the global gitignore or merged into this file. For a more nuclear
|
|
175
|
+
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
|
176
|
+
#.idea/
|
|
177
|
+
|
|
178
|
+
# Abstra
|
|
179
|
+
# Abstra is an AI-powered process automation framework.
|
|
180
|
+
# Ignore directories containing user credentials, local state, and settings.
|
|
181
|
+
# Learn more at https://abstra.io/docs
|
|
182
|
+
.abstra/
|
|
183
|
+
|
|
184
|
+
# Visual Studio Code
|
|
185
|
+
# Visual Studio Code specific template is maintained in a separate VisualStudioCode.gitignore
|
|
186
|
+
# that can be found at https://github.com/github/gitignore/blob/main/Global/VisualStudioCode.gitignore
|
|
187
|
+
# and can be added to the global gitignore or merged into this file. However, if you prefer,
|
|
188
|
+
# you could uncomment the following to ignore the entire vscode folder
|
|
189
|
+
# .vscode/
|
|
190
|
+
|
|
191
|
+
# Ruff stuff:
|
|
192
|
+
.ruff_cache/
|
|
193
|
+
|
|
194
|
+
# PyPI configuration file
|
|
195
|
+
.pypirc
|
|
196
|
+
|
|
197
|
+
# Cursor
|
|
198
|
+
# Cursor is an AI-powered code editor. `.cursorignore` specifies files/directories to
|
|
199
|
+
# exclude from AI features like autocomplete and code analysis. Recommended for sensitive data
|
|
200
|
+
# refer to https://docs.cursor.com/context/ignore-files
|
|
201
|
+
.cursorignore
|
|
202
|
+
.cursorindexingignore
|
|
203
|
+
|
|
204
|
+
# Marimo
|
|
205
|
+
marimo/_static/
|
|
206
|
+
marimo/_lsp/
|
|
207
|
+
__marimo__/
|
dfm_python-0.1.1/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 ywcpar
|
|
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.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: dfm-python
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.1
|
|
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
|
|
@@ -8,6 +8,7 @@ Project-URL: Repository, https://github.com/yourusername/dfm-python
|
|
|
8
8
|
Project-URL: Issues, https://github.com/yourusername/dfm-python/issues
|
|
9
9
|
Author: DFM Python Contributors
|
|
10
10
|
License: MIT
|
|
11
|
+
License-File: LICENSE
|
|
11
12
|
Keywords: dfm,dynamic-factor-model,econometrics,forecasting,nowcasting,time-series
|
|
12
13
|
Classifier: Development Status :: 4 - Beta
|
|
13
14
|
Classifier: Intended Audience :: Science/Research
|
|
@@ -97,6 +98,67 @@ factors = Res.Z # Extracted factors
|
|
|
97
98
|
loadings = Res.C # Factor loadings
|
|
98
99
|
```
|
|
99
100
|
|
|
101
|
+
### Complete Example with Sample Data
|
|
102
|
+
|
|
103
|
+
The package includes sample data and configuration files for testing. Here's a complete working example:
|
|
104
|
+
|
|
105
|
+
```python
|
|
106
|
+
from dfm_python import load_config, load_data, dfm
|
|
107
|
+
import pandas as pd
|
|
108
|
+
import numpy as np
|
|
109
|
+
|
|
110
|
+
# Load configuration (YAML or CSV format)
|
|
111
|
+
config = load_config('config/example_config.yaml')
|
|
112
|
+
# Alternative: config = load_config('spec/example_spec.csv')
|
|
113
|
+
|
|
114
|
+
# Load sample data
|
|
115
|
+
X, Time, Z = load_data(
|
|
116
|
+
'data/sample_data.csv',
|
|
117
|
+
config,
|
|
118
|
+
sample_start=pd.Timestamp('2000-01-01')
|
|
119
|
+
)
|
|
120
|
+
|
|
121
|
+
print(f"Data shape: {X.shape}")
|
|
122
|
+
print(f"Time range: {Time[0]} to {Time[-1]}")
|
|
123
|
+
print(f"Number of series: {len(config.series)}")
|
|
124
|
+
|
|
125
|
+
# Estimate DFM model
|
|
126
|
+
print("\nEstimating DFM model...")
|
|
127
|
+
Res = dfm(X, config, threshold=1e-4, max_iter=1000)
|
|
128
|
+
|
|
129
|
+
# Access results
|
|
130
|
+
print(f"\nExtracted {Res.Z.shape[1]} factors")
|
|
131
|
+
print(f"Factor loadings shape: {Res.C.shape}")
|
|
132
|
+
print(f"Transition matrix shape: {Res.A.shape}")
|
|
133
|
+
|
|
134
|
+
# Display factor estimates
|
|
135
|
+
factors = Res.Z # Factor estimates (T x r)
|
|
136
|
+
loadings = Res.C # Factor loadings (N x r)
|
|
137
|
+
transition = Res.A # Transition matrix
|
|
138
|
+
covariance = Res.Q # Factor covariance
|
|
139
|
+
|
|
140
|
+
print(f"\nFirst few factor values:")
|
|
141
|
+
print(factors[:5, :])
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
**Expected Output:**
|
|
145
|
+
```
|
|
146
|
+
Loading data...
|
|
147
|
+
Data shape: (128, 10)
|
|
148
|
+
Time range: 2000-05-01 00:00:00 to 2010-12-01 00:00:00
|
|
149
|
+
Number of series: 10
|
|
150
|
+
|
|
151
|
+
Estimating DFM model...
|
|
152
|
+
Extracted 4 factors
|
|
153
|
+
Factor loadings shape: (10, 4)
|
|
154
|
+
Transition matrix shape: (4, 4)
|
|
155
|
+
|
|
156
|
+
First few factor values:
|
|
157
|
+
[[ 0.123 -0.045 0.012 0.008]
|
|
158
|
+
[ 0.145 -0.032 0.015 0.011]
|
|
159
|
+
...]
|
|
160
|
+
```
|
|
161
|
+
|
|
100
162
|
### Configuration
|
|
101
163
|
|
|
102
164
|
The DFM module uses a configuration object (`DFMConfig`) that defines:
|
|
@@ -107,21 +169,32 @@ The DFM module uses a configuration object (`DFMConfig`) that defines:
|
|
|
107
169
|
|
|
108
170
|
#### YAML Configuration Example
|
|
109
171
|
|
|
172
|
+
The package includes a sample configuration file (`config/example_config.yaml`) that demonstrates the full configuration structure:
|
|
173
|
+
|
|
110
174
|
```yaml
|
|
111
|
-
# config.yaml
|
|
175
|
+
# config/example_config.yaml
|
|
112
176
|
model:
|
|
113
177
|
series:
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
transformation: "pch"
|
|
117
|
-
blocks: [Global]
|
|
118
|
-
series_2:
|
|
178
|
+
gdp_real:
|
|
179
|
+
series_name: "Real GDP (Quarterly)"
|
|
119
180
|
frequency: "q"
|
|
120
181
|
transformation: "pca"
|
|
121
|
-
|
|
182
|
+
category: "GDP"
|
|
183
|
+
units: "Index (2000=100)"
|
|
184
|
+
blocks: [Global, Consumption, Investment]
|
|
185
|
+
|
|
186
|
+
consumption:
|
|
187
|
+
series_name: "Consumption (Monthly)"
|
|
188
|
+
frequency: "m"
|
|
189
|
+
transformation: "pch"
|
|
190
|
+
category: "Consumption"
|
|
191
|
+
units: "Index (2000=100)"
|
|
192
|
+
blocks: [Global, Consumption]
|
|
122
193
|
|
|
123
194
|
blocks:
|
|
124
195
|
Global:
|
|
196
|
+
factors: 2
|
|
197
|
+
Consumption:
|
|
125
198
|
factors: 1
|
|
126
199
|
Investment:
|
|
127
200
|
factors: 1
|
|
@@ -134,27 +207,39 @@ dfm:
|
|
|
134
207
|
|
|
135
208
|
#### CSV Configuration Example
|
|
136
209
|
|
|
210
|
+
The package also includes a CSV configuration file (`spec/example_spec.csv`) for simpler setups:
|
|
211
|
+
|
|
137
212
|
```csv
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
213
|
+
series_id,series_name,frequency,transformation,category,units,Block_Global,Block_Consumption,Block_Investment
|
|
214
|
+
gdp_real,Real GDP (Quarterly),q,pca,GDP,Index (2000=100),1,1,1
|
|
215
|
+
consumption,Consumption (Monthly),m,pch,Consumption,Index (2000=100),1,1,0
|
|
216
|
+
investment,Investment (Monthly),m,pch,Investment,Index (2000=100),1,0,1
|
|
141
217
|
```
|
|
142
218
|
|
|
219
|
+
**Note:** The first block (Global) must always have value `1` for all series, as it represents the common factor that all series load on.
|
|
220
|
+
|
|
143
221
|
### Data Format
|
|
144
222
|
|
|
145
223
|
CSV data files should have:
|
|
146
224
|
- First column: Date (YYYY-MM-DD format)
|
|
147
|
-
- Subsequent columns: One per series (matching
|
|
148
|
-
- Column names:
|
|
225
|
+
- Subsequent columns: One per series (matching `series_id` from config)
|
|
226
|
+
- Column names: Must match `series_id` from configuration exactly
|
|
227
|
+
|
|
228
|
+
The package includes sample data (`data/sample_data.csv`) with 10 time series spanning 2000-2010:
|
|
149
229
|
|
|
150
|
-
Example:
|
|
151
230
|
```csv
|
|
152
|
-
Date,
|
|
153
|
-
2000-01-01,100.0,
|
|
154
|
-
2000-02-01,
|
|
231
|
+
Date,gdp_real,gdp_nominal,consumption,investment,exports,imports,unemployment,industrial_production,retail_sales,consumer_confidence
|
|
232
|
+
2000-01-01,100.0,105.0,98.5,95.0,102.0,100.5,5.2,98.0,97.5,100.0
|
|
233
|
+
2000-02-01,100.2,105.3,98.7,95.2,102.2,100.7,5.1,98.3,97.8,100.2
|
|
155
234
|
...
|
|
156
235
|
```
|
|
157
236
|
|
|
237
|
+
**Important Notes:**
|
|
238
|
+
- Date column must be named `Date` (case-sensitive)
|
|
239
|
+
- Series column names must exactly match `series_id` values in the configuration
|
|
240
|
+
- Missing values should be represented as empty cells or `NaN`
|
|
241
|
+
- The data supports mixed frequencies (monthly and quarterly series are handled automatically)
|
|
242
|
+
|
|
158
243
|
## Core Components
|
|
159
244
|
|
|
160
245
|
### DFMConfig
|
|
@@ -239,6 +324,45 @@ The DFM module is designed to be **generic and application-agnostic**:
|
|
|
239
324
|
|
|
240
325
|
This separation allows the core module to be used in any context while keeping application-specific code separate.
|
|
241
326
|
|
|
327
|
+
## Testing with Sample Data
|
|
328
|
+
|
|
329
|
+
The package includes sample data and configuration files for testing and demonstration:
|
|
330
|
+
|
|
331
|
+
- **Data**: `data/sample_data.csv` - 10 time series from 2000-2010
|
|
332
|
+
- **Config (YAML)**: `config/example_config.yaml` - Full configuration example
|
|
333
|
+
- **Config (CSV)**: `spec/example_spec.csv` - Simplified CSV configuration
|
|
334
|
+
|
|
335
|
+
To test the package with sample data:
|
|
336
|
+
|
|
337
|
+
```python
|
|
338
|
+
from dfm_python import load_config, load_data, dfm
|
|
339
|
+
import pandas as pd
|
|
340
|
+
|
|
341
|
+
# Load sample configuration
|
|
342
|
+
config = load_config('config/example_config.yaml')
|
|
343
|
+
|
|
344
|
+
# Load sample data
|
|
345
|
+
X, Time, Z = load_data('data/sample_data.csv', config)
|
|
346
|
+
|
|
347
|
+
# Estimate model
|
|
348
|
+
result = dfm(X, config, threshold=1e-4)
|
|
349
|
+
|
|
350
|
+
# Check results
|
|
351
|
+
print(f"Factors extracted: {result.Z.shape[1]}")
|
|
352
|
+
print(f"Factor loadings shape: {result.C.shape}")
|
|
353
|
+
print(f"Number of series: {result.C.shape[0]}")
|
|
354
|
+
print(f"Number of time periods: {result.Z.shape[0]}")
|
|
355
|
+
```
|
|
356
|
+
|
|
357
|
+
You can also run the test suite:
|
|
358
|
+
|
|
359
|
+
```bash
|
|
360
|
+
# From project root
|
|
361
|
+
python -m pytest src/test/
|
|
362
|
+
# Or run specific test
|
|
363
|
+
python src/test/test_synthetic.py
|
|
364
|
+
```
|
|
365
|
+
|
|
242
366
|
## Requirements
|
|
243
367
|
|
|
244
368
|
- Python >= 3.12
|
|
@@ -56,6 +56,67 @@ factors = Res.Z # Extracted factors
|
|
|
56
56
|
loadings = Res.C # Factor loadings
|
|
57
57
|
```
|
|
58
58
|
|
|
59
|
+
### Complete Example with Sample Data
|
|
60
|
+
|
|
61
|
+
The package includes sample data and configuration files for testing. Here's a complete working example:
|
|
62
|
+
|
|
63
|
+
```python
|
|
64
|
+
from dfm_python import load_config, load_data, dfm
|
|
65
|
+
import pandas as pd
|
|
66
|
+
import numpy as np
|
|
67
|
+
|
|
68
|
+
# Load configuration (YAML or CSV format)
|
|
69
|
+
config = load_config('config/example_config.yaml')
|
|
70
|
+
# Alternative: config = load_config('spec/example_spec.csv')
|
|
71
|
+
|
|
72
|
+
# Load sample data
|
|
73
|
+
X, Time, Z = load_data(
|
|
74
|
+
'data/sample_data.csv',
|
|
75
|
+
config,
|
|
76
|
+
sample_start=pd.Timestamp('2000-01-01')
|
|
77
|
+
)
|
|
78
|
+
|
|
79
|
+
print(f"Data shape: {X.shape}")
|
|
80
|
+
print(f"Time range: {Time[0]} to {Time[-1]}")
|
|
81
|
+
print(f"Number of series: {len(config.series)}")
|
|
82
|
+
|
|
83
|
+
# Estimate DFM model
|
|
84
|
+
print("\nEstimating DFM model...")
|
|
85
|
+
Res = dfm(X, config, threshold=1e-4, max_iter=1000)
|
|
86
|
+
|
|
87
|
+
# Access results
|
|
88
|
+
print(f"\nExtracted {Res.Z.shape[1]} factors")
|
|
89
|
+
print(f"Factor loadings shape: {Res.C.shape}")
|
|
90
|
+
print(f"Transition matrix shape: {Res.A.shape}")
|
|
91
|
+
|
|
92
|
+
# Display factor estimates
|
|
93
|
+
factors = Res.Z # Factor estimates (T x r)
|
|
94
|
+
loadings = Res.C # Factor loadings (N x r)
|
|
95
|
+
transition = Res.A # Transition matrix
|
|
96
|
+
covariance = Res.Q # Factor covariance
|
|
97
|
+
|
|
98
|
+
print(f"\nFirst few factor values:")
|
|
99
|
+
print(factors[:5, :])
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
**Expected Output:**
|
|
103
|
+
```
|
|
104
|
+
Loading data...
|
|
105
|
+
Data shape: (128, 10)
|
|
106
|
+
Time range: 2000-05-01 00:00:00 to 2010-12-01 00:00:00
|
|
107
|
+
Number of series: 10
|
|
108
|
+
|
|
109
|
+
Estimating DFM model...
|
|
110
|
+
Extracted 4 factors
|
|
111
|
+
Factor loadings shape: (10, 4)
|
|
112
|
+
Transition matrix shape: (4, 4)
|
|
113
|
+
|
|
114
|
+
First few factor values:
|
|
115
|
+
[[ 0.123 -0.045 0.012 0.008]
|
|
116
|
+
[ 0.145 -0.032 0.015 0.011]
|
|
117
|
+
...]
|
|
118
|
+
```
|
|
119
|
+
|
|
59
120
|
### Configuration
|
|
60
121
|
|
|
61
122
|
The DFM module uses a configuration object (`DFMConfig`) that defines:
|
|
@@ -66,21 +127,32 @@ The DFM module uses a configuration object (`DFMConfig`) that defines:
|
|
|
66
127
|
|
|
67
128
|
#### YAML Configuration Example
|
|
68
129
|
|
|
130
|
+
The package includes a sample configuration file (`config/example_config.yaml`) that demonstrates the full configuration structure:
|
|
131
|
+
|
|
69
132
|
```yaml
|
|
70
|
-
# config.yaml
|
|
133
|
+
# config/example_config.yaml
|
|
71
134
|
model:
|
|
72
135
|
series:
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
transformation: "pch"
|
|
76
|
-
blocks: [Global]
|
|
77
|
-
series_2:
|
|
136
|
+
gdp_real:
|
|
137
|
+
series_name: "Real GDP (Quarterly)"
|
|
78
138
|
frequency: "q"
|
|
79
139
|
transformation: "pca"
|
|
80
|
-
|
|
140
|
+
category: "GDP"
|
|
141
|
+
units: "Index (2000=100)"
|
|
142
|
+
blocks: [Global, Consumption, Investment]
|
|
143
|
+
|
|
144
|
+
consumption:
|
|
145
|
+
series_name: "Consumption (Monthly)"
|
|
146
|
+
frequency: "m"
|
|
147
|
+
transformation: "pch"
|
|
148
|
+
category: "Consumption"
|
|
149
|
+
units: "Index (2000=100)"
|
|
150
|
+
blocks: [Global, Consumption]
|
|
81
151
|
|
|
82
152
|
blocks:
|
|
83
153
|
Global:
|
|
154
|
+
factors: 2
|
|
155
|
+
Consumption:
|
|
84
156
|
factors: 1
|
|
85
157
|
Investment:
|
|
86
158
|
factors: 1
|
|
@@ -93,27 +165,39 @@ dfm:
|
|
|
93
165
|
|
|
94
166
|
#### CSV Configuration Example
|
|
95
167
|
|
|
168
|
+
The package also includes a CSV configuration file (`spec/example_spec.csv`) for simpler setups:
|
|
169
|
+
|
|
96
170
|
```csv
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
171
|
+
series_id,series_name,frequency,transformation,category,units,Block_Global,Block_Consumption,Block_Investment
|
|
172
|
+
gdp_real,Real GDP (Quarterly),q,pca,GDP,Index (2000=100),1,1,1
|
|
173
|
+
consumption,Consumption (Monthly),m,pch,Consumption,Index (2000=100),1,1,0
|
|
174
|
+
investment,Investment (Monthly),m,pch,Investment,Index (2000=100),1,0,1
|
|
100
175
|
```
|
|
101
176
|
|
|
177
|
+
**Note:** The first block (Global) must always have value `1` for all series, as it represents the common factor that all series load on.
|
|
178
|
+
|
|
102
179
|
### Data Format
|
|
103
180
|
|
|
104
181
|
CSV data files should have:
|
|
105
182
|
- First column: Date (YYYY-MM-DD format)
|
|
106
|
-
- Subsequent columns: One per series (matching
|
|
107
|
-
- Column names:
|
|
183
|
+
- Subsequent columns: One per series (matching `series_id` from config)
|
|
184
|
+
- Column names: Must match `series_id` from configuration exactly
|
|
185
|
+
|
|
186
|
+
The package includes sample data (`data/sample_data.csv`) with 10 time series spanning 2000-2010:
|
|
108
187
|
|
|
109
|
-
Example:
|
|
110
188
|
```csv
|
|
111
|
-
Date,
|
|
112
|
-
2000-01-01,100.0,
|
|
113
|
-
2000-02-01,
|
|
189
|
+
Date,gdp_real,gdp_nominal,consumption,investment,exports,imports,unemployment,industrial_production,retail_sales,consumer_confidence
|
|
190
|
+
2000-01-01,100.0,105.0,98.5,95.0,102.0,100.5,5.2,98.0,97.5,100.0
|
|
191
|
+
2000-02-01,100.2,105.3,98.7,95.2,102.2,100.7,5.1,98.3,97.8,100.2
|
|
114
192
|
...
|
|
115
193
|
```
|
|
116
194
|
|
|
195
|
+
**Important Notes:**
|
|
196
|
+
- Date column must be named `Date` (case-sensitive)
|
|
197
|
+
- Series column names must exactly match `series_id` values in the configuration
|
|
198
|
+
- Missing values should be represented as empty cells or `NaN`
|
|
199
|
+
- The data supports mixed frequencies (monthly and quarterly series are handled automatically)
|
|
200
|
+
|
|
117
201
|
## Core Components
|
|
118
202
|
|
|
119
203
|
### DFMConfig
|
|
@@ -198,6 +282,45 @@ The DFM module is designed to be **generic and application-agnostic**:
|
|
|
198
282
|
|
|
199
283
|
This separation allows the core module to be used in any context while keeping application-specific code separate.
|
|
200
284
|
|
|
285
|
+
## Testing with Sample Data
|
|
286
|
+
|
|
287
|
+
The package includes sample data and configuration files for testing and demonstration:
|
|
288
|
+
|
|
289
|
+
- **Data**: `data/sample_data.csv` - 10 time series from 2000-2010
|
|
290
|
+
- **Config (YAML)**: `config/example_config.yaml` - Full configuration example
|
|
291
|
+
- **Config (CSV)**: `spec/example_spec.csv` - Simplified CSV configuration
|
|
292
|
+
|
|
293
|
+
To test the package with sample data:
|
|
294
|
+
|
|
295
|
+
```python
|
|
296
|
+
from dfm_python import load_config, load_data, dfm
|
|
297
|
+
import pandas as pd
|
|
298
|
+
|
|
299
|
+
# Load sample configuration
|
|
300
|
+
config = load_config('config/example_config.yaml')
|
|
301
|
+
|
|
302
|
+
# Load sample data
|
|
303
|
+
X, Time, Z = load_data('data/sample_data.csv', config)
|
|
304
|
+
|
|
305
|
+
# Estimate model
|
|
306
|
+
result = dfm(X, config, threshold=1e-4)
|
|
307
|
+
|
|
308
|
+
# Check results
|
|
309
|
+
print(f"Factors extracted: {result.Z.shape[1]}")
|
|
310
|
+
print(f"Factor loadings shape: {result.C.shape}")
|
|
311
|
+
print(f"Number of series: {result.C.shape[0]}")
|
|
312
|
+
print(f"Number of time periods: {result.Z.shape[0]}")
|
|
313
|
+
```
|
|
314
|
+
|
|
315
|
+
You can also run the test suite:
|
|
316
|
+
|
|
317
|
+
```bash
|
|
318
|
+
# From project root
|
|
319
|
+
python -m pytest src/test/
|
|
320
|
+
# Or run specific test
|
|
321
|
+
python src/test/test_synthetic.py
|
|
322
|
+
```
|
|
323
|
+
|
|
201
324
|
## Requirements
|
|
202
325
|
|
|
203
326
|
- Python >= 3.12
|