@@ -65,6 +65,7 @@ mutable struct StructuralModel <: StateSpaceLearningModel
65
65
freq_seasonal:: Union{Int,Vector{Int}}
66
66
cycle_period:: Union{Union{Int,<:AbstractFloat},Vector{Int},Vector{<:AbstractFloat}}
67
67
outlier:: Bool
68
+ ξ_threshold:: Int
68
69
ζ_threshold:: Int
69
70
ω_threshold:: Int
70
71
ϕ_threshold:: Int
@@ -82,6 +83,7 @@ mutable struct StructuralModel <: StateSpaceLearningModel
82
83
freq_seasonal:: Union{Int,Vector{Int}} = 12 ,
83
84
cycle_period:: Union{Union{Int,<:AbstractFloat},Vector{Int},Vector{<:AbstractFloat}} = 0 ,
84
85
outlier:: Bool = true ,
86
+ ξ_threshold:: Int = 1 ,
85
87
ζ_threshold:: Int = 12 ,
86
88
ω_threshold:: Int = 12 ,
87
89
ϕ_threshold:: Int = 12 ,
@@ -156,6 +158,7 @@ mutable struct StructuralModel <: StateSpaceLearningModel
156
158
freq_seasonal,
157
159
cycle_period,
158
160
outlier,
161
+ ξ_threshold,
159
162
ζ_threshold,
160
163
ω_threshold,
161
164
ϕ_threshold,
@@ -180,6 +183,7 @@ mutable struct StructuralModel <: StateSpaceLearningModel
180
183
freq_seasonal,
181
184
cycle_period,
182
185
outlier,
186
+ ξ_threshold,
183
187
ζ_threshold,
184
188
ω_threshold,
185
189
ϕ_threshold,
@@ -191,6 +195,45 @@ mutable struct StructuralModel <: StateSpaceLearningModel
191
195
end
192
196
end
193
197
198
+ """
199
+ Create a Basic Structural Model.
200
+
201
+ # Arguments
202
+ - `y::Union{Vector,Matrix}`: Time series to be modeled.
203
+ - `level::String="stochastic"`: Level component of the model.
204
+ - `slope::String="stochastic"`: Slope component of the model.
205
+ - `seasonal::String="stochastic"`: Seasonal component of the model.
206
+ - `freq_seasonal::Union{Int,Vector{Int}}=12`: Seasonal period of the model.
207
+
208
+ # Returns
209
+ - `StructuralModel`: Basic Structural Model.
210
+ """
211
+ function BasicStructuralModel (
212
+ y:: Union{Vector,Matrix} ;
213
+ level:: String = " stochastic" ,
214
+ slope:: String = " stochastic" ,
215
+ seasonal:: String = " stochastic" ,
216
+ freq_seasonal:: Union{Int,Vector{Int}} = 12 ,
217
+ )
218
+ return StructuralModel (
219
+ y;
220
+ level= level,
221
+ slope= slope,
222
+ seasonal= seasonal,
223
+ cycle= " none" ,
224
+ freq_seasonal= freq_seasonal,
225
+ cycle_period= 0 ,
226
+ outlier= false ,
227
+ ξ_threshold= 0 ,
228
+ ζ_threshold= 0 ,
229
+ ω_threshold= 0 ,
230
+ ϕ_threshold= 0 ,
231
+ stochastic_start= 1 ,
232
+ exog= zeros (length (y), 0 ),
233
+ dynamic_exog_coefs= nothing ,
234
+ )
235
+ end
236
+
194
237
"""
195
238
ξ_size(T::Int, stochastic_start::Int)::Int
196
239
204
247
- `Int`: Size of ξ calculated from T.
205
248
206
249
"""
207
- ξ_size (T:: Int , stochastic_start:: Int ):: Int = T - max (2 , stochastic_start)
250
+ ξ_size (T:: Int , ξ_threshold:: Int , stochastic_start:: Int ):: Int =
251
+ T - max (2 , stochastic_start) + 1 - ξ_threshold
208
252
209
253
"""
210
254
ζ_size(T::Int, ζ_threshold::Int, stochastic_start::Int)::Int
@@ -273,27 +317,28 @@ o_size(T::Int, stochastic_start::Int)::Int = T - max(1, stochastic_start) + 1
273
317
(2 * (T - max (2 , stochastic_start) + 1 ) - (max (1 , ϕ_threshold) * 2 ))
274
318
275
319
"""
276
- create_ξ(T::Int, stochastic_start::Int)::Matrix
320
+ create_ξ(T::Int, ξ_threshold::Int, stochastic_start::Int)::Matrix
277
321
278
322
Creates a matrix of innovations ξ based on the input sizes, and the desired steps ahead (this is necessary for the forecast function)
279
323
280
324
# Arguments
281
325
- `T::Int`: Length of the original time series.
326
+ - `ξ_threshold::Int`: Stabilize parameter ξ.
282
327
- `stochastic_start::Int`: parameter to set at which time stamp the stochastic component starts.
283
328
284
329
# Returns
285
330
- `Matrix`: Matrix of innovations ξ constructed based on the input sizes.
286
331
287
332
"""
288
- function create_ξ (T:: Int , stochastic_start:: Int ):: Matrix
333
+ function create_ξ (T:: Int , ξ_threshold :: Int , stochastic_start:: Int ):: Matrix
289
334
stochastic_start = max (2 , stochastic_start)
290
335
ξ_matrix = zeros (T, T - stochastic_start + 1 )
291
336
ones_indexes = findall (
292
337
I -> Tuple (I)[1 ] - (stochastic_start - 2 ) > Tuple (I)[2 ],
293
- CartesianIndices ((T, T - stochastic_start)),
338
+ CartesianIndices ((T, T - stochastic_start + 1 )),
294
339
)
295
340
ξ_matrix[ones_indexes] .= 1
296
- return ξ_matrix[:, 1 : (end - 1 )]
341
+ return ξ_matrix[:, 1 : (end - ξ_threshold )]
297
342
end
298
343
299
344
"""
@@ -524,6 +569,7 @@ create_dynamic_exog_coefs_matrix(dynamic_exog_coefs::Vector{<:Tuple}, T::Int,ζ_
524
569
function create_dynamic_exog_coefs_matrix (
525
570
dynamic_exog_coefs:: Vector{<:Tuple} ,
526
571
T:: Int ,
572
+ ξ_threshold:: Int ,
527
573
ζ_threshold:: Int ,
528
574
ω_threshold:: Int ,
529
575
ϕ_threshold:: Int ,
@@ -537,7 +583,7 @@ function create_dynamic_exog_coefs_matrix(
537
583
nothing
538
584
else
539
585
state_components_dict[" level" ] = hcat (
540
- ones (T, 1 ), create_ξ (T, stochastic_start)
586
+ ones (T, 1 ), create_ξ (T, ξ_threshold, stochastic_start)
541
587
)
542
588
end
543
589
key_name = " level"
@@ -588,6 +634,7 @@ create_forecast_dynamic_exog_coefs_matrix(dynamic_exog_coefs::Vector{<:Tuple}, T
588
634
- `dynamic_exog_coefs::Vector{<:Tuple}`: Vector of tuples containing the combination components.
589
635
- `T::Int`: Length of the original time series.
590
636
- `steps_ahead::Int`: Steps ahead.
637
+ - `ξ_threshold::Int`: Stabilize parameter ξ.
591
638
- `ζ_threshold::Int`: Stabilize parameter ζ.
592
639
- `ω_threshold::Int`: Stabilize parameter ω.
593
640
- `ϕ_threshold::Int`: Stabilize parameter ϕ.
@@ -600,6 +647,7 @@ function create_forecast_dynamic_exog_coefs_matrix(
600
647
dynamic_exog_coefs:: Vector{<:Tuple} ,
601
648
T:: Int ,
602
649
steps_ahead:: Int ,
650
+ ξ_threshold:: Int ,
603
651
ζ_threshold:: Int ,
604
652
ω_threshold:: Int ,
605
653
ϕ_threshold:: Int ,
@@ -613,7 +661,8 @@ function create_forecast_dynamic_exog_coefs_matrix(
613
661
nothing
614
662
else
615
663
state_components_dict[" level" ] = hcat (
616
- ones (T + steps_ahead, 1 ), create_ξ (T + steps_ahead, stochastic_start)
664
+ ones (T + steps_ahead, 1 ),
665
+ create_ξ (T + steps_ahead, ξ_threshold, stochastic_start),
617
666
)[
618
667
(end - steps_ahead + 1 ): end , 1 : combination[4 ]
619
668
]
@@ -680,6 +729,7 @@ create_X(
680
729
freq_seasonal::Union{Int,Vector{Int}},
681
730
cycle_period::Union{Int,Vector{Int}},
682
731
outlier::Bool,
732
+ ξ_threshold::Int,
683
733
ζ_threshold::Int,
684
734
ω_threshold::Int,
685
735
ϕ_threshold::Int,
@@ -701,6 +751,7 @@ create_X(
701
751
- `freq_seasonal::Union{Int, Vector{Int}}`: Seasonal period.
702
752
- `cycle_period::Union{Int,Vector{Int}}`: Cycle period.
703
753
- `outlier::Bool`: Flag for considering outlier component.
754
+ - `ξ_threshold::Int`: Stabilize parameter ξ.
704
755
- `ζ_threshold::Int`: Stabilize parameter ζ.
705
756
- `ω_threshold::Int`: Stabilize parameter ω.
706
757
- `ϕ_threshold::Int`: Stabilize parameter ϕ.
@@ -722,6 +773,7 @@ function create_X(
722
773
freq_seasonal:: Union{Int,Vector{Int}} ,
723
774
cycle_period:: Union{Union{Int,<:AbstractFloat},Vector{Int},Vector{<:AbstractFloat}} ,
724
775
outlier:: Bool ,
776
+ ξ_threshold:: Int ,
725
777
ζ_threshold:: Int ,
726
778
ω_threshold:: Int ,
727
779
ϕ_threshold:: Int ,
@@ -732,7 +784,7 @@ function create_X(
732
784
T = size (exog, 1 )
733
785
734
786
ξ_matrix = if stochastic_level
735
- create_ξ (T, stochastic_start)
787
+ create_ξ (T, ξ_threshold, stochastic_start)
736
788
else
737
789
zeros (T, 0 )
738
790
end
@@ -770,6 +822,7 @@ function create_X(
770
822
create_dynamic_exog_coefs_matrix (
771
823
dynamic_exog_coefs,
772
824
T,
825
+ ξ_threshold,
773
826
ζ_threshold,
774
827
ω_threshold,
775
828
ϕ_threshold,
@@ -847,7 +900,9 @@ function get_components_indexes(model::StructuralModel)::Dict
847
900
848
901
if model. stochastic_level
849
902
ξ_indexes = collect (
850
- (FINAL_INDEX + 1 ): (FINAL_INDEX + ξ_size (T, model. stochastic_start))
903
+ (FINAL_INDEX + 1 ): (FINAL_INDEX + ξ_size (
904
+ T, model. ξ_threshold, model. stochastic_start
905
+ )),
851
906
)
852
907
FINAL_INDEX += length (ξ_indexes)
853
908
else
@@ -908,7 +963,6 @@ function get_components_indexes(model::StructuralModel)::Dict
908
963
FINAL_INDEX += length (exogenous_indexes)
909
964
910
965
dynamic_exog_coefs_indexes = collect ((FINAL_INDEX + 1 ): size (model. X, 2 ))
911
- FINAL_INDEX += length (dynamic_exog_coefs_indexes)
912
966
913
967
components_indexes_dict = Dict (
914
968
" μ1" => μ1_indexes,
@@ -940,6 +994,43 @@ function get_components_indexes(model::StructuralModel)::Dict
940
994
end
941
995
end
942
996
997
+ if ! isnothing (model. dynamic_exog_coefs)
998
+ for i in eachindex (model. dynamic_exog_coefs)
999
+ if model. dynamic_exog_coefs[i][2 ] == " level"
1000
+ components_indexes_dict[" dynamic_exog_coefs_$(i) " ] = collect (
1001
+ (FINAL_INDEX + 1 ): (FINAL_INDEX + 1 + ξ_size (
1002
+ T, model. ξ_threshold, model. stochastic_start
1003
+ )),
1004
+ )
1005
+ FINAL_INDEX += length (components_indexes_dict[" dynamic_exog_coefs_$(i) " ])
1006
+ elseif model. dynamic_exog_coefs[i][2 ] == " slope"
1007
+ components_indexes_dict[" dynamic_exog_coefs_$(i) " ] = collect (
1008
+ (FINAL_INDEX + 1 ): (FINAL_INDEX + 1 + ζ_size (
1009
+ T, model. ζ_threshold, model. stochastic_start
1010
+ )),
1011
+ )
1012
+ FINAL_INDEX += length (components_indexes_dict[" dynamic_exog_coefs_$(i) " ])
1013
+ elseif model. dynamic_exog_coefs[i][2 ] == " seasonal"
1014
+ components_indexes_dict[" dynamic_exog_coefs_$(i) " ] = collect (
1015
+ (FINAL_INDEX + 1 ): (FINAL_INDEX + model. dynamic_exog_coefs[i][3 ] + ω_size (
1016
+ T,
1017
+ model. dynamic_exog_coefs[i][3 ],
1018
+ model. ω_threshold,
1019
+ model. stochastic_start,
1020
+ )),
1021
+ )
1022
+ FINAL_INDEX += length (components_indexes_dict[" dynamic_exog_coefs_$(i) " ])
1023
+ elseif model. dynamic_exog_coefs[i][2 ] == " cycle"
1024
+ components_indexes_dict[" dynamic_exog_coefs_$(i) " ] = collect (
1025
+ (FINAL_INDEX + 1 ): (FINAL_INDEX + 2 + ϕ_size (
1026
+ T, model. ϕ_threshold, model. stochastic_start
1027
+ )),
1028
+ )
1029
+ FINAL_INDEX += length (components_indexes_dict[" dynamic_exog_coefs_$(i) " ])
1030
+ end
1031
+ end
1032
+ end
1033
+
943
1034
return components_indexes_dict
944
1035
end
945
1036
@@ -979,47 +1070,6 @@ function get_variances(
979
1070
return variances
980
1071
end
981
1072
982
- """
983
- get_variances(
984
- model::StructuralModel,
985
- ε::Vector{Vector{Fl}},
986
- coefs::Vector{Vector{Tl}},
987
- components_indexes::Dict{String,Vector{Int}},
988
- )::Vector{Dict} where {Fl, Tl}
989
-
990
- Calculates variances for each innovation component and for the residuals.
991
-
992
- # Arguments
993
- - `model::StructuralModel`: StructuralModel object.
994
- - `ε::Vector{Vector{Fl}}`: Vector of residuals.
995
- - `coefs::Vector{Vector{Fl}}`: Vector of coefficients.
996
- - `components_indexes::Dict{String, Vector{Int}}`: Dictionary containing indexes for different components.
997
-
998
- # Returns
999
- - `Vector{Dict}`: Dictionary containing variances for each innovation component.
1000
-
1001
- """
1002
- function get_variances (
1003
- model:: StructuralModel ,
1004
- ε:: Vector{Vector{Fl}} ,
1005
- coefs:: Vector{Vector{Tl}} ,
1006
- components_indexes:: Dict{String,Vector{Int}} ,
1007
- ):: Vector{Dict} where {Fl,Tl}
1008
- model_innovations = get_model_innovations (model)
1009
-
1010
- variances_vec = Dict[]
1011
-
1012
- for i in eachindex (coefs)
1013
- variances = Dict ()
1014
- for component in model_innovations
1015
- variances[component] = var (coefs[i][components_indexes[component]])
1016
- end
1017
- variances[" ε" ] = var (ε[i])
1018
- push! (variances_vec, variances)
1019
- end
1020
- return variances_vec
1021
- end
1022
-
1023
1073
"""
1024
1074
get_model_innovations(model::StructuralModel)::Vector
1025
1075
@@ -1053,6 +1103,12 @@ function get_model_innovations(model::StructuralModel)
1053
1103
push! (model_innovations, " ϕ_$i " )
1054
1104
end
1055
1105
end
1106
+
1107
+ if ! isnothing (model. dynamic_exog_coefs)
1108
+ for i in eachindex (model. dynamic_exog_coefs)
1109
+ push! (model_innovations, " dynamic_exog_coefs_$i " )
1110
+ end
1111
+ end
1056
1112
return model_innovations
1057
1113
end
1058
1114
@@ -1083,7 +1139,11 @@ function get_trend_decomposition(
1083
1139
end
1084
1140
1085
1141
if model. stochastic_level && ! isempty (components[" ξ" ][" Coefs" ])
1086
- ξ = vcat (zeros (max (2 , model. stochastic_start) - 1 ), components[" ξ" ][" Coefs" ], 0.0 )
1142
+ ξ = vcat (
1143
+ zeros (max (2 , model. stochastic_start) - 1 ),
1144
+ components[" ξ" ][" Coefs" ],
1145
+ zeros (model. ξ_threshold),
1146
+ )
1087
1147
@assert length (ξ) == T
1088
1148
else
1089
1149
ξ = zeros (AbstractFloat, T)
@@ -1572,7 +1632,7 @@ function forecast_dynamic_exog_coefs(
1572
1632
dynamic_exog_coefs = Vector {Tuple} (undef, length (model. dynamic_exog_coefs))
1573
1633
for i in eachindex (model. dynamic_exog_coefs)
1574
1634
if model. dynamic_exog_coefs[i][2 ] == " level"
1575
- n_coefs = 1 + ξ_size (T, model. stochastic_start)
1635
+ n_coefs = 1 + ξ_size (T, model. ξ_threshold, model . stochastic_start)
1576
1636
extra_param = " "
1577
1637
elseif model. dynamic_exog_coefs[i][2 ] == " slope"
1578
1638
n_coefs = 1 + ζ_size (T, model. ζ_threshold, model. stochastic_start)
@@ -1601,6 +1661,7 @@ function forecast_dynamic_exog_coefs(
1601
1661
dynamic_exog_coefs,
1602
1662
T,
1603
1663
steps_ahead,
1664
+ model. ξ_threshold,
1604
1665
model. ζ_threshold,
1605
1666
model. ω_threshold,
1606
1667
model. ϕ_threshold,
0 commit comments