macroshock 0.1.2__tar.gz → 0.2.2__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 (25) hide show
  1. macroshock-0.2.2/PKG-INFO +206 -0
  2. macroshock-0.2.2/README.md +169 -0
  3. {macroshock-0.1.2 → macroshock-0.2.2}/pyproject.toml +4 -1
  4. {macroshock-0.1.2 → macroshock-0.2.2}/src/macroshock/bootstrap.py +33 -16
  5. {macroshock-0.1.2 → macroshock-0.2.2}/src/macroshock/data.py +3 -3
  6. {macroshock-0.1.2 → macroshock-0.2.2}/src/macroshock/fc.py +1 -1
  7. macroshock-0.2.2/src/macroshock/fevd.py +63 -0
  8. macroshock-0.2.2/src/macroshock/identification.py +531 -0
  9. {macroshock-0.1.2 → macroshock-0.2.2}/src/macroshock/irf.py +5 -5
  10. {macroshock-0.1.2 → macroshock-0.2.2}/src/macroshock/macroshock.py +207 -297
  11. {macroshock-0.1.2 → macroshock-0.2.2}/src/macroshock/plotting.py +61 -39
  12. {macroshock-0.1.2 → macroshock-0.2.2}/src/macroshock/var.py +5 -6
  13. macroshock-0.2.2/src/macroshock.egg-info/PKG-INFO +206 -0
  14. {macroshock-0.1.2 → macroshock-0.2.2}/src/macroshock.egg-info/SOURCES.txt +1 -0
  15. macroshock-0.1.2/PKG-INFO +0 -216
  16. macroshock-0.1.2/README.md +0 -180
  17. macroshock-0.1.2/src/macroshock/identification.py +0 -315
  18. macroshock-0.1.2/src/macroshock.egg-info/PKG-INFO +0 -216
  19. {macroshock-0.1.2 → macroshock-0.2.2}/LICENSE +0 -0
  20. {macroshock-0.1.2 → macroshock-0.2.2}/setup.cfg +0 -0
  21. {macroshock-0.1.2 → macroshock-0.2.2}/src/macroshock/__init__.py +0 -0
  22. {macroshock-0.1.2 → macroshock-0.2.2}/src/macroshock/stats.py +0 -0
  23. {macroshock-0.1.2 → macroshock-0.2.2}/src/macroshock.egg-info/dependency_links.txt +0 -0
  24. {macroshock-0.1.2 → macroshock-0.2.2}/src/macroshock.egg-info/requires.txt +0 -0
  25. {macroshock-0.1.2 → macroshock-0.2.2}/src/macroshock.egg-info/top_level.txt +0 -0
