Skip to content

Commit

Permalink
General docs improvements (#34)
Browse files Browse the repository at this point in the history
  • Loading branch information
Tortar authored Nov 28, 2024
1 parent 6f75482 commit 23c4f51
Show file tree
Hide file tree
Showing 12 changed files with 99 additions and 115 deletions.
2 changes: 1 addition & 1 deletion Project.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name = "BeforeIT"
uuid = "ca9fcad7-41d0-4f76-b1e5-366c28bce52e"
authors = ["Aldo Glielmo <[email protected]>", "Mitja Devetak <[email protected]>"]
authors = ["Aldo Glielmo <[email protected]>", "Mitja Devetak <[email protected]>", "Adriano Meligrana <[email protected]>"]
version = "0.1.2"

[deps]
Expand Down
5 changes: 2 additions & 3 deletions docs/src/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ CurrentModule = BeforeIT

# Behavioural agent-based economic forecasting in Julia


Welcome to BeforeIT.jl, a Julia implementation of the agent-based model presented in [Economic forecasting with an agent-based model](https://www.sciencedirect.com/science/article/pii/S0014292122001891), the first ABM matching the performance of traditional economic forecasting tools.

With BeforeIT.jl, you can perform economic forecasting and explore different counterfactual scenarios. Thanks to its modular design, the package is also a great starting point for anyone looking to extend its capabilities or integrate it with other tools.
Expand Down Expand Up @@ -40,7 +39,7 @@ model = BeforeIT.initialise_model(parameters, initial_conditions, T)
data = BeforeIT.run_one_sim!(model)
```

To plot the results of the simulation, install the `Plots` package via ```Pkg.add("Plots")``` and then run
To plot the results of the simulation, you can use the `Plots` package

```julia
using Plots
Expand All @@ -52,7 +51,7 @@ plot(data.real_gdp)

BeforeIT.jl is released under the GNU Affero General Public License v3 or later (AGPLv3+).

Copyright 2024- Banca d'Italia and the authors.
Copyright 2024 - Banca d'Italia and the authors.

## Main developers and maintainers

Expand Down
6 changes: 1 addition & 5 deletions examples/basic_example.jl
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
import BeforeIT as Bit
using FileIO, Plots


# We then initialise the model loading some precomputed set of parameters and by specifying a number of epochs.
# In another tutorial we will illustrate how to compute parameters and initial conditions.

Expand All @@ -17,7 +16,6 @@ initial_conditions = Bit.AUSTRIA2010Q1.initial_conditions
T = 16
model = Bit.init_model(parameters, initial_conditions, T)


# Note that the it is very simple to inspect the model by typing

fieldnames(typeof(model))
Expand All @@ -33,13 +31,12 @@ data = Bit.init_data(model);
# We can run now the model for a number of epochs and progressively update the data tracker.

for t in 1:T
println(t)
Bit.run_one_epoch!(model; multi_threading = true)
Bit.update_data!(data, model)
end

# Note that we can equivalently run the model for a number of epochs in the single command
# `data = BeforeIT.run_one_sim!(model)` , but writing the loop explicitely is more instructive.
# `data = BeforeIT.run_one_sim!(model)`, but writing the loop explicitely is more instructive.

# We can then plot any time series stored in the data tracker, for example

Expand Down Expand Up @@ -67,4 +64,3 @@ Threads.nthreads()

ps = Bit.plot_data_vector(data_vector)
plot(ps..., layout = (3, 3))

20 changes: 9 additions & 11 deletions examples/benchmark_w_matlab.jl
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@

# # Comparing the performance of the Julia and MATLAB implementations
## Comparing the performance of the Julia and MATLAB implementations

# We can compare the performance of the Julia and MATLAB implementations
# by running the same model for the same number of epochs and measuring
Expand All @@ -22,11 +22,11 @@ parameters = BeforeIT.AUSTRIA2010Q1.parameters
initial_conditions = BeforeIT.AUSTRIA2010Q1.initial_conditions
T = 12

# we run the code to compile it first
# We run the code to compile it first
@time run(parameters, initial_conditions, T; multi_threading = false);
@time run(parameters, initial_conditions, T; multi_threading = true);

# time taken by the MATLAB code and the Generated C code with MATLAB Coder
# Time taken by the MATLAB code and the Generated C code with MATLAB Coder
# (6 threads for the parallel version), computed independently on an AMD Ryzen 5 5600H
matlab_times = [4.399592, 4.398576, 4.352314, 4.385039, 4.389989]
matlab_time = mean(matlab_times)
Expand All @@ -40,7 +40,7 @@ c_times_multi_thread = [0.305, 0.324, 0.330, 0.334, 0.323]
c_time_multi_thread = mean(c_times_multi_thread)
c_time_multi_thread_std = std(c_times_multi_thread)

# time taken by the Julia code (same platform as in the the matlab benchmarks),
# Time taken by the Julia code (same platform as in the the matlab benchmarks),
# computed as the average of 5 runs
n_runs = 5

Expand All @@ -58,13 +58,12 @@ end
julia_time_multi_thread = mean(julia_times_multi_thread)
julia_time_multi_thread_std = std(julia_times_multi_thread)

# get the number of threads used
# Get the number of threads used
n_threads = Threads.nthreads()

theme(:default, bg = :white)

# bar chart of the time taken vs the time taken by the MATLAB code, also plot the stds as error bars
# make a white background with no grid
# Bar chart of the time taken vs the time taken by the MATLAB code, also plot the stds as error bars
bar(
["MATLAB", "Gen. C, 1 thread", "Gen. C, 6 threads", "Julia, 1 thread", "Julia, $n_threads threads"],
[matlab_time, c_time, c_time_multi_thread, julia_time_1_thread, julia_time_multi_thread],
Expand All @@ -79,9 +78,8 @@ bar(
guidefont = font(6)
)

# Save the image
savefig("benchmark_w_matlab.png")

# the Julia implementation is faster than the MATLAB implementation, and the multi-threaded version is
# The Julia implementation is faster than the MATLAB implementation, and the multi-threaded version is
# faster than the single-threaded version.

# save the image
savefig("benchmark_w_matlab.png")
20 changes: 10 additions & 10 deletions examples/change_expectations.jl
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
# # Changing expectations via function overloading

# In this tutorial we will illustrate how to experiment with different expectations of the agents in the model.
# In this tutorial we will illustrate how to experiment with
# different expectations of the agents in the model.

import BeforeIT as Bit
using Random, Plots


# Import standard parameters and initial conditions

par = Bit.AUSTRIA2010Q1.parameters
Expand All @@ -19,21 +19,21 @@ model = Bit.init_model(par, init, T)
data = Bit.run_one_sim!(model)

# Now we can experiment with changing expectations of the agents in the model.
# We will change the function 'estimate_next_value' to make the agents expect
# the last value of the time series (in way representing backward looking expectations)
# We will change the function `estimate_next_value` to make the agents expect
# the last value of the time series (so to represent backward looking expectations)

import BeforeIT: estimate_next_value
function estimate_next_value(data)
return data[end]
end

# run the model again, with the same seed
# Run the model again, with the same seed

Random.seed!(1234)
model = Bit.init_model(par, init, T)
data_back = Bit.run_one_sim!(model)

# plot the results, comparing the two cases as different lines
# Plot the results, comparing the two cases as different lines

p1 = plot(data.real_gdp, title = "gdp", titlefont = 10, label = "forward looking")
plot!(p1, data_back.real_gdp, titlefont = 10, label = "backward looking")
Expand All @@ -43,7 +43,7 @@ plot!(p2, data_back.real_household_consumption, titlefont = 10, label = "backwar

plot(p1, p2, layout = (2, 1), legend = true)

# plot all time series
# Plot all time series

p1 = plot(data.real_gdp, title = "gdp", titlefont = 10)
plot!(p1, data_back.real_gdp, titlefont = 10)
Expand All @@ -66,6 +66,6 @@ plot!(p9, data_back.nominal_gdp ./ data_back.real_gdp, titlefont = 10)

plot(p1, p2, p3, p4, p5, p6, p7, p8, p9, layout = (3, 3), legend = false)

# Note that, importantly, once the function estimate_next_value has been changed, the model will use the new
# expectations in all the simulations, unless the function is changed again.
# To restore the original expectations you need to close the Julia session.
# Note that, importantly, once the function `estimate_next_value` has been changed,
# the model will use the new expectations in all the simulations, unless the function
# is changed again. To restore the original expectations you could close the Julia session.
31 changes: 13 additions & 18 deletions examples/compare_model_vs_real.jl
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ real_data = BeforeIT.ITALY_CALIBRATION.data
model = load("data/italy/abm_predictions/2015Q1.jld2")["model_dict"]

function plot_model_vs_real(model, real, varname; crop = true)

if length(varname) > 9
if varname[(end - 8):end] == "quarterly"
x_nums = "quarters_num"
Expand Down Expand Up @@ -39,14 +38,12 @@ function plot_model_vs_real(model, real, varname; crop = true)
xlimits = :auto
end


if crop
all_tick_numbers = model[x_nums]
else
all_tick_numbers = real[x_nums]
end


num_ticks = []
year_ticks = []
for r in all_tick_numbers
Expand All @@ -59,7 +56,6 @@ function plot_model_vs_real(model, real, varname; crop = true)
end
end


p = plot(
real[x_nums],
1e6 * real[varname],
Expand All @@ -76,7 +72,6 @@ function plot_model_vs_real(model, real, varname; crop = true)
return p
end


num_ticks = []
year_ticks = []
for r in real_data["years_num"]
Expand All @@ -89,42 +84,42 @@ for r in real_data["years_num"]
end
end

# plot real gdp
# Plot real gdp
plot_model_vs_real(model, real_data, "real_gdp")

# plot real household consumption
# Plot real household consumption
plot_model_vs_real(model, real_data, "real_household_consumption")

# plot real fixed capital formation
# Plot real fixed capital formation
plot_model_vs_real(model, real_data, "real_fixed_capitalformation")

# plot real government consumption
# Plot real government consumption
plot_model_vs_real(model, real_data, "real_government_consumption")

# plot real exports
# Plot real exports
plot_model_vs_real(model, real_data, "real_exports")

# plot real imports
# Plot real imports
plot_model_vs_real(model, real_data, "real_imports")

### quarterly plots ###
### Quarterly Plots ###

# plot real gdp quarterly
# Plot real gdp quarterly
p1 = plot_model_vs_real(model, real_data, "real_gdp_quarterly")

# plot real household consumption quarterly
# Plot real household consumption quarterly
p2 = plot_model_vs_real(model, real_data, "real_household_consumption_quarterly")

# plot real fixed capital formation quarterly
# Plot real fixed capital formation quarterly
p3 = plot_model_vs_real(model, real_data, "real_fixed_capitalformation_quarterly")

# plot real government consumption quarterly
# Plot real government consumption quarterly
p4 = plot_model_vs_real(model, real_data, "real_government_consumption_quarterly")

# plot real exports quarterly
# Plot real exports quarterly
p5 = plot_model_vs_real(model, real_data, "real_exports_quarterly")

# plot real imports quarterly
# Plot real imports quarterly
p6 = plot_model_vs_real(model, real_data, "real_imports_quarterly")

plot(p1, p2, p3, p4, p5, p6, layout = (3, 2), legend = false)
Expand Down
25 changes: 12 additions & 13 deletions examples/get_parameters_and_initial_conditions.jl
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,23 @@
import BeforeIT as Bit
using Dates, FileIO


# We start from loading the calibration oject for italy, which contains 4 datasets: calibration_data, figaro, data, and ea
# These are saved within BeforeIT for the Italian case, and would need to be appropriately generated for other countries
# We start from loading the calibration object for italy, which contains
# 4 datasets: `calibration_data`, `figaro`, `data`, and `ea`. These are
# saved within `BeforeIT.jl` for the Italian case, and would need to be
# appropriately generated for other countries.

cal = Bit.ITALY_CALIBRATION

fieldnames(typeof(cal))

# These are essentually 4 dictionaries with well defined keys, such as
# These are essentially 4 dictionaries with well defined keys, such as

println(keys(cal.calibration))
println(keys(cal.figaro))
println(keys(cal.data))
println(keys(cal.ea))

# The object also contains two time variables related to the data

println(cal.max_calibration_date)
println(cal.estimation_date)

Expand All @@ -26,29 +28,26 @@ println(cal.estimation_date)
calibration_date = DateTime(2010, 03, 31)
parameters, initial_conditions = Bit.get_params_and_initial_conditions(cal, calibration_date; scale = 0.01)

# In sgeneral, we might want to repeat this operation for multiple quarters.
# In the following, we loop over all quarters from 2010Q1 to 2019Q4
# In general, we might want to repeat this operation for multiple quarters.
# In the following, we loop over all quarters from `2010Q1` to `2019Q4`
# and save the parameters and initial conditions in separate files.
# We can then load these files later to run the model for each quarter.

start_calibration_date = DateTime(2010, 03, 31)
end_calibration_date = DateTime(2019, 12, 31)

for calibration_date in collect(start_calibration_date:Dates.Month(3):end_calibration_date)
params, init_conds = Bit.get_params_and_initial_conditions(cal, calibration_date; scale = 0.0005)
save(
"data/" *
"italy/" *
"/parameters/" *
"data/italy/parameters/" *
string(year(calibration_date)) *
"Q" *
string(Dates.quarterofyear(calibration_date)) *
".jld2",
params,
)
save(
"data/" *
"italy/" *
"/initial_conditions/" *
"data/italy/initial_conditions/" *
string(year(calibration_date)) *
"Q" *
string(Dates.quarterofyear(calibration_date)) *
Expand Down
13 changes: 4 additions & 9 deletions examples/get_predictions.jl
Original file line number Diff line number Diff line change
@@ -1,34 +1,29 @@
# In this tutorial we illustrate how to get predictions from the model for a number of quarters starting from previous simulations.
# In this tutorial we illustrate how to get predictions from the model for
# a number of quarters starting from previous simulations.

using BeforeIT, FileIO
using Dates

year_ = 2010
number_years = 9#10
number_years = 9
number_quarters = 4 * number_years
horizon = 12#12
horizon = 12
number_seeds = 4
number_sectors = 62

# Load the real time series
data = BeforeIT.ITALY_CALIBRATION.data


quarters_num = []
year_m = year_
for month in 4:3:((number_years + 1) * 12 + 1)

year_m = year_ + (month ÷ 12)
mont_m = month % 12
date = DateTime(year_m, mont_m, 1) - Day(1)

push!(quarters_num, BeforeIT.date2num(date))
end

for i in 1:number_quarters

quarter_num = quarters_num[i]

BeforeIT.get_predictions_from_sims(data, quarter_num, horizon, number_seeds)

end
Loading

0 comments on commit 23c4f51

Please sign in to comment.