dfm-python 0.1.6__py3-none-any.whl → 0.2.0__py3-none-any.whl

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/__init__.py CHANGED
@@ -1,60 +1,184 @@
1
1
  """Dynamic Factor Model (DFM) package for Python.
2
2
 
3
3
  This package implements a comprehensive Dynamic Factor Model framework with support for:
4
- - Mixed-frequency time series data (daily, weekly, monthly, quarterly, semi-annual, annual)
4
+ - Mixed-frequency time series data (monthly, quarterly, semi-annual, annual)
5
5
  - Clock-based synchronization of latent factors
6
6
  - Tent kernel aggregation for low-to-high frequency mapping
7
7
  - Expectation-Maximization (EM) algorithm for parameter estimation
8
8
  - Kalman filtering and smoothing for factor extraction
9
9
  - News decomposition for nowcasting
10
10
 
11
- The package follows the FRBNY (Federal Reserve Bank of New York) approach to mixed-frequency
12
- DFMs, where all latent factors (global and block-level) are synchronized to a common "clock"
13
- frequency, typically monthly. Lower-frequency observed variables are mapped to higher-frequency
14
- latent states using deterministic tent kernels in the observation equation.
11
+ The package implements a clock-based approach to mixed-frequency DFMs, where all latent
12
+ factors (global and block-level) are synchronized to a common "clock" frequency, typically
13
+ monthly. Lower-frequency observed variables are mapped to higher-frequency latent states
14
+ using deterministic tent kernels in the observation equation.
15
+
16
+ Note: Higher frequencies (daily, weekly) than the clock are not supported. If any series
17
+ has a frequency faster than the clock, a ValueError will be raised.
15
18
 
16
19
  Key Features:
17
- - Unified configuration system (YAML/CSV)
20
+ - Unified configuration system (YAML with Hydra/OmegaConf, or direct DFMConfig objects)
18
21
  - Flexible block structure for factor modeling
19
22
  - Robust handling of missing data
20
23
  - Comprehensive transformation support
21
24
  - News decomposition for forecast updates
22
25
 
23
- Example:
24
- >>> from dfm_python import load_config, load_data, dfm
26
+ Example (High-level API - Recommended):
27
+ >>> import dfm_python as dfm
28
+ >>> dfm.load_config('config/default.yaml')
29
+ >>> dfm.load_data('data/sample_data.csv')
30
+ >>> dfm.train(max_iter=1)
31
+ >>> Xf, Zf = dfm.predict(horizon=6)
32
+ >>> dfm.plot(kind='factor', factor_index=0, forecast_horizon=6, save_path='outputs/factor_forecast.png')
33
+ >>> factors = dfm.get_result().Z # Access factors via result
34
+
35
+ Example (Low-level API - For advanced usage):
36
+ >>> from dfm_python import DFM, DFMConfig, SeriesConfig
37
+ >>> from dfm_python.data_loader import load_data
38
+ >>> # Option 1: Load from YAML
25
39
  >>> config = load_config('config.yaml')
26
- >>> X, Time, _ = load_data('data.csv', config)
27
- >>> result = dfm(X, config)
40
+ >>> # Option 2: Create directly
41
+ >>> config = DFMConfig(
42
+ ... series=[SeriesConfig(frequency='m', transformation='lin', blocks=[1], series_id='series1')],
43
+ ... block_names=['Global']
44
+ ... )
45
+ >>> X, Time, _ = load_data('data.csv', config) # or use database adapter
46
+ >>> model = DFM()
47
+ >>> result = model.fit(X, config)
28
48
  >>> factors = result.Z # Extract estimated factors
29
49
 
30
- For detailed documentation, see the README.md file.
50
+ For detailed documentation, see the README.md file and the tutorial notebooks/scripts.
31
51
  """
32
52
 
33
- __version__ = "0.1.6"
53
+ __version__ = "0.2.0"
34
54
 
