Skip to content

Commit

Permalink
Fix some issues
Browse files Browse the repository at this point in the history
  • Loading branch information
junyuan-chen committed Apr 20, 2024
1 parent afc9a32 commit 9485386
Show file tree
Hide file tree
Showing 2 changed files with 75 additions and 24 deletions.
49 changes: 31 additions & 18 deletions src/dfm.jl
Original file line number Diff line number Diff line change
Expand Up @@ -106,25 +106,31 @@ end

nfactor(f::DynamicFactor) = nfactor(f.f)

function _dfm_est!(Y, facX, crossfacX, Λ, u, lagca, crosslagca, arcoef, resid, σ, narlag)
function _dfm_est!(Y, facX, crossfacX, Λ, u, lagca, crosslagca, arcoef, resid, σ, narlag, arexclude)
Tfull, N = size(Y)
# Estimate coefficients for common components
Y1 = view(Y, Tfull-size(facX,1)+1:Tfull, :)
_ols!(Y1, facX, crossfacX, Λ, u)
T = size(lagca, 1)
T1 = size(u, 1)
t1 = T1 - T + 1
dofr = size(lagca, 1) - size(lagca, 2)
dofr = T - narlag
# Estimate coefficients for idiosyncratic components
for n in 1:N
coefn = view(arcoef, :, n)
un = view(u, t1:T1, n)
residn = view(resid, :, n)
for l in 1:narlag
lagca[:,l] .= view(u, t1-l:T1-l, n)
if arexclude !== nothing && n in arexclude
fill!(coefn, zero(eltype(coefn)))
copyto!(residn, un)
σ[n] = sqrt(sum(abs2, residn) / T)
else
for l in 1:narlag
lagca[:,l] .= view(u, t1-l:T1-l, n)
end
_ols!(un, lagca, crosslagca, coefn, residn)
σ[n] = sqrt(sum(abs2, residn) / dofr)
end
_ols!(un, lagca, crosslagca, coefn, residn)
σ[n] = sqrt(sum(abs2, residn) / dofr)
end
end

