Skip to content

Commit 4456d6b

Browse files
Add visualization and fix backtests (#129)
1 parent 1b1c6f6 commit 4456d6b

File tree

8 files changed

+96
-16
lines changed

8 files changed

+96
-16
lines changed

Project.toml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,17 @@ HypothesisTests = "09f84164-cd44-5f33-b23f-e6b0d136a0d5"
99
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
1010
Optim = "429524aa-4258-5aef-a3af-852621145aeb"
1111
Printf = "de0858da-6303-5e67-8744-51eddeeeb8d7"
12+
RecipesBase = "3cdcf5f2-1ef4-517c-9805-6587b60abb01"
1213
SpecialFunctions = "276daf66-3868-5448-9aa4-cd146d93841b"
14+
StatsBase = "2913bbd2-ae8a-5f71-8c99-4fb6c76f3a91"
1315

1416
[compat]
1517
Distributions = "0.23"
18+
HypothesisTests = "0.10"
1619
Optim = "0.20, 0.21, 0.22, 1.2"
20+
RecipesBase = "1"
1721
SpecialFunctions = "0.8"
1822
julia = "1"
19-
HypothesisTests = "0.9"
2023

2124
[extras]
2225
DelimitedFiles = "8bb1440f-4735-579b-a4ab-409b98df4dab"

src/ScoreDrivenModels.jl

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
module ScoreDrivenModels
22

3-
using Distributions, Optim, SpecialFunctions, HypothesisTests
3+
using Distributions, Optim, SpecialFunctions, HypothesisTests, RecipesBase, StatsBase
44
using LinearAlgebra, Printf
55

66
import Base: length, deepcopy, show
@@ -45,4 +45,7 @@ include("distributions/tdist.jl")
4545
include("distributions/tdistlocationscale.jl")
4646
include("distributions/weibull.jl")
4747

48+
include("visualization/forecast.jl")
49+
include("visualization/residuals.jl")
50+
4851
end

src/backtest.jl

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -35,11 +35,11 @@ end
3535
TODO
3636
"""
3737
function backtest(gas::Model{<:Distribution, T}, y::Vector{T}, steps_ahead::Int, start_idx::Int;
38-
S::Int = 1000,
39-
initial_params::Matrix{T} = stationary_initial_params(gas),
40-
opt_method = NelderMead(gas, DEFAULT_NUM_SEEDS)) where T
38+
S::Int = 10_000,
39+
initial_params = stationary_initial_params(gas),
40+
opt_method = NelderMead(gas, 3)) where T
4141
num_mle = length(y) - start_idx - steps_ahead
42-
backtest = Backtest(num_mle, steps_ahead)
42+
b = Backtest(num_mle, steps_ahead)
4343
for i in 1:num_mle
4444
println("Backtest: step $i of $num_mle")
4545
gas_to_fit = deepcopy(gas)
@@ -49,8 +49,8 @@ function backtest(gas::Model{<:Distribution, T}, y::Vector{T}, steps_ahead::Int,
4949
forec = forecast(y_to_fit, gas_to_fit, steps_ahead; S=S, initial_params=initial_params)
5050
abs_errors = evaluate_abs_error(y_to_verify, forec.observation_forecast)
5151
crps_scores = evaluate_crps(y_to_verify, forec.observation_scenarios)
52-
backtest.abs_errors[i, :] = abs_errors
53-
backtest.crps_scores[i, :] = crps_scores
52+
b.abs_errors[i, :] = abs_errors
53+
b.crps_scores[i, :] = crps_scores
5454
end
55-
return backtest
55+
return b
5656
end

src/simulate.jl

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,7 @@ function simulate(series::Vector{T}, gas::Model{D, T}, H::Int, S::Int;
3636
sim, param = simulate_recursion(gas, H + biggest_lag; initial_params = params_simulation)
3737
observation_scenarios[:, scenario] = sim[biggest_lag+1:end]
3838
# The first param is known
39-
parameter_scenarios[1, :, scenario] = params_simulation[end, :]
40-
# The last param (param[end, :]) is actually in a time step bigger
41-
# than H
42-
parameter_scenarios[2:end, :, scenario] = param[biggest_lag+1:end-1, :]
39+
parameter_scenarios[:, :, scenario] = param[biggest_lag+1:end, :]
4340
end
4441
return observation_scenarios, parameter_scenarios
4542
end
@@ -69,12 +66,18 @@ function forecast(series::Vector{T}, gas::Model{D, T}, H::Int;
6966

7067
observation_scenarios, parameter_scenarios = simulate(series, gas, H, S;
7168
initial_params = initial_params)
69+
parameters_forecast = mean(parameter_scenarios, dims = 3)[:, :, 1]
70+
observations_forecast = Vector{T}(undef, H)
71+
for i in 1:H
72+
dist = update_dist(D, parameters_forecast, i)
73+
observations_forecast[i] = mean(dist)
74+
end
7275
return Forecast(
7376
get_quantiles(quantiles, observation_scenarios),
74-
mean(observation_scenarios, dims = 2)[:],
77+
observations_forecast,
7578
observation_scenarios,
7679
get_quantiles(quantiles, parameter_scenarios),
77-
mean(parameter_scenarios, dims = 3)[:, :, 1],
80+
parameters_forecast,
7881
parameter_scenarios
7982
)
8083
end

src/visualization/forecast.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
#TODO

src/visualization/residuals.jl

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
RecipesBase.@recipe function f(fi::ScoreDrivenModels.Fitted)
2+
layout := (2, 2)
3+
acf = autocor(fi.pearson_residuals)[2:end]
4+
@series begin
5+
seriestype := :path
6+
label := ""
7+
seriescolor := "black"
8+
subplot := 1
9+
fi.pearson_residuals
10+
end
11+
@series begin
12+
seriestype := :bar
13+
label := ""
14+
seriescolor := "black"
15+
subplot := 2
16+
acf
17+
end
18+
ub = ones(length(acf)) * 1.96 / sqrt(fi.num_obs)
19+
lb = ones(length(acf)) * -1.96 / sqrt(fi.num_obs)
20+
@series begin
21+
seriestype := :path
22+
linestyle := :dash
23+
seriescolor := "red"
24+
label := ""
25+
subplot := 2
26+
ub
27+
end
28+
@series begin
29+
seriestype := :path
30+
linestyle := :dash
31+
label := ""
32+
seriescolor := "red"
33+
subplot := 2
34+
lb
35+
end
36+
@series begin
37+
seriestype := :histogram
38+
label := ""
39+
seriescolor := "black"
40+
subplot := 3
41+
fi.pearson_residuals
42+
end
43+
qqpair = qqbuild(Normal(), fi.pearson_residuals)
44+
@series begin
45+
seriestype := :scatter
46+
label := ""
47+
seriescolor := "black"
48+
subplot := 4
49+
qqpair.qx, qqpair.qy
50+
end
51+
@series begin
52+
seriestype := :path
53+
seriescolor := "red"
54+
label := ""
55+
subplot := 4
56+
collect(-3:0.01:3), collect(-3:0.01:3)
57+
end
58+
end

test/runtests.jl

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
using ScoreDrivenModels, Distributions, LinearAlgebra
1+
using ScoreDrivenModels, Distributions, LinearAlgebra, RecipesBase
22

33
using Test, Random, HypothesisTests, DelimitedFiles
44

@@ -12,3 +12,4 @@ include("test_diagnostics.jl")
1212
include("test_estimate.jl")
1313
include("test_simulate.jl")
1414
include("test_backtest.jl")
15+
include("test_visualization.jl")

test/test_visualization.jl

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
@testset "Visualization Residuals" begin
2+
ω = [0.1, 0.1]
3+
A = [0.5 0; 0 0.5]
4+
B = [0.5 0; 0 0.5]
5+
simulation = simulate_GAS_1_1(Normal, 0.0, ω, A, B, 1)
6+
# LBFGS
7+
gas = Model(1, 1, Normal, 0.0)
8+
f = fit!(gas, simulation; verbose = 2, opt_method = ScoreDrivenModels.LBFGS(gas, 3))
9+
rec = RecipesBase.apply_recipe(Dict{Symbol, Any}(), f)
10+
@test length(rec) == 7
11+
end

0 commit comments

Comments
 (0)