35
- from .config import DFMConfig
36
- from .data_loader import (
37
- load_config, load_config_from_yaml, load_config_from_csv, load_data, transform_data
55
+ from .config import DFMConfig, SeriesConfig, BlockConfig, Params, DEFAULT_GLOBAL_BLOCK_NAME
56
+ from .config import (
57
+ ConfigSource,
58
+ YamlSource,
59
+ DictSource,
60
+ SpecCSVSource,
61
+ HydraSource,
62
+ MergedConfigSource,
63
+ make_config_source,
38
64
  )
39
- from .dfm import DFMResult, dfm, calculate_rmse, diagnose_series, print_series_diagnosis
65
+ from .data_loader import transform_data
66
+ from .dfm import DFMResult, calculate_rmse, diagnose_series, print_series_diagnosis
67
+ from .dfm import DFM as _DFMCore # Core DFM class from dfm.py
40
68
  from .kalman import run_kf, skf, fis, miss_data
41
69
  from .news import update_nowcast, news_dfm, para_const
42
70
 
43
- # Backward compatibility aliases
44
- ModelConfig = DFMConfig # Deprecated: ModelConfig merged into DFMConfig
45
- ModelSpec = DFMConfig # Deprecated: use DFMConfig
46
- load_spec = load_config # Deprecated: use load_config
71
+ # Import high-level API (extends core DFM with convenience methods)
72
+ from .dfm_api import DFM, _dfm_instance, from_yaml, from_spec, from_spec_df, from_dict
73
+
74
+ # Module-level API: expose singleton instance methods and properties
75
+ # This allows: import dfm_python as dfm; dfm.load_config(...); dfm.result
76
+ def load_config(
77
+ source=None,
78
+ *,
79
+ yaml=None,
80
+ mapping=None,
81
+ spec=None,
82
+ hydra=None,
83
+ base=None,
84
+ override=None,
85
+ config=None,
86
+ ):
87
+ """Load configuration (module-level convenience function).
88
+
89
+ See DFM.load_config() for parameter documentation.
90
+ """
91
+ return _dfm_instance.load_config(
92
+ source=source,
93
+ yaml=yaml,
94
+ mapping=mapping,
95
+ spec=spec,
96
+ hydra=hydra,
97
+ base=base,
98
+ override=override,
99
+ config=config,
100
+ )
101
+
102
+ def load_data(data_path=None, data=None, **kwargs):
103
+ """Load data (module-level convenience function)."""
104
+ return _dfm_instance.load_data(data_path=data_path, data=data, **kwargs)
105
+
106
+ def train(threshold=None, max_iter=None, **kwargs):
107
+ """Train the model (module-level convenience function)."""
108
+ return _dfm_instance.train(threshold=threshold, max_iter=max_iter, **kwargs)
109
+
110
+ def predict(horizon=12, **kwargs):
111
+ """Forecast using the trained model (module-level convenience function)."""
112
+ return _dfm_instance.predict(horizon=horizon, **kwargs)
113
+
114
+ def plot(**kwargs):
115
+ """Plot common visualizations (module-level convenience function)."""
116
+ return _dfm_instance.plot(**kwargs)
117
+
118
+ def reset():
119
+ """Reset state (module-level convenience function)."""
120
+ return _dfm_instance.reset()
121
+
122
+ # Expose properties as module-level attributes
123
+ # Use property-like access via functions or direct attribute access
124
+ # Since 'config' conflicts with the config module, we'll use a different approach
125
+ # Users can access: dfm.get_config(), dfm.get_data(), dfm.get_result()
126
+ def get_config():
127
+ """Get current configuration."""
128
+ return _dfm_instance.config
129
+
130
+ def get_data():
131
+ """Get current data matrix."""
132
+ return _dfm_instance.data
133
+
134
+ def get_time():
135
+ """Get current time index."""
136
+ return _dfm_instance.time
137
+
138
+ def get_result():
139
+ """Get training result."""
140
+ return _dfm_instance.result
141
+
142
+ def get_original_data():
143
+ """Get original (untransformed) data matrix."""
144
+ return _dfm_instance.original_data
145
+
146
+ # For direct attribute access, we'll use __getattr__ but handle config module conflict
147
+
148
+ def __getattr__(name):
149
+ """Allow access to DFM instance properties at module level."""
150
+ # Handle special cases that conflict with submodules
151
+ if name == 'config' and _dfm_instance.config is not None:
152
+ return _dfm_instance.config
153
+ elif name == 'data':
154
+ return _dfm_instance.data
155
+ elif name == 'time':
156
+ return _dfm_instance.time
157
+ elif name == 'result':
158
+ return _dfm_instance.result
159
+ elif name == 'original_data':
160
+ return _dfm_instance.original_data
161
+ # For other attributes, try normal import
162
+ raise AttributeError(f"module '{__name__}' has no attribute '{name}'")
47
163
 
48
164
  __all__ = [
49
- 'DFMConfig',
50
- # Backward compatibility
51
- 'ModelConfig', # Alias for DFMConfig
52
- 'load_config', 'load_config_from_yaml', 'load_config_from_csv',
53
- 'load_data', 'transform_data',
54
- 'DFMResult', 'dfm', 'calculate_rmse', 'diagnose_series', 'print_series_diagnosis',
165
+ # Core classes
166
+ 'DFMConfig', 'SeriesConfig', 'BlockConfig', 'Params', 'DFM',
167
+ # Constants
168
+ 'DEFAULT_GLOBAL_BLOCK_NAME',
169
+ # Config sources
170
+ 'ConfigSource', 'YamlSource', 'DictSource', 'SpecCSVSource', 'HydraSource',
171
+ 'MergedConfigSource', 'make_config_source',
172
+ # High-level API (module-level - recommended)
173
+ 'load_config',
174
+ 'load_data', 'train', 'predict', 'plot', 'reset',
175
+ 'get_config', 'get_data', 'get_time', 'get_result', 'get_original_data',
176
+ # Convenience constructors (cleaner API)
177
+ 'from_yaml', 'from_spec', 'from_spec_df', 'from_dict',
178
+ # Low-level API (functional interface - advanced usage)
179
+ 'transform_data',
180
+ 'DFMResult', 'calculate_rmse', 'diagnose_series', 'print_series_diagnosis',
55
181
  'run_kf', 'skf', 'fis', 'miss_data',
56
182
  'update_nowcast', 'news_dfm', 'para_const',
57
- # Deprecated aliases
58
- 'ModelSpec', 'load_spec',
59
183
  ]
60
184