Expand All @@ -133,7 +139,7 @@ function DynamicFactor(Y::AbstractMatrix, facobs::Union{AbstractVecOrMat, Nothin
FacProc::Union{Type, Nothing}, nfaclag::Integer, narlag::Integer,
X::Union{AbstractVecOrMat, Nothing}=nothing;
svdalg::Algorithm=default_svd_alg(Y), maxiter::Integer=10000, tol::Real=1e-8,
facprockwargs::NamedTuple=NamedTuple())
arexclude=nothing, facprockwargs::NamedTuple=NamedTuple())
Y = convert(Matrix, Y)
Tfull, N = size(Y)
nsk = nskip(trans)
Expand All @@ -149,7 +155,7 @@ function DynamicFactor(Y::AbstractMatrix, facobs::Union{AbstractVecOrMat, Nothin
size(facobs, 1) == Tfull || throw(DimensionMismatch(
"facobs and Y do not have the same number of rows"))
facobs = convert(Matrix, facobs)
facobs0 = similar(facobs, T-nsk, size(facobs,2))
facobs0 = similar(facobs, Tfull-nsk, size(facobs,2))
detrend!(trans, facobs0, facobs)
end
f = Factor(Y0, facobs0, nfac; svdalg=svdalg, maxiter=maxiter, tol=tol)
Expand All @@ -175,7 +181,8 @@ function DynamicFactor(Y::AbstractMatrix, facobs::Union{AbstractVecOrMat, Nothin
arcoef = similar(Y, narlag, N)
resid = similar(Y, T, N)
σ = similar(Y, N)
_dfm_est!(Y, facX, crossfacX, Λ, u, lagca, crosslagca, arcoef, resid, σ, narlag)
_dfm_est!(Y, facX, crossfacX, Λ, u, lagca, crosslagca, arcoef, resid, σ,
narlag, arexclude)
if FacProc !== nothing
facproc = fit(FacProc, view(facX,:,1:nfac), nfaclag; facprockwargs...)
else
Expand All @@ -186,17 +193,17 @@ function DynamicFactor(Y::AbstractMatrix, facobs::Union{AbstractVecOrMat, Nothin
end

function fit!(f::DynamicFactor; maxiter::Integer=10000, tol::Real=1e-8,
facprockwargs::NamedTuple=NamedTuple())
arexclude=nothing, facprockwargs::NamedTuple=NamedTuple())
detrend!(f.trans, f.Y0, f.Y)
if f.facobs !== nothing
facobs0 = nothing
detrend!(f.trans, facobs0, facobs)
detrend!(f.trans, f.facobs0, f.facobs)
copyto!(view(f.f.fac,:,1:f.f.nfaco), f.facobs0)
end
fit!(f.f; maxiter=maxiter, tol=tol)
nfac = size(f.f.fac, 2)
invdetrend!(f.trans, view(f.facX,:,1:nfac), f.f.fac)
_dfm_est!(f.Y, f.facX, f.crossfacX, f.Λ, f.u, f.lagca, f.crosslagca, f.arcoef, f.resid,
f.σ, f.narlag)
f.σ, f.narlag, arexclude)
f.facproc === nothing ||
fit!(f.facproc, view(f.facX,:,1:nfac); facprockwargs...)
return f
Expand All @@ -216,12 +223,17 @@ When only unobserved factors are involved,
the number of factors may be selected based on a defined criterion.
The type of the model for the evolution of factors
may be specified with `FacProc`.
See also [`DynamicFactor`](@ref) and [`fit!`](@ref).
The meaning of the remaining arguments matches
the corresponding fields in [`DynamicFactor`](@ref).
All keyword arguments for fitting [`Factor`](@ref) are accepted.
Any keyword argument for `FacProc` may be provided
as a `NamedTuple` for the keyword `facprockwargs`.
See also [`DynamicFactor`](@ref) and [`fit!`](@ref).
The following are the additional keywords accepted.
# Keywords
- `arexclude=nothing`: set of indices for variables to be excluded from estimating
the autoregressive coefficients of the idiosyncratic components.
- `facprockwargs::NamedTuple=NamedTuple()`: keyword argument for `FacProc`.
# Reference
**Stock, James H. and Mark W. Watson.** 2016.
Expand All @@ -235,11 +247,12 @@ function fit(::Type{<:DynamicFactor}, data, names, fonames, trans::AbstractDetre
X::Union{AbstractVecOrMat, Nothing}=nothing;
subset::Union{BitVector, Nothing}=nothing, TF::Type=Float64,
svdalg::Algorithm=DivideAndConquer(), maxiter::Integer=10000, tol::Real=1e-8,
facprockwargs::NamedTuple=NamedTuple())
arexclude=nothing, facprockwargs::NamedTuple=NamedTuple())
Y, faco = _factor_tabletomat(data, names, fonames, subset, TF)
X !== nothing && subset !== nothing && (X = view(X, subset, :))
return DynamicFactor(Y, faco, trans, nfac, FacProc, nfaclag, narlag, X;
svdalg=svdalg, maxiter=maxiter, tol=tol, facprockwargs=facprockwargs)
svdalg=svdalg, maxiter=maxiter, tol=tol,
arexclude=arexclude, facprockwargs=facprockwargs)
end

show(io::IO, f::DynamicFactor) =
Expand Down
50 changes: 44 additions & 6 deletions test/dfm.jl
Original file line number Diff line number Diff line change
Expand Up @@ -98,16 +98,54 @@ end
Not estimated"""
end

f2 = fit(DynamicFactor, tb, ibal, nothing, FirstDiff(), BaiNg(30),
w = data[2:end,1:1]
f2 = DynamicFactor(xbal, w, FirstDiff(), 4, nothing, 4, 4, 1:223, arexclude=(1,))
@test abs.(f2.facX[10,1:4]) abs.([2.647070534273070, -0.409233763390545,
-2.448583354331101, 0.777062133958662]) atol=1e-10
@test abs.(f2.Λ[1:4,:]') abs.([
1.000000000000000 -0.000000000000085 -0.000000000000253 -0.000000000000277;
-0.176869660254340 0.341326133790815 -0.531832560474252 -0.050548484398590;
0.138280288564886 0.176289518804467 -0.003579973854560 0.127784818344253;
-0.017376912623149 1.389248038370042 1.590214827285696 0.053961254580756;
-0.288853468488554 1.295956580093574 1.340073720674857 0.376761035586924;
0.741342427554159 0.746936517706743 -0.836747380775329 -0.637279129786421;
-0.000057553428649 0.000331665615867 0.000731261496305 0.000272838958179;
-0.146403622040140 -0.016342164982163 0.008833758737728 1.871736796403937
]) atol=1e-10
@test f2.arcoef'
[ 0 0 0 0;
0.616037967310018 0.107591400424874 0.069023223680326 0.043873141740624;
0.769836475718294 -0.022464276053618 0.061128324277641 0.072377642177374;
0.573263857098401 0.120224782292888 0.044175367824055 -0.054197784792354;
0.746501793004697 0.124187288728450 0.044444174053458 -0.125784699949580;
1.030744790868324 0.093747757564231 -0.116526277928615 -0.082567084371622;
0.511383934328558 0.102277378712291 0.059272962038230 -0.059105468722871;
0.560208207607704 0.105367527318873 0.098177242590535 -0.027960067387970
] atol=1e-10
@test f2.σ[2:end] [0.412619331990811, 0.617549404907423, 1.252061775182155,
1.315822943598192, 3.738078775682554, 0.002967937991064, 0.615717221130628
] atol=1e-10

f21 = deepcopy(f2)
fill!(f21.Y0, 0)
fill!(f21.facobs0, 0)
fill!(f21.f.fac, 0)
fill!(f21.arcoef, 0)
fit!(f21, arexclude=1)
@test f21.f.fac f2.f.fac
@test f21.Λ f2.Λ
@test f21.arcoef f2.arcoef

f3 = fit(DynamicFactor, tb, ibal, nothing, FirstDiff(), BaiNg(30),
VAROLS, 4, 4, 1:224; subset=(1:224).>1)
@test abs.(f2.facX[1,1:3])
@test abs.(f3.facX[1,1:3])
abs.([2.633579135057327, -4.515438104711660, 0.967695227734307]) atol=1e-10
@test abs.(f2.facX[20,1:3])
@test abs.(f3.facX[20,1:3])
abs.([-11.213179331809721, -10.755437451370934, -9.740548002249279]) atol=1e-10
# Li, Plagborg-Møller and Wolf (2024) has an initial row of zeros
# for lagmatrix generated from cumsum_nan
# Removing the initial row yields the same estimates here
@test abs.(coef(f2.facproc))
@test abs.(coef(f3.facproc))
abs.([0.673856090754789 -0.081037456424403 -0.490680042824428;
1.616377319397290 0.296011178122282 -0.131965176312504;
-0.244663060538245 1.369015986230120 -0.098455471141018;
Expand All @@ -121,10 +159,10 @@ end
-0.215963192051662 -0.118458036521081 -0.102091302758074;
0.026271389380724 -0.163505737633263 -0.041529088862164;
-0.179952139267754 0.145787466313025 -0.151287681694109]) atol=1e-10
@test sprint(show, f2) ==
@test sprint(show, f3) ==
"222×3 DynamicFactor{Float64, FirstDiff, Nothing, Factor{Float64, SDDcache{Float64}}, VAROLS{Float64, Vector{Float64}, Nothing, Nothing, Nothing}}"
if VERSION >= v"1.7"
@test sprint(show, MIME("text/plain"), f2, context=:displaysize=>(10,120)) == """
@test sprint(show, MIME("text/plain"), f3, context=:displaysize=>(10,120)) == """
222×3 DynamicFactor{Float64, FirstDiff, Nothing, Factor{Float64, SDDcache{Float64}}, VAROLS{Float64, Vector{Float64}, Nothing, Nothing, Nothing}} with 3 unobserved factors and 0 observed factor:
2.63358 4.51544 -0.967695
Expand Down

0 comments on commit 9485386

Please sign in to comment.