Marcos0807 commited on
Commit
cf689f0
·
verified ·
1 Parent(s): 48f5b9c

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +52 -104
app.py CHANGED
@@ -10,6 +10,8 @@ import matplotlib.pyplot as plt
10
  import seaborn as sns
11
 
12
 
 
 
13
  alphacast = Alphacast("ak_rjVLScLXFCHwimxt5Qew")
14
  dataset = alphacast.datasets.dataset(5664)
15
  df = dataset.download_data(format = "pandas", startDate=None, endDate=None, filterVariables = [], filterEntities = {})
@@ -28,31 +30,31 @@ subdatasets = {}
28
  rbc_data = {}
29
 
30
  for pais in paises:
31
- # Filtrar los datos por país
32
  df_pais = data[data['country'] == pais]
33
  df_pais = df_pais.rename(columns = {"Date":"DATE"})
 
34
 
35
- # Establecer la columna "Date" como índice
36
  df_pais.set_index('DATE', inplace=True)
 
37
 
38
- # Filtrar para que la data empiece desde 1991
39
  df_pais = df_pais[df_pais.index >= '1990-01-01']
 
40
 
41
- # Cálculo en términos per cápita (C, L, I, N)
42
- N = df_pais['N'] # Población
43
- C = df_pais['C'] / N # Consumo per cápita
44
- I = df_pais['I'] / N # Inversión per cápita
45
- L = df_pais['L'] # Horas trabajadas (asumiendo que ya es per cápita o representa la fuerza laboral)
46
 
47
- # Calcular el ingreso (output) como la suma de Consumo e Inversión
48
- Y = C + I # Ingreso per cápita
49
 
50
- # Logaritmo natural y diferencia temporal (detrending)
51
- y = np.log(Y).diff()[1:] # Producto
52
- c = np.log(C).diff()[1:] # Consumo
53
- n = np.log(L).diff()[1:] # Horas trabajadas
54
 
55
- # Concatenar los resultados en un DataFrame con el índice "Date"
56
  rbc_data[pais] = pd.concat((y, n, c), axis=1)
57
  rbc_data[pais].columns = ['output', 'labor', 'consumption']
58
 
@@ -72,58 +74,52 @@ subdatasets_2 = {}
72
  rbc_data_2 = {}
73
 
74
  for pais in paises:
75
- # Filtrar los datos por país
76
  df_pais = data_2[data_2['country'] == pais]
77
  df_pais = df_pais.rename(columns = {"Date":"DATE"})
 
78
 
79
- # Establecer la columna "Date" como índice
80
  df_pais.set_index('DATE', inplace=True)
 
81
 
82
- # Filtrar para que la data empiece desde 1991
83
  df_pais = df_pais[df_pais.index >= '1990-01-01']
 
84
 
85
- # Cálculo en términos per cápita (C, L, I, N)
86
- N = df_pais['N'] # Población
87
  Y = df_pais["Y"] / N
88
- C = df_pais['C'] / N # Consumo per cápita
89
- I = df_pais['I'] / N # Inversión per cápita
90
- L = df_pais['L'] # Horas trabajadas (asumiendo que ya es per cápita o representa la fuerza laboral)
91
-
92
-
93
-
94
- # Logaritmo natural y diferencia temporal (detrending)
95
- y = np.log(Y).diff()[1:] # Producto
96
- c = np.log(C).diff()[1:] # Consumo
97
- n = np.log(L).diff()[1:] # Horas trabajadas
98
-
99
- # Concatenar los resultados en un DataFrame con el índice "Date"
100
  rbc_data_2[pais] = pd.concat((y, n, c), axis=1)
101
  rbc_data_2[pais].columns = ['output', 'labor', 'consumption']
102
 
103
 
104
  def generar_grafico_pais(pais):
105
- # Filtrar los datos del país
106
  df_pais = rbc_data[pais]
107
 
108
- # Crear el gráfico interactivo
109
  fig = go.Figure()
110
 
111
- # Añadir las tres series: output (y), labor (n), consumption (c)
112
- fig.add_trace(go.Scatter(x=df_pais.index, y=df_pais['output'],
113
  mode='lines+markers', name='Output (y)', marker=dict(symbol='circle')))
114
- fig.add_trace(go.Scatter(x=df_pais.index, y=df_pais['labor'],
115
  mode='lines+markers', name='Labor (n)', marker=dict(symbol='x')))
116
- fig.add_trace(go.Scatter(x=df_pais.index, y=df_pais['consumption'],
117
  mode='lines+markers', name='Consumption (c)', marker=dict(symbol='square')))
118
 
119
- # Personalizar el layout (título, etiquetas, etc.)
120
  fig.update_layout(title=f'Producción, Trabajo, y Consumo para {pais} (1991 - 2019)',
121
  xaxis_title='Fecha',
122
  yaxis_title='Log Differences',
123
  legend_title='Variables',
124
  template='plotly_dark')
125
 
126
- # Mostrar el gráfico
127
  fig.show()
128
 
129
 
@@ -143,7 +139,6 @@ class SimpleRBC(sm.tsa.statespace.MLEModel):
143
  endog, k_states=2, k_posdef=1, initialization='stationary')
144
  self.k_predetermined = 1
145
 
146
- # Save the calibrated vs. estimated parameters
147
  parameters = list(self.parameters.keys())
148
  calibrated = calibrated or {}
149
  self.calibrated = OrderedDict([
@@ -162,7 +157,6 @@ class SimpleRBC(sm.tsa.statespace.MLEModel):
162
  self.idx_tech_pers = parameters.index('technology_shock_persistence')
163
  self.idx_tech_var = parameters.index('technology_shock_var')
164
 
165
- # Setup fixed elements of system matrices
166
  self['selection', 1, 0] = 1
167
 
168
  @property
@@ -178,17 +172,14 @@ class SimpleRBC(sm.tsa.statespace.MLEModel):
178
  return structural_params.tolist() + measurement_variances
179
 
180
  def log_linearize(self, params):
181
- # Extract the parameters
182
  (discount_rate, disutility_labor, depreciation_rate, capital_share,
183
  technology_shock_persistence, technology_shock_var) = params
184
 
185
- # Temporary values
186
  tmp = (1. / discount_rate - (1. - depreciation_rate))
187
  theta = (capital_share / tmp)**(1. / (1. - capital_share))
188
  gamma = 1. - depreciation_rate * theta**(1. - capital_share)
189
  zeta = capital_share * discount_rate * theta**(capital_share - 1)
190
 
191
- # Coefficient matrices from linearization
192
  A = np.eye(2)
193
 
194
  B11 = 1 + depreciation_rate * (gamma / (1 - gamma))
@@ -210,19 +201,15 @@ class SimpleRBC(sm.tsa.statespace.MLEModel):
210
  capital_share = params[self.idx_cap_share]
211
  technology_shock_persistence = params[self.idx_tech_pers]
212
 
213
- # Get the coefficient matrices from linearization
214
  A, B, C = self.log_linearize(params)
215
 
216
- # Jordan decomposition of B
217
  eigvals, right_eigvecs = np.linalg.eig(np.transpose(B))
218
  left_eigvecs = np.transpose(right_eigvecs)
219
 
220
- # Re-order, ascending
221
  idx = np.argsort(eigvals)
222
  eigvals = np.diag(eigvals[idx])
223
  left_eigvecs = left_eigvecs[idx, :]
224
 
225
- # Blanchard-Kahn conditions
226
  k_nonpredetermined = self.k_states - self.k_predetermined
227
  k_stable = len(np.where(eigvals.diagonal() < 1)[0])
228
  k_unstable = self.k_states - k_stable
@@ -230,7 +217,6 @@ class SimpleRBC(sm.tsa.statespace.MLEModel):
230
  raise RuntimeError('Blanchard-Kahn condition not met.'
231
  ' Unique solution does not exist.')
232
 
233
- # Create partition indices
234
  k = self.k_predetermined
235
  p1 = np.s_[:k]
236
  p2 = np.s_[k:]
@@ -240,16 +226,11 @@ class SimpleRBC(sm.tsa.statespace.MLEModel):
240
  p21 = np.s_[k:, :k]
241
  p22 = np.s_[k:, k:]
242
 
243
- # Decouple the system
244
  decoupled_C = np.dot(left_eigvecs, C)
245
 
246
- # Solve the explosive component (controls) in terms of the
247
- # non-explosive component (states) and shocks
248
  tmp = np.linalg.inv(left_eigvecs[p22])
249
 
250
- # This is \phi_{ck}, above
251
  policy_state = - np.dot(tmp, left_eigvecs[p21]).squeeze()
252
- # This is \phi_{cz}, above
253
  policy_shock = -(
254
  np.dot(tmp, 1. / eigvals[p22]).dot(
255
  np.linalg.inv(
@@ -259,20 +240,15 @@ class SimpleRBC(sm.tsa.statespace.MLEModel):
259
  ).dot(decoupled_C[p2])
260
  ).squeeze()
261
 
262
- # Solve for the non-explosive transition
263
- # This is T_{kk}, above
264
  transition_state = np.squeeze(B[p11] + np.dot(B[p12], policy_state))
265
- # This is T_{kz}, above
266
  transition_shock = np.squeeze(np.dot(B[p12], policy_shock) + C[p1])
267
 
268
- # Create the full design matrix
269
  tmp = (1 - capital_share) / capital_share
270
  tmp1 = 1. / capital_share
271
  design = np.array([[1 - tmp * policy_state, tmp1 - tmp * policy_shock],
272
  [1 - tmp1 * policy_state, tmp1 * (1-policy_shock)],
273
  [policy_state, policy_shock]])
274
 
275
- # Create the transition matrix
276
  transition = (
277
  np.array([[transition_state, transition_shock],
278
  [0, technology_shock_persistence]]))
@@ -280,38 +256,32 @@ class SimpleRBC(sm.tsa.statespace.MLEModel):
280
  return design, transition
281
 
282
  def transform_discount_rate(self, param, untransform=False):
283
- # Discount rate must be between 0 and 1
284
- epsilon = 1e-4 # bound it slightly away from exactly 0 or 1
285
  if not untransform:
286
  return np.abs(1 / (1 + np.exp(param)) - epsilon)
287
  else:
288
  return np.log((1 - param + epsilon) / (param + epsilon))
289
 
290
  def transform_disutility_labor(self, param, untransform=False):
291
- # Disutility of labor must be positive
292
  return param**2 if not untransform else param**0.5
293
 
294
  def transform_depreciation_rate(self, param, untransform=False):
295
- # Depreciation rate must be positive
296
  return param**2 if not untransform else param**0.5
297
 
298
  def transform_capital_share(self, param, untransform=False):
299
- # Capital share must be between 0 and 1
300
- epsilon = 1e-4 # bound it slightly away from exactly 0 or 1
301
  if not untransform:
302
  return np.abs(1 / (1 + np.exp(param)) - epsilon)
303
  else:
304
  return np.log((1 - param + epsilon) / (param + epsilon))
305
 
306
  def transform_technology_shock_persistence(self, param, untransform=False):
307
- # Persistence parameter must be between -1 and 1
308
  if not untransform:
309
  return param / (1 + np.abs(param))
310
  else:
311
  return param / (1 - param)
312
 
313
  def transform_technology_shock_var(self, unconstrained, untransform=False):
314
- # Variances must be positive
315
  return unconstrained**2 if not untransform else unconstrained**0.5
316
 
317
  def transform_params(self, unconstrained):
@@ -324,7 +294,6 @@ class SimpleRBC(sm.tsa.statespace.MLEModel):
324
  constrained[i] = method(unconstrained[i])
325
  i += 1
326
 
327
- # Measurement error variances must be positive
328
  constrained[self.k_estimated:] = unconstrained[self.k_estimated:]**2
329
 
330
  return constrained
@@ -339,7 +308,6 @@ class SimpleRBC(sm.tsa.statespace.MLEModel):
339
  unconstrained[i] = method(constrained[i], untransform=True)
340
  i += 1
341
 
342
- # Measurement error variances must be positive
343
  unconstrained[self.k_estimated:] = constrained[self.k_estimated:]**0.5
344
 
345
  return unconstrained
@@ -347,17 +315,13 @@ class SimpleRBC(sm.tsa.statespace.MLEModel):
347
  def update(self, params, **kwargs):
348
  params = super(SimpleRBC, self).update(params, **kwargs)
349
 
350
- # Reconstruct the full parameter vector from the
351
- # estimated and calibrated parameters
352
  structural_params = np.zeros(self.k_params, dtype=params.dtype)
353
  structural_params[self.idx_calibrated] = list(self.calibrated.values())
354
  structural_params[self.idx_estimated] = params[:self.k_estimated]
355
  measurement_variances = params[self.k_estimated:]
356
 
357
- # Solve the model
358
  design, transition = self.solve(structural_params)
359
 
360
- # Update the statespace representation
361
  self['design'] = design
362
  self['obs_cov', 0, 0] = measurement_variances[0]
363
  self['obs_cov', 1, 1] = measurement_variances[1]
@@ -384,9 +348,9 @@ def plot_irfs_plotly(irfs):
384
  fig.add_trace(go.Scatter(x=list(range(len(irfs['consumption']))), y=irfs['consumption'], mode='lines+markers', name='Consumption'))
385
 
386
  fig.update_layout(
387
- title="Impulse Responses (RBC Model)",
388
- xaxis_title="Quarters after impulse",
389
- yaxis_title="Impulse response (%)",
390
  legend_title="Variables",
391
  template = "plotly_dark"
392
  )
@@ -396,7 +360,6 @@ def plot_irfs_plotly(irfs):
396
  def plot_states_plotly(res, rbc_data):
397
  fig = go.Figure()
398
 
399
- # Capital plot with confidence interval
400
  capital = res.smoothed_state[0, :]
401
  shock = res.smoothed_state[1, :]
402
 
@@ -415,39 +378,32 @@ def plot_states_plotly(res, rbc_data):
415
  return fig
416
 
417
  def plot_rbc_model(pais, persistence, shock_variance, discount_rate, disutility_labor, capital_share, depreciation_rate):
418
- # Crear el diccionario de parámetros calibrados con los valores ingresados
419
  calibrated = {
420
  'discount_rate': discount_rate,
421
  'disutility_labor': disutility_labor,
422
  'capital_share': capital_share,
423
  'depreciation_rate': depreciation_rate,
424
  'technology_shock_persistence': persistence,
425
- 'technology_shock_var': shock_variance ** 2 # El usuario ingresa la desviación estándar
426
  }
427
 
428
- # Calibrar el modelo
429
  calibrated_mod = SimpleRBC(rbc_data[pais], calibrated=calibrated)
430
  calibrated_res = calibrated_mod.fit(method='nm', maxiter=1000, disp=0)
431
 
432
- # Obtener las respuestas ante choques
433
  calibrated_irfs_pos = calibrated_res.impulse_responses(40, orthogonalized=True) * 100
434
- calibrated_irfs_neg = -calibrated_irfs_pos # Efecto negativo
435
 
436
- # Graficar los IRF para el choque positivo
437
  fig_pos = plot_irfs_plotly(pd.DataFrame(calibrated_irfs_pos, columns=['output', 'labor', 'consumption']))
438
 
439
- # Graficar los IRF para el choque negativo
440
  fig_neg = plot_irfs_plotly(pd.DataFrame(calibrated_irfs_neg, columns=['output', 'labor', 'consumption']))
441
 
442
- # Output estadístico del modelo como un DataFrame
443
  summary_df = calibrated_res.summary().tables[1].data
444
- summary_df = pd.DataFrame(summary_df[1:], columns=summary_df[0]) # Crear DataFrame de la tabla resumen
445
 
446
- estimated_coefficients = summary_df['coef'].astype(float) # Convertir a float
447
- # Usar el índice en lugar de la columna 'Variable'
448
- estimated_var_output = estimated_coefficients[summary_df.index[0]]
449
- estimated_var_labor = estimated_coefficients[summary_df.index[1]]
450
- estimated_var_consumption = estimated_coefficients[summary_df.index[2]]
451
 
452
 
453
 
@@ -455,18 +411,16 @@ def plot_rbc_model(pais, persistence, shock_variance, discount_rate, disutility_
455
  var_consumption = np.var(rbc_data_2[pais]["consumption"])
456
  var_labor = np.var(rbc_data_2[pais]["labor"])
457
 
458
- # Crear un DataFrame con los resultados de la varianza
459
  var_data = pd.DataFrame({
460
  'Variable': ['Output Real', 'Consumption', 'Labor'],
461
  'Varianza Real': [var_output, var_consumption, var_labor],
462
  'Varianza Estimada': [estimated_var_output, estimated_var_consumption, estimated_var_labor],
463
  'Diferencia': [abs(var_output - estimated_var_output), abs(var_consumption - estimated_var_consumption), abs(var_labor - estimated_var_labor)]
464
  })
465
-
466
 
467
  return fig_pos, fig_neg, summary_df, var_data
468
 
469
- # Interfaz de Gradio
470
  with gr.Blocks() as demo:
471
  with gr.Row():
472
  gr.Markdown("### Real Business Cycle (RBC) Model Dashboard")
@@ -498,12 +452,10 @@ with gr.Blocks() as demo:
498
  """)
499
 
500
  with gr.Tab("Gráfico del País"):
501
- pais_selec_grafico = gr.Dropdown(choices=["Argentina", "Brazil", "Chile", "Uruguay", "Colombia"], label="Selecciona un país")
502
  grafico_pais = gr.Plot(label="Producción, Trabajo y Consumo")
503
-
504
- # Generar gráfico al cambiar la selección
505
- pais_selec_grafico.change(fn=generar_grafico_pais, inputs=pais_selec_grafico, outputs=grafico_pais)
506
- # Parámetros calibrados: casillas para ingresar valores
507
  with gr.Tab("Calibración del Modelo"):
508
  pais_selec = gr.Dropdown(choices=["Argentina", "Brazil", "Chile", "Uruguay", "Colombia"], label="Selecciona un país")
509
  persistence = gr.Slider(label="Persistencia del choque tecnológico", minimum=0.5, maximum=1.0, value=0.85)
@@ -513,10 +465,8 @@ with gr.Blocks() as demo:
513
  capital_share = gr.Number(label="Participación del capital (α)", value=0.36)
514
  depreciation_rate = gr.Number(label="Tasa de depreciación", value=0.025)
515
 
516
- # Botón para actualizar los gráficos
517
  btn = gr.Button("Actualizar Modelo")
518
 
519
- # Gráficos de las respuestas ante choques
520
  output_pos = gr.Plot(label="Respuesta ante un Choque Tecnológico Positivo")
521
  output_neg = gr.Plot(label="Respuesta ante un Choque Tecnológico Negativo")
522
 
@@ -524,10 +474,8 @@ with gr.Blocks() as demo:
524
  output_stats = gr.DataFrame(label="Output estadístico del modelo", type="pandas")
525
  output_var = gr.DataFrame(label="Varianzas reales", type = "pandas")
526
 
527
- # Funcionalidad del botón
528
  btn.click(fn=plot_rbc_model,
529
  inputs=[pais_selec,persistence, shock_variance, discount_rate, disutility_labor, capital_share, depreciation_rate],
530
  outputs=[output_pos, output_neg, output_stats,output_var])
531
 
532
- # Ejecutar la aplicación
533
  demo.launch()
 
10
  import seaborn as sns
11
 
12
 
13
+
14
+
15
  alphacast = Alphacast("ak_rjVLScLXFCHwimxt5Qew")
16
  dataset = alphacast.datasets.dataset(5664)
17
  df = dataset.download_data(format = "pandas", startDate=None, endDate=None, filterVariables = [], filterEntities = {})
 
30
  rbc_data = {}
31
 
32
  for pais in paises:
33
+
34
  df_pais = data[data['country'] == pais]
35
  df_pais = df_pais.rename(columns = {"Date":"DATE"})
36
+
37
 
 
38
  df_pais.set_index('DATE', inplace=True)
39
+
40
 
 
41
  df_pais = df_pais[df_pais.index >= '1990-01-01']
42
+
43
 
44
+ N = df_pais['N']
45
+ C = df_pais['C'] / N
46
+ I = df_pais['I'] / N
47
+ L = df_pais['L']
48
+
49
 
50
+ Y = C + I
51
+
52
 
53
+ y = np.log(Y).diff()[1:]
54
+ c = np.log(C).diff()[1:]
55
+ n = np.log(L).diff()[1:]
56
+
57
 
 
58
  rbc_data[pais] = pd.concat((y, n, c), axis=1)
59
  rbc_data[pais].columns = ['output', 'labor', 'consumption']
60
 
 
74
  rbc_data_2 = {}
75
 
76
  for pais in paises:
77
+
78
  df_pais = data_2[data_2['country'] == pais]
79
  df_pais = df_pais.rename(columns = {"Date":"DATE"})
80
+
81
 
 
82
  df_pais.set_index('DATE', inplace=True)
83
+
84
 
 
85
  df_pais = df_pais[df_pais.index >= '1990-01-01']
86
+
87
 
88
+ N = df_pais['N']
 
89
  Y = df_pais["Y"] / N
90
+ C = df_pais['C'] / N
91
+ I = df_pais['I'] / N
92
+ L = df_pais['L']
93
+
94
+
95
+
96
+ y = np.log(Y).diff()[1:]
97
+ c = np.log(C).diff()[1:]
98
+ n = np.log(L).diff()[1:]
99
+
 
 
100
  rbc_data_2[pais] = pd.concat((y, n, c), axis=1)
101
  rbc_data_2[pais].columns = ['output', 'labor', 'consumption']
102
 
103
 
104
  def generar_grafico_pais(pais):
105
+
106
  df_pais = rbc_data[pais]
107
 
 
108
  fig = go.Figure()
109
 
110
+ fig.add_trace(go.Scatter(x=df_pais.index, y=df_pais['output'],
 
111
  mode='lines+markers', name='Output (y)', marker=dict(symbol='circle')))
112
+ fig.add_trace(go.Scatter(x=df_pais.index, y=df_pais['labor'],
113
  mode='lines+markers', name='Labor (n)', marker=dict(symbol='x')))
114
+ fig.add_trace(go.Scatter(x=df_pais.index, y=df_pais['consumption'],
115
  mode='lines+markers', name='Consumption (c)', marker=dict(symbol='square')))
116
 
 
117
  fig.update_layout(title=f'Producción, Trabajo, y Consumo para {pais} (1991 - 2019)',
118
  xaxis_title='Fecha',
119
  yaxis_title='Log Differences',
120
  legend_title='Variables',
121
  template='plotly_dark')
122
 
 
123
  fig.show()
124
 
125
 
 
139
  endog, k_states=2, k_posdef=1, initialization='stationary')
140
  self.k_predetermined = 1
141
 
 
142
  parameters = list(self.parameters.keys())
143
  calibrated = calibrated or {}
144
  self.calibrated = OrderedDict([
 
157
  self.idx_tech_pers = parameters.index('technology_shock_persistence')
158
  self.idx_tech_var = parameters.index('technology_shock_var')
159
 
 
160
  self['selection', 1, 0] = 1
161
 
162
  @property
 
172
  return structural_params.tolist() + measurement_variances
173
 
174
  def log_linearize(self, params):
 
175
  (discount_rate, disutility_labor, depreciation_rate, capital_share,
176
  technology_shock_persistence, technology_shock_var) = params
177
 
 
178
  tmp = (1. / discount_rate - (1. - depreciation_rate))
179
  theta = (capital_share / tmp)**(1. / (1. - capital_share))
180
  gamma = 1. - depreciation_rate * theta**(1. - capital_share)
181
  zeta = capital_share * discount_rate * theta**(capital_share - 1)
182
 
 
183
  A = np.eye(2)
184
 
185
  B11 = 1 + depreciation_rate * (gamma / (1 - gamma))
 
201
  capital_share = params[self.idx_cap_share]
202
  technology_shock_persistence = params[self.idx_tech_pers]
203
 
 
204
  A, B, C = self.log_linearize(params)
205
 
 
206
  eigvals, right_eigvecs = np.linalg.eig(np.transpose(B))
207
  left_eigvecs = np.transpose(right_eigvecs)
208
 
 
209
  idx = np.argsort(eigvals)
210
  eigvals = np.diag(eigvals[idx])
211
  left_eigvecs = left_eigvecs[idx, :]
212
 
 
213
  k_nonpredetermined = self.k_states - self.k_predetermined
214
  k_stable = len(np.where(eigvals.diagonal() < 1)[0])
215
  k_unstable = self.k_states - k_stable
 
217
  raise RuntimeError('Blanchard-Kahn condition not met.'
218
  ' Unique solution does not exist.')
219
 
 
220
  k = self.k_predetermined
221
  p1 = np.s_[:k]
222
  p2 = np.s_[k:]
 
226
  p21 = np.s_[k:, :k]
227
  p22 = np.s_[k:, k:]
228
 
 
229
  decoupled_C = np.dot(left_eigvecs, C)
230
 
 
 
231
  tmp = np.linalg.inv(left_eigvecs[p22])
232
 
 
233
  policy_state = - np.dot(tmp, left_eigvecs[p21]).squeeze()
 
234
  policy_shock = -(
235
  np.dot(tmp, 1. / eigvals[p22]).dot(
236
  np.linalg.inv(
 
240
  ).dot(decoupled_C[p2])
241
  ).squeeze()
242
 
 
 
243
  transition_state = np.squeeze(B[p11] + np.dot(B[p12], policy_state))
 
244
  transition_shock = np.squeeze(np.dot(B[p12], policy_shock) + C[p1])
245
 
 
246
  tmp = (1 - capital_share) / capital_share
247
  tmp1 = 1. / capital_share
248
  design = np.array([[1 - tmp * policy_state, tmp1 - tmp * policy_shock],
249
  [1 - tmp1 * policy_state, tmp1 * (1-policy_shock)],
250
  [policy_state, policy_shock]])
251
 
 
252
  transition = (
253
  np.array([[transition_state, transition_shock],
254
  [0, technology_shock_persistence]]))
 
256
  return design, transition
257
 
258
  def transform_discount_rate(self, param, untransform=False):
259
+ epsilon = 1e-4
 
260
  if not untransform:
261
  return np.abs(1 / (1 + np.exp(param)) - epsilon)
262
  else:
263
  return np.log((1 - param + epsilon) / (param + epsilon))
264
 
265
  def transform_disutility_labor(self, param, untransform=False):
 
266
  return param**2 if not untransform else param**0.5
267
 
268
  def transform_depreciation_rate(self, param, untransform=False):
 
269
  return param**2 if not untransform else param**0.5
270
 
271
  def transform_capital_share(self, param, untransform=False):
272
+ epsilon = 1e-4
 
273
  if not untransform:
274
  return np.abs(1 / (1 + np.exp(param)) - epsilon)
275
  else:
276
  return np.log((1 - param + epsilon) / (param + epsilon))
277
 
278
  def transform_technology_shock_persistence(self, param, untransform=False):
 
279
  if not untransform:
280
  return param / (1 + np.abs(param))
281
  else:
282
  return param / (1 - param)
283
 
284
  def transform_technology_shock_var(self, unconstrained, untransform=False):
 
285
  return unconstrained**2 if not untransform else unconstrained**0.5
286
 
287
  def transform_params(self, unconstrained):
 
294
  constrained[i] = method(unconstrained[i])
295
  i += 1
296
 
 
297
  constrained[self.k_estimated:] = unconstrained[self.k_estimated:]**2
298
 
299
  return constrained
 
308
  unconstrained[i] = method(constrained[i], untransform=True)
309
  i += 1
310
 
 
311
  unconstrained[self.k_estimated:] = constrained[self.k_estimated:]**0.5
312
 
313
  return unconstrained
 
315
  def update(self, params, **kwargs):
316
  params = super(SimpleRBC, self).update(params, **kwargs)
317
 
 
 
318
  structural_params = np.zeros(self.k_params, dtype=params.dtype)
319
  structural_params[self.idx_calibrated] = list(self.calibrated.values())
320
  structural_params[self.idx_estimated] = params[:self.k_estimated]
321
  measurement_variances = params[self.k_estimated:]
322
 
 
323
  design, transition = self.solve(structural_params)
324
 
 
325
  self['design'] = design
326
  self['obs_cov', 0, 0] = measurement_variances[0]
327
  self['obs_cov', 1, 1] = measurement_variances[1]
 
348
  fig.add_trace(go.Scatter(x=list(range(len(irfs['consumption']))), y=irfs['consumption'], mode='lines+markers', name='Consumption'))
349
 
350
  fig.update_layout(
351
+ title="Función Impulso Respuesta",
352
+ xaxis_title="Años después del shcok",
353
+ yaxis_title="Impulso respuesta (%)",
354
  legend_title="Variables",
355
  template = "plotly_dark"
356
  )
 
360
  def plot_states_plotly(res, rbc_data):
361
  fig = go.Figure()
362
 
 
363
  capital = res.smoothed_state[0, :]
364
  shock = res.smoothed_state[1, :]
365
 
 
378
  return fig
379
 
380
  def plot_rbc_model(pais, persistence, shock_variance, discount_rate, disutility_labor, capital_share, depreciation_rate):
 
381
  calibrated = {
382
  'discount_rate': discount_rate,
383
  'disutility_labor': disutility_labor,
384
  'capital_share': capital_share,
385
  'depreciation_rate': depreciation_rate,
386
  'technology_shock_persistence': persistence,
387
+ 'technology_shock_var': shock_variance ** 2
388
  }
389
 
 
390
  calibrated_mod = SimpleRBC(rbc_data[pais], calibrated=calibrated)
391
  calibrated_res = calibrated_mod.fit(method='nm', maxiter=1000, disp=0)
392
 
 
393
  calibrated_irfs_pos = calibrated_res.impulse_responses(40, orthogonalized=True) * 100
394
+ calibrated_irfs_neg = -calibrated_irfs_pos
395
 
 
396
  fig_pos = plot_irfs_plotly(pd.DataFrame(calibrated_irfs_pos, columns=['output', 'labor', 'consumption']))
397
 
 
398
  fig_neg = plot_irfs_plotly(pd.DataFrame(calibrated_irfs_neg, columns=['output', 'labor', 'consumption']))
399
 
 
400
  summary_df = calibrated_res.summary().tables[1].data
401
+ summary_df = pd.DataFrame(summary_df[1:], columns=summary_df[0])
402
 
403
+ estimated_coefficients = summary_df['coef'].astype(float)
404
+ estimated_var_output = estimated_coefficients[summary_df.index[0]]
405
+ estimated_var_labor = estimated_coefficients[summary_df.index[1]]
406
+ estimated_var_consumption = estimated_coefficients[summary_df.index[2]]
 
407
 
408
 
409
 
 
411
  var_consumption = np.var(rbc_data_2[pais]["consumption"])
412
  var_labor = np.var(rbc_data_2[pais]["labor"])
413
 
 
414
  var_data = pd.DataFrame({
415
  'Variable': ['Output Real', 'Consumption', 'Labor'],
416
  'Varianza Real': [var_output, var_consumption, var_labor],
417
  'Varianza Estimada': [estimated_var_output, estimated_var_consumption, estimated_var_labor],
418
  'Diferencia': [abs(var_output - estimated_var_output), abs(var_consumption - estimated_var_consumption), abs(var_labor - estimated_var_labor)]
419
  })
420
+
421
 
422
  return fig_pos, fig_neg, summary_df, var_data
423
 
 
424
  with gr.Blocks() as demo:
425
  with gr.Row():
426
  gr.Markdown("### Real Business Cycle (RBC) Model Dashboard")
 
452
  """)
453
 
454
  with gr.Tab("Gráfico del País"):
455
+ pais = gr.Dropdown(choices=["Argentina", "Brazil", "Chile", "Uruguay", "Colombia"], label="Selecciona un país")
456
  grafico_pais = gr.Plot(label="Producción, Trabajo y Consumo")
457
+
458
+ pais.change(generar_grafico_pais,pais,grafico_pais)
 
 
459
  with gr.Tab("Calibración del Modelo"):
460
  pais_selec = gr.Dropdown(choices=["Argentina", "Brazil", "Chile", "Uruguay", "Colombia"], label="Selecciona un país")
461
  persistence = gr.Slider(label="Persistencia del choque tecnológico", minimum=0.5, maximum=1.0, value=0.85)
 
465
  capital_share = gr.Number(label="Participación del capital (α)", value=0.36)
466
  depreciation_rate = gr.Number(label="Tasa de depreciación", value=0.025)
467
 
 
468
  btn = gr.Button("Actualizar Modelo")
469
 
 
470
  output_pos = gr.Plot(label="Respuesta ante un Choque Tecnológico Positivo")
471
  output_neg = gr.Plot(label="Respuesta ante un Choque Tecnológico Negativo")
472
 
 
474
  output_stats = gr.DataFrame(label="Output estadístico del modelo", type="pandas")
475
  output_var = gr.DataFrame(label="Varianzas reales", type = "pandas")
476
 
 
477
  btn.click(fn=plot_rbc_model,
478
  inputs=[pais_selec,persistence, shock_variance, discount_rate, disutility_labor, capital_share, depreciation_rate],
479
  outputs=[output_pos, output_neg, output_stats,output_var])
480
 
 
481
  demo.launch()