Marcos0807 commited on
Commit
0b8ecb9
·
verified ·
1 Parent(s): 1d611f1

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +533 -0
app.py ADDED
@@ -0,0 +1,533 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import numpy as np
2
+ import pandas as pd
3
+ import statsmodels.api as sm
4
+ from collections import OrderedDict
5
+ import datetime
6
+ from alphacast import Alphacast
7
+ import gradio as gr
8
+ import plotly.graph_objects as go
9
+ 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 = {})
16
+ data = df[["country","Date","Real Consumption at constant 2017 national prices (In mil. 2017US$)",
17
+ "Average annual hours worked by persons engaged",
18
+ "Capital Stock at constant 2017 national prices (In mil. 2017US$)",
19
+ "Population (In millions)"]]
20
+ data = data.rename(columns={
21
+ "Real Consumption at constant 2017 national prices (In mil. 2017US$)": "C",
22
+ "Average annual hours worked by persons engaged": "L",
23
+ "Capital Stock at constant 2017 national prices (In mil. 2017US$)": "I",
24
+ "Population (In millions)": "N"
25
+ })
26
+ paises = ["Argentina", "Brazil", "Chile", "Uruguay", "Colombia"]
27
+ 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
+
59
+ data_2 = df[["country","Date","Real GDP at constant 2017 national prices (In mil. 2017US$)","Real Consumption at constant 2017 national prices (In mil. 2017US$)",
60
+ "Average annual hours worked by persons engaged",
61
+ "Capital Stock at constant 2017 national prices (In mil. 2017US$)",
62
+ "Population (In millions)"]]
63
+ data_2= data_2.rename(columns={"Real GDP at constant 2017 national prices (In mil. 2017US$)":"Y",
64
+ "Real Consumption at constant 2017 national prices (In mil. 2017US$)": "C",
65
+ "Average annual hours worked by persons engaged": "L",
66
+ "Capital Stock at constant 2017 national prices (In mil. 2017US$)": "I",
67
+ "Population (In millions)": "N"
68
+ })
69
+
70
+
71
+ 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
+
130
+ class SimpleRBC(sm.tsa.statespace.MLEModel):
131
+
132
+ parameters = OrderedDict([
133
+ ('discount_rate', 0.95),
134
+ ('disutility_labor', 3.),
135
+ ('depreciation_rate', 0.025),
136
+ ('capital_share', 0.36),
137
+ ('technology_shock_persistence', 0.85),
138
+ ('technology_shock_var', 0.04**2)
139
+ ])
140
+
141
+ def __init__(self, endog, calibrated=None):
142
+ super(SimpleRBC, self).__init__(
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([
150
+ (param, calibrated[param]) for param in parameters
151
+ if param in calibrated
152
+ ])
153
+ self.idx_calibrated = np.array([
154
+ param in self.calibrated for param in parameters])
155
+ self.idx_estimated = ~self.idx_calibrated
156
+
157
+ self.k_params = len(self.parameters)
158
+ self.k_calibrated = len(self.calibrated)
159
+ self.k_estimated = self.k_params - self.k_calibrated
160
+
161
+ self.idx_cap_share = parameters.index('capital_share')
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
169
+ def start_params(self):
170
+ structural_params = np.array(list(self.parameters.values()))[self.idx_estimated]
171
+ measurement_variances = [0.1] * 3
172
+ return np.r_[structural_params, measurement_variances]
173
+
174
+ @property
175
+ def param_names(self):
176
+ structural_params = np.array(list(self.parameters.keys()))[self.idx_estimated]
177
+ measurement_variances = ['%s.var' % name for name in self.endog_names]
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))
195
+ B12 = (-depreciation_rate *
196
+ (1 - capital_share + gamma * capital_share) /
197
+ (capital_share * (1 - gamma)))
198
+ B21 = 0
199
+ B22 = capital_share / (zeta + capital_share*(1 - zeta))
200
+ B = np.array([[B11, B12], [B21, B22]])
201
+
202
+ C1 = depreciation_rate / (capital_share * (1 - gamma))
203
+ C2 = (zeta * technology_shock_persistence /
204
+ (zeta + capital_share*(1 - zeta)))
205
+ C = np.array([[C1], [C2]])
206
+
207
+ return A, B, C
208
+
209
+ def solve(self, params):
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
229
+ if not k_stable == self.k_predetermined:
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:]
237
+
238
+ p11 = np.s_[:k, :k]
239
+ p12 = np.s_[:k, k:]
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(
256
+ np.eye(k_nonpredetermined) -
257
+ technology_shock_persistence / eigvals[p22]
258
+ )
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]]))
279
+
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):
318
+ constrained = np.zeros(unconstrained.shape, unconstrained.dtype)
319
+
320
+ i = 0
321
+ for param in self.parameters.keys():
322
+ if param not in self.calibrated:
323
+ method = getattr(self, 'transform_%s' % param)
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
331
+
332
+ def untransform_params(self, constrained):
333
+ unconstrained = np.zeros(constrained.shape, constrained.dtype)
334
+
335
+ i = 0
336
+ for param in self.parameters.keys():
337
+ if param not in self.calibrated:
338
+ method = getattr(self, 'transform_%s' % param)
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
346
+
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]
364
+ self['obs_cov', 2, 2] = measurement_variances[2]
365
+ self['transition'] = transition
366
+ self['state_cov', 0, 0] = structural_params[self.idx_tech_var]
367
+
368
+ calibrated = {
369
+ 'discount_rate': 0.95,
370
+ 'disutility_labor': 3.0,
371
+ 'capital_share': 0.36,
372
+ 'depreciation_rate': 0.025,
373
+ 'technology_shock_persistence': 0.85,
374
+ 'technology_shock_var': 0.012**2
375
+ }
376
+
377
+
378
+
379
+ def plot_irfs_plotly(irfs):
380
+ fig = go.Figure()
381
+
382
+ fig.add_trace(go.Scatter(x=list(range(len(irfs['output']))), y=irfs['output'], mode='lines+markers', name='Output'))
383
+ fig.add_trace(go.Scatter(x=list(range(len(irfs['labor']))), y=irfs['labor'], mode='lines+markers', name='Labor'))
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
+ )
393
+
394
+ return fig
395
+
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
+
403
+ fig.add_trace(go.Scatter(x=rbc_data.index, y=capital, mode='lines', name='Capital'))
404
+ fig.add_trace(go.Scatter(x=rbc_data.index, y=shock, mode='lines', name='Technology process'))
405
+
406
+ fig.update_layout(
407
+ title="State Variables over Time",
408
+ xaxis_title="Time",
409
+ yaxis_title="Value",
410
+ legend_title="Variables",
411
+ template = "plotly_dark"
412
+ )
413
+
414
+
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
+
454
+ var_output = np.var(rbc_data_2[pais]["output"])
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")
473
+
474
+ with gr.Tab("Ecuaciones del Modelo"):
475
+ gr.Markdown(r"""
476
+ ### Ecuaciones del Modelo RBC
477
+
478
+ - **FOC estática**:
479
+ $$ \psi c_t = (1 - \alpha) z_t \left( \frac{k_t}{n_t} \right)^{\alpha} $$
480
+
481
+ - **Ecuación de Euler**:
482
+ $$ \frac{1}{c_t} = \beta E_t \left\{ \frac{1}{c_{t+1}} \left[ \alpha z_{t+1} \left( \frac{k_{t+1}}{n_{t+1}} \right)^{\alpha-1} + (1 - \delta) \right] \right\} $$
483
+
484
+ - **Función de producción**:
485
+ $$ y_t = z_t k_t^{\alpha} n_t^{1 - \alpha} $$
486
+
487
+ - **Restricción de recursos agregados**:
488
+ $$ y_t = c_t + i_t $$
489
+
490
+ - **Acumulación de capital**:
491
+ $$ k_{t+1} = (1 - \delta)k_t + i_t $$
492
+
493
+ - **Comercio entre trabajo y ocio**:
494
+ $$ 1 = l_t + n_t $$
495
+
496
+ - **Transición del choque tecnológico**:
497
+ $$ \log z_t = \rho \log z_{t-1} + \varepsilon_t $$
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)
510
+ shock_variance = gr.Slider(label="Desviación estándar del choque tecnológico", minimum=0.01, maximum=0.05, value=0.012)
511
+ discount_rate = gr.Number(label="Tasa de descuento (β)", value=0.95)
512
+ disutility_labor = gr.Number(label="Desutilidad del trabajo", value=3.0)
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
+
523
+ with gr.Tab("Estadísticas del Modelo"):
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()