Skip to content

Commit 0c18941

Browse files
committed
docs: update scenario_analysis_via_shock example with productivity and consumption shocks
1 parent e60ffd5 commit 0c18941

File tree

1 file changed

+67
-41
lines changed

1 file changed

+67
-41
lines changed

examples/scenario_analysis_via_shock.jl

+67-41
Original file line numberDiff line numberDiff line change
@@ -6,68 +6,94 @@
66

77
import BeforeIT as Bit
88

9-
using Plots, StatsPlots
9+
using Plots, StatsBase
1010

1111
parameters = Bit.AUSTRIA2010Q1.parameters
1212
initial_conditions = Bit.AUSTRIA2010Q1.initial_conditions
1313

1414
# Initialise the model and the data collector
15-
T = 20
15+
16+
T = 16
1617
model = Bit.init_model(parameters, initial_conditions, T);
1718

18-
# Simulate the model for T quarters
19-
data_vec_baseline = Bit.ensemblerun(model, 4)
19+
# Simulate the baseline model for T quarters, N_reps times, and collect the data
20+
21+
N_reps = 64
22+
data_vec_baseline = Bit.ensemblerun(model, N_reps)
2023

2124
# Now, apply a shock to the model and simulate it again.
2225
# A shock is simply a function that takes the model and changes some of
2326
# its parameters for a specific time period.
27+
# We do this by first defining a "struct" with useful attributes.
28+
# For example, we can define an productivity and a consumption shock with the following structs
29+
30+
struct ProductivityShock
31+
productivity_multiplier::Float64 # productivity multiplier
32+
end
33+
34+
struct ConsumptionShock
35+
consumption_multiplier::Float64 # productivity multiplier
36+
final_time::Int
37+
end
38+
39+
# and then by making the structs callable functions that change the parameters of the model,
40+
# this is done in Julia using the syntax below
2441

25-
# In this case, let's define an interest rate shock that sets the interest
26-
# rate for a number of epochs.
42+
# A permanent change in the labour productivities by the factor s.productivity_multiplier
2743

28-
# We do this by first defining a "struct" with some useful attributes
29-
struct CustomShock
30-
rate::Float64 # target rate for the first 10 epochs
31-
final_time::Int # number of epochs for the shock
44+
function (s::ProductivityShock)(model::Bit.Model)
45+
model.firms.alpha_bar_i .= model.firms.alpha_bar_i .* s.productivity_multiplier
3246
end
3347

34-
# and then by making the struct a callable function that changes the interest
35-
# rate in the model, this is done in Julia using the syntax below
36-
function (s::CustomShock)(model::Bit.Model)
37-
if model.agg.t <= s.final_time
38-
model.cb.r_bar = s.rate
48+
# A temporary change in the propensity to consume model.prop.psi by the factor s.consumption_multiplier
49+
50+
function (s::ConsumptionShock)(model::Bit.Model)
51+
if model.agg.t == 1
52+
model.prop.psi = model.prop.psi * s.consumption_multiplier
53+
elseif model.agg.t == s.final_time
54+
model.prop.psi = model.prop.psi / s.consumption_multiplier
3955
end
4056
end
4157

42-
# Now we define a specific shock with a rate of 0.01 for the first 10 epochs,
43-
# and run a shocked simulation
58+
# Define specific shocks, for example a 2% increase in productivity
4459

45-
custom_shock = CustomShock(0.0, 10)
46-
data_vec_shocked = Bit.ensemblerun(model, 4; shock = custom_shock)
60+
productivity_shock = ProductivityShock(1.02)
4761

48-
# Finally, we can plot baseline and shocked simulations
62+
# or a 4 quarters long 2% increase in consumption
4963

50-
Te = T + 1
51-
StatsPlots.errorline(
52-
1:Te,
53-
data_vec_baseline.real_gdp,
54-
errortype = :sem,
55-
label = "baseline",
56-
titlefont = 10,
57-
xlabel = "quarters",
58-
ylabel = "GDP",
59-
)
60-
StatsPlots.errorline!(
61-
1:Te,
62-
data_vec_shocked.real_gdp,
63-
errortype = :sem,
64-
label = "shock",
65-
titlefont = 10,
64+
consumption_shock = ConsumptionShock(1.02, 4)
65+
66+
# Simulate the model with the shock
67+
68+
data_vec_shocked = Bit.ensemblerun(model, N_reps; shock = consumption_shock)
69+
70+
# Compute mean and standard error of GDP for the baseline and shocked simulations
71+
72+
mean_gdp_baseline = mean(data_vec_baseline.real_gdp, dims = 2)
73+
mean_gdp_shocked = mean(data_vec_shocked.real_gdp, dims = 2)
74+
sem_gdp_baseline = std(data_vec_baseline.real_gdp, dims = 2) / sqrt(N_reps)
75+
sem_gdp_shocked = std(data_vec_shocked.real_gdp, dims = 2) / sqrt(N_reps)
76+
77+
# Compute the ratio of shocked to baseline GDP
78+
79+
gdp_ratio = mean_gdp_shocked ./ mean_gdp_baseline
80+
81+
# the standard error on a ratio of two variables is computed with the error propagation formula
82+
83+
sem_gdp_ratio = gdp_ratio .* ((sem_gdp_baseline ./ mean_gdp_baseline).^2 .+ (sem_gdp_shocked ./ mean_gdp_shocked).^2).^0.5
84+
85+
# Finally, we can plot the impulse response curve
86+
87+
plot(
88+
1:T+1,
89+
gdp_ratio,
90+
ribbon = sem_gdp_ratio,
91+
fillalpha = 0.2,
92+
label = "",
6693
xlabel = "quarters",
67-
ylabel = "GDP",
94+
ylabel = "GDP change",
95+
size = (350, 220),
96+
dpi = 300,
6897
)
6998

70-
# Note that, importantly, once the function `central_bank_rate` has been changed,
71-
# the model will use the new interest rate in all the simulations, unless the function
72-
# is changed again. To restore the original interest rate, we can simply re-import the
73-
# function `central_bank_rate`.
99+
# We can save the figure using: savefig("gdp_shock.png")

0 commit comments

Comments
 (0)