Skip to content

Commit 46c366d

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

File tree

1 file changed

+54
-41
lines changed

1 file changed

+54
-41
lines changed

examples/scenario_analysis_via_shock.jl

+54-41
Original file line numberDiff line numberDiff line change
@@ -6,68 +6,81 @@
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+
T = 16
1616
model = Bit.init_model(parameters, initial_conditions, T);
1717

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

2122
# Now, apply a shock to the model and simulate it again.
2223
# A shock is simply a function that takes the model and changes some of
2324
# its parameters for a specific time period.
2425

25-
# In this case, let's define an interest rate shock that sets the interest
26-
# rate for a number of epochs.
26+
# We do this by first defining a "struct" with useful attributes.
27+
# For example, we can define an productivity and a consumption shock with the following structs
28+
struct ProductivityShock
29+
productivity_multiplier::Float64 # productivity multiplier
30+
end
31+
struct ConsumptionShock
32+
consumption_multiplier::Float64 # productivity multiplier
33+
final_time::Int
34+
end
2735

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
36+
# and then by making the structs callable functions that change the parameters of the model,
37+
# this is done in Julia using the syntax below
38+
39+
# A permanent change in the labour productivities by the factor s.productivity_multiplier
40+
function (s::ProductivityShock)(model::Bit.Model)
41+
model.firms.alpha_bar_i .= model.firms.alpha_bar_i .* s.productivity_multiplier
3242
end
3343

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
44+
# A temporary change in the propensity to consume model.prop.psi by the factor s.consumption_multiplier
45+
function (s::ConsumptionShock)(model::Bit.Model)
46+
if model.agg.t == 1
47+
model.prop.psi = model.prop.psi * s.consumption_multiplier
48+
elseif model.agg.t == s.final_time
49+
model.prop.psi = model.prop.psi / s.consumption_multiplier
3950
end
4051
end
4152

42-
# Now we define a specific shock with a rate of 0.01 for the first 10 epochs,
43-
# and run a shocked simulation
53+
# Define specific shocks, for example a 2% increase in productivity
54+
productivity_shock = ProductivityShock(1.02)
55+
# or a 4 quarters long 2% increase in consumption
56+
consumption_shock = ConsumptionShock(1.02, 4)
4457

45-
custom_shock = CustomShock(0.0, 10)
46-
data_vec_shocked = Bit.ensemblerun(model, 4; shock = custom_shock)
58+
# Simulate the model with the shock
59+
data_vec_shocked = Bit.ensemblerun(model, N_reps; shock = consumption_shock)
4760

48-
# Finally, we can plot baseline and shocked simulations
61+
# Compute mean and standard error of GDP for the baseline and shocked simulations
62+
mean_gdp_baseline = mean(data_vec_baseline.real_gdp, dims = 2)
63+
mean_gdp_shocked = mean(data_vec_shocked.real_gdp, dims = 2)
4964

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,
65+
sem_gdp_baseline = std(data_vec_baseline.real_gdp, dims = 2) / sqrt(N_reps)
66+
sem_gdp_shocked = std(data_vec_shocked.real_gdp, dims = 2) / sqrt(N_reps)
67+
68+
# Compute the ratio of shocked to baseline GDP
69+
gdp_ratio = mean_gdp_shocked ./ mean_gdp_baseline
70+
# the standard error on a ratio of two variables is computed with the error propagation formula
71+
sem_gdp_ratio = gdp_ratio .* ((sem_gdp_baseline ./ mean_gdp_baseline).^2 .+ (sem_gdp_shocked ./ mean_gdp_shocked).^2).^0.5
72+
73+
# Finally, we can plot the impulse response curve
74+
plot(
75+
1:T+1,
76+
gdp_ratio,
77+
ribbon = sem_gdp_ratio,
78+
fillalpha = 0.2,
79+
label = "",
6680
xlabel = "quarters",
67-
ylabel = "GDP",
81+
ylabel = "GDP change",
82+
size = (350, 220),
83+
dpi = 300,
6884
)
6985

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`.
86+
# We can save the figure using: savefig("gdp_shock.png")

0 commit comments

Comments
 (0)