Scenario analysis via custom shocks
In this tutorial we will illustrate how to perform a scenario analysis by running the model multiple times under a specific shock and comparing the results with the unshocked model.
import BeforeIT as Bit
import StatsBase: mean, std
using Plots
parameters = Bit.AUSTRIA2010Q1.parameters;
initial_conditions = Bit.AUSTRIA2010Q1.initial_conditions;Initialise the model
model = Bit.Model(parameters, initial_conditions);Simulate the baseline model for T quarters, N_reps times, and collect the data
T = 16
n_sims = 64
model_vec_baseline = Bit.ensemblerun!((deepcopy(model) for _ in 1:n_sims), T);Now, apply a shock to the model and simulate it again. A shock is simply a function that takes the model and changes some of its parameters for a specific time period. We do this by first defining a "struct" with useful attributes. For example, we can define an productivity and a consumption shock with the following structs
struct ProductivityShock
productivity_multiplier::Float64 # productivity multiplier
end
struct ConsumptionShock
consumption_multiplier::Float64 # productivity multiplier
final_time::Int
endand then by making the structs callable functions that change the parameters of the model, this is done in Julia using the syntax below
A permanent change in the labour productivities by the factor s.productivity_multiplier
function (s::ProductivityShock)(model::Bit.Model)
return model.firms.alpha_bar_i .= model.firms.alpha_bar_i .* s.productivity_multiplier
endA temporary change in the propensity to consume model.prop.psi by the factor s.consumption_multiplier
function (s::ConsumptionShock)(model::Bit.Model)
return if model.agg.t == 1
model.prop.psi = model.prop.psi * s.consumption_multiplier
elseif model.agg.t == s.final_time
model.prop.psi = model.prop.psi / s.consumption_multiplier
end
endDefine specific shocks, for example a 2% increase in productivity
productivity_shock = ProductivityShock(1.02)Main.ProductivityShock(1.02)or a 4 quarters long 2% increase in consumption
consumption_shock = ConsumptionShock(1.02, 4)Main.ConsumptionShock(1.02, 4)Simulate the model with the shock
model_vec_shocked = Bit.ensemblerun!((deepcopy(model) for _ in 1:n_sims), T; shock! = consumption_shock);extract the data vectors from the model vectors
data_vector_baseline = Bit.DataVector(model_vec_baseline);
data_vector_shocked = Bit.DataVector(model_vec_shocked);Compute mean and standard error of GDP for the baseline and shocked simulations
mean_gdp_baseline = mean(data_vector_baseline.real_gdp, dims = 2)
mean_gdp_shocked = mean(data_vector_shocked.real_gdp, dims = 2)
sem_gdp_baseline = std(data_vector_baseline.real_gdp, dims = 2) / sqrt(n_sims)
sem_gdp_shocked = std(data_vector_shocked.real_gdp, dims = 2) / sqrt(n_sims)17×1 Matrix{Float64}:
1.8333689901882087e-12
60.128272094555946
79.7181412002593
88.7719983059957
99.35776348115112
114.92913333163956
138.08734331198838
152.85617852756903
161.65879737226635
156.2954302423599
173.32656435516284
183.53326096573068
194.69374823738386
195.9256573420693
196.4660336844836
205.54109182911503
213.57231936406652Compute the ratio of shocked to baseline GDP
gdp_ratio = mean_gdp_shocked ./ mean_gdp_baseline17×1 Matrix{Float64}:
1.0
1.0008946461240995
1.0062534593476045
1.0075669620836272
1.0077154276814582
1.006884115512943
1.0065333391480922
1.0072085973704124
1.0041260777753365
1.0029618377548135
1.0020445617723448
1.0011055927830592
0.9978509299880831
0.9966522206073718
0.9966192001541059
0.9967038672849
0.9965736141400551the standard error on a ratio of two variables is computed with the error propagation formula
sem_gdp_ratio = gdp_ratio .* ((sem_gdp_baseline ./ mean_gdp_baseline) .^ 2 .+ (sem_gdp_shocked ./ mean_gdp_shocked) .^ 2) .^ 0.517×1 Matrix{Float64}:
3.580093467121083e-17
0.0011690134629178085
0.0015009764340500533
0.0016549969260215933
0.0019720130514554665
0.002362100726369281
0.002568486694282764
0.002815930229491186
0.002948259059376254
0.0029977760812237818
0.003388435353488575
0.003516637730665198
0.0037080056308955328
0.003701499636094884
0.003835233234177931
0.003991571278703198
0.004179424225053973Finally, we can plot the impulse response curve
plot(
1:(T + 1),
gdp_ratio,
ribbon = sem_gdp_ratio,
fillalpha = 0.2,
label = "",
xlabel = "quarters",
ylabel = "GDP change",
)We can save the figure using: savefig("gdp_shock.png")