@@ -0,0 +1,206 @@
1
+ Metadata-Version: 2.4
2
+ Name: macroshock
3
+ Version: 0.2.2
4
+ Summary: Powerful time series econometrics for Structural Vector Autoregressions (SVAR)
5
+ Author-email: Patricio Arias <patoariaslopez2@gmail.com>
6
+ License: MIT License
7
+
8
+ Copyright (c) 2026 Patricio
9
+
10
+ Permission is hereby granted, free of charge, to any person obtaining a copy
11
+ of this software and associated documentation files (the "Software"), to deal
12
+ in the Software without restriction, including without limitation the rights
13
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14
+ copies of the Software, and to permit persons to whom the Software is
15
+ furnished to do so, subject to the following conditions:
16
+
17
+ The above copyright notice and this permission notice shall be included in all
18
+ copies or substantial portions of the Software.
19
+
20
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26
+ SOFTWARE.
27
+
28
+ Project-URL: GitHub repository, https://github.com/patricioariaslpz/macroshock.git
29
+ Requires-Python: >=3.10
30
+ Description-Content-Type: text/markdown
31
+ License-File: LICENSE
32
+ Requires-Dist: numpy>=1.24.0
33
+ Requires-Dist: pandas>=2.0.0
34
+ Requires-Dist: scipy>=1.10.0
35
+ Requires-Dist: matplotlib>=3.7.0
36
+ Dynamic: license-file
37
+
38
+ # macroshock
39
+
40
+ **macroshock** is a Python library for the estimation and analysis of **SVAR** (Structural Vector Autoregression) models aimed at applied macroeconometrics. It allows you to estimate restricted VARs, identify the structural system using four different methodologies, compute impulse-response functions (IRF), forecast error variance decomposition (FEVD), and forecasts, all with bootstrap confidence intervals and ready-to-use plotting.
41
+
42
+ ## Main Features
43
+
44
+ * - **Restricted VAR estimation** (Lütkepohl-style GLS), with support for:
45
+
46
+ - Constant, trend and quadratic trend.
47
+ - Exogenous variables.
48
+ - Seasonal dummies (quarterly or monthly).
49
+ - Linear restrictions on the coefficients (`restrictions='zeros'` or `'custom zeros'`).
50
+ * - **Four structural identification methods**:
51
+
52
+ |Method|Description|
53
+ |-|-|
54
+ |`short`|Short-run restrictions (Cholesky or custom restrictions via optimization)|
55
+ |`long`|Long-run restrictions (Cholesky or custom restrictions via optimization)|
56
+ |`signs`|Sign restrictions (orthogonal rotation sampling with acceptance/rejection)|
57
+ |`IV`|Instrumental variable identification (proxy-SVAR)|
58
+
59
+ * - **Impulse-response functions (IRF)** with confidence bands.
60
+ * - **Forecast error variance decomposition (FEVD)**.
61
+ * - **Conditional forecasts** with confidence bands.
62
+ * - **Bootstrap** (normal or *wild* resampling) for inference.
63
+ * - **Built-in plots** for IRF, forecasts and FEVD, publication-ready.
64
+ * - **Stability test** of the system (characteristic polynomial roots).
65
+
66
+ ## Installation
67
+
68
+ ```bash
69
+ pip install macroshock
70
+ ```
71
+
72
+ ### Requirements
73
+
74
+ * Python >= 3.9
75
+ * `numpy >= 1.24.0`
76
+ * `pandas >= 2.0.0`
77
+ * `scipy`
78
+ * `matplotlib >= 3.7.0`
79
+
80
+ ## Quick Start
81
+
82
+ ```python
83
+ import pandas as pd
84
+ from macroshock import SVAR
85
+
86
+ # df is a DataFrame with your series in columns
87
+ df = pd.read\_csv("my\_dataset.csv")
88
+
89
+ model = SVAR(
90
+ data=df,
91
+ variables=\["gdp", "inflation", "interest\_rate"],
92
+ lags=4,
93
+ const=1, # 0: no constant, 1: constant, 2: +trend, 3: +quadratic trend
94
+ method="short", # 'short', 'long', 'signs' or 'IV'
95
+ steps=24, # horizon for IRF/FEVD
96
+ horizon=8, # forecast horizon
97
+ past=12, # past periods to show in the forecast
98
+ alpha=32, # confidence interval level (32 -> 68% central band)
99
+ reps=1000, # bootstrap replications
100
+ )
101
+
102
+ # Runs the complete pipeline: Y/X construction, VAR estimation,
103
+ # structural identification and results summary
104
+ model.run(showIR=True, showFC=True, showVD=True)
105
+
106
+ # System stability check
107
+ model.stability(show=True)
108
+ ```
109
+
110
+ ### Step-by-step Usage
111
+
112
+ ```python
113
+ model.YX() # builds Y, X and the restriction matrix R
114
+ model.VAR() # estimates the reduced-form VAR and the companion matrix F
115
+ model.S() # identifies the structural system (matrix B)
116
+ model.summary() # prints the estimation summary
117
+
118
+ # Impulse response to shock 1, with "pair" bands (low/high percentile)
119
+ ir = model.ImpulseResponse(1, show=True, bands="pair")
120
+
121
+ # Forecast with "many" bands (multiple stacked confidence levels)
122
+ fc = model.Forecast(show=True, bands="many")
123
+
124
+ # Forecast error variance decomposition for variable 1
125
+ vd = model.VarianceDecomp(1, show=True)
126
+ ```
127
+
128
+ Each of these methods returns a dictionary with the point estimate and confidence bands at different levels (`'point'`, `'low'`, `'high'`, `2.5`, `5`, `95`, `97.5`, `0.5`, `99.5`), indexed by variable name.
129
+
130
+ ## Structural Identification
131
+
132
+ ### 1\. Short-run (Cholesky / custom restrictions)
133
+
134
+ ```python
135
+ model = SVAR(data=df, variables=variables, lags=4, method="short")
136
+ ```
137
+
138
+ By default it uses the Cholesky decomposition. If `matrix\_short` is passed (a binary matrix of 1s and 0s), the `B` matrix satisfying the indicated zero restrictions is solved numerically.
139
+
140
+ ### 2\. Long-run (Blanchard-Quah)
141
+
142
+ ```python
143
+ model = SVAR(data=df, variables=variables, lags=4, method="long")
144
+ ```
145
+
146
+ By default it uses the Cholesky decomposition. If `matrix\_long` is passed (a binary matrix of 1s and 0s), the `B` matrix satisfying the indicated zero restrictions is solved numerically.
147
+
148
+ ### 3\. Sign restrictions
149
+
150
+ ```python
151
+ matrix\_signs = \[\[1, -1, 0],
152
+ \[1, 1, 0],
153
+ \[0, 0, 1]]
154
+
155
+ model = SVAR(
156
+ data=df, variables=variables, lags=4,
157
+ method="signs",
158
+ matrix\_signs=matrix\_signs,
159
+ steps\_signs=4, # horizons over which signs are checked
160
+ reps=1000, # number of accepted B matrices
161
+ )
162
+ ```
163
+
164
+ ### 4\. Instrumental variables (Proxy-SVAR)
165
+
166
+ ```python
167
+ model = SVAR(
168
+ data=df, variables=variables, lags=4,
169
+ method="IV",
170
+ iv=\["instrument\_1"], # DataFrame column(s) with the instrument(s)
171
+ )
172
+ ```
173
+
174
+ ## Package Structure
175
+
176
+
177
+ ```
178
+ macroshock/
179
+ ├── data.py # construction of Y, X and restriction matrix R
180
+ ├── var.py # reduced-form VAR estimation (restricted GLS, IC, t-stats)
181
+ ├── stats.py # statistical utilities (Student's t CDF and p-values)
182
+ ├── identification.py # the 4 structural identification methods
183
+ ├── irf.py # impulse-response functions and bands from bootstrap
184
+ ├── fevd.py # forecast error variance decomposition
185
+ ├── fc.py # forecast computation
186
+ ├── bootstrap.py # bootstrap (normal / wild) for IR, FC and FEVD
187
+ ├── plotting.py # IRF, forecast and FEVD plots
188
+ └── macroshock.py # main SVAR class (and SVEC, LP scaffolds for future development)
189
+ ```
190
+
191
+ ## Roadmap
192
+
193
+ * Full documentation (Sphinx / ReadTheDocs)
194
+ * SVEC model (structural Vector Error Correction)
195
+ * Local Projections (LP)
196
+ * Historical decomposition (`HistoricalDecomp`)
197
+ * Unit tests and CI
198
+
199
+ ## Contributing
200
+
201
+ Issues and pull requests are welcome. If you find a bug or have an improvement proposal, open an issue in the project's repository.
202
+
203
+ ## License
204
+
205
+ This project is distributed under the MIT license. See the `LICENSE` file for more details.
206
+
@@ -0,0 +1,169 @@
1
+ # macroshock
2
+
3
+ **macroshock** is a Python library for the estimation and analysis of **SVAR** (Structural Vector Autoregression) models aimed at applied macroeconometrics. It allows you to estimate restricted VARs, identify the structural system using four different methodologies, compute impulse-response functions (IRF), forecast error variance decomposition (FEVD), and forecasts, all with bootstrap confidence intervals and ready-to-use plotting.
4
+
5
+ ## Main Features
6
+
7
+ * - **Restricted VAR estimation** (Lütkepohl-style GLS), with support for:
8
+
9
+ - Constant, trend and quadratic trend.
10
+ - Exogenous variables.
11
+ - Seasonal dummies (quarterly or monthly).
12
+ - Linear restrictions on the coefficients (`restrictions='zeros'` or `'custom zeros'`).
13
+ * - **Four structural identification methods**:
14
+
15
+ |Method|Description|
16
+ |-|-|
17
+ |`short`|Short-run restrictions (Cholesky or custom restrictions via optimization)|
18
+ |`long`|Long-run restrictions (Cholesky or custom restrictions via optimization)|
19
+ |`signs`|Sign restrictions (orthogonal rotation sampling with acceptance/rejection)|
20
+ |`IV`|Instrumental variable identification (proxy-SVAR)|
21
+
22
+ * - **Impulse-response functions (IRF)** with confidence bands.
23
+ * - **Forecast error variance decomposition (FEVD)**.
24
+ * - **Conditional forecasts** with confidence bands.
25
+ * - **Bootstrap** (normal or *wild* resampling) for inference.
26
+ * - **Built-in plots** for IRF, forecasts and FEVD, publication-ready.
27
+ * - **Stability test** of the system (characteristic polynomial roots).
28
+
29
+ ## Installation
30
+
31
+ ```bash
32
+ pip install macroshock
33
+ ```
34
+
35
+ ### Requirements
36
+
37
+ * Python >= 3.9
38
+ * `numpy >= 1.24.0`
39
+ * `pandas >= 2.0.0`
40
+ * `scipy`
41
+ * `matplotlib >= 3.7.0`
42
+
43
+ ## Quick Start
44
+
45
+ ```python
46
+ import pandas as pd
47
+ from macroshock import SVAR
48
+
49
+ # df is a DataFrame with your series in columns
50
+ df = pd.read\_csv("my\_dataset.csv")
51
+
52
+ model = SVAR(
53
+ data=df,
54
+ variables=\["gdp", "inflation", "interest\_rate"],
55
+ lags=4,
56
+ const=1, # 0: no constant, 1: constant, 2: +trend, 3: +quadratic trend
57
+ method="short", # 'short', 'long', 'signs' or 'IV'
58
+ steps=24, # horizon for IRF/FEVD
59
+ horizon=8, # forecast horizon
60
+ past=12, # past periods to show in the forecast
61
+ alpha=32, # confidence interval level (32 -> 68% central band)
62
+ reps=1000, # bootstrap replications
63
+ )
64
+
65
+ # Runs the complete pipeline: Y/X construction, VAR estimation,
66
+ # structural identification and results summary
67
+ model.run(showIR=True, showFC=True, showVD=True)
68
+
69
+ # System stability check
70
+ model.stability(show=True)
71
+ ```
72
+
73
+ ### Step-by-step Usage
74
+
75
+ ```python
76
+ model.YX() # builds Y, X and the restriction matrix R
77
+ model.VAR() # estimates the reduced-form VAR and the companion matrix F
78
+ model.S() # identifies the structural system (matrix B)
79
+ model.summary() # prints the estimation summary
80
+
81
+ # Impulse response to shock 1, with "pair" bands (low/high percentile)
82
+ ir = model.ImpulseResponse(1, show=True, bands="pair")
83
+
84
+ # Forecast with "many" bands (multiple stacked confidence levels)
85
+ fc = model.Forecast(show=True, bands="many")
86
+
87
+ # Forecast error variance decomposition for variable 1
88
+ vd = model.VarianceDecomp(1, show=True)
89
+ ```
90
+
91
+ Each of these methods returns a dictionary with the point estimate and confidence bands at different levels (`'point'`, `'low'`, `'high'`, `2.5`, `5`, `95`, `97.5`, `0.5`, `99.5`), indexed by variable name.
92
+
93
+ ## Structural Identification
94
+
95
+ ### 1\. Short-run (Cholesky / custom restrictions)
96
+
97
+ ```python
98
+ model = SVAR(data=df, variables=variables, lags=4, method="short")
99
+ ```
100
+
101
+ By default it uses the Cholesky decomposition. If `matrix\_short` is passed (a binary matrix of 1s and 0s), the `B` matrix satisfying the indicated zero restrictions is solved numerically.
102
+
103
+ ### 2\. Long-run (Blanchard-Quah)
104
+
105
+ ```python
106
+ model = SVAR(data=df, variables=variables, lags=4, method="long")
107
+ ```
108
+
109
+ By default it uses the Cholesky decomposition. If `matrix\_long` is passed (a binary matrix of 1s and 0s), the `B` matrix satisfying the indicated zero restrictions is solved numerically.
110
+
111
+ ### 3\. Sign restrictions
112
+
113
+ ```python
114
+ matrix\_signs = \[\[1, -1, 0],
115
+ \[1, 1, 0],
116
+ \[0, 0, 1]]
117
+
118
+ model = SVAR(
119
+ data=df, variables=variables, lags=4,
120
+ method="signs",
121
+ matrix\_signs=matrix\_signs,
122
+ steps\_signs=4, # horizons over which signs are checked
123
+ reps=1000, # number of accepted B matrices
124
+ )
125
+ ```
126
+
127
+ ### 4\. Instrumental variables (Proxy-SVAR)
128
+
129
+ ```python
130
+ model = SVAR(
131
+ data=df, variables=variables, lags=4,
132
+ method="IV",
133
+ iv=\["instrument\_1"], # DataFrame column(s) with the instrument(s)
134
+ )
135
+ ```
136
+
137
+ ## Package Structure
138
+
139
+
140
+ ```
141
+ macroshock/
142
+ ├── data.py # construction of Y, X and restriction matrix R
143
+ ├── var.py # reduced-form VAR estimation (restricted GLS, IC, t-stats)
144
+ ├── stats.py # statistical utilities (Student's t CDF and p-values)
145
+ ├── identification.py # the 4 structural identification methods
146
+ ├── irf.py # impulse-response functions and bands from bootstrap
147
+ ├── fevd.py # forecast error variance decomposition
148
+ ├── fc.py # forecast computation
149
+ ├── bootstrap.py # bootstrap (normal / wild) for IR, FC and FEVD
150
+ ├── plotting.py # IRF, forecast and FEVD plots
151
+ └── macroshock.py # main SVAR class (and SVEC, LP scaffolds for future development)
152
+ ```
153
+
154
+ ## Roadmap
155
+
156
+ * Full documentation (Sphinx / ReadTheDocs)
157
+ * SVEC model (structural Vector Error Correction)
158
+ * Local Projections (LP)
159
+ * Historical decomposition (`HistoricalDecomp`)
160
+ * Unit tests and CI
161
+
162
+ ## Contributing
163
+
164
+ Issues and pull requests are welcome. If you find a bug or have an improvement proposal, open an issue in the project's repository.
165
+
166
+ ## License
167
+
168
+ This project is distributed under the MIT license. See the `LICENSE` file for more details.
169
+
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "macroshock"
7
- version = "0.1.2"
7
+ version = "0.2.2"
8
8
  requires-python = ">=3.10"
9
9
  dependencies = [
10
10
  "numpy>=1.24.0",
@@ -18,3 +18,6 @@ authors = [
18
18
  description = "Powerful time series econometrics for Structural Vector Autoregressions (SVAR)"
19
19
  readme = {file = "README.md", content-type = "text/markdown"}
20
20
  license = { file = "LICENSE"}
21
+
22
+ [project.urls]
23
+ "GitHub repository" = "https://github.com/patricioariaslpz/macroshock.git"
@@ -5,10 +5,12 @@ import numpy as np
5
5
  import pandas as pd
6
6
  from scipy.linalg import solve_triangular
7
7
  from .var import estimate_var
8
+ from .irf import impulse_response
8
9
  from .fc import compute_forecast
10
+ from .fevd import forecast_error_variance_decomposition
9
11
 
10
12
 
11
- def bootstrap_svar(model, typ: str, shock: int = 1):
13
+ def bootstrap_svar(model, typ: str, shock: int = 1, reps: int = 100, impact: float = 1.0, steps: int = 30, horizon: int = 5, past: int = 24):
12
14
  """
13
15
  Replica la lógica original de SVAR.Bootstrap, pero fuera de la clase.
14
16
 
@@ -28,25 +30,28 @@ def bootstrap_svar(model, typ: str, shock: int = 1):
28
30
  - IR: (reps, steps)
29
31
  - FC: (reps, past + horizon)
30
32
  """
33
+ if model.method == 'signs':
34
+ raise ValueError("No bootstrap in sign restriction SVAR")
35
+
36
+
31
37
  # BEGIN BOOTSTRAP
32
38
  b = 0
33
39
 
34
40
  if typ == "IR":
35
- draws = {var: np.zeros((model.reps, model.steps)) for var in model.variables}
41
+ draws = {var: np.zeros((reps, steps)) for var in model.variables}
36
42
  elif typ == "FC":
37
- draws = {
38
- var: np.zeros((model.reps, model.past + model.horizon))
39
- for var in model.variables
40
- }
43
+ draws = {var: np.zeros((reps, past + horizon)) for var in model.variables}
44
+ elif typ == "VD":
45
+ draws = {var: np.zeros((reps, steps)) for var in model.variables}
41
46
  else:
42
- raise ValueError("typ must be 'IR' or 'FC'.")
47
+ raise ValueError("typ must be 'IR', 'FC' or 'VD'.")
43
48
 
44
49
  while True:
45
50
  # progreso
46
51
  if b in list(
47
- range(int(model.reps / 10) - 1, model.reps, int(model.reps / 10))
52
+ range(int(reps / 10) - 1, reps, int(reps / 10))
48
53
  ):
49
- print(str(b + 1) + "/" + str(model.reps))
54
+ print(str(b + 1) + "/" + str(reps))
50
55
 
51
56
  # ---------- tipo de remuestreo ----------
52
57
  if model.resampling == 1: # normal
@@ -152,11 +157,11 @@ def bootstrap_svar(model, typ: str, shock: int = 1):
152
157
  [np.ones((model.n_obs, 1)), trend, trend**2, Xsim]
153
158
  )
154
159
 
155
- if model.EXOGdata is not None:
156
- if len(model.EXOG) == model.n_obs:
157
- Xsim_exog = model.EXOGdata
160
+ if model.data_exogenous is not None:
161
+ if len(model.variables_exogenous) == model.n_obs:
162
+ Xsim_exog = model.data_exogenous
158
163
  else:
159
- Xsim_exog = model.EXOGdata[-model.n_obs :]
164
+ Xsim_exog = model.data_exogenous[-model.n_obs :]
160
165
  if len(Xsim_exog) != model.n_obs:
161
166
  print("Exogenous variables in different domain")
162
167
  Xsim = np.hstack([Xsim, Xsim_exog])
@@ -237,8 +242,8 @@ def bootstrap_svar(model, typ: str, shock: int = 1):
237
242
 
238
243
  # ---------- almacenar draws ----------
239
244
  if typ == "IR":
240
- ir_b = model.IR(Bsim, Fsim, shock)
241
-
245
+ ir_b = impulse_response(Bsim, Fsim, shock, steps=steps, impact=impact)
246
+
242
247
  if np.any(Bsim != 0):
243
248
  if model.method in ("short", "long", "IV"):
244
249
  for k in range(model.n_vars):
@@ -252,8 +257,20 @@ def bootstrap_svar(model, typ: str, shock: int = 1):
252
257
  for k in range(model.n_vars):
253
258
  draws[model.variables[k]][b, :] = fc_b[:, k]
254
259
  b += 1
260
+
261
+ if typ == "VD":
262
+ vd_dict = forecast_error_variance_decomposition(
263
+ Bsim, Fsim, steps=steps
264
+ )
265
+ if np.any(Bsim != 0):
266
+ if model.method in ("short", "long", "IV"):
267
+ for k in range(model.n_vars):
268
+ # vd_dict[k + 1] gets the (steps, n_vars) FEVD matrix for variable k+1.
269
+ # [:, shock - 1] isolates the proportion of variance explained by 'shock'.
270
+ draws[model.variables[k]][b, :] = vd_dict[k + 1][:, shock - 1]
271
+ b += 1
255
272
 
256
- if b >= model.reps:
273
+ if b >= reps:
257
274
  break
258
275
 
259
276
  return draws
@@ -32,11 +32,11 @@ def YX(model) -> YXR:
32
32
 
33
33
  model.n_obs, _ = X.shape
34
34
 
35
- if model.EXOGdata is not None:
35
+ if model.data_exogenous is not None:
36
36
  if model.n_obsex==model.n_obs:
37
- X_exog=model.EXOGdata
37
+ X_exog=model.data_exogenous
38
38
  else:
39
- X_exog=model.EXOGdata[-model.n_obs:]
39
+ X_exog=model.data_exogenous[-model.n_obs:]
40
40
  if len(X_exog)!=model.n_obs:
41
41
  print('Exogenous variables in different domain')
42
42
  X=np.hstack([X,X_exog])
@@ -38,7 +38,7 @@ def compute_forecast(modelo, F):
38
38
  if modelo.const == 1:
39
39
  FYs += beta_const
40
40
  elif modelo.const == 2:
41
- FYs += beta_const + ((i + modelo.lags) * beta_trend)
41
+ FYs += beta_const + (i * beta_trend)
42
42
  elif modelo.const == 3:
43
43
  FYs += beta_const + (i * beta_trend) + ((i**2) * beta_sqrd)
44
44
 
@@ -0,0 +1,63 @@
1
+ # fevd.py
2
+ from __future__ import annotations
3
+
4
+ import numpy as np
5
+
6
+
7
+ def forecast_error_variance_decomposition(
8
+ B: np.ndarray,
9
+ F: np.ndarray,
10
+ steps: int = 10,
11
+ ) -> dict[int, np.ndarray]:
12
+ """Compute Forecast Error Variance Decomposition (FEVD) for a given structural matrix B
13
+
14
+ and companion matrix F.
15
+
16
+ Parameters
17
+ ----------
18
+ B : np.ndarray
19
+ Impact matrix of shape (n_vars, n_vars).
20
+ F : np.ndarray
21
+ Companion matrix of shape (n_vars * lags, n_vars * lags).
22
+ steps : int, optional
23
+ Forecast horizon steps (default is 10).
24
+
25
+ Returns
26
+ -------
27
+ dict[int, np.ndarray]
28
+ Dictionary keyed by 1-based variable index (1, 2, ..., n_vars).
29
+ Each value is an array of shape (steps, n_vars) containing the share
30
+ of variance contributed by each shock j to variable i over horizon h.
31
+ """
32
+ B = np.asarray(B, dtype=float)
33
+ F = np.asarray(F, dtype=float)
34
+
35
+ n_vars = B.shape[0]
36
+
37
+ # 1. Pre-calculate Orthogonalized Impulse Responses for all horizons.
38
+ # Accumulate F^h incrementally (F^h = F^(h-1) @ F) instead of calling
39
+ # np.linalg.matrix_power(F, h) from scratch at every horizon.
40
+ theta = np.zeros((steps, n_vars, n_vars))
41
+ F_power = np.eye(F.shape[0]) # F^0
42
+ for h in range(steps):
43
+ Psi_h = F_power[:n_vars, :n_vars]
44
+ theta[h] = Psi_h @ B
45
+ F_power = F_power @ F # advance to F^(h+1) for the next iteration
46
+
47
+ # 2. Calculate Variance Decomposition per variable
48
+ VD = {}
49
+ for i in range(n_vars):
50
+ vardec = np.zeros((steps, n_vars))
51
+ for k in range(steps):
52
+ # Squared responses of variable i to all shocks j up to step k
53
+ squared_responses = theta[: k + 1, i, :] ** 2
54
+ mse_ij = np.sum(squared_responses, axis=0)
55
+
56
+ total_mse_i = np.sum(mse_ij)
57
+ if total_mse_i > 0:
58
+ vardec[k, :] = mse_ij / total_mse_i
59
+
60
+ # Store using 1-based variable index
61
+ VD[i + 1] = vardec
62
+
63
+ return VD