├── .gitattributes ├── .gitignore ├── AssetPricingTest ├── AssetPricingTest3bPs.jl ├── AssetPricingTest3dPs.jl ├── ExampleAPTsT.jl ├── FF25Ps.csv ├── FFmFactorsPs.csv ├── HDirProdPs.jl ├── NewEst3Ps.jl ├── Readme.md ├── TestingPricingErrors.pdf └── excise.jl ├── DriscollKraay ├── DVMS.pdf ├── Data │ ├── BA.csv │ ├── Size.csv │ ├── TRMS.csv │ ├── TRMS2.csv │ └── aVol.csv ├── Example.ipynb ├── Example.jl ├── Readme.md └── jlFiles │ ├── FindNN.jl │ ├── PanelOls.jl │ └── printmat.jl ├── FittingNfromHist ├── AbelComm200504.pdf ├── Example.ipynb ├── Example.jl ├── HistogramFitFn.jl ├── InfForc200204.pdf └── Readme.md ├── LICENSE.txt ├── LStar ├── CTData.csv ├── CarryTradeCRS201002.pdf ├── Example.ipynb ├── Example.jl ├── Readme.md └── jlFiles │ ├── FindNoNaNPs.jl │ ├── NewEst3Ps.jl │ ├── OlsLStar3Ps.jl │ ├── OlsPs.jl │ └── printmat.jl ├── NelsonSiegel ├── Example.ipynb ├── Example.jl ├── FinInfo199611.pdf ├── Readme.md └── jlFiles │ ├── BondNSxPs.jl │ ├── BondPricePs.jl │ └── printmat.jl ├── Readme.md └── SolvingReModels ├── Example.ipynb ├── Example.jl ├── MonEEA199812.pdf ├── Readme.md └── jlFiles ├── ComItAlg.jl ├── DiscAlg.jl ├── Fuhrer1.jl ├── SimpRulT.jl ├── VAR1SimPs.jl └── printmat.jl /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | 7 | # Standard to msysgit 8 | *.doc diff=astextplain 9 | *.DOC diff=astextplain 10 | *.docx diff=astextplain 11 | *.DOCX diff=astextplain 12 | *.dot diff=astextplain 13 | *.DOT diff=astextplain 14 | *.pdf diff=astextplain 15 | *.PDF diff=astextplain 16 | *.rtf diff=astextplain 17 | *.RTF diff=astextplain 18 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Windows image file caches 2 | Thumbs.db 3 | ehthumbs.db 4 | 5 | # Folder config file 6 | Desktop.ini 7 | 8 | # Recycle Bin used on file shares 9 | $RECYCLE.BIN/ 10 | 11 | # Windows Installer files 12 | *.cab 13 | *.msi 14 | *.msm 15 | *.msp 16 | 17 | # Windows shortcuts 18 | *.lnk 19 | 20 | # ========================= 21 | # Operating System Files 22 | # ========================= 23 | 24 | # OSX 25 | # ========================= 26 | 27 | .DS_Store 28 | .AppleDouble 29 | .LSOverride 30 | 31 | # Thumbnails 32 | ._* 33 | 34 | # Files that might appear in the root of a volume 35 | .DocumentRevisions-V100 36 | .fseventsd 37 | .Spotlight-V100 38 | .TemporaryItems 39 | .Trashes 40 | .VolumeIcon.icns 41 | 42 | # Directories potentially created on remote AFP share 43 | .AppleDB 44 | .AppleDesktop 45 | Network Trash Folder 46 | Temporary Items 47 | .apdisk 48 | -------------------------------------------------------------------------------- /AssetPricingTest/AssetPricingTest3bPs.jl: -------------------------------------------------------------------------------- 1 | function AssetPricingTest3bPs(Re1,Re2,f,h,bandwidth=0,q=0,PointEstOnlyQ=false) 2 | #AssetPricingTest3bPs Testing difference of two linear factor models by testing the 3 | # difference of the intercepts, or some other combination of 4 | # parameters 5 | # 6 | # 7 | # 8 | # 9 | # Usage: fnOutput = AssetPricingTest3bPs(Re1,Re2,f,h[,bandwidth[,q[,PointEstOnlyQ]]]) 10 | # 11 | # Input: Re1 Txn1, test assets 12 | # Re2 Txn2, test assets (in many applications, Re2 = Re1) 13 | # f TxK, 1st set of factors 14 | # h TxL, 2nd set of factors 15 | # bandwidth (optional) scalar of Newey-West band width, [0] 16 | # q (optional) heterogenous array of vectors, 17 | # expected values of R*theta: Any[alpha,delta], [0] 18 | # PointEstOnlyQ (optional), bool: if true, then only the point estimates are calculated [false] 19 | # 20 | # Output: fnOutput 8x1 heterogeneous array with the following content: 21 | # [1] Joint 3x1, in each row WaldStat for alpha, delta, alpha-delta (if n1=n2) 22 | # [2] Indiv 3xmax(n1,n2), t-stat of alfa,delta and alpha-delta (if n1=n2) 23 | # [3] bf n1x(1+K), [alpha beta] in Re1 = alpha + beta*f + errors 24 | # [4] bh n2x(1+L), [delta gamma] in Re2 = delta+ gamma*h + errors 25 | # [5] EReFit 1x2 cell array, each cell is a nx2 matrix with [actual,fitted ERe] 26 | # [6] theta [n1(1+K)+n2(1+L)]x1, estimated parameters, [alpha;vec(beta);delta;vec(gamma)] 27 | # [7] V matrix, Cov[sqrt(T)*theta] 28 | # 29 | # 30 | # 31 | # Notice: (a) the order of parameters in theta are [alpha;vec(beta);delta;vec(gamma)] from 32 | # Re1 = alpha + beta*f + errors 33 | # Re2 = delta + gamma*h + errors, 34 | # where Re1 is an n1x1 vector, Re2 is n2x1, f is is Kx1 and h is Lx1 35 | # 36 | # (b) theta2 = reshape(theta,n,1+K+1+L) 37 | # creates a matrix with [alpha beta delta gamma] 38 | # 39 | # 40 | # 41 | # 42 | # Uses: excise4mPs, HDirProdPs, NewEst3Ps 43 | # 44 | # 45 | # 46 | # 47 | # Paul.Soderlind@unisg.ch, April 2015, To Julia Oct 2015 48 | #------------------------------------------------------------------------------ 49 | 50 | n1 = size(Re1,2) 51 | n2 = size(Re2,2) 52 | if q == 0 #scalar 0 53 | q = Any[zeros(n1,1),zeros(n2,1)] #default values for options 54 | end 55 | #---------------------------------------------------------- 56 | 57 | K = size(f,2) 58 | L = size(h,2) 59 | 60 | (Re1,Re2,f,h,) = excise4mPs(Re1,Re2,f,h) 61 | T = size(Re1,1) #no. obs 62 | 63 | Ef = mean(f,1)' 64 | Eh = mean(h,1)' 65 | ERe1 = mean(Re1,1)' 66 | ERe2 = mean(Re2,1)' 67 | 68 | f1 = [ones(T,1) f] 69 | K1 = 1 + K 70 | h1 = [ones(T,1) h] 71 | L1 = 1 + L 72 | #bf = f1\Re1; epsf = Re1 - bf*f1 73 | bf = f1\Re1 74 | epsf = Re1 - f1*bf 75 | bf = bf' #n1xK1 76 | alfaM = bf[:,1] 77 | betaM = bf[:,2:end] #n1xK, Re1(t) = alfa * beta*f(t) + e(t) 78 | gf = HDirProdPs(f1,epsf) #moment conditions 79 | ERe1Hatf = betaM*Ef #n1xK1 * K1x1 80 | 81 | bh = h1\Re2 82 | epsh = Re2 - h1*bh 83 | bh = bh' #n2xL1 84 | deltaM = bh[:,1] 85 | gammaM = bh[:,2:end] #n2xL 86 | gh = HDirProdPs(h1,epsh) 87 | ERe2Hath = gammaM*Eh #n2xL1 * L1x1 88 | 89 | ERe1Fit = [ERe1 ERe1Hatf] #actual and fitted ERe 90 | ERe2Fit = [ERe2 ERe2Hath] 91 | EReFit = Any[ERe1Fit,ERe2Fit] 92 | 93 | theta = [vec(bf);vec(bh)] #parameters (combined) 94 | 95 | if PointEstOnlyQ 96 | fnOutput = Any[NaN,NaN,bf,bh,EReFit,theta,NaN,NaN] 97 | return fnOutput 98 | end 99 | #---------------------------------------------------------- 100 | 101 | g = [gf gh] #moment conditions (combined) 102 | S0 = NewEst3Ps(g,bandwidth) #Cov[sqrt(T)*gbar] 103 | g = nothing #can save some memory 104 | gf = nothing 105 | gh = nothing 106 | 107 | Sff = f1'f1/T 108 | Df_1 = -kron(inv(Sff),eye(n1)) #upper left corner of inverse of Jacobian 109 | Shh = h1'h1/T 110 | Dh_1 = -kron(inv(Shh),eye(n2)) #lower right corner of inverse of Jacobian 111 | D_1 = cat([1,2],Df_1,Dh_1) #inverse of Jacobian 112 | 113 | V = D_1*S0*D_1' #Cov[sqrt(T)*theta] 114 | #---------------------------------------------------------- 115 | 116 | RM = Any[[eye(n1) zeros(n1,n1*K) zeros(n1,n2) zeros(n1,n2*L)], #alpha 117 | [zeros(n2,n1) zeros(n2,n1*K) eye(n2) zeros(n2,n2*L)]] #delta 118 | 119 | if n1 == n2 #alpha - delta, if n1=n2 120 | RM = Any[RM[1],RM[2],RM[1] - RM[2]] 121 | q = Any[ q[1], q[2], q[1] - q[2]] 122 | end 123 | 124 | Indiv = fill(NaN,(length(RM),max(n1,n2))) #t-stat 125 | Joint = fill(NaN,length(RM)) #WaldStat 126 | for i = 1:length(RM) #loop over (alpha,delta,alpha-delta) 127 | R = RM[i] 128 | q_i = q[i] 129 | Rstat = R*theta - q_i #eg. alpha - delta - expected value 130 | Lambda = R*V*R' #eg. Cov[sqrt(T)*(alpha-delta)] 131 | stat_std = sqrt(diag(Lambda/T)) 132 | tstat = Rstat./stat_std 133 | Joint[i] = (T * Rstat'inv(Lambda)*Rstat)[1] #[1] to make it a scalar 134 | Indiv[i,1:length(tstat)] = tstat' 135 | end 136 | #---------------------------------------------------------- 137 | 138 | # 1 2 3 4 5 6 7 139 | fnOutput = Any[Joint,Indiv,bf,bh,EReFit,theta,V] 140 | 141 | return fnOutput 142 | 143 | end 144 | #------------------------------------------------------------------------------ 145 | -------------------------------------------------------------------------------- /AssetPricingTest/AssetPricingTest3dPs.jl: -------------------------------------------------------------------------------- 1 | function AssetPricingTest3dPs(Re1,Re2,f,h,bandwidth=0,q=0,CrossRegType="beta",vvR=0) 2 | #AssetPricingTest3dPs Testing difference of two linear factor models by testing the 3 | # difference of cross-sectional pricing errors. Allows Re1 ~= Re2 4 | # 5 | # 6 | # 7 | # 8 | # Usage: fnOutput = AssetPricingTest3dPs(Re1,Re2,f,h,[,bandwidth[,q[,CrossRegType[,vvR]]]]) 9 | # 10 | # Input: Re1 Txn1, test assets 11 | # Re2 Txn2, test assets (in many applications, Re2 = Re1) 12 | # f TxK, 1st set of factors, not necessarily excess returns 13 | # h TxL, 2nd set of factors 14 | # bandwidth (optional) scalar of Newey-West band width, [0] 15 | # q (optional) vector, expected values of R*theta: [alpha delta] 16 | # CrossRegType (optional) ('beta' or 'GLS') or {Kxn1;Lxn2} cell arrray, ['beta'] 17 | # vvR (optional) heterogeneous array of vectors, indices of 18 | # moment conditions to test with R*g-q 19 | # 20 | # 21 | # Output: fnOutput 8x1 heterogeneous array with the following contents: 22 | # [1] Joint 3x1, in each row WaldStat for alpha, delta, alpha-delta (if n1=n2) 23 | # [2] Indiv 3xmax(n1,n2), t-stat of alfa,delta and alpha-delta (if n1=n2) 24 | # [3] bf 25 | # [4] bh 26 | # [5] EReFit 1x2 cell array, each cell is a nx2 matrix with [actual,fitted ERe] 27 | # [6] theta [n1(1+K)+n2(1+L)]x1, estimated parameters, [alpha;vec(beta);delta;vec(gamma)] 28 | # Notice the order of parameters: [for const; for factor 1;...] 29 | # [7] V matrix, Cov[sqrt(T)*theta] 30 | # 31 | # 32 | # 33 | # Uses: excise, HDirProdPs, NewEst3Ps 34 | # 35 | # 36 | # 37 | # 38 | # Paul.Soderlind@unisg.ch, June 2015, to Julia Dec 2015 39 | #------------------------------------------------------------------------------ 40 | 41 | n1 = size(Re1,2) 42 | n2 = size(Re2,2) 43 | if q == 0 #scalar 0 44 | q = Any[zeros(n1,1),zeros(n2,1)] #default values for options 45 | end 46 | if vvR == 0 47 | vvR = Any[1:n1,1:n2] 48 | end 49 | #---------------------------------------------------------- 50 | 51 | K = size(f,2) 52 | L = size(h,2) 53 | 54 | (Re1,Re2,f,h,) = excise4mPs(Re1,Re2,f,h) 55 | T = size(Re1,1) #no. obs 56 | 57 | Ef = mean(f,1)' 58 | Eh = mean(h,1)' 59 | ERe1 = mean(Re1,1)' 60 | ERe2 = mean(Re2,1)' 61 | 62 | f1 = [ones(T,1) f] 63 | K1 = 1 + K 64 | h1 = [ones(T,1) h] 65 | L1 = 1 + L 66 | 67 | bf = f1\Re1 68 | epsf = Re1 - f1*bf 69 | bf = bf' #n1xK1 70 | alfaM = bf[:,1] 71 | betaM = bf[:,2:end] #n1xK, Re1(t) = alfa * beta*f(t) + e(t) 72 | gf = HDirProdPs(f1,epsf) #moment conditions 73 | 74 | bh = h1\Re2 75 | epsh = Re2 - h1*bh 76 | bh = bh' #n2xL1 77 | deltaM = bh[:,1] 78 | gammaM = bh[:,2:end] #n2xL 79 | gh = HDirProdPs(h1,epsh) 80 | #---------------------------------------------------------- 81 | 82 | if CrossRegType == "beta" 83 | B = betaM' #traditional cross-sectional regression 84 | G = gammaM' 85 | elseif CrossRegType == "GLS" 86 | B = betaM'* inv(cov(epsf)) #GLS 87 | G = gammaM'*inv(cov(epsh)) 88 | else 89 | B = CrossRegType[1] #predefined matrix 90 | G = CrossRegType[2] 91 | end 92 | #cross-sectional estimate of price of factor risk 93 | lambda = (B*betaM)\(B*ERe1) #solve (B*betaM)*lambda = B*ERe 94 | psi = (G*gammaM)\(G*ERe2) 95 | theta = [vec(bf);lambda;vec(bh);psi] #parameters (combined) 96 | 97 | EReHatf = betaM*lambda #nxK1 * K1x1 98 | EReHath = gammaM*psi #nxL1 * L1x1 99 | EReFit = Any[[ERe1 EReHatf],[ERe2 EReHath]] #actual and fitted ERe 100 | 101 | gfb = Re1 .- EReHatf' #moment condition ERe - beta*lambda 102 | ghb = Re2 .- EReHath' #moment condition ERe - gamma*psi 103 | 104 | g = [gf gfb gh ghb] #moment conditions (combined) 105 | S = NewEst3Ps(g,bandwidth) #Cov[sqrt(T)*gbar] 106 | gf = nothing #can save some memory 107 | gfb = nothing 108 | gh = nothing 109 | ghb = nothing 110 | 111 | gbar = mean(g,1)' #moment conditions, sample average 112 | gNum = size(g,2) #no. moment conditions 113 | 114 | 115 | Sff = f1'f1/T #Jacobian 116 | Df11 = kron(Sff,eye(n1)) #upper left corner 117 | Shh = h1'h1/T 118 | Dh11 = kron(Shh,eye(n2)) 119 | Df12 = kron([0.0 vec(lambda)'],eye(n1)) #lower left 120 | Dh12 = kron([0.0 vec(psi)'], eye(n2)) 121 | Df = - [ Df11 zeros(n1*(1+K),K); 122 | Df12 betaM ] 123 | Dh = - [ Dh11 zeros(n2*(1+L),L); 124 | Dh12 gammaM ] 125 | D = cat([1,2],Df,Dh) #block diagonal cat 126 | 127 | A = cat([1,2],eye(n1*K1),B,eye(n2*L1),G) 128 | 129 | 130 | AD_1 = inv(A*D) 131 | V = AD_1*A*S*A'AD_1' #Cov[sqrt(T)*theta] 132 | Psia = eye(gNum) - D*AD_1*A 133 | Psi = Psia*S*Psia' #Cov[sqrt(T) gbar], rank gNum-k 134 | #---------------------------------------------------------- 135 | 136 | RM1 = [zeros(n1,n1*K1) eye(n1) zeros(n1,n2*L1) zeros(n1,n2)] #Re1 - beta*lambda 137 | RM2 = [zeros(n2,n1*K1) zeros(n2,n1) zeros(n2,n2*L1) eye(n2) ] #Re2 - gamma*psi 138 | RM = Any[RM1[vvR[1],:],RM2[vvR[2],:]] #pick out rows 139 | 140 | if size(RM[1],1) == size(RM[2],1) 141 | RM = Any[RM[1],RM[2],RM[1] - RM[2]] 142 | q = Any[ q[1], q[2], q[1] - q[2]] 143 | end 144 | 145 | Indiv = fill(NaN,(length(RM),max(n1,n2))) #t-stat 146 | Joint = fill(NaN,length(RM)) #WaldStat 147 | for i = 1:length(RM) #loop over (alpha,delta,alpha-delta) 148 | R = RM[i] 149 | q_i = q[i] 150 | Rstat = R*gbar - vec(q_i) #eg. gbar[2:3] 151 | Lambda = R*Psi*R' #eg. Cov[sqrt(T)*gbar[2:3] 152 | stat_std = sqrt(diag(Lambda/T)) 153 | tstat = Rstat./stat_std 154 | Joint_i = T * Rstat'pinv(Lambda)*Rstat #reduced rank 155 | Joint[i] = Joint_i[1] #[1] to make it a scalar 156 | Indiv[i,1:length(tstat)] = tstat' 157 | end 158 | #---------------------------------------------------------- 159 | 160 | # 1 2 3 4 5 6 7 161 | fnOutput = Any[Joint,Indiv,bf,bh,EReFit,theta,V] 162 | 163 | return fnOutput 164 | 165 | end 166 | #------------------------------------------------------------------------------ 167 | -------------------------------------------------------------------------------- /AssetPricingTest/ExampleAPTsT.jl: -------------------------------------------------------------------------------- 1 | #------------------------------------------------------------------------------ 2 | # ExampleAPTsT.jl 3 | # 4 | # For testing the AssetPricingTest3bPs (alpha test) and 5 | # AssetPricingTest3dPs (cross-sectional test) functions 6 | # 7 | # The data is from the webpage of Kenneth R. French, 8 | # http://mba.tuck.dartmouth.edu/pages/faculty/ken.french/data_library.html 9 | # 10 | # 11 | # 12 | # Paul.Soderlind@unisg.ch May 2015, To Julia Oct/Dec 2015 13 | #------------------------------------------------------------------------------ 14 | 15 | include("excise.jl") 16 | include("NewEst3Ps.jl") 17 | include("HDirProdPs.jl") 18 | include("AssetPricingTest3bPs.jl") 19 | include("AssetPricingTest3dPs.jl") 20 | #------------------------------------------------------------------------------ 21 | 22 | vvRe = [1;6;13;19;25] #which of the 25 FF portfolios to use as test assets 23 | 24 | xx = readdlm("FFmFactorsPs.csv",',',header=true) 25 | x = xx[1] 26 | Rme = x[:,2] 27 | RSMB = x[:,3] #small minus big firms 28 | RHML = x[:,4] #high minus low book-to-market ratio 29 | Rf = x[:,5] #interest rate 30 | xx = nothing 31 | x = nothing 32 | 33 | 34 | f = Rme + 0.0 35 | g = [RSMB RHML] 36 | h = [f g] 37 | 38 | 39 | x = readdlm("FF25Ps.csv",',') #no header line: x is matrix 40 | R = x[:,2:end] #returns for 25 FF portfolios 41 | Re = R .- Rf #excess returns for the 25 FF portfolios 42 | Re = Re[:,vvRe] 43 | (T,n) = size(Re) 44 | K = size(f,2) 45 | L = size(h,2) 46 | M = L - K 47 | x = nothing 48 | #------------------------------------------------------------------------------ 49 | 50 | println("\n------------AssetPricingTest3bPs-----------------") 51 | 52 | fnOutput = AssetPricingTest3bPs(Re,Re,f,h) 53 | Joint_b = fnOutput[1] 54 | Indiv_b = fnOutput[2] 55 | 56 | println("\n 3x1, WaldStat for alpha, delta, alpha-delta ") 57 | println(round(Joint_b,2)) 58 | println("\n nx3, Individual t-stats for alpha, delta, alpha-delta ") 59 | display(round(Indiv_b',2)) 60 | #---------------------------------------------------------- 61 | 62 | 63 | println("\n ---------------AssetPricingTest3dPs: test of ERe - beta*lambda--------") 64 | 65 | fnOutput = AssetPricingTest3dPs(Re,Re,f,h,0,0,"GLS") 66 | Joint_d = fnOutput[1] 67 | println("\n 3x1, WaldStat for pricing error 1, pricing error 2, difference of pricing errors ") 68 | println(round(Joint_d,2)) 69 | 70 | 71 | println("\n ---------------AssetPricingTest3dPs: test of ERe - beta*lambda, II--------") 72 | println("set up to replicate TS approach") 73 | 74 | vvR = Any[1:n,1:n] 75 | q = Any[zeros(n,1),zeros(n,1)] 76 | BG = Any[[zeros(K,n) eye(K)],[zeros(L,n) eye(L)]] 77 | fnOutput = AssetPricingTest3dPs([Re f],[Re h],f,h,0,q,BG,vvR) 78 | Joint_d = fnOutput[1] 79 | println("3x1, WaldStat for pricing error 1, pricing error 2, difference of pricing errors ") 80 | println(round(Joint_d,2)) 81 | #------------------------------------------------------------------------------ 82 | 83 | -------------------------------------------------------------------------------- /AssetPricingTest/FFmFactorsPs.csv: -------------------------------------------------------------------------------- 1 | ,Mkt-RF,SMB,HML,RF,Mom,ST_Rev,LT_Rev 2 | 197901,4.23,3.69,2.25,0.77,-1.27,5.49,-0.76 3 | 197902,-3.56,0.46,1.18,0.73,-1.05,1.28,0.94 4 | 197903,5.68,3.19,-0.65,0.81,2.89,1.41,-0.35 5 | 197904,-0.06,2.16,1.07,0.8,0.8,-0.35,-0.39 6 | 197905,-2.21,0.49,1.83,0.82,-0.26,0.88,0.75 7 | 197906,3.85,1.16,1.44,0.81,0.84,1.21,-2.71 8 | 197907,0.82,1.26,1.72,0.77,-1.09,0.61,-2.02 9 | 197908,5.53,2.08,-1.52,0.77,-0.25,0.8,-1.73 10 | 197909,-0.82,-0.26,-0.92,0.83,5.32,-1.56,0.06 11 | 197910,-8.1,-3.33,-1.86,0.87,2.15,-1.95,1.54 12 | 197911,5.21,2.74,-3.28,0.99,7.95,1.37,-2.26 13 | 197912,1.79,4.17,-2.01,0.95,4.77,-1.92,-0.3 14 | 198001,5.51,1.65,1.82,0.8,7.5,-3.39,-0.91 15 | 198002,-1.22,-1.81,0.61,0.89,7.86,-4.97,-0.07 16 | 198003,-12.9,-6.64,-1.06,1.21,-9.58,8.38,2.62 17 | 198004,3.97,0.97,1.06,1.26,-0.42,1.37,-0.13 18 | 198005,5.26,2.16,0.4,0.81,-1.12,2.87,0.75 19 | 198006,3.06,1.67,-0.9,0.61,1.59,2.18,-2.9 20 | 198007,6.49,4.24,-6.35,0.53,0.37,2.91,-1.67 21 | 198008,1.8,3.9,-2.65,0.64,3.2,-0.99,-1.54 22 | 198009,2.19,0.86,-4.74,0.75,5.43,-1.43,-1.76 23 | 198010,1.06,2.49,-2.77,0.95,7.33,-1.99,-2.84 24 | 198011,9.59,-3.48,-8.45,0.96,15.24,-9.84,-7.79 25 | 198012,-4.52,-0.28,2.69,1.31,-6.63,6.39,3.45 26 | 198101,-5.04,3,6.82,1.04,-7.94,-2.26,7.6 27 | 198102,0.56,-0.3,1.02,1.07,-1.39,-2.22,2.58 28 | 198103,3.56,3.58,0.7,1.21,0.74,1.62,1.57 29 | 198104,-2.1,4.43,2.29,1.08,-0.96,-1.53,2.83 30 | 198105,0.11,2.01,-0.41,1.15,3.75,-3.71,1.61 31 | 198106,-2.36,-0.84,5.09,1.35,-5.91,4.75,0.95 32 | 198107,-1.54,-2.17,-0.6,1.24,-2.52,-0.59,-3.53 33 | 198108,-7.03,-1.95,4.83,1.28,-1.12,-0.66,1.27 34 | 198109,-7.17,-2.66,5.17,1.24,1.98,-1.15,5.23 35 | 198110,4.92,2.16,-4.19,1.21,4.08,4.66,-4.9 36 | 198111,3.36,-0.96,1.9,1.07,-0.26,2.59,0.6 37 | 198112,-3.65,1.19,0.75,0.87,1.31,1.62,1.38 38 | 198201,-3.24,-1.28,3.12,0.8,1.71,-1.22,6.42 39 | 198202,-5.86,0.45,6.04,0.92,5,-4.32,5.95 40 | 198203,-1.87,-0.18,3.82,0.98,2.93,-1.86,3.99 41 | 198204,3.27,1.51,-2.8,1.13,-0.41,1.66,-1.72 42 | 198205,-3.99,0.46,1.83,1.06,2.55,1.93,1.58 43 | 198206,-3.09,-0.39,1.54,0.96,4.99,0.16,1.93 44 | 198207,-3.19,0.86,0.2,1.05,4.47,-2.91,2.36 45 | 198208,11.14,-4.11,1.16,0.76,-3.52,1.12,-0.99 46 | 198209,1.29,2.89,0.34,0.51,4.16,4.29,-0.45 47 | 198210,11.3,2.36,-3.69,0.59,0.03,2.88,-0.95 48 | 198211,4.67,4.79,-1.92,0.63,5.9,-4.47,1.03 49 | 198212,0.55,-0.18,0.02,0.67,0.02,3.78,1.05 50 | 198301,3.6,2.7,-0.86,0.69,-1.7,3.13,0.06 51 | 198302,2.59,3.24,0.68,0.62,3.82,2.69,-0.46 52 | 198303,2.82,1.77,2.07,0.63,0.93,0.37,0.94 53 | 198304,6.67,0.52,0.58,0.71,1.81,-0.51,3.21 54 | 198305,0.52,6.15,-1.4,0.69,-1.58,2.74,-2.1 55 | 198306,3.07,0.91,-3.89,0.67,1.78,0.2,-0.9 56 | 198307,-4.07,1.48,5.58,0.74,-3.12,2,1.04 57 | 198308,-0.5,-4.29,5.54,0.76,-5.44,-0.6,0.1 58 | 198309,0.92,0.56,1.06,0.76,-0.11,2.33,0.82 59 | 198310,-3.44,-3.6,5,0.76,-4.56,-1.68,1.11 60 | 198311,2.16,2.05,-0.65,0.7,-0.08,4.88,-1.34 61 | 198312,-1.78,-0.28,1.68,0.73,0.77,1.9,1.36 62 | 198401,-1.92,-0.42,7.6,0.76,-2.49,0.66,4.25 63 | 198402,-4.82,-1.68,3.31,0.71,0.19,-2.02,0.23 64 | 198403,0.63,0.08,0.49,0.73,1.1,2.42,0.74 65 | 198404,-0.52,-1.19,1.24,0.81,2.05,1.51,-1.58 66 | 198405,-5.97,0.04,0.23,0.78,1.53,0.86,-0.23 67 | 198406,1.82,-0.28,-2.63,0.75,-0.7,0.94,-3.63 68 | 198407,-2.74,-2.22,0.39,0.82,2.93,-1.49,-1.63 69 | 198408,10.28,-0.22,-1.83,0.83,-5.68,7.28,-1.69 70 | 198409,-0.8,0.21,5.31,0.86,3.7,4.35,1.78 71 | 198410,-0.84,-1.2,0.48,1,3.22,-1.26,-1.77 72 | 198411,-1.76,-0.62,4.04,0.73,1.7,-0.67,1.03 73 | 198412,1.84,-0.58,-0.14,0.64,1.53,0.75,-3.09 74 | 198501,7.99,3.26,-5.39,0.65,-6.91,2.32,-1.91 75 | 198502,1.22,0.78,-0.17,0.58,1.82,2.43,-0.13 76 | 198503,-0.84,-1.11,4.03,0.62,1.69,-1.29,-0.72 77 | 198504,-0.96,0.17,3.71,0.72,3.05,-2.47,0.15 78 | 198505,5.09,-2.27,-0.88,0.66,4,-0.49,-3.99 79 | 198506,1.27,0.5,0.46,0.55,3.63,-0.63,-2.38 80 | 198507,-0.74,2.85,-1.67,0.62,-3.94,3.62,1.67 81 | 198508,-1.02,-0.32,2.29,0.55,1.81,1.82,0.11 82 | 198509,-4.54,-1.59,1.29,0.6,1.48,-1.83,-0.8 83 | 198510,4.02,-1.56,0.77,0.65,4.87,0.72,-2.44 84 | 198511,6.48,0.21,-2.93,0.61,-0.41,2.35,-2.39 85 | 198512,3.88,-0.49,-1.56,0.65,-0.12,-0.63,-3.14 86 | 198601,0.65,1.2,0.53,0.56,2.96,0.73,-2.83 87 | 198602,7.13,-0.64,-0.88,0.53,2.77,-1.64,-3.66 88 | 198603,4.88,-0.51,-0.51,0.6,2.45,-0.23,-2.24 89 | 198604,-1.31,2.83,-2.9,0.52,-0.5,2.84,-1.17 90 | 198605,4.62,-1.31,-0.12,0.49,2.02,0.97,-1.37 91 | 198606,1.03,-0.93,1.39,0.52,5.14,-2.36,-6.44 92 | 198607,-6.45,-3.37,4.76,0.52,1.8,-3.05,-4.02 93 | 198608,6.07,-4.17,3.52,0.46,-5.02,1.16,4.76 94 | 198609,-8.6,2.28,3.2,0.45,-5.86,-0.33,3.83 95 | 198610,4.66,-2.56,-1.44,0.46,2.7,3.55,0.64 96 | 198611,1.17,-1.98,-0.09,0.39,-0.33,0.69,0.13 97 | 198612,-3.27,0.08,0.31,0.49,0.4,0.56,0.54 98 | 198701,12.47,-1.79,-3.21,0.42,2.08,0.42,3.13 99 | 198702,4.39,3.46,-5.96,0.43,-2.17,-1.08,-0.13 100 | 198703,1.64,0.4,1.59,0.47,1.6,1.81,4.22 101 | 198704,-2.11,-1.7,-0.32,0.44,0.25,-1.89,3.92 102 | 198705,0.11,-0.55,0.16,0.38,-0.68,-0.25,2.22 103 | 198706,3.94,-2.17,1.06,0.48,-0.2,0.11,-1.45 104 | 198707,3.85,-0.63,0.71,0.46,2.68,-0.16,2.34 105 | 198708,3.52,-0.75,-0.91,0.47,-0.89,2.55,-3.06 106 | 198709,-2.59,0.54,0.28,0.45,0.72,-0.39,3.07 107 | 198710,-23.24,-8.4,4.2,0.6,-7.87,0.11,-6.27 108 | 198711,-7.77,2.64,3.23,0.35,-1.13,-0.79,-0.42 109 | 198712,6.81,0.15,-4.43,0.39,5.81,5.93,2.87 110 | 198801,4.21,-0.69,5.16,0.29,-7.63,7.89,-1.6 111 | 198802,4.75,3.35,-1.64,0.46,-1.54,4.35,1.52 112 | 198803,-2.27,6.15,0.74,0.44,0.64,-0.89,1.21 113 | 198804,0.56,0.96,1.7,0.46,2.28,0.34,0.47 114 | 198805,-0.29,-2.65,2.28,0.51,0.65,0.57,-0.17 115 | 198806,4.79,2.1,-1.12,0.49,-2.92,1.83,1.75 116 | 198807,-1.25,-0.19,2.26,0.51,0.64,3.39,-1.34 117 | 198808,-3.31,0.09,2.08,0.59,0.33,-1.95,-2.02 118 | 198809,3.3,-1.27,-0.67,0.62,0.24,-0.14,-1.91 119 | 198810,1.15,-2.9,1.67,0.61,1.31,-0.92,-0.11 120 | 198811,-2.29,-1.72,1.27,0.57,0.42,-0.67,-0.84 121 | 198812,1.49,1.94,-1.54,0.63,0.42,2.25,0.79 122 | 198901,6.1,-2.13,0.53,0.55,-0.14,1.06,2.9 123 | 198902,-2.25,2.77,0.86,0.61,0.93,1.08,0.9 124 | 198903,1.57,0.73,0.48,0.67,3.56,-0.88,0.14 125 | 198904,4.33,-0.6,-1.45,0.67,1.7,-0.71,-1.1 126 | 198905,3.35,-0.04,-0.84,0.79,1.55,-2.74,-1.69 127 | 198906,-1.35,-1.01,2.17,0.71,0.66,2.25,-0.72 128 | 198907,7.2,-4.02,-2.81,0.7,5.4,1.29,-1.82 129 | 198908,1.44,0.53,0.65,0.74,-0.14,1.85,0.17 130 | 198909,-0.76,0.3,-1.34,0.65,3.39,1.18,-2.81 131 | 198910,-3.67,-3.26,-1.09,0.68,1.37,-4.26,-3.56 132 | 198911,1.03,-1.22,-1.08,0.69,2.57,-1.75,-1.25 133 | 198912,1.16,-2.38,0.24,0.61,2.78,-2.54,-0.86 134 | 199001,-7.85,-1.3,0.89,0.57,-3.32,1.09,3.24 135 | 199002,1.11,1.05,0.63,0.57,-0.52,0.43,1.9 136 | 199003,1.83,1.48,-2.86,0.64,1.66,0.23,-0.13 137 | 199004,-3.36,-0.5,-2.58,0.69,2.46,-2.02,-1.12 138 | 199005,8.42,-2.56,-3.74,0.68,3.05,-0.45,0.93 139 | 199006,-1.09,1.45,-2.01,0.63,2.42,-0.19,-1.47 140 | 199007,-1.9,-3.2,-0.01,0.68,5.93,-0.56,-1.8 141 | 199008,-10.14,-3.59,1.6,0.66,1.8,-3.51,1.59 142 | 199009,-6.12,-3.67,0.74,0.6,5.52,-6,0.7 143 | 199010,-1.92,-5.54,0.25,0.68,6.73,-2.64,-3.5 144 | 199011,6.35,0.33,-3.07,0.57,-5.61,5.89,-0.64 145 | 199012,2.46,0.82,-1.55,0.6,0.15,-3.1,-2.26 146 | 199101,4.69,3.8,-1.84,0.52,-6.52,-2.04,6.16 147 | 199102,7.19,3.91,-0.6,0.48,-4.82,1.97,1.13 148 | 199103,2.65,3.9,-1.2,0.44,2.81,0.48,-0.36 149 | 199104,-0.28,0.51,1.4,0.53,-2.39,1.6,-1.19 150 | 199105,3.64,-0.34,-0.55,0.47,-0.11,0.35,1.36 151 | 199106,-4.94,0.06,1.19,0.42,0.46,2.1,-1.69 152 | 199107,4.24,-0.94,-1.29,0.49,4.32,2.07,0.81 153 | 199108,2.32,1.6,-0.8,0.46,1.6,-2.92,-0.44 154 | 199109,-1.59,1.63,-1,0.46,1.73,-0.85,-0.79 155 | 199110,1.28,0.89,-0.48,0.42,3.19,-1.28,2.24 156 | 199111,-4.19,-0.48,-1.92,0.39,1.26,-0.4,-2.68 157 | 199112,10.83,-2.25,-4.04,0.38,8.29,1.01,-0.95 158 | 199201,-0.59,8.46,4.53,0.34,-2.47,5.29,9.48 159 | 199202,1.09,0.88,6.38,0.28,-0.61,-2.69,5.42 160 | 199203,-2.65,-1.02,3.67,0.34,-0.35,-1.09,1.41 161 | 199204,1.08,-6.1,4.32,0.32,-2.6,-3.36,0.7 162 | 199205,0.3,0.39,1.25,0.28,0.1,-0.17,-0.47 163 | 199206,-2.34,-3.1,3.39,0.32,-0.6,0.87,1.28 164 | 199207,3.77,-0.43,-0.53,0.31,1.43,2.05,-1.23 165 | 199208,-2.38,-0.11,-1.05,0.26,-0.52,-1.55,-4.08 166 | 199209,1.19,0.55,-0.24,0.26,1.44,-1.15,-0.02 167 | 199210,1.02,2.05,-2.09,0.23,2.73,-0.16,-1.09 168 | 199211,4.13,3.7,-1.47,0.23,-0.34,-1.05,0.28 169 | 199212,1.53,1.65,2.52,0.28,4.47,1.21,0.8 170 | 199301,0.93,2.05,5.89,0.23,4.82,-0.52,5.54 171 | 199302,0.13,-3.43,6.45,0.22,3.13,-1.41,4.28 172 | 199303,2.3,0.25,1.27,0.25,3.74,-0.94,1.74 173 | 199304,-3.05,-0.68,2.64,0.24,0.34,-1.71,2.5 174 | 199305,2.88,1.96,-3.42,0.22,0.29,1.45,1.22 175 | 199306,0.31,-0.3,2.62,0.25,4.59,2.25,1.71 176 | 199307,-0.34,0.95,3.26,0.24,3.24,-2.67,0.98 177 | 199308,3.72,0.32,-0.44,0.25,2.58,1.23,1.24 178 | 199309,-0.12,3.12,-0.48,0.26,3.4,0.66,0.36 179 | 199310,1.41,1.44,-1.56,0.22,-2.67,1.93,1.74 180 | 199311,-1.89,-1.43,-0.26,0.25,-4.71,-1.37,1.47 181 | 199312,1.65,1.22,0.58,0.23,2.29,1.14,0.5 182 | 199401,2.87,0.13,2.09,0.25,0.01,1.73,3.76 183 | 199402,-2.56,2.72,-1.41,0.21,-0.26,0.42,-0.18 184 | 199403,-4.78,-0.97,1.33,0.27,-1.32,0.11,0.59 185 | 199404,0.68,-0.92,1.68,0.27,0.41,-0.34,0.17 186 | 199405,0.58,-2.02,0.17,0.31,-2.16,0.07,1.63 187 | 199406,-3.03,-0.48,1.68,0.31,-0.83,0.18,0.45 188 | 199407,2.82,-1.77,0.97,0.28,0.19,1.41,0.5 189 | 199408,4.01,1.44,-3.45,0.37,1.54,1.46,2.32 190 | 199409,-2.31,2.67,-1.81,0.37,1.31,-0.73,1.71 191 | 199410,1.34,-2.2,-2.36,0.38,1.45,-0.25,0.54 192 | 199411,-4.04,-0.17,-0.05,0.37,-0.19,-2.1,-1.63 193 | 199412,0.86,0.05,0.27,0.44,3.5,0.83,0.1 194 | 199501,1.8,-2.95,1.64,0.42,-1.83,4.06,-0.61 195 | 199502,3.63,-0.33,0.38,0.4,-0.34,2.39,-1.01 196 | 199503,2.18,-0.38,-2.05,0.46,0.36,-0.12,1.12 197 | 199504,2.11,-0.42,1.7,0.44,1.82,-0.56,0.4 198 | 199505,2.9,-2.25,1.92,0.54,-0.44,-0.41,-1.09 199 | 199506,2.72,3.06,-2.99,0.47,2.89,1.24,-1.82 200 | 199507,3.72,2.23,-2.24,0.45,2.55,-2.24,-0.92 201 | 199508,0.55,1.83,1.93,0.47,0.09,1.32,-1.13 202 | 199509,3.35,-2.07,-0.95,0.43,2.72,-0.84,-0.95 203 | 199510,-1.52,-3.95,-0.09,0.47,4.14,-1.06,0.51 204 | 199511,3.95,-0.83,0.34,0.42,-0.62,0.55,0.62 205 | 199512,1.03,0.37,1.41,0.49,2.57,-0.95,3.96 206 | 199601,2.26,-2.48,0.4,0.43,0.56,1.07,1.29 207 | 199602,1.33,2.06,-2.33,0.39,0.58,2.15,-1.33 208 | 199603,0.73,1.31,1.27,0.39,-1.89,-0.06,-0.25 209 | 199604,2.06,4.87,-4.02,0.46,-0.92,0.72,-0.77 210 | 199605,2.36,3.16,-1.4,0.42,1.59,-1.05,1.17 211 | 199606,-1.14,-3.64,1.92,0.4,1,-0.23,-0.13 212 | 199607,-5.97,-3.58,4.37,0.45,-0.12,-2.51,-0.01 213 | 199608,2.76,2.29,-0.6,0.41,0,2.66,-1.54 214 | 199609,5.02,-0.8,-3.77,0.44,2.71,0.55,-2.13 215 | 199610,0.86,-4.11,4.8,0.42,3.9,-1.12,0.06 216 | 199611,6.25,-3.59,0.16,0.41,-2.24,0.17,-2.44 217 | 199612,-1.7,3.08,1.01,0.46,0.57,0.54,-0.57 218 | 199701,4.99,-1.52,-2.33,0.45,1.95,2.71,-1.58 219 | 199702,-0.49,-2.6,4.68,0.39,-2.03,1.28,0.83 220 | 199703,-5.03,-0.33,3.86,0.43,0.94,0.9,2.07 221 | 199704,4.04,-5.2,-1.03,0.43,4.9,2.38,-4.07 222 | 199705,6.74,4.83,-4.37,0.49,-5.17,2.84,-2.21 223 | 199706,4.1,1.49,0.75,0.37,2.62,0.82,0.18 224 | 199707,7.33,-2.51,-0.13,0.43,3.83,3.83,-1.16 225 | 199708,-4.15,7.34,1.36,0.41,-2.51,-0.06,3.17 226 | 199709,5.35,2.68,-0.23,0.44,1.45,1.67,-0.4 227 | 199710,-3.8,-0.79,2.18,0.42,-0.4,-1,0.37 228 | 199711,2.98,-5.06,0.98,0.39,0.29,-2.02,1.01 229 | 199712,1.32,-2.4,3.8,0.48,3.87,-2.98,0.1 230 | 199801,0.15,-0.92,-2.03,0.43,0.08,4.96,-1.11 231 | 199802,7.03,0.33,-0.88,0.39,-1.1,1.87,-1.2 232 | 199803,4.76,-1,1.25,0.39,2.14,1.8,2.3 233 | 199804,0.73,0.48,0.32,0.43,0.78,1.72,-0.93 234 | 199805,-3.07,-3.54,4.11,0.4,1.87,0.69,1.49 235 | 199806,3.18,-3.14,-2.2,0.41,7.27,-1.45,-0.73 236 | 199807,-2.46,-4.92,-1.16,0.4,3.69,-1.98,0.42 237 | 199808,-16.08,-5.75,5.22,0.43,1.9,-2.68,4.47 238 | 199809,6.15,-0.17,-3.88,0.46,-0.71,2.8,0.24 239 | 199810,7.13,-3.19,-2.75,0.32,-5.36,9.87,-4.19 240 | 199811,6.1,1.14,-3.44,0.31,1.17,1.27,-0.38 241 | 199812,6.16,-0.3,-4.7,0.38,9.04,-1.65,-1 242 | 199901,3.5,0.86,-5.56,0.35,3.02,-2.29,1.12 243 | 199902,-4.08,-5.54,1.56,0.35,-0.13,2.4,0.37 244 | 199903,3.45,-3.83,-2.9,0.43,-1.35,0.24,-0.97 245 | 199904,4.33,3.19,2.43,0.37,-9.13,2.37,5.11 246 | 199905,-2.46,3.62,2.68,0.34,-5.25,1.13,3.4 247 | 199906,4.77,3.46,-4.19,0.4,4.93,1.58,0.39 248 | 199907,-3.47,2.21,0.54,0.38,1.61,1.39,1.92 249 | 199908,-1.38,-1.34,-0.88,0.39,3.01,-3.52,-1.55 250 | 199909,-2.81,3.18,-3.04,0.39,6.49,-0.82,0.17 251 | 199910,6.13,-6.79,-3.18,0.39,5.47,-1.17,-2.71 252 | 199911,3.37,7.76,-7.96,0.36,5.69,0.1,5.13 253 | 199912,7.72,7,-9.17,0.44,13.19,-14.03,5.59 254 | 200001,-4.74,4.37,0.26,0.41,1.88,2.71,1.89 255 | 200002,2.45,22.02,-12.61,0.43,18.39,-13.4,7.56 256 | 200003,5.2,-16.4,7.65,0.47,-6.84,10.09,-5.17 257 | 200004,-6.4,-7.7,9.09,0.46,-8.47,-1.96,0.33 258 | 200005,-4.42,-4.85,3.72,0.5,-9.07,-8.77,-1.75 259 | 200006,4.64,13.69,-10.02,0.4,16.52,12.28,2.4 260 | 200007,-2.51,-2.78,8.49,0.48,-0.12,6.5,-3.31 261 | 200008,7.03,-0.92,-1.23,0.5,5.68,0.43,1 262 | 200009,-5.45,-1.94,6.8,0.51,2.15,2.47,-2.57 263 | 200010,-2.76,-3.62,4.81,0.56,-4.69,-4.78,-1.1 264 | 200011,-10.72,-3.14,12.32,0.51,-2.5,-14.54,0.34 265 | 200012,1.19,1.52,6.17,0.5,6.84,-6.63,2.92 266 | 200101,3.13,7.1,-5.74,0.54,-24.95,16.22,-2.5 267 | 200102,-10.05,-1.18,13.88,0.38,12.57,12.35,11.06 268 | 200103,-7.26,0.55,6.35,0.42,8.38,-7.68,3.86 269 | 200104,7.94,0.29,-4.36,0.39,-8.13,9.98,-3.84 270 | 200105,0.72,3,2.77,0.32,2.38,3.61,4.02 271 | 200106,-1.94,6.43,-2.27,0.28,0.36,0.49,1.9 272 | 200107,-2.13,-4.23,5.64,0.3,5.5,1.17,2.77 273 | 200108,-6.46,2.09,3.43,0.31,5.6,-3.98,5.91 274 | 200109,-9.25,-6.59,1.78,0.28,11.57,-4.91,-0.04 275 | 200110,2.46,6.88,-7.06,0.22,-8.41,14.85,-1.61 276 | 200111,7.54,0.32,0.76,0.17,-8.55,-3.1,0.29 277 | 200112,1.61,5.13,0.45,0.15,-0.03,1.65,1.26 278 | 200201,-1.44,1.11,3.46,0.14,3.78,1.53,3.5 279 | 200202,-2.29,-1.62,3.92,0.13,6.79,-0.1,4.1 280 | 200203,4.24,4.32,1.15,0.13,-1.73,2.86,2.16 281 | 200204,-5.2,5.85,4.23,0.15,7.92,2.09,6.15 282 | 200205,-1.38,-3.7,2.51,0.14,3.16,-2.74,2.61 283 | 200206,-7.21,3.54,1.49,0.13,6.17,-3.37,2.23 284 | 200207,-8.18,-5.19,-3.65,0.15,3.41,1.53,-2.87 285 | 200208,0.5,-2.26,2.29,0.14,1.76,1.4,-0.64 286 | 200209,-10.35,2.71,1.25,0.14,9.12,-1.82,-0.6 287 | 200210,7.84,-2.96,-6.46,0.14,-5.47,7.49,-0.4 288 | 200211,5.96,3.15,-1.54,0.12,-16.3,0.37,3.95 289 | 200212,-5.76,-0.46,3.87,0.11,9.64,10.57,2.23 290 | 200301,-2.57,1.39,-0.84,0.1,1.54,0.26,0.43 291 | 200302,-1.88,-0.29,-1.44,0.09,1.23,-0.79,-1.9 292 | 200303,1.09,0.74,-1.59,0.1,1.56,-0.25,-2.64 293 | 200304,8.22,1.08,-0.04,0.1,-9.45,3.19,-0.97 294 | 200305,6.05,4.83,0.09,0.09,-10.74,-1.43,3.36 295 | 200306,1.42,1.5,0.73,0.1,-1.01,-0.12,1.42 296 | 200307,2.35,5.51,-2.06,0.07,-0.37,2.54,0.4 297 | 200308,2.34,2.7,1.71,0.07,-0.51,-1.46,-0.33 298 | 200309,-1.24,0.58,0.98,0.08,-0.06,4.44,1.14 299 | 200310,6.08,2.88,1.79,0.07,3.71,2.04,2.04 300 | 200311,1.35,2.23,1.46,0.07,1.63,-1.45,1.94 301 | 200312,4.29,-2.79,2.71,0.08,-5.73,1.73,2.09 302 | 200401,2.15,2.67,1.55,0.07,2.62,2.27,1.87 303 | 200402,1.4,-1.17,0.45,0.06,-1.11,1.45,-3.02 304 | 200403,-1.32,1.84,0.07,0.09,0.19,-2.15,-1.71 305 | 200404,-1.83,-2.59,-1.67,0.08,-5.36,-0.21,-2.33 306 | 200405,1.17,-0.1,-0.33,0.06,1.61,2.28,0.91 307 | 200406,1.86,2.32,1.67,0.08,2.07,0.31,1.73 308 | 200407,-4.06,-3.8,4.52,0.1,-2.31,-1.36,-2.45 309 | 200408,0.08,-1.59,1.13,0.11,-1.49,-2.37,-2.77 310 | 200409,1.6,2.93,0.39,0.11,5.25,3.05,-1.25 311 | 200410,1.43,0.44,-0.83,0.11,-1.53,0.19,1.02 312 | 200411,4.54,4.16,1.94,0.15,3.23,1.47,-1.17 313 | 200412,3.43,0.18,-0.36,0.16,-2.84,0.93,0.86 314 | 200501,-2.76,-1.63,2.67,0.16,3.13,1.56,-2.87 315 | 200502,1.89,-0.66,2.85,0.16,3.19,-2.31,-1.48 316 | 200503,-1.97,-1.39,1.75,0.21,0.55,0.15,-0.68 317 | 200504,-2.61,-4,-0.46,0.21,-0.86,-1.79,-1.53 318 | 200505,3.65,2.99,-1.24,0.24,0.4,3.19,0.49 319 | 200506,0.57,2.59,2.82,0.23,2.08,0.04,-1.5 320 | 200507,3.92,2.78,-0.48,0.24,0.01,-0.16,0.97 321 | 200508,-1.22,-0.89,1.45,0.3,2.25,-1.45,0.35 322 | 200509,0.49,-0.68,1.13,0.29,3.47,-3.71,-0.07 323 | 200510,-2.02,-1.03,-0.69,0.27,-1.3,1.58,-1.01 324 | 200511,3.61,0.99,-1.79,0.31,0.36,0.13,0.29 325 | 200512,-0.25,-0.52,0.49,0.32,0.71,1.98,-0.87 326 | 200601,3.04,5.32,1.19,0.35,2.79,-1.08,1.16 327 | 200602,-0.3,-0.32,-0.82,0.34,-1.78,3.28,1.26 328 | 200603,1.46,3.55,-0.1,0.37,1.3,0.01,0.36 329 | 200604,0.73,-1.24,3.07,0.36,0.69,-0.35,-0.42 330 | 200605,-3.57,-3.06,2.81,0.43,-3.74,-0.01,-0.17 331 | 200606,-0.35,-0.54,1.59,0.4,1.48,-0.56,-1.09 332 | 200607,-0.78,-4,3.27,0.4,-2.22,0.23,1.37 333 | 200608,2.03,0.83,-1.76,0.42,-3.47,1.75,2.93 334 | 200609,1.84,-1.24,-0.43,0.41,-0.97,0.75,1.63 335 | 200610,3.23,1.63,0.48,0.41,-0.22,-0.24,-0.45 336 | 200611,1.71,0.78,0.48,0.42,-1.02,-0.95,-1.93 337 | 200612,0.87,-0.89,2.52,0.4,0.82,2.37,1.94 338 | 200701,1.4,0.09,-0.02,0.44,0.25,1.04,-0.68 339 | 200702,-1.96,1.37,0.24,0.38,-1.32,0.29,-0.64 340 | 200703,0.68,-0.26,0.39,0.43,2.51,-2.02,-1.18 341 | 200704,3.49,-2.1,-0.97,0.44,-0.19,-0.29,0.29 342 | 200705,3.24,-0.02,-0.14,0.41,-0.29,-1.09,-2.48 343 | 200706,-1.96,0.76,-1.07,0.4,0.31,-0.85,-0.28 344 | 200707,-3.73,-2.68,-2.99,0.4,2.78,-3.34,-2.05 345 | 200708,0.92,-0.15,-2.38,0.42,0.09,-2.57,-0.26 346 | 200709,3.22,-2.46,-2.14,0.32,4.66,0.28,-2.8 347 | 200710,1.8,0.19,-1.95,0.32,4.89,-3.96,-1.63 348 | 200711,-4.83,-2.8,-1.09,0.34,0.91,-1.71,0.43 349 | 200712,-0.87,0.02,0,0.27,6.54,-2.06,-2.24 350 | 200801,-6.36,-0.75,3.07,0.21,-7.83,6.93,1.76 351 | 200802,-3.09,-0.57,-0.03,0.13,6.1,5,-2.14 352 | 200803,-0.93,0.81,0.28,0.17,4.13,-0.29,2.73 353 | 200804,4.6,-1.49,-0.08,0.18,-0.2,3.15,-4.53 354 | 200805,1.86,3.03,-0.38,0.18,3.22,-2.29,-4.42 355 | 200806,-8.44,1.09,-1.06,0.17,12.53,-7.12,-3.1 356 | 200807,-0.77,3.59,3.69,0.15,-5.29,8.15,7.76 357 | 200808,1.53,3.73,1.48,0.13,-3.81,-0.62,1.05 358 | 200809,-9.24,-0.37,4.41,0.15,0.33,-3.78,5.81 359 | 200810,-17.23,-2.27,-2.99,0.08,7.77,-9.58,2.51 360 | 200811,-7.86,-3.64,-4.93,0.03,7.19,-10.22,-2.31 361 | 200812,1.74,3.99,-1.2,0,-5.03,5.33,0.31 362 | 200901,-8.12,-0.98,-9.86,0,-1.9,0.49,-7.04 363 | 200902,-10.1,-0.36,-6.91,0.01,4.22,-6.75,1.09 364 | 200903,8.95,0.75,2.6,0.02,-11.36,3.26,4.18 365 | 200904,10.19,5.35,5.42,0.01,-34.72,-7.12,-0.37 366 | 200905,5.21,-2.66,0.56,0,-12.46,-2.88,-1.97 367 | 200906,0.43,2.66,-2.44,0.01,5.33,4.91,1.33 368 | 200907,7.72,2.5,4.79,0.01,-5.48,4.34,4.98 369 | 200908,3.33,-0.52,7.57,0.01,-8.88,-2.08,5.5 370 | 200909,4.08,2.48,1.39,0.01,-4.98,1.17,-1.7 371 | 200910,-2.59,-4.22,-4.37,0,2.68,2.16,-4.7 372 | 200911,5.56,-2.67,0.17,0,0.38,0.35,1.52 373 | 200912,2.75,5.78,0.73,0.01,2.9,1.59,0.7 374 | 201001,-3.36,0.21,0.6,0,-5.34,3.66,1.62 375 | 201002,3.4,1.43,2.73,0,3.63,1.83,2.59 376 | 201003,6.31,1.58,2.05,0.01,3.74,0.78,4.25 377 | 201004,2,4.93,3.19,0.01,3.14,-1.85,4.84 378 | 201005,-7.89,-0.08,-2.35,0.01,-0.21,0.54,-3.01 379 | 201006,-5.56,-2.12,-4.28,0.01,-2.97,-4.87,-5.35 380 | 201007,6.93,0.27,0.09,0.01,1.9,4.07,0.6 381 | 201008,-4.77,-3.02,-1.4,0.01,-0.13,1.07,-3.85 382 | 201009,9.54,3.86,-2.85,0.01,1.35,3.19,1.96 383 | 201010,3.88,1.05,-2.22,0.01,1.59,-1.39,-2.21 384 | 201011,0.6,3.67,-0.59,0.01,2.51,-0.9,-0.77 385 | 201012,6.82,0.78,3.36,0.01,-3.19,2.39,4.82 386 | 201101,1.99,-2.44,0.7,0.01,-0.23,0.02,1.03 387 | 201102,3.49,1.56,1.72,0.01,2.05,-1.07,1.35 388 | 201103,0.45,2.7,-1.16,0.01,3.59,-0.82,-1.85 389 | 201104,2.9,-0.36,-2.17,0,0.08,-1.01,-2.16 390 | 201105,-1.27,-0.64,-2.07,0,-0.61,-1.23,-2.62 391 | 201106,-1.75,-0.12,-0.23,0,1.76,-1.05,-1.98 392 | 201107,-2.36,-1.43,-1.14,0,0.04,-1.07,-2.4 393 | 201108,-5.99,-3.3,-1.57,0.01,-0.35,-1.39,-6.3 394 | 201109,-7.59,-3.72,-0.99,0,-2.55,-9.6,-5.08 395 | 201110,11.35,3.59,-0.92,0,-1.41,12.32,3.38 396 | 201111,-0.28,-0.26,-0.16,0,3.97,1.25,-3.5 397 | 201112,0.74,-0.57,1.54,0,1.88,-1.5,1.85 398 | 201201,5.05,2.53,-2.16,0,-7.94,6.6,1.49 399 | 201202,4.42,-1.64,0.04,0,-0.39,-0.42,1.69 400 | 201203,3.11,-0.24,-0.06,0,1.45,-0.72,2.63 401 | 201204,-0.85,-0.62,-0.17,0,3.81,-0.51,-1.84 402 | 201205,-6.19,-0.12,0.11,0.01,6.64,-3.5,-1.66 403 | 201206,3.89,0.82,0.48,0,-1.16,-0.79,1.64 404 | 201207,0.79,-2.6,0.02,0,3.06,1.43,-1.91 405 | 201208,2.55,0.71,0.55,0.01,-2.46,2.92,1.88 406 | 201209,2.73,0.49,1.57,0.01,-1.02,-0.13,1.77 407 | 201210,-1.76,-1.07,4.14,0.01,0.1,0.33,0.89 408 | 201211,0.78,0.67,-1.1,0.01,0.33,0.88,-0.75 409 | 201212,1.18,1.62,3.25,0.01,-2.96,0.02,3.64 410 | 201301,5.57,0.47,1.31,0,-1.91,-1.37,3.44 411 | 201302,1.29,-0.39,0.29,0,1.47,-1.15,-0.13 412 | 201303,4.03,0.83,-0.06,0,2.09,-1.98,1.32 413 | 201304,1.56,-2.4,0.41,0,0.35,-1.14,-0.25 414 | 201305,2.8,1.95,1.32,0,-1.88,1.74,3.29 415 | 201306,-1.2,1.23,-0.44,0,0.66,0.57,-0.84 416 | 201307,5.65,1.87,0.74,0,1.72,1.94,1.54 417 | 201308,-2.71,0.29,-2.46,0,0.07,-0.65,-1.32 418 | 201309,3.77,2.85,-1.59,0,2.99,-0.49,0.09 419 | 201310,4.18,-1.57,1.3,0,0.2,-0.25,0.23 420 | 201311,3.12,1.34,-0.33,0,0.48,0.77,0.37 421 | 201312,2.81,-0.43,-0.15,0,0.11,1.18,-1.03 422 | 201401,-3.32,0.84,-1.86,0,1.72,0.21,0.95 423 | 201402,4.65,0.32,-0.48,0,2.07,-0.28,-1.46 424 | 201403,0.43,-1.83,4.67,0,-3.24,2.64,2.9 425 | 201404,-0.19,-4.19,1.57,0,-3.9,-2.06,0.15 426 | 201405,2.06,-1.87,-0.38,0,0.99,0.52,-0.6 427 | 201406,2.61,2.99,-0.66,0,0.61,-0.73,0.43 428 | 201407,-2.04,-4.28,0.01,0,-0.27,2.76,0.3 429 | 201408,4.23,0.49,-0.75,0,0.74,1.52,-1.29 430 | 201409,-1.97,-3.8,-1.61,0,0.58,-0.1,-1.2 431 | 201410,2.52,4.17,-1.89,0,0.1,-2.84,-3.41 432 | 201411,2.54,-2.14,-3.42,0,1.13,-3.29,-1.76 433 | 201412,-0.06,2.57,1.53,0,1.05,-0.83,0.53 434 | -------------------------------------------------------------------------------- /AssetPricingTest/HDirProdPs.jl: -------------------------------------------------------------------------------- 1 | function HDirProdPs(x,y) 2 | #HDirProdFn Calculates horizontal direct product of two matrices with equal number of rows. 3 | # z[i,:] is the Kronecker product of x[i:i,:] and y[i:i,:] 4 | # 5 | # 6 | # Usage: z = HDirProdFn(x,y) 7 | # 8 | # Input: x T x Kx matrix 9 | # y T x Ky matrix 10 | # 11 | # Output: z T x (Kx*Ky) 12 | # 13 | # 14 | # Example: x = [ 1 2; 15 | # 3 4] 16 | # y = [5 6 1; 17 | # 7 8 1] 18 | # 19 | # the z = HDirProdFn(x,y) gives 20 | # 21 | # z = [ 5 6 1 10 12 2; 22 | # 21 24 3 28 32 4] 23 | # 24 | # Paul.Soderlind@unisg.ch, Oct 2015 25 | #---------------------------------------------------------------------------- 26 | 27 | #T = size(x,1) #rows and columns in x 28 | Kx = size(x,2) #columns in x 29 | Ky = size(y,2) #columns in y 30 | 31 | z = repmat(y,1,Kx) .* kron(x,ones(1,Ky)) 32 | 33 | return z 34 | 35 | end 36 | #---------------------------------------------------------------------------- 37 | -------------------------------------------------------------------------------- /AssetPricingTest/NewEst3Ps.jl: -------------------------------------------------------------------------------- 1 | function NewEst3Ps(g0,m) 2 | #NewEst3Ps Calculates covariance matrix of sqrt(T)*sample average. 3 | # 4 | # 5 | # Usage: Shat = NewEst3Ps(hhat,m) 6 | # 7 | # Input: g0 TxK matrix of moment functions 8 | # m order of autoregression 9 | # 10 | # Output: Shat covariance matrix of sum( hhat/sqrt(T) ), 11 | # that is the covariance matrix of sqrt(T)*mean(hhat) 12 | # 13 | # 14 | # Note: The CLT typically say that sqrt(T)*sample average ->d N(mu,Shat), 15 | # where Shat is what this code estimates. Clearly, Var(sample average) = 16 | # Shat/T. 17 | # 18 | # 19 | # Reference: Newey and West, 1987, Econometrica 20 | # Newey, 1985, Journal of Econometrics 21 | # 22 | # 23 | # Paul Soderlind (Paul.Soderlind@unisg.ch), to Julia Oct 2015 24 | #----------------------------------------------------------------------- 25 | 26 | T = size(g0,1) #g is Txq 27 | m = min(m,T-1) #number of lags 28 | 29 | g = g0 .- mean(g0,1) #Normalizing to Eg=0 30 | 31 | S = g'g/T #(qxT)*(Txq) 32 | for s = 1:m 33 | Omega_s = g[s+1:T,:]'g[1:T-s,:]/T #same as Sum[g(t)*g(t-s)',t=s+1,T] 34 | S = S + (1 - s/(m+1))*(Omega_s + Omega_s') 35 | end 36 | 37 | return S 38 | 39 | end 40 | #----------------------------------------------------------------------- 41 | -------------------------------------------------------------------------------- /AssetPricingTest/Readme.md: -------------------------------------------------------------------------------- 1 | Readme for AssetPricingTest 2 | =========================== 3 | 4 | Julia code for AssetPricingTest 5 | 6 | 1. ExampleAPTsT.jl: example (try to run it) 7 | 8 | 2. AssetPricingTest3bPs.jl: function for testing differences in alphas (excess return factors) 9 | 10 | 3. AssetPricingTest3dPs.jl: function for testing differences in cross-sectional pricing errors (general factors) 11 | 12 | 4. The other *.jl files are functions used in the main function and/or the example 13 | 14 | 5. *.csv: equity market data used in the example 15 | 16 | 6. TestingPricingErrors.pdf: the paper that describes the tests 17 | -------------------------------------------------------------------------------- /AssetPricingTest/TestingPricingErrors.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PaulSoderlind/PaulSoderlindCode/00fcd5520d86575f436ea3d6b7e0a9f7981be1bc/AssetPricingTest/TestingPricingErrors.pdf -------------------------------------------------------------------------------- /AssetPricingTest/excise.jl: -------------------------------------------------------------------------------- 1 | #------------------------------------------------------------------------------ 2 | function excise(x) 3 | 4 | vv = vec(any(isnan(x),2)) 5 | 6 | if any(vv) #only keep rows with no NaNs 7 | x = x[!vv,:] 8 | end 9 | 10 | return x 11 | 12 | end 13 | #------------------------------------------------------------------------------ 14 | 15 | 16 | #------------------------------------------------------------------------------ 17 | function exciseCopy(x) 18 | 19 | vv = vec(any(isnan(x),2)) 20 | 21 | if any(vv) #only keep rows with no NaNs 22 | x1 = x[!vv,:] 23 | else 24 | x1 = deepcopy(x) 25 | end 26 | 27 | return x1 28 | 29 | end 30 | #------------------------------------------------------------------------------ 31 | 32 | 33 | #------------------------------------------------------------------------------ 34 | function excise1mPs(x) 35 | 36 | vv = vec(any(isnan(x),2)) 37 | 38 | if any(vv) #only keep rows with no NaNs 39 | x = x[!vv,:] 40 | end 41 | 42 | return x,vv 43 | 44 | end 45 | #------------------------------------------------------------------------------ 46 | 47 | 48 | #------------------------------------------------------------------------------ 49 | function excise1mCopyPs(x) 50 | 51 | vv = vec(any(isnan(x),2)) 52 | 53 | if any(vv) #only keep rows with no NaNs 54 | x1 = x[!vv,:] 55 | else 56 | x1 = deepcopy(x) 57 | end 58 | 59 | return x1,vv 60 | 61 | end 62 | #------------------------------------------------------------------------------ 63 | 64 | 65 | #------------------------------------------------------------------------------ 66 | function excise2mPs(x,y) 67 | 68 | vv = vec(any(isnan([x y]),2)) 69 | 70 | if any(vv) #only keep rows with no NaNs 71 | x = x[!vv,:] 72 | y = y[!vv,:] 73 | end 74 | 75 | return x,y,vv 76 | 77 | end 78 | #------------------------------------------------------------------------------ 79 | 80 | 81 | #------------------------------------------------------------------------------ 82 | function excise2mCopyPs(x,y) 83 | 84 | vv = vec(any(isnan([x y]),2)) 85 | 86 | if any(vv) #only keep rows with no NaNs 87 | x1 = x[!vv,:] 88 | y1 = y[!vv,:] 89 | else 90 | x1 = deepcopy(x) 91 | y1 = deepcopy(y) 92 | end 93 | 94 | return x1,y1,vv 95 | 96 | end 97 | #------------------------------------------------------------------------------ 98 | 99 | 100 | #------------------------------------------------------------------------------ 101 | function excise3mPs(x,y,z) 102 | 103 | vv = vec(any(isnan([x y z]),2)) 104 | 105 | if any(vv) #only keep rows with no NaNs 106 | x = x[!vv,:] 107 | y = y[!vv,:] 108 | z = z[!vv,:] 109 | end 110 | 111 | return x,y,z,vv 112 | 113 | end 114 | #------------------------------------------------------------------------------ 115 | 116 | 117 | #------------------------------------------------------------------------------ 118 | function excise3mCopyPs(x,y,z) 119 | 120 | vv = vec(any(isnan([x y z]),2)) 121 | 122 | if any(vv) #only keep rows with no NaNs 123 | x1 = x[!vv,:] 124 | y1 = y[!vv,:] 125 | z1 = z[!vv,:] 126 | else 127 | x1 = deepcopy(x) 128 | y1 = deepcopy(y) 129 | z1 = deepcopy(z) 130 | end 131 | 132 | return x1,y1,z1,vv 133 | 134 | end 135 | #------------------------------------------------------------------------------ 136 | 137 | 138 | #------------------------------------------------------------------------------ 139 | function excise4mPs(x,y,z,w) 140 | 141 | vv = vec(any(isnan([x y z w]),2)) 142 | 143 | if any(vv) #only keep rows with no NaNs 144 | x = x[!vv,:] 145 | y = y[!vv,:] 146 | z = z[!vv,:] 147 | w = w[!vv,:] 148 | end 149 | 150 | return x,y,z,w,vv 151 | 152 | end 153 | #------------------------------------------------------------------------------ 154 | 155 | 156 | #------------------------------------------------------------------------------ 157 | function excise4mCopyPs(x,y,z,w) 158 | 159 | vv = vec(any(isnan([x y z w]),2)) 160 | 161 | if any(vv) #only keep rows with no NaNs 162 | x1 = x[!vv,:] 163 | y1 = y[!vv,:] 164 | z1 = z[!vv,:] 165 | w1 = w[!vv,:] 166 | else 167 | x1 = deepcopy(x) 168 | y1 = deepcopy(y) 169 | z1 = deepcopy(z) 170 | w1 = deepcopy(w) 171 | end 172 | 173 | return x1,y1,z1,w1,vv 174 | 175 | end 176 | #------------------------------------------------------------------------------ 177 | -------------------------------------------------------------------------------- /DriscollKraay/DVMS.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PaulSoderlind/PaulSoderlindCode/00fcd5520d86575f436ea3d6b7e0a9f7981be1bc/DriscollKraay/DVMS.pdf -------------------------------------------------------------------------------- /DriscollKraay/Example.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | " Example.jl\n", 8 | "\n", 9 | "\n", 10 | " This file imports the data from csv files with Hoechle's data and then\n", 11 | " runs the regressions.\n", 12 | "\n", 13 | " Compare the results to Table 2 in Hoechle, 2007, \"Robust Standard Errors...\",\n", 14 | " Stata Journal, 7, 281-312.\n", 15 | "\n", 16 | "\n", 17 | "\n", 18 | "\n", 19 | " Paul.Soderlind@unisg.ch" 20 | ] 21 | }, 22 | { 23 | "cell_type": "code", 24 | "execution_count": 1, 25 | "metadata": {}, 26 | "outputs": [], 27 | "source": [ 28 | "using Printf, DelimitedFiles, LinearAlgebra, Statistics\n", 29 | "\n", 30 | "include(\"jlFiles/printmat.jl\")\n", 31 | "include(\"jlFiles/FindNN.jl\")\n", 32 | "include(\"jlFiles/PanelOls.jl\");" 33 | ] 34 | }, 35 | { 36 | "cell_type": "code", 37 | "execution_count": 2, 38 | "metadata": {}, 39 | "outputs": [ 40 | { 41 | "data": { 42 | "text/plain": [ 43 | "(61, 219)" 44 | ] 45 | }, 46 | "execution_count": 2, 47 | "metadata": {}, 48 | "output_type": "execute_result" 49 | } 50 | ], 51 | "source": [ 52 | "BA = readdlm(\"Data/BA.csv\",',')\n", 53 | "TRMS = readdlm(\"Data/TRMS.csv\",',')\n", 54 | "TRMS2 = readdlm(\"Data/TRMS2.csv\",',')\n", 55 | "aVol = readdlm(\"Data/aVol.csv\",',')\n", 56 | "Size = readdlm(\"Data/Size.csv\",',')\n", 57 | "\n", 58 | "(T,N) = size(BA)" 59 | ] 60 | }, 61 | { 62 | "cell_type": "code", 63 | "execution_count": 3, 64 | "metadata": {}, 65 | "outputs": [ 66 | { 67 | "name": "stdout", 68 | "output_type": "stream", 69 | "text": [ 70 | "\n", 71 | "Pooled OLS\n", 72 | "OLS, assuming iid errors\n", 73 | " coef std t-stat\n", 74 | "aVol -0.0018 0.0004 -4.0070\n", 75 | "Size -0.1519 0.0087 -17.4151\n", 76 | "TRMS2 0.0033 0.0006 5.2959\n", 77 | "TRMS -0.0018 0.0050 -0.3698\n", 78 | "c 1.4591 0.0577 25.2702\n", 79 | "\n" 80 | ] 81 | } 82 | ], 83 | "source": [ 84 | "println(\"\\nPooled OLS\")\n", 85 | "x = [vec(aVol') vec(Size') vec(TRMS2') vec(TRMS') vec(ones(T,N)')]\n", 86 | "y = vec(BA') #stack rows in column vector\n", 87 | "\n", 88 | "vv = FindNN(y,x)\n", 89 | "(y,x) = (y[vv],x[vv,:]) #prune NaNs\n", 90 | "\n", 91 | "b = x\\y\n", 92 | "res = y - x*b\n", 93 | "Covb = inv(x'x)*var(res)\n", 94 | "Stdb = sqrt.(diag(Covb))\n", 95 | "\n", 96 | "println(\"OLS, assuming iid errors\")\n", 97 | "colNames = [\"coef\",\"std\",\"t-stat\"]\n", 98 | "rowNames = [\"aVol\",\"Size\",\"TRMS2\",\"TRMS\",\"c\"]\n", 99 | "printmat(b,Stdb,b./Stdb;colNames,rowNames,prec=4)" 100 | ] 101 | }, 102 | { 103 | "cell_type": "code", 104 | "execution_count": 4, 105 | "metadata": {}, 106 | "outputs": [ 107 | { 108 | "name": "stdout", 109 | "output_type": "stream", 110 | "text": [ 111 | "panel regression, LS standard errors\n", 112 | " coef std t-stat\n", 113 | "aVol -0.0018 0.0004 -4.0071\n", 114 | "Size -0.1519 0.0087 -17.4158\n", 115 | "TRMS2 0.0033 0.0006 5.2962\n", 116 | "TRMS -0.0018 0.0050 -0.3698\n", 117 | "c 1.4591 0.0577 25.2713\n", 118 | "\n", 119 | "panel regression, White's standard errors\n", 120 | " coef std t-stat\n", 121 | "aVol -0.0018 0.0009 -2.0435\n", 122 | "Size -0.1519 0.0122 -12.4981\n", 123 | "TRMS2 0.0033 0.0006 5.5216\n", 124 | "TRMS -0.0018 0.0052 -0.3529\n", 125 | "c 1.4591 0.0807 18.0709\n", 126 | "\n", 127 | "panel regression, Newey-West's standard errors\n", 128 | " coef std t-stat\n", 129 | "aVol -0.0018 0.0010 -1.7600\n", 130 | "Size -0.1519 0.0142 -10.7190\n", 131 | "TRMS2 0.0033 0.0006 5.5827\n", 132 | "TRMS -0.0018 0.0054 -0.3398\n", 133 | "c 1.4591 0.0980 14.8861\n", 134 | "\n", 135 | "panel regression, DK's standard errors\n", 136 | " coef std t-stat\n", 137 | "aVol -0.0018 0.0011 -1.6336\n", 138 | "Size -0.1519 0.0102 -14.9314\n", 139 | "TRMS2 0.0033 0.0009 3.7866\n", 140 | "TRMS -0.0018 0.0055 -0.3365\n", 141 | "c 1.4591 0.1348 10.8226\n", 142 | "\n", 143 | "Compare the results to Table 2 in Hoechle, 2007, 'Robust Standard Errors...'\n" 144 | ] 145 | } 146 | ], 147 | "source": [ 148 | "x0 = cat(aVol,Size,TRMS2,TRMS,ones(T,N),dims=3)\n", 149 | "x = permutedims(x0,[1,3,2]) #TxNxK -> TxKxN\n", 150 | "\n", 151 | "fnO = PanelOls(BA,x,0;FixNaNQ=true) #no lags in covariance estimation\n", 152 | "θ = fnO.theta #coefs\n", 153 | "stdLS = sqrt.(diag(fnO.CovLS)) #standard errors from LS, White, DK\n", 154 | "stdW = sqrt.(diag(fnO.CovNW))\n", 155 | "\n", 156 | "fn8 = PanelOls(BA,x,8;FixNaNQ=true) #8 lags in covariance estimation\n", 157 | "stdNW = sqrt.(diag(fn8.CovNW))\n", 158 | "stdDK = sqrt.(diag(fn8.CovDK))\n", 159 | "\n", 160 | "\n", 161 | "println(\"panel regression, LS standard errors\")\n", 162 | "printmat(θ,stdLS,θ./stdLS;colNames,rowNames,prec=4)\n", 163 | "\n", 164 | "println(\"panel regression, White's standard errors\")\n", 165 | "printmat(θ,stdW,θ./stdW;colNames,rowNames,prec=4)\n", 166 | "\n", 167 | "println(\"panel regression, Newey-West's standard errors\")\n", 168 | "printmat(θ,stdNW,θ./stdNW;colNames,rowNames,prec=4)\n", 169 | "\n", 170 | "println(\"panel regression, DK's standard errors\")\n", 171 | "printmat(θ,stdDK,θ./stdDK;colNames,rowNames,prec=4)\n", 172 | "\n", 173 | "println(\"Compare the results to Table 2 in Hoechle, 2007, 'Robust Standard Errors...'\")" 174 | ] 175 | } 176 | ], 177 | "metadata": { 178 | "kernelspec": { 179 | "display_name": "Julia 1.11.1", 180 | "language": "julia", 181 | "name": "julia-1.11" 182 | }, 183 | "language_info": { 184 | "file_extension": ".jl", 185 | "mimetype": "application/julia", 186 | "name": "julia", 187 | "version": "1.11.1" 188 | } 189 | }, 190 | "nbformat": 4, 191 | "nbformat_minor": 4 192 | } 193 | -------------------------------------------------------------------------------- /DriscollKraay/Example.jl: -------------------------------------------------------------------------------- 1 | #------------------------------------------------------------------------------ 2 | # Example.jl 3 | # 4 | # 5 | # This file imports the data from csv files with Hoechle's data and then 6 | # runs the regressions. 7 | # 8 | # Compare the results to Table 2 in Hoechle, 2007, "Robust Standard Errors...", 9 | # Stata Journal, 7, 281-312. 10 | # 11 | # 12 | # 13 | # 14 | # Paul.Soderlind@unisg.ch 15 | #------------------------------------------------------------------------------ 16 | 17 | using Printf, DelimitedFiles, LinearAlgebra, Statistics 18 | 19 | include("jlFiles/printmat.jl") 20 | include("jlFiles/FindNN.jl") 21 | include("jlFiles/PanelOls.jl") 22 | #------------------------------------------------------------------------------ 23 | 24 | BA = readdlm("Data/BA.csv",',') 25 | TRMS = readdlm("Data/TRMS.csv",',') 26 | TRMS2 = readdlm("Data/TRMS2.csv",',') 27 | aVol = readdlm("Data/aVol.csv",',') 28 | Size = readdlm("Data/Size.csv",',') 29 | 30 | (T,N) = size(BA) 31 | #------------------------------------------------------------------------------ 32 | 33 | println("\nPooled OLS") 34 | x = [vec(aVol') vec(Size') vec(TRMS2') vec(TRMS') vec(ones(T,N)')] 35 | y = vec(BA') #stack rows in column vector 36 | 37 | vv = FindNN(y,x) 38 | (y,x) = (y[vv],x[vv,:]) #prune NaNs 39 | 40 | b = x\y 41 | res = y - x*b 42 | Covb = inv(x'x)*var(res) 43 | Stdb = sqrt.(diag(Covb)) 44 | 45 | println("OLS, assuming iid errors") 46 | colNames = ["coef","std","t-stat"] 47 | rowNames = ["aVol","Size","TRMS2","TRMS","c"] 48 | printmat(b,Stdb,b./Stdb;colNames,rowNames,prec=4) 49 | #------------------------------------------------------------------------------ 50 | 51 | x0 = cat(aVol,Size,TRMS2,TRMS,ones(T,N),dims=3) 52 | x = permutedims(x0,[1,3,2]) #TxNxK -> TxKxN 53 | 54 | fnO = PanelOls(BA,x,0;FixNaNQ=true) #no lags in covariance estimation 55 | θ = fnO.theta #coefs 56 | stdLS = sqrt.(diag(fnO.CovLS)) #standard errors from LS, White, DK 57 | stdW = sqrt.(diag(fnO.CovNW)) 58 | 59 | fn8 = PanelOls(BA,x,8;FixNaNQ=true) #8 lags in covariance estimation 60 | stdNW = sqrt.(diag(fn8.CovNW)) 61 | stdDK = sqrt.(diag(fn8.CovDK)) 62 | 63 | 64 | println("panel regression, LS standard errors") 65 | printmat(θ,stdLS,θ./stdLS;colNames,rowNames,prec=4) 66 | 67 | println("panel regression, White's standard errors") 68 | printmat(θ,stdW,θ./stdW;colNames,rowNames,prec=4) 69 | 70 | println("panel regression, Newey-West's standard errors") 71 | printmat(θ,stdNW,θ./stdNW;colNames,rowNames,prec=4) 72 | 73 | println("panel regression, DK's standard errors") 74 | printmat(θ,stdDK,θ./stdDK;colNames,rowNames,prec=4) 75 | 76 | println("Compare the results to Table 2 in Hoechle, 2007, 'Robust Standard Errors...'") 77 | #------------------------------------------------------------------------------ 78 | -------------------------------------------------------------------------------- /DriscollKraay/Readme.md: -------------------------------------------------------------------------------- 1 | Readme for DriscollKraay 2 | ======================== 3 | 4 | Julia code for panel regressions with Driscoll-Kraay standard errors 5 | 6 | This code uses som of the panel regression routines in 7 | my repository [Financial Econometrics](https://github.com/PaulSoderlind/FinancialEconometrics), 8 | in particular, the functions in PanelOls.jl. 9 | -------------------------------------------------------------------------------- /DriscollKraay/jlFiles/FindNN.jl: -------------------------------------------------------------------------------- 1 | """ 2 | FindNN(x...;Keepdim=1) 3 | 4 | Find rows (if Keepdim==1) which have no NaNs missing in other dimensions (eg. in no columns). 5 | 6 | ### Input 7 | - `z::Array`: one or several numerical arrays 8 | - `Keepdim::Int`: (keyword) 1 if check rows, 2 if check columns, etc 9 | 10 | ### Output 11 | - `vvb::BitVector`: vector, element t is true if row (if Keepdim==1) t has no NaN or missing 12 | 13 | ### Notice 14 | - Set Keepdim=2 if we should instead look for NaNs/missings along rows (and other dimensions). 15 | - For heterogenous arrays like `x=[x1,x1]`, use `FindNN(x...)` 16 | 17 | Paul.Soderlind@unisg.ch 18 | 19 | """ 20 | function FindNN(x...;Keepdim=1) 21 | 22 | N = length(x) 23 | T = size(x[1],Keepdim) #length of output 24 | 25 | xDims = maximum(ndims,x) #max of ndims(x[i]) for i=1:N 26 | dims = setdiff(1:xDims,Keepdim) #dimensions to check 27 | 28 | vvM = falses(T,N) 29 | for i = 1:N #loop over inputs 30 | vvM[:,i] = any(isunordered,x[i],dims=dims) 31 | end 32 | 33 | vvb = vec(.!any(vvM,dims=2)) #rows witout NaN/missing in any of the x matrices 34 | 35 | return vvb 36 | 37 | end 38 | -------------------------------------------------------------------------------- /DriscollKraay/jlFiles/PanelOls.jl: -------------------------------------------------------------------------------- 1 | """ 2 | PanelOls(y,x,m=0,clust=[];FixNaNQ=false) 3 | 4 | Pooled OLS estimation. 5 | 6 | ### Input 7 | - `y0::Matrix`: TxN matrix with the dependent variable, `y[t,i]` is for period `t`, individual `i` 8 | - `x0::3D Array`: TxKxN matrix with K regressors 9 | - `m::Int`: (optional), scalar, number of lags in covariance estimation 10 | - `clust::Vector{Int}`: (optional), N vector with cluster number for each individual, [`ones(N)`] 11 | - `FixNaNQ::Bool`: (optional), true: replace all cases (y[t,i],x[t,:,i]) with some NaN/missing with (0,0), using PanelReplaceNaN() 12 | 13 | ### Output 14 | - `fnOutput::NamedTuple`: named tuple with the following elements 15 | 1. `theta` (K*L)x1 vector, LS estimates of regression coeefficients on kron(z,x) 16 | 2. `CovDK` (K*L)x(K*L) matrix, Driscoll-Kraay covariance matrix 17 | 3. `CovC` covariance matrix, cluster 18 | 4. `CovNW` covariance matrix, Newey-West (or White if m=0) 19 | 5. `CovLS` covariance matrix, iid 20 | 6. `R2` scalar, (pseudo-) R2 21 | 7. `yhat` TxN matrix with fitted values 22 | 8. `Nb` T-vector, number of obs in each period 23 | 24 | ### Notice 25 | - for TxNxK -> TxKxN, do `x = permutedims(z,[1,3,2])` 26 | 27 | """ 28 | function PanelOls(y0,x0,m=0,clust=[];FixNaNQ=false) 29 | 30 | (T,N) = (size(y0,1),size(y0,2)) 31 | K = size(x0,2) #TxKxN 32 | 33 | if FixNaNQ 34 | (vvM,y,x) = PanelReplaceNaN(y0,x0) 35 | else 36 | vvM = FindNNPanel(y0,x0) 37 | any(!,vvM) && error("still some NaN/missing") 38 | (y,x) = (y0,x0) 39 | end 40 | 41 | Nb = vec(sum(vvM,dims=2)) #observations in each period 42 | Tb = sum(>(0),Nb) #effective number of time periods 43 | TNb = sum(vvM) #effective number of observations 44 | 45 | isempty(clust) && (clust = ones(Int,N)) #all in the same cluster 46 | clustU = unique(clust) #unique cluster indicators 47 | G = length(clustU) #number of clusters 48 | vvClust = vec(clust) .== clustU' #NxG indicators of cluster membership 49 | 50 | xx = zeros(K,K) #Sum[x(t)*x(t)',t=1:T] 51 | xy = zeros(K) #Sum[x(t)*y(t),t=1:T] 52 | for t in 1:T #loop over time 53 | y_t = y[t,:] #dependent variable, Nx1 54 | x_t = x[t,:,:]' #regressors, NxK 55 | xx .= xx .+ x_t'x_t 56 | xy .= xy .+ x_t'y_t 57 | end 58 | 59 | xx = xx 60 | xy = xy 61 | theta = xx\xy #ols estimates, solves xx*theta = xy 62 | 63 | yhat = fill(NaN,T,N) #fitted values 64 | for i in 1:N #loop over cross section 65 | yhat[:,i] = x[:,:,i]*theta 66 | end 67 | r = y - yhat #fitted residuals 68 | 69 | h = fill(NaN,T,K,N) #moment conditions, individual 70 | for i in 1:N 71 | h[:,:,i] = r[:,i].*x[:,:,i] 72 | end 73 | h_tM = dropdims(sum(h,dims=3),dims=3) #TxK, moment conditions, aggregated over all 74 | 75 | hG_tM = fill(NaN,T,K,G) #moment conditions, aggregated to clusters 76 | for g in 1:G #loop over clusters 77 | vvg = vvClust[:,g] 78 | hG_tM[:,:,g] = sum(view(h,:,:,vvg),dims=3) 79 | end 80 | 81 | s2 = sum(abs2,r)/TNb 82 | 83 | (omega0DK,omega0W,omega0C) = [zeros(K,K) for i in 1:3] #DK lag 0,White's,cluster 84 | (omegajDK,omegajW,omegajC) = [zeros(K,K,m) for i in 1:3] #lags 1 to m 85 | for t in 1:T #loop over time 86 | h_it = h[t,:,:] #moment conditions, KxN 87 | h_t = h_tM[t,:] #Kx1 88 | omega0DK .= omega0DK .+ h_t*h_t' #Kx1 * 1xK 89 | omega0W .= omega0W .+ h_it*h_it' #KxN * NxK 90 | for g in 1:G #loop over clusters 91 | omega0C .= omega0C + hG_tM[t,:,g]*hG_tM[t,:,g]' #Kx1 * 1xK 92 | end 93 | for j in 1:min(t-1,m) #0,1,2,2,... for m=2 94 | omegajDK[:,:,j] = omegajDK[:,:,j] + h_t*h_tM[t-j,:]' #h(t)*h(t-j)' 95 | omegajW[:,:,j] = omegajW[:,:,j] + h_it*h[t-j,:,:]' 96 | for g in 1:G #loop over clusters 97 | omegajC[:,:,j] = omegajC[:,:,j] + hG_tM[t,:,g]*hG_tM[t-j,:,g]' #Kx1 * 1xK 98 | end 99 | end 100 | end 101 | 102 | ShatDK = NWCovPs(omega0DK,omegajDK,1) #estimate of S, DK 103 | ShatC = NWCovPs(omega0C, omegajC, 1) #estimate of S, cluster 104 | ShatW = NWCovPs(omega0W, omegajW, 1) #estimate of S, White's 105 | 106 | xx_1 = inv(xx) 107 | CovDK = xx_1 * ShatDK * xx_1' #covariance matrix, DK 108 | CovC = xx_1 * ShatC * xx_1' #covariance matrix, cluster 109 | CovNW = xx_1 * ShatW * xx_1' #covariance matrix, Newey-West (White if m=0) 110 | CovLS = xx_1 * s2 #covariance matrix, LS 111 | 112 | R2 = cor(vec(y[vvM]),vec(yhat[vvM]))^2 113 | any(.!vvM) && (yhat[.!vvM] .= NaN) #0 -> NaN 114 | 115 | fnOutput = (;theta,CovDK,CovC,CovNW,CovLS,R2,yhat,Nb) 116 | 117 | return fnOutput 118 | 119 | end 120 | 121 | 122 | """ 123 | NWCovPs(omega0,omegaj,T) 124 | 125 | Calculate covariance matrix of sample average as in Newey-West from a 126 | KxK `omega0` matrix and a KxKxm array `omegaj`. The latter contains m KxK 127 | matrices with autocovariances. 128 | """ 129 | function NWCovPs(omega0,omegaj,T) 130 | m = size(omegaj,3) 131 | Shat = omega0/T^2 132 | for j in 1:m 133 | Shat .= Shat .+ (1-j/(m+1))*(omegaj[:,:,j] + omegaj[:,:,j]')/T^2 134 | end 135 | return Shat 136 | end 137 | 138 | 139 | """ 140 | PanelReshuffle(y,x,z,id,per) 141 | 142 | Reshuffle the dependent variable into an TxN matrix `Y` (`T` periods, `N` cross-sectional units) 143 | and the regressors into a TxKxN array `X`. Handles unbalanced data sets. 144 | This reshuffling allows the `PaneslOls()` function to 145 | handle autocorrelation and cross-sectional clustering. 146 | 147 | ### Input 148 | - `y::Vector`: NT-vector of dependent variable, NT <= N*T 149 | - `x::VecOrMat`: NTxK matrix with regressors 150 | - `z::VecOrMat`: NTxL matrix with dummies (or other variables used for fixed effects, perhaps `[]`) 151 | - `id::Vector`: NT-vector of identity of cross-sectional unit 152 | - `per::Vector`: NT-vector of period (time) indicator 153 | 154 | ### Output 155 | - `t::Tuple`: (`Y,X`) TxN and TxKxN if `z=[]`, otherwise (`Y,X,Z`) where `Z` is TxLxN 156 | 157 | """ 158 | function PanelReshuffle(y,x,z,id,per) 159 | 160 | id_uniq = sort(unique(id)) 161 | N = length(id_uniq) #no. cross-sectional units 162 | per_uniq = sort(unique(per)) 163 | T = length(per_uniq) #no. periods 164 | K = size(x,2) #no. regressors 165 | 166 | Y = fill(NaN,T,N) #TxN 167 | X = fill(NaN,T,K,N) #TxKxN 168 | Z = fill(NaN,T,size(z,2),N) 169 | for i in 1:N 170 | vv_i = id .== id_uniq[i] #rows in y which refer to individual i 171 | per_i = per[vv_i] #periods for which individual i has data 172 | vv_t = indexin(per_i,per_uniq) 173 | Y[vv_t,i] = y[vv_i] 174 | X[vv_t,:,i] = x[vv_i,:] 175 | !isempty(z) && (Z[vv_t,:,i] = z[vv_i,:]) 176 | end 177 | 178 | t = isempty(z) ? (Y,X) : (Y,X,Z) 179 | return t 180 | 181 | end 182 | 183 | 184 | """ 185 | FindNNPanel(y,x,z=[]) 186 | 187 | Create TxN matrix with true/false indicating if observation `(y[t,i],x[t,:,i])` 188 | is valid (that is, contains no NaN/missing) 189 | 190 | ### Example 191 | - `vv = FindNNPanel(y,x)` where `y` is TxN and `x` is TxKxN 192 | 193 | ### Requires 194 | - the function `FindNN()` 195 | 196 | """ 197 | function FindNNPanel(y,x,z=[]) 198 | (T,K,N) = size(x) 199 | vv = falses(T,N) 200 | for i = 1:N 201 | if isempty(z) 202 | vv[:,i] = FindNN(view(y,:,i),view(x,:,:,i)) 203 | else 204 | vv[:,i] = FindNN(view(y,:,i),view(x,:,:,i),view(z,:,:,i)) 205 | end 206 | end 207 | return vv 208 | end 209 | 210 | 211 | """ 212 | PanelReplaceNaN(Y,X,Z=[]) 213 | 214 | Replaces any rows in `Y[:,i]` and `X[:,:,i]` (and optionally `Z[:,:,i]`) with zeros 215 | if there is any NaN/missing. Can be used to prepare an unbalanced panel data set for 216 | use in a fuction meant for a balanced data set. The function creates `(Yb,Xb)` or `(Yb,Xb,Zb)` 217 | and also outputs a TxN matrix `vvM` indicating with (t,i) observations that have been zeroed out. 218 | 219 | ### Requires 220 | - the function `FindNNPanel()` 221 | 222 | ### Notice 223 | - For a similar function that overwrites the existing (Y,X,Z), see PanelReplaceNaN!(Y,X). 224 | 225 | """ 226 | function PanelReplaceNaN(Y,X,Z=Float64[]) 227 | 228 | (Yb,Xb,Zb) = (copy(Y),copy(X),copy(Z)) 229 | N = size(Y,2) 230 | vvM = isempty(Z) ? FindNNPanel(Y,X) : FindNNPanel(Y,X,Z) #TxN, rows that have no NaNs/missings 231 | 232 | for i in 1:N #loop over cross-section 233 | vvi = .!vvM[:,i] #rows that should be set to 0.0 234 | Yb[vvi,i] .= 0.0 235 | Xb[vvi,:,i] .= 0.0 236 | !isempty(Z) && (Zb[vvi,:,i] .= 0.0) 237 | end 238 | 239 | t = isempty(Z) ? (vvM,Yb,Xb) : (vvM,Yb,Xb,Zb) 240 | 241 | return t 242 | 243 | end 244 | 245 | 246 | function PanelReplaceNaN!(Y,X,Z=Float64[]) 247 | 248 | N = size(Y,2) 249 | vvM = isempty(Z) ? FindNNPanel(Y,X) : FindNNPanel(Y,X,Z) #TxN, rows that have no NaNs/missings 250 | 251 | for i in 1:N #loop over cross-section 252 | vvi = .!vvM[:,i] #rows that should be set to 0.0 253 | Y[vvi,i] .= 0.0 254 | X[vvi,:,i] .= 0.0 255 | !isempty(Z) && (Z[vvi,:,i] .= 0.0) 256 | end 257 | 258 | return vvM 259 | 260 | end 261 | 262 | 263 | """ 264 | DummiesCreate(z) 265 | 266 | Create TxM dummies from a T-vector of M unique values 267 | 268 | """ 269 | function DummiesCreate(z) 270 | z_uniq = sort(unique(z)) 271 | dum = z .== permutedims(z_uniq) 272 | return dum 273 | end 274 | 275 | 276 | """ 277 | TimeDummiesTTN(T,N) 278 | 279 | Create TxTxN array of time dummies 280 | 281 | """ 282 | function TimeDummiesTTN(T,N,drop1Q=true) 283 | Z = repeat(1.0I[1:T,1:T],outer=(1,1,N)) 284 | drop1Q && (Z = Z[:,2:end,:]) 285 | return Z 286 | end 287 | 288 | 289 | """ 290 | IndivDummiesTNN(T,N) 291 | 292 | Create TxNxN array of individual dummies 293 | 294 | """ 295 | function IndivDummiesTNN(T,N) 296 | Z = zeros(T,N,N) 297 | for i in 1:N 298 | Z[:,i,i] .= 1 299 | end 300 | return Z 301 | end 302 | 303 | 304 | """ 305 | FixedIndivEffects(y0,x0,z0=[]) 306 | 307 | Demeans `y0` and `x0` (and possibly any `z0`) by taking out individual and/or time fixed effects. 308 | Loops to handle unbalanced panels. Notice that if `(y[t,i],x[t,:,i])` contains 309 | any missing value/NaN, then this oservation is excluded from the computations. 310 | 311 | 312 | ### Input 313 | - `y0::Matrix`: TxN matrix of dependent variables 314 | - `x0::Array`: TxKxN array with regressors, nregressor k for cross-sectional unit i is in `x0[:,k,i]` 315 | - `z0::Array`: (optional) TxLxN array with dummies etc 316 | 317 | ### Output 318 | - `y::Matrix`: 319 | - `x::Array`: 320 | - `z::Array`: 321 | - `yxAvg::Named tuple`: `yAvg_i,xAvg_i,zAvg_i,vvt` 322 | 323 | ### Requires 324 | - the function `FindNNPanel()` 325 | 326 | ### Notice 327 | - for TxKxN -> TxNxK (or vice versa), do `permutedims(z,[1,3,2])` 328 | 329 | """ 330 | function FixedIndivEffects(y0,x0,z0=Float64[]) 331 | 332 | (T,N) = (size(y0,1),size(y0,2)) 333 | (K,L) = (size(x0,2),size(z0,2)) #TxKxN 334 | 335 | DoZQ = !isempty(z0) 336 | 337 | vvt = DoZQ ? FindNNPanel(y0,x0,z0) : FindNNPanel(y0,x0) #use (t,i) data or not 338 | 339 | (yAvg_i,xAvg_i,zAvg_i) = (fill(NaN,1,N),fill(NaN,1,K,N),fill(NaN,1,L,N)) 340 | for i = 1:N #loop over cross section 341 | vv = vvt[:,i] 342 | yAvg_i[1,i] = mean(view(y0,vv,i)) 343 | xAvg_i[1,:,i] = mean(view(x0,vv,:,i),dims=1) 344 | DoZQ && (zAvg_i[1,:,i] = mean(view(z0,vv,:,i),dims=1)) 345 | end 346 | y = y0 .- yAvg_i #subtract fixed individual effects 347 | x = x0 .- xAvg_i 348 | z = DoZQ ? z0 .- zAvg_i : Float64[] 349 | 350 | yxAvg = (;yAvg_i,xAvg_i,zAvg_i,vvt) 351 | 352 | return y, x, z, yxAvg 353 | 354 | end 355 | 356 | 357 | """ 358 | FixedTimeEffects(y0,x0,z0) 359 | 360 | Demeans `y0` and `x0` (and possibly any `z0`) by taking out time fixed effects. 361 | Loops to handle unbalanced panels. Notice that if `(y[t,i],x[t,:,i],z[t,:,i])` contains 362 | any missing value/NaN, then this observation is excluded from the computations. 363 | 364 | 365 | ### Input 366 | - `y0::Matrix`: TxN matrix of dependent variables 367 | - `x0::Array`: TxKxN array with regressors, nregressor k for cross-sectional unit i is in `x0[:,k,i]` 368 | - `z0::Array`: (optional) TxLxN array with dummies etc 369 | 370 | ### Output 371 | - `y::Matrix`: 372 | - `x::Array`: 373 | - `z::Array`: 374 | - `yxAvg::Named tuple`: `yAvg_t,xAvg_t,zAvg_t,vvt` 375 | 376 | ### Requires 377 | - the function `FindNNPanel()` 378 | 379 | """ 380 | function FixedTimeEffects(y0,x0,z0=Float64[]) 381 | 382 | (T,N) = (size(y0,1),size(y0,2)) 383 | (K,L) = (size(x0,2),size(z0,2)) #TxKxN 384 | 385 | DoZQ = !isempty(z0) 386 | 387 | vvt = DoZQ ? FindNNPanel(y0,x0,z0) : FindNNPanel(y0,x0) #use (t,i) data or not 388 | 389 | (yAvg_t,xAvg_t,zAvg_t) = (fill(NaN,T),fill(NaN,T,K),fill(NaN,T,L)) 390 | for t = 1:T #loop over time 391 | vv = vvt[t,:] 392 | yAvg_t[t] = mean(view(y0,t,vv)) 393 | xAvg_t[t,:] = mean(view(x0,t,:,vv),dims=2) 394 | DoZQ && (zAvg_t[t,:] = mean(view(z0,t,:,vv),dims=2)) 395 | end 396 | y = y0 .- yAvg_t #subtract individual and time fixed effects 397 | x = x0 .- xAvg_t 398 | z = DoZQ ? z0 .- zAvg_t : Float64[] 399 | 400 | yxAvg = (;yAvg_t,xAvg_t,zAvg_t,vvt) 401 | 402 | return y, x, z, yxAvg 403 | 404 | end 405 | 406 | 407 | """ 408 | FixedIndivTimeEffects(Y,X,p=10) 409 | 410 | Estimate 2-way (individual and time) fixed effects model, by first applying an individual 411 | within-adjustment to (Y,X,time dummies), then applying a repeated Frisch-Waugh approach to 412 | partial out the time dummies. To be used when N > T. 413 | 414 | """ 415 | function FixedIndivTimeEffects(Y,X,p=10) 416 | 417 | (T,N) = size(Y) 418 | 419 | Z = TimeDummiesTTN(T,N) #create Tx(T-1)xN time dummies 420 | (Y,X,Z) = FixedIndivEffects(Y,X,Z) 421 | vvM = PanelReplaceNaN!(Y,X,Z) 422 | 423 | (Y,X,Z) = FWonZRepeated!(Y,X,Z,p) 424 | 425 | return Y,X 426 | 427 | end 428 | 429 | 430 | 431 | """ 432 | FixedTimeIndivEffects(Y,X,p=10) 433 | 434 | Estimate 2-way (time and individual) fixed effects model, by first applying a time 435 | within-adjustment to (Y,X,individual dummies), then applying a repeated Frisch-Waugh a 436 | pproach to partial out the individual dummies. To be used when T > N. 437 | 438 | """ 439 | function FixedTimeIndivEffects(Y,X,p=10) 440 | 441 | (T,N) = size(Y) 442 | 443 | Z = IndivDummiesTNN(T,N) #create TxXxN individual dummies 444 | (Y,X,Z) = FixedTimeEffects(Y,X,Z) 445 | vvM = PanelReplaceNaN!(Y,X,Z) 446 | 447 | (Y,X,Z) = FWonZRepeated!(Y,X,Z,p) 448 | 449 | return Y,X 450 | 451 | end 452 | 453 | 454 | """ 455 | OlsWrite!(y,x,Sxx_f,InOutMat,i,d1Q=false) 456 | 457 | Regress `y` on `x` using a precalculated `Sxx=factorize(x'x)` as input. 458 | The residuals are written to `InOutMat` if `d1Q=true` and to `InOutMat[:,i,:]` if 459 | `d1Q=false`. 460 | 461 | """ 462 | function OlsWrite!(y,x,Sxx_f,InOutMat,i,d1Q=false) 463 | Sxy = x'*y 464 | b = Sxx_f\Sxy #cf. b = x\y 465 | if d1Q 466 | copyto!(InOutMat,y - x*b) #same as Y[:] = y - x*b 467 | else 468 | InOutMat[:,i,:] = y - x*b 469 | end 470 | return InOutMat 471 | end 472 | 473 | 474 | """ 475 | FWonZRepeated!(Y,X,Z,p=10) 476 | 477 | Recursive Frisch-Waugh of (a) (Y,X,Z[:,4:end,]) on Z[:,1:3,:]; 478 | (b) get the (Y,X) residuals and then regress those on the Z[:,4:6,:] residuals, etc. Iterate 479 | until we have projected on all columns in Z. 480 | 481 | ### Input 482 | - `Y::Matrix`: TxN 483 | - `X::Array`: TxKxN 484 | - `Z::Array`: TxLxN 485 | - `p::Int`: number of Z variables to project on in each iteration 486 | 487 | ### Output 488 | similar matrices but filled with the residuals after projecting on Z 489 | 490 | 491 | ### Remark 492 | The following could potentially be used (in a future version) to have a tailor made loop. 493 | ``` 494 | jseq = vcat(1:p-1,p:p:M) 495 | n_jseq = length(jseq) 496 | for j in 1:n_jseq 497 | vj = j < n_jseq ? (jseq[j]:jseq[j+1]-1) : (jseq[j]:jseq[end]) 498 | end 499 | ``` 500 | 501 | """ 502 | function FWonZRepeated!(Y,X,Z,p=10) 503 | 504 | Zreshape(Z) = reshape( permutedims(Z,(1,3,2)),:,size(Z,2) ) #TxKxN => TNxK matrix 505 | 506 | M = size(Z,2) 507 | (T,N,K) = (size(Y,1),size(Y,2),size(X,2)) 508 | 509 | for j in 1:p:M #loop over 1,4,7, etc for p = 3 510 | vj = j:min(j+p-1,M) #Z[:,vj,:], 1:3,4:6,7:9, etc 511 | (mod(j-1,p*10)==0) && print("\rProcessed $(vj[1])-$(vj[end]) of $M") 512 | #println(j," ",vj," ",maximum(vj)+1," ",M) 513 | Zj = copy(Zreshape(Z[:,vj,:])) 514 | Sxx_f = factorize(Zj'*Zj) 515 | OlsWrite!( vec(Y),Zj,Sxx_f,Y,0,true ) #Y on Z[:,vj,:] 516 | Threads.@threads for i in 1:K #X[:,i,:] on Z[:,vj,:] 517 | OlsWrite!( vec(X[:,i,:]),Zj,Sxx_f,X,i,false ) 518 | end 519 | Threads.@threads for i in maximum(vj)+1:M #Z[:,vj+1,:] on Z[:,vj,:] 520 | OlsWrite!( vec(Z[:,i,:]),Zj,Sxx_f,Z,i,false ) 521 | end 522 | Z[:,vj,:] .= NaN #done Z[:,vj,:], set to NaN 523 | end 524 | println() 525 | 526 | return Y,X,Z 527 | 528 | end 529 | -------------------------------------------------------------------------------- /DriscollKraay/jlFiles/printmat.jl: -------------------------------------------------------------------------------- 1 | #------------------------------------------------------------------------------ 2 | """ 3 | printmat([fh::IO],x...;colNames=[],rowNames=[], 4 | width=10,prec=3,NoPrinting=false,StringFmt="",cell00="",colUnderlineQ=false) 5 | 6 | Print all elements of a matrix (or several) with predefined formatting. It can also handle 7 | OffsetArrays and Tables (from Tables.jl). StringFmt = "csv" prints using a csv format. 8 | The `colNames` for Tables default to the `Tables.columnnames()`. 9 | 10 | # Input 11 | - `fh::IO`: (optional) file handle. If not supplied, prints to screen 12 | - `x::Array(s) or Tables`: (of numbers, dates, strings, ...) to print 13 | - `colNames::Array`: of strings with column headers, alternatively like "c" to get "c1,c2,..." 14 | - `rowNames::Array`: of strings with row labels, alternatively like "r" to get "r1,r2,..." 15 | - `width::Int`: (keyword) minimum width of printed cells 16 | - `prec::Int`: (keyword) precision of printed cells (number of digits after .) 17 | - `NoPrinting::Bool`: (keyword) if true: no printing, just return formatted string [false] 18 | - `StringFmt::String`: (keyword) "csv" to create a csv formatted string, otherwise "" 19 | - `cell00::String`: (keyword) text for row 0, column 0 20 | - `colUnderlineQ::Bool`: (keyword) if true: column names are underlined 21 | 22 | # Output 23 | - str (if NoPrinting) string, (otherwise nothing) 24 | 25 | # Examples 26 | ``` 27 | x = [11 12;21 22] 28 | printmat(x) 29 | ``` 30 | ``` 31 | x = [1 "ab"; Date(2018,10,7) 3.14] 32 | printmat(x;width=20,colNames=["col 1","col 2"]) 33 | ``` 34 | ``` 35 | printmat([11,12],[21,22]) 36 | ``` 37 | Can also call as 38 | ``` 39 | opt = Dict(:rowNames=>["1";"4"],:width=>10,:prec=>3,:NoPrinting=>false,:StringFmt=>"") 40 | printmat(x;colNames=["a","b"],opt...) #notice ; and ... 41 | ``` 42 | (not all keywords are needed) 43 | 44 | # Requires 45 | - Printf 46 | - (the functions fmtNumPs,table_to_matrix,hcatWithTypePs(x...) are further down in this file) 47 | 48 | # Notice 49 | - For Tables.table, the Tables.columnnames() are used for colNames (if they exist and colNames=[]) 50 | - The code is not optimized for speed. I just aims to be fairly simple and get the job done. 51 | 52 | Paul.Soderlind@unisg.ch 53 | 54 | """ 55 | function printmat(fh::IO,x...;colNames=String[],rowNames=String[], 56 | width=10,prec=3,NoPrinting=false,StringFmt="",cell00="",colUnderlineQ=false) 57 | 58 | isempty(x) && return nothing #do nothing if isempty(x) 59 | 60 | delim = StringFmt == "csv" ? "," : "" #delimiter between cells 61 | 62 | if isdefined(Main,:Tables) && any(Tables.istable,x) #use only if Tables.jl is loaded && x contains Table 63 | xx = ntuple(i->table_to_matrix(x[i]),length(x)) 64 | (x,x_names) = (getindex.(xx,1),getindex.(xx,2)) #unpack into 2 n-tuples 65 | (isempty(colNames) && all(!isempty,x_names)) && (colNames = vcat(x_names...)) #use Tables.columnnames 66 | end 67 | 68 | x = hcatWithTypePs(x...) #create matrix as in hcat(x...), but defaulting to Any if eltypes differ 69 | (m,n) = (size(x,1),size(x,2)) #hcat(x...) also converts OffsetArrays to tradional arrays 70 | 71 | colNames = ExpandrcNamesPs(colNames,n) #(a) if non-empty, single string to Vector; 72 | rowNames = ExpandrcNamesPs(rowNames,m) #(b) if non-empty, to n-vector with numbers 73 | 74 | cell00 = isempty(rowNames) ? "" : cell00 #force cell00="" if no rowNames 75 | col0Width = isempty(rowNames) ? 0 : maximum(length,vcat(cell00,rowNames)) #width of column 0 (cell00 and rowNames) 76 | colWidth = fill(width,n) #widths of column 1:n 77 | 78 | iob = IOBuffer() 79 | 80 | if isa(colNames,Vector) && (length(colNames)==n) #if there are column names 81 | colNamesPrint(iob,colNames,n,cell00,col0Width,colWidth,delim) 82 | colUnderlineQ && colNamesPrint(iob,colNames,n,cell00,col0Width,colWidth,delim,true) 83 | end 84 | 85 | aLine = fill("",1+n) 86 | isempty(rowNames) && (rowNames = fill("",m)) #empty rowNames, if needed 87 | for i = 1:m #print each line: [rowName[i] x[i,:]] 88 | aLine .= "" #reset the line to empty 89 | aLine[1] = rpad(rowNames[i],col0Width) 90 | for j = 1:n #loop over columns 91 | aLine[1+j] = fmtNumPs(x[i,j],width,prec,"right") 92 | end 93 | col0Width == 0 ? join(iob,view(aLine,2:1+n),delim) : join(iob,aLine,delim) 94 | print(iob,"\n") 95 | end 96 | 97 | str = String(take!(iob)) 98 | 99 | if NoPrinting #no printing, just return str 100 | return str 101 | else #print, return nothing 102 | print(fh,str,"\n") 103 | return nothing 104 | end 105 | 106 | end 107 | 108 | #when fh is not supplied: printing to screen 109 | printmat(x...;colNames=String[],rowNames=String[],width=10,prec=3,NoPrinting=false,StringFmt="",cell00="",colUnderlineQ=false) = 110 | printmat(stdout::IO,x...;colNames,rowNames,width,prec,NoPrinting,StringFmt,cell00,colUnderlineQ) 111 | #------------------------------------------------------------------------------ 112 | 113 | 114 | #------------------------------------------------------------------------------ 115 | """ 116 | printlnPs([fh::IO],z...;width=10,prec=3) 117 | 118 | Subsitute for println, with predefined formatting. 119 | 120 | 121 | # Input 122 | - `fh::IO`: (optional) file handle. If not supplied, prints to screen 123 | - `z::String`: string, numbers and arrays to print 124 | 125 | Paul.Soderlind@unisg.ch 126 | 127 | """ 128 | function printlnPs(fh::IO,z...;width=10,prec=3) 129 | 130 | for x in z #loop over inputs in z... 131 | if isa(x,AbstractArray) 132 | iob = IOBuffer() 133 | for x_i in x 134 | print(iob,fmtNumPs(x_i,width,prec,"right")) 135 | end 136 | print(fh,String(take!(iob))) 137 | else 138 | print(fh,fmtNumPs(x,width,prec,"right")) 139 | end 140 | end 141 | 142 | print(fh,"\n") 143 | 144 | end 145 | #when fh is not supplied: printing to screen 146 | printlnPs(z...;width=10,prec=3) = printlnPs(stdout::IO,z...;width,prec) 147 | #------------------------------------------------------------------------------ 148 | 149 | 150 | #------------------------------------------------------------------------------ 151 | """ 152 | fmtNumPs(z,width=10,prec=2,justify="right") 153 | 154 | Create a formatted string of a float (eg, "%10.4f"), nothing (""), 155 | while other values are passed through. Strings are right (or left) justified. 156 | 157 | # Notice 158 | - With prec > 0 and isa(z,Integer), then the string is padded with 1+prec spaces 159 | to align with the printing of floats with the same prec. 160 | 161 | # Requires 162 | - Printf 163 | 164 | """ 165 | function fmtNumPs(z,width=10,prec=2,justify="right") 166 | 167 | isa(z,Bool) && (z = convert(Int,z)) #Bool -> Int 168 | 169 | if isa(z,AbstractFloat) #example: 101.0234, prec=3 170 | fmt = Printf.Format("%$(width).$(prec)f") 171 | strLR = Printf.format(fmt,z) 172 | elseif isa(z,Nothing) 173 | strLR = "" 174 | elseif isa(z,Integer) && prec > 0 #integer followed by (1+prec spaces) 175 | strLR = string(z,repeat(" ",1+prec)) 176 | else #Int, String, Date, Missing, etc 177 | strLR = string(z) 178 | end 179 | #justification 180 | strLR = justify == "left" ? rpad(strLR,width) : lpad(strLR,width) 181 | 182 | return strLR 183 | 184 | end 185 | #---------------------------------------------------s--------------------------- 186 | 187 | 188 | ##------------------------------------------------------------------------------ 189 | """ 190 | hcatWithTypePs(x...) 191 | 192 | Does hcat(x...), but defaults to an `Any` matrix if the `eltype`s 193 | differ across `x[i]`. Otherwise, a standard `hcat(x...)` 194 | 195 | """ 196 | function hcatWithTypePs(x...) 197 | typeTestQ = any(!=(eltype(x[1])),eltype.(x)) #test if eltype(x[i]) differs 198 | if typeTestQ #create matrix from tuple created by x... 199 | x = hcat(convert(Array{Any},hcat(x[1])),x[2:end]...) #preserving types of x[i] 200 | else #hcat(x[1]) to guarantee a matrix 201 | x = hcat(x...) 202 | end 203 | return x 204 | end 205 | ##------------------------------------------------------------------------------ 206 | 207 | 208 | #------------------------------------------------------------------------------ 209 | """ 210 | table_to_matrix(tab) 211 | 212 | Help function to facilitate printing of a Tables.table. The function creates a matrix from 213 | a row or column table, and also extract the column names. If `tab` is an array, then it is 214 | just copied. 215 | 216 | """ 217 | function table_to_matrix(tab) 218 | if Tables.istable(tab) 219 | x_mat = Tables.matrix(tab) #create matrix 220 | x_names = Tables.isrowtable(tab) ? "" : string.(Tables.columnnames(tab)) 221 | else 222 | x_mat = tab #for an array: just copy 223 | x_names = "" 224 | end 225 | return x_mat, x_names 226 | end 227 | #------------------------------------------------------------------------------ 228 | 229 | 230 | ##------------------------------------------------------------------------------ 231 | """ 232 | ExpandrcNamesPs(rcNames,n) 233 | 234 | Expand "abc" to ["abc"] (leaving ["def"] and "" untouched) and then also create 235 | a vector of ["def1","def2",...,"defn"] (or similarly for any non-empty string) 236 | 237 | """ 238 | function ExpandrcNamesPs(rcNames,n) 239 | if isa(rcNames,String) && !isempty(rcNames) #"abc" to ["abc"], but leave "" untouched 240 | rcNames = [rcNames] 241 | end 242 | if length(rcNames) == 1 < n 243 | rcNames = string.(only(rcNames),1:n) #create "ci" from ["c"] for i=1:n 244 | end 245 | return rcNames 246 | end 247 | ##------------------------------------------------------------------------------ 248 | 249 | 250 | ##------------------------------------------------------------------------------ 251 | """ 252 | 253 | 254 | """ 255 | function colNamesPrint(iob,colNames,n,cell00,col0Width,colWidth,delim="",DoUnderline=false) 256 | aLine = fill("",1+n) #intermediate storage 257 | aLine[1] = DoUnderline ? rpad(repeat("¯",length(cell00)),col0Width) : 258 | rpad(cell00,col0Width) 259 | for j = 1:n #loop over columns 260 | aLine[1+j] = DoUnderline ? lpad(repeat("¯",length(colNames[j])),colWidth[j]) : 261 | lpad(colNames[j],colWidth[j]) 262 | end 263 | aString = col0Width == 0 ? join(view(aLine,2:1+n),delim) : join(aLine,delim) #join into string 264 | print(iob,aString,"\n") 265 | return nothing 266 | end 267 | ##------------------------------------------------------------------------------ 268 | 269 | 270 | #------------------------------------------------------------------------------ 271 | function printblue(x...) 272 | foreach(z->printstyled(z,color=:blue,bold=true),x) 273 | print("\n") 274 | end 275 | function printred(x...) 276 | foreach(z->printstyled(z,color=:red,bold=true),x) 277 | print("\n") 278 | end 279 | function printmagenta(x...) 280 | foreach(z->printstyled(z,color=:magenta,bold=true),x) 281 | print("\n") 282 | end 283 | function printyellow(x...) 284 | foreach(z->printstyled(z,color=:yellow,bold=true),x) 285 | print("\n") 286 | end 287 | #------------------------------------------------------------------------------ 288 | 289 | 290 | #------------------------------------------------------------------------------ 291 | """ 292 | doc2(fn) 293 | 294 | Macro to display the documentation of a function or other object. 295 | Call it as `@doc2 printmat`. For use in notebooks in VS code. 296 | (In most other cases `@doc printmat` works well.) 297 | 298 | """ 299 | macro doc2(fn) 300 | return :( display("text/markdown",Base.doc($(esc(fn))))) 301 | end 302 | #------------------------------------------------------------------------------ 303 | -------------------------------------------------------------------------------- /FittingNfromHist/AbelComm200504.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PaulSoderlind/PaulSoderlindCode/00fcd5520d86575f436ea3d6b7e0a9f7981be1bc/FittingNfromHist/AbelComm200504.pdf -------------------------------------------------------------------------------- /FittingNfromHist/Example.jl: -------------------------------------------------------------------------------- 1 | #------------------------------------------------------------------------------ 2 | # Example.jl 3 | # 4 | # 5 | # 6 | # 7 | # 8 | # 9 | # 10 | # 11 | # 12 | # 13 | # 14 | # 15 | # 16 | # Paul.Soderlind@unisg.ch May 2013, to Julia Jan 2016 17 | #------------------------------------------------------------------------------ 18 | 19 | using Optim, SpecialFunctions, Statistics 20 | include("HistogramFitfn.jl") #functions used 21 | 22 | 23 | CaseQ = 3 #try 1,2, or 3 (see Prob below) 24 | #------------------------------------------------------------------------------ 25 | 26 | #DATA 27 | #catogories, -Inf 0) #no. intervals with non-zero probabilities 53 | 54 | if NActiveCat == 1 #if only one active intervals: triangular distribution 55 | parM = Any[MeanCrude;sqrt(BinWidth^2/24);NActiveCat] 56 | elseif NActiveCat == 2 #if only two active intervals: N(MeanCrude,VarSheppard) 57 | parM = Any[MeanCrude;sqrt(VarSheppard);NActiveCat] 58 | elseif NActiveCat > 2 #if three or more active intervals: N(estimate,estimate) 59 | par0 = [MeanCrude;sqrt(VarSheppard)] 60 | Sol = optimize(par->NormalHistLoss(par,Prob,CatBounds),par0) 61 | par1 = Optim.minimizer(Sol) 62 | parM = Any[par1;NActiveCat] 63 | end 64 | println("\n[mean,std]=$(round.(parM[1:2]',digits=3)), no. active intervals: $(parM[3])") 65 | #------------------------------------------------------------------------------ 66 | 67 | #Comment out this if you do not have PyPlot installed. 68 | 69 | using PyPlot 70 | #PyPlot.svg(true) #for ipynb notebooks 71 | close("all") 72 | 73 | if NActiveCat == 1 #assumed triangular dist 74 | whichBin = findfirst(Prob .== 1) 75 | (a,b,c) = (CatBounds[whichBin-1],CatBounds[whichBin],CatMid[whichBin]) #for distribution 76 | y = range(a,stop=b,length=101) 77 | pdfy = TriangularPdfPs.(y,a,b,c) 78 | figure() 79 | bar(CatMid,Prob/BinWidth,width=BinWidth,color="lightgray",edgecolor="black",align="center") 80 | xlim(-2,6) 81 | title("Histogram and assumed triangular distribution") 82 | plot(y,pdfy) 83 | #display(gcf()) #uncomment in VsCode 84 | elseif NActiveCat >= 2 #fitted N(mu,s^2) 85 | y = range(-2,stop=6,length=101) 86 | pdfy = NormPdfPs.(y,parM[1],parM[2]^2) 87 | figure() 88 | bar(CatMid,Prob/BinWidth,width=BinWidth,color="lightgray",edgecolor="black",align="center") 89 | xlim(-2,6) 90 | title("Histogram and fitted \$N(\\mu,\\sigma^2)\$") 91 | plot(y,pdfy) 92 | #display(gcf()) #uncomment in VsCode 93 | end 94 | 95 | #------------------------------------------------------------------------------- 96 | -------------------------------------------------------------------------------- /FittingNfromHist/HistogramFitFn.jl: -------------------------------------------------------------------------------- 1 | """ 2 | NormalHistLoss 3 | 4 | Create loss function from observed histogram and fitted probabilities from normal distribution. 5 | 6 | # Notice 7 | n interval boundaries, z(1), z(2), and z(3) for which the survey gives the following probabilities: 8 | Pr(x < z(1)), Pr(z(1) <= x b) #outside (a,b) 63 | pdfx = 0 64 | elseif a <= x < c 65 | pdfx = 2*(x-a)/((b-a)*(c-a)) 66 | elseif y == c 67 | pdfx = 2/(b-a) 68 | else 69 | pdfx = 2*(b-x)/((b-a)*(b-c)) 70 | end 71 | 72 | return pdfx 73 | 74 | end 75 | #------------------------------------------------------------------------------ 76 | -------------------------------------------------------------------------------- /FittingNfromHist/InfForc200204.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PaulSoderlind/PaulSoderlindCode/00fcd5520d86575f436ea3d6b7e0a9f7981be1bc/FittingNfromHist/InfForc200204.pdf -------------------------------------------------------------------------------- /FittingNfromHist/Readme.md: -------------------------------------------------------------------------------- 1 | Readme for FittingNfromHist 2 | =========================== 3 | 4 | Julia code for fitting N(mu,sigma2) from a histogram. 5 | 6 | 1. Run or just click to view the (jupyter) notebook Example.ipynb. Alternatively, use the julia script Example.jl. 7 | 8 | 2. The other jl files are functions used in the example. 9 | 10 | 3. InfForc200204.pdf and AbelComm200504.pdf: papers using this approach, published as 11 | Paolo Giordani and Paul Söderlind, "Inflation Forecast Uncertainty," European Economic Review, 47, 1037-1059, 2003 and 12 | Paolo Giordani and Paul Söderlind, "Is there Evidence of Pessimism and Doubt in Subjective Distributions? Implications for the Equity Premium Puzzle," Journal of Economic Dynamics and Control, 30, 1027-1043, 2006. 13 | 14 | 4. The current version has been tested on Julia 1.9. 15 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | Copyright (c) 2016 Paul Söderlind 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 5 | 6 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 7 | 8 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 9 | -------------------------------------------------------------------------------- /LStar/CarryTradeCRS201002.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PaulSoderlind/PaulSoderlindCode/00fcd5520d86575f436ea3d6b7e0a9f7981be1bc/LStar/CarryTradeCRS201002.pdf -------------------------------------------------------------------------------- /LStar/Example.jl: -------------------------------------------------------------------------------- 1 | #------------------------------------------------------------------------------ 2 | # Example.jl 3 | # 4 | # Test of LSTAR code used in "Carry Trade" paper. 5 | # 6 | # 7 | # 8 | # 9 | # 10 | # 11 | # 12 | # 13 | # Paul.Soderlind@unisg.ch 18 January 2013, to Julia Nov 2015 14 | #------------------------------------------------------------------------------ 15 | 16 | using Statistics, Dates, DelimitedFiles, LinearAlgebra, Optim, ForwardDiff 17 | 18 | include("jlFiles/FindNoNaNPs.jl") 19 | include("jlFiles/NewEst3Ps.jl") 20 | include("jlFiles/OlsPs.jl") 21 | include("jlFiles/OlsLStar3Ps.jl") 22 | include("jlFiles/printmat.jl") 23 | #------------------------------------------------------------------------------ 24 | 25 | x = readdlm("CTData.csv",',') #date, FXV, Return_CT, SP, Ty 26 | 27 | FXV = x[:,2] #FX volatility 28 | Re_CT = x[:,3] #carry trade return 29 | SP = x[:,4] #S&P return 30 | Ty = x[:,5] #treasury return 31 | 32 | T = size(Re_CT,1) 33 | 34 | gM = range(1,stop=4,length=15) 35 | cM = range(-2,stop=3,length=21) 36 | 37 | z = (FXV .- mean(FXV))/std(FXV) #standardised regime variable 38 | #------------------------------------------------------------------------------ 39 | 40 | gcKeep = [NaN;NaN] #(gamma,c) set to NaN if estimated in NLS, otherwise imposed 41 | #gcKeep = [3.0;NaN] #try to uncomment this to restrict gamma to 3 42 | #gcKeep = [NaN;1.3] #or this 43 | 44 | 45 | w = zeros(T,0) #no regressors without "regimes": empty vector 46 | (theta,Stdtheta,fnOutput) = OlsLStar3Ps(Re_CT,[ones(T) SP Ty],w,true,z,gM,cM,gcKeep) 47 | 48 | if all(isnan.(gcKeep)) 49 | println("\n","theta is [g;c;b_low;b_high;(slopes without regimes, if any)]") 50 | rowNames = ["γ";"c";string.("b",1:3,"_L");string.("b",1:3,"_H")] 51 | elseif isnan.(gcKeep) == [true;false] 52 | println("\n","theta is [g;b_low;b_high;(slopes without regimes, if any)]") 53 | rowNames = ["γ";string.("b",1:3,"_L"); string.("b",1:3,"_H")] 54 | elseif isnan.(gcKeep) == [false;true] 55 | println("\n","theta is [c;b_low;b_high;(slopes without regimes, if any)]") 56 | rowNames = ["c";string.("b",1:3,"_L");string.("b",1:3,"_H")] 57 | end 58 | 59 | println("Estimates and t-stats") 60 | printTable([theta Stdtheta],["coef","t-stat"],rowNames) 61 | 62 | println("\n","difference of slope (b, high minus low state)") 63 | printTable(fnOutput.slopeDiff,["coef","t-stat"],string.("b",1:3)) 64 | #------------------------------------------------------------------------------ 65 | 66 | #Plot of the loss function. Comment out this if you do not have PyPlot installed. 67 | using PyPlot 68 | #PyPlot.svg(true) #for ipynb notebooks 69 | 70 | using3D() #active 3D plotting 71 | fig = figure(figsize=(12,8)) 72 | ax = PyPlot.axes(projection="3d") 73 | surf(gM,cM,fnOutput.sseM',rstride=2,cstride=2,cmap=ColorMap("summer"),alpha=0.8) 74 | scatter(fnOutput.gcHat[1],fnOutput.gcHat[2],zs=minimum(fnOutput.sseM),s=200,color="k") 75 | ax.view_init(elev=20.0, azim=10) 76 | title("Sum of squared residuals (optimum at the dot)") 77 | xlabel(L"$\gamma$") 78 | ylabel(L"$c$") 79 | #display(gcf()) #uncomment in VsCode 80 | #------------------------------------------------------------------------------ 81 | -------------------------------------------------------------------------------- /LStar/Readme.md: -------------------------------------------------------------------------------- 1 | Readme for LStar 2 | ================ 3 | 4 | Julia code for LSTAR regressions 5 | 6 | 7 | 1. Run or just click to view the (jupyter) notebook Example.ipynb. Alternatively, use the julia script Example.jl. 8 | 9 | 2. The subfolder jlFiles contains jl files with functions used in the example. 10 | 11 | 3. CTData.csv: FX data used in the example 12 | 13 | 4. CarryTradeCRS201002.pdf: paper using this approach, published as 14 | Charlotte Christiansen, Angelo Ranaldo and Paul Söderlind, "The Time-Varying Systematic Risk of Carry Trade Strategies," Journal of Financial and Quantitative Analysis, 46, 1107-1125, 2011. 15 | 16 | 5. The current version has been tested on Julia 1.9. 17 | -------------------------------------------------------------------------------- /LStar/jlFiles/FindNoNaNPs.jl: -------------------------------------------------------------------------------- 1 | #------------------------------------------------------------------------------ 2 | """ 3 | FindNNPs(x...;Keepdim=1) 4 | 5 | Find rows (if Keepdim==1) which have no NaNs missing in other dimensions (eg. in no columns). 6 | 7 | # Input 8 | - `z::Array`: one or several numerical arrays 9 | - `Keepdim::Int`: (keyword) 1 if check rows, 2 if check columns, etc 10 | 11 | # Output 12 | - `vvb::BitArray(T)`: vector, element t is true if row (if Keepdim==1) t has no NaN or missing 13 | 14 | # Notice 15 | - Set Keepdim=2 if we should instead look for NaNs/missings along rows (and other dimensions). 16 | - For heterogenous arrays like `x=[x1,x1]`, use `FindNNPs(x...)` 17 | 18 | Paul.Soderlind@unisg.ch 19 | 20 | """ 21 | function FindNNPs(x...;Keepdim=1) 22 | 23 | Base.require_one_based_indexing(x) 24 | 25 | xNum = length(x) 26 | T = size(x[1],Keepdim) #length of output 27 | 28 | xDims = maximum([ndims(x[i]) for i=1:xNum]) 29 | dims = setdiff(1:xDims,Keepdim) #dimensions to check 30 | 31 | vvM = falses(T,xNum) 32 | for i = 1:xNum #loop over inputs 33 | vvM[:,i] = any(isnan.(x[i]) .| ismissing.(x[i]),dims=dims) 34 | end 35 | 36 | vvb = vec(.!any(vvM,dims=2)) #rows witout NaN/missing in any of the x matrices 37 | 38 | return vvb 39 | 40 | end 41 | #------------------------------------------------------------------------------ 42 | 43 | 44 | #------------------------------------------------------------------------------ 45 | """ 46 | FindNNDictPs(D...) 47 | 48 | Find rows that have no missing values in any of the arrays in the dictionaries D..., 49 | assuming all arrays have the same number of rows. 50 | 51 | # Input 52 | - `D::Dict`: One (D) or several (D1,D2) dictionaries with N different Tx? arrays. 53 | 54 | """ 55 | function FindNNDictPs(D...) 56 | 57 | N = length(D) 58 | 59 | TM = hcat( [hcat([size(x,1) for x in values(D[i])]...) for i=1:N]... ) #size(x,1) 60 | all(TM .== TM[1]) ? T = TM[1] : error("different number of rows") 61 | 62 | vv2 = falses(T,N) 63 | for i = 1:N 64 | vv = hcat([FindNNPs(x) for x in values(D[i])]...) 65 | vv2[:,i] = vec(all(vv,dims=2)) 66 | end 67 | 68 | vvb = vec(all(vv2,dims=2)) 69 | 70 | return vvb 71 | 72 | end 73 | #------------------------------------------------------------------------------ 74 | 75 | 76 | #------------------------------------------------------------------------------ 77 | """ 78 | DictSelectRowsPs(D,vv) 79 | 80 | Create new dictionary where we pick rows of D[i] to vv () 81 | 82 | """ 83 | function DictSelectRowsPs(D,vv) 84 | Dnew = Dict() 85 | for (k,v) in D 86 | ndims(v) == 1 ? Dnew[k] = v[vv] : Dnew[k] = v[vv,:] 87 | end 88 | return Dnew 89 | end 90 | #------------------------------------------------------------------------------ 91 | 92 | 93 | #------------------------------------------------------------------------------ 94 | """ 95 | FindNoNaNPs(Keepdim,x...) 96 | 97 | Find rows (if Keepdim==1) which have no NaNs missing in other dimensions (eg. in no columns). 98 | 99 | # Input 100 | - `Keepdim::Int`: 1 if check rows, 2 if check columns, etc 101 | - `z::Array`: one or several numerical arrays 102 | 103 | # Output 104 | - `vvb::BitArray(T)`: vector, element t is true if row (if Keepdim==1) t has no NaN or missing 105 | 106 | # Notice 107 | - Set Keepdim=2 if we should instead look for NaNs/missings along rows (and other dimensions). 108 | 109 | 110 | Paul.Soderlind@unisg.ch 111 | 112 | """ 113 | function FindNoNaNPs(Keepdim,x...) 114 | 115 | xNum = length(x) 116 | T = size(x[1],Keepdim) #length of output 117 | 118 | xDims = maximum([ndims(x[i]) for i=1:xNum]) 119 | dims = setdiff(1:xDims,Keepdim) #dimensions to check 120 | 121 | vvM = falses(T,xNum) 122 | for i = 1:xNum #loop over inputs 123 | vvM[:,i] = any(isnan.(x[i]) .| ismissing.(x[i]),dims=dims) 124 | end 125 | 126 | vvb = vec(.!any(vvM,dims=2)) #rows witout NaN/missing in any of the x matrices 127 | 128 | return vvb 129 | 130 | end 131 | #------------------------------------------------------------------------------ 132 | -------------------------------------------------------------------------------- /LStar/jlFiles/NewEst3Ps.jl: -------------------------------------------------------------------------------- 1 | """ 2 | NewEst3Ps(g0,m=0,HHQ=false) 3 | 4 | Calculate covariance matrix of sqrt(T)*sample average. 5 | 6 | 7 | # Input 8 | - `g0::Array`: Txq array or T-element vector of q (1) moment conditions 9 | - `m::Int`: scalar, number of lags to use 10 | - `HHQ::Bool`: bool, true: do Hansen-Hodrick, else Newey-West 11 | 12 | # Output 13 | - `S::Array`: qxq covariance matrix of sum( g0/sqrt(T) ) 14 | 15 | # Notice 16 | - The CLT typically say that sqrt(T)*sample average ->d N(mu,Shat), where Shat is 17 | what this code estimates. Clearly, Var(sample average) = Shat/T. 18 | - Rule-of-thumb for m are floor(0.75*T^(1/3)) and floor(4*(T/100)^(2/9)). 19 | 20 | # Reference 21 | Newey and West, 1987 (Econometrica), Newey, 1985 (Journal of Econometrics) 22 | 23 | """ 24 | function NewEst3Ps(g0,m=0,HHQ=false) 25 | 26 | Base.require_one_based_indexing(g0) 27 | 28 | (T,q) = (size(g0,1),size(g0,2)) #g is Txq 29 | m = min(m,T-1) #number of lags 30 | 31 | g = g0 .- mean(g0,dims=1) #normalizing to mean(g)=0 32 | 33 | S = g'g/T #(qxT)*(Txq) 34 | isa(S,Number) && (S=fill(S,1,1)) #to [1,1] matrix if S is a scalar 35 | 36 | for s = 1:m 37 | Omega_s = g[s+1:T,:]'g[1:T-s,:]/T #same as Sum[g(t)*g(t-s)',t=s+1,T] 38 | HHQ ? w = 1 : w = (1 - s/(m+1)) #Hansen-Hodrick or Newey-West 39 | S = S + w*(Omega_s + Omega_s') #( ) is a matrix, S should be too 40 | end 41 | 42 | (q == 1) && (S = S[1,1]) #to scalar 43 | 44 | return S 45 | 46 | end 47 | #----------------------------------------------------------------------- 48 | -------------------------------------------------------------------------------- /LStar/jlFiles/OlsLStar3Ps.jl: -------------------------------------------------------------------------------- 1 | function OlsLStar3Ps(y,x0,w,ExciseIt,z,gM,cM,gcKeep=[],NWm=0) 2 | #OlsLStar3Ps LSTAR LS of y on (x0,w), y = (1-G)*b1*x0 + G*b2*x0 + d*w, 3 | # G = 1/(1 + exp(-g*(z-c))) 4 | # 5 | # 6 | # 7 | # 8 | # Usage: (theta,Stdtheta,fnOutput) = OlsLStar3Ps(y,x0,w,ExciseIt,z,gM,cM[,gcKeep[,NWm]]) 9 | # 10 | # 11 | # Input: y Tx1, dependent variable 12 | # x0 Txk, regressors that have regime shifts (including deterministic ones) 13 | # w Txkw, regressors that do not have regime shifts, can be empty, zeros(T,0) 14 | # ExciseIt bool, if true: excise([y,x0,w,z]) 15 | # z Tx1, argument of G(z) function 16 | # gM Ngx1, different values of g to try in a loop 17 | # cM Ncx1, different values of c to try in a loop 18 | # gcKeep (optional) 2x1, [g;c], if an element is a NaN, then this parameter is estimated 19 | # NWm integer, Newey-West bandwidth [0] 20 | # 21 | # Output: theta (2+2k+kw)x1, (1+2k+kw)x1 or (0+2k+kw)x1, parameter estimates: 22 | # [g;c;b;d],[c;b;d],[g;b;d] or [b;d], 23 | # b is a (k+k)x1 vector for x0, the first k elements are for z=-Inf 24 | # and the second k elements for z=Inf 25 | # d are coefficiets for w (no regimes) 26 | # Stdtheta "", standard errors of theta 27 | # fnOutput named tuple with 28 | # [1] Covtheta cov(theta) 29 | # [2] slopeDiff matrix, [b tstat] 30 | # [3] R2a scalar, coefficient of determination 31 | # [4] T scalar, no of effective data points 32 | # [5] gcHat 2x1, [g;c] prespecified/estimated 33 | # [6] G Tx1, value of G function at estimated parameters 34 | # [7] sseM NgxNc, sum of squared errors for different values of g and c 35 | # [8] sse scalar, loss fn value at point estimate 36 | # [9] b coeffs from traditional LS (conditional on g and c) 37 | # [10] Stdb_ols standard errors according to traditional LS (conditional on g and c) 38 | # 39 | # 40 | # Calls on: Optim (package), ForwardDiff (package), FindNoNaNPs, OlsPs, NewEst3Ps 41 | # 42 | # Notice: (a) z is NOT standardized inside this function 43 | # (b) when only one of the (g,c) parameters is estimated, 44 | # then extrema(gM) or extrema(cM) defines the bounded 45 | # interval used by optimize() 46 | # 47 | # 48 | # Paul.Soderlind@unisg.ch, Jan 2013, to Julia Nov 2015 49 | #---------------------------------------------------------------------------- 50 | 51 | Base.require_one_based_indexing(y,x0,w,z,gM,cM) 52 | 53 | (Ng,Nc) = (length(gM),length(cM)) 54 | (k,kw) = (size(x0,2),size(w,2)) 55 | 56 | if ExciseIt 57 | vv = FindNNPs(y,x0,w,z) #find rows with no NaNs 58 | (y,x0,w,z) = (y[vv,:],x0[vv,:],w[vv,:],z[vv,:]) 59 | end 60 | 61 | sseM = fill(Inf,(Ng,Nc)) #calculate sse in double loop over g and c values 62 | for i = 1:Ng, j = 1:Nc #to get good starting values for optimization 63 | sseM[i,j] = OlsLStar3LossPs([gM[i];cM[j]],y,x0,w,z,[gM[i],cM[j]])[1] 64 | end #i,j 65 | ij = argmin(sseM) 66 | par0 = OlsLStar3Par(gcKeep,[NaN;NaN;NaN],[gM[ij[1]],cM[ij[2]]])[4] 67 | 68 | if !isempty(par0) 69 | if length(par0) == 1 70 | if isnan(gcKeep[1]) #bracket for univariate optimization 71 | (par0a,par0b) = (minimum(gM),maximum(gM)) #estimate g, must be positive 72 | else 73 | (par0a,par0b) = (minimum(cM),maximum(cM)) #estimate c 74 | end 75 | Sol = optimize(par->1.0 + OlsLStar3LossPs(par,y,x0,w,z,gcKeep)[1],par0a,par0b) 76 | else 77 | Sol = optimize(par->1.0 + OlsLStar3LossPs(par,y,x0,w,z,gcKeep)[1],par0) 78 | end 79 | parX = Optim.minimizer(Sol) 80 | if !Optim.converged(Sol) 81 | @warn("no convergence") 82 | return 83 | end 84 | else 85 | parX = Float64[] 86 | end 87 | 88 | (sse,resA) = OlsLStar3LossPs(parX,y,x0,w,z,gcKeep,true,NWm) 89 | (theta,Stdtheta,Covtheta) = (resA.theta,resA.Stdtheta,resA.Covtheta) 90 | 91 | kgc = length(theta) - (2*k + kw) #no. of estimated pars in [g;c] 92 | (bDiff,tstatbDiff) = [fill(NaN,k) for i=1:2] #calculate and test b2-b1=0 93 | for j = 1:k 94 | R = zeros(size(theta)) 95 | vv = kgc .+ [j;j+k] #location of b1 and b2 for same x0[:,j] 96 | R[vv] = [-1;1] 97 | bDiff[j] = R'theta 98 | tstatbDiff[j] = (R'theta)/sqrt(R'Covtheta*R) 99 | end 100 | slopeDiff = cat(bDiff,tstatbDiff,dims=2) 101 | 102 | fnOutput = (Covtheta=Covtheta,slopeDiff=slopeDiff, 103 | R2a=resA.R2a,T=resA.T,gcHat=resA.gcHat,G=resA.G, 104 | sseM=sseM,sse=sse,b=resA.b,Stdb_ols=resA.Stdb_ols) 105 | 106 | return theta, Stdtheta, fnOutput 107 | 108 | end 109 | #------------------------------------------------------------------------------ 110 | 111 | 112 | #------------------------------------------------------------------------------ 113 | function OlsLStar3LossPs(par,y,x0,w,z,gcKeep=Float64[],DetailsIt=false,NWm=0) 114 | 115 | (T,k) = (size(x0,1),size(x0,2)) 116 | 117 | (g,c,) = OlsLStar3Par(gcKeep,[par;NaN],[NaN;NaN]) 118 | (G,x) = GxPs(z,c,g,x0,w) #G and x 119 | 120 | (b,res,_,Covb,R2a,) = OlsPs(y,x) 121 | Stdb_ols = sqrt.(diag(Covb)) 122 | sse = sum(abs2,res) 123 | theta = [par;vec(b)] #b is nx1 array 124 | 125 | if DetailsIt 126 | (_,m) = OlsLStar3MomCondPs(theta,y,x0,w,z,gcKeep) 127 | S0 = NewEst3Ps(m,NWm) #ACov(sqrt(T)*mbar) 128 | D0 = ForwardDiff.jacobian(p->OlsLStar3MomCondPs(p,y,x0,w,z,gcKeep)[1],theta) 129 | Covtheta = inv(D0)*S0*inv(D0)'/T #Cov(theta) 130 | Stdtheta = sqrt.(diag(Covtheta)) 131 | gcHat = [g;c] 132 | else 133 | (Covtheta,Stdtheta,G,gcHat) = (Float64[],Float64[],Float64[],Float64[]) 134 | end 135 | 136 | fnOutput = (theta=theta,Stdtheta=Stdtheta,Covtheta=Covtheta, 137 | R2a=R2a,T=T,gcHat=gcHat,G=G,b=b,Stdb_ols=Stdb_ols) 138 | 139 | return sse, fnOutput 140 | 141 | end 142 | #------------------------------------------------------------------------------ 143 | 144 | 145 | #------------------------------------------------------------------------------ 146 | function OlsLStar3MomCondPs(theta,y,x0,w,z,gcKeep) #moment conditions 147 | 148 | (k,kw) = (size(x0,2),size(w,2)) 149 | 150 | (g,c,b,_,EstType) = OlsLStar3Par(gcKeep,theta,[NaN;NaN]) 151 | (G,x) = GxPs(z,c,g,x0,w) #G and x 152 | res = y - x*b 153 | 154 | (b1,b2) = (b[1:k],b[k+1:2*k]) 155 | 156 | b1_b2x0 = x0*(b2-b1) #Tx1 157 | dF_dg = (1.0.-G).*G.*(z.-c).*b1_b2x0 #Tx1 158 | dF_dc = (1.0.-G).*G.*(-g) .*b1_b2x0 #Tx1 159 | 160 | mg = res.*dF_dg 161 | mc = res.*dF_dc 162 | mb = res.*x 163 | 164 | if EstType == 1 #estimate (g,c,b) 165 | m = -[mg mc mb] 166 | elseif EstType == 2 #(c,b) 167 | m = -[ mc mb] 168 | elseif EstType == 3 #(g,b) 169 | m = -[mg mb] 170 | elseif EstType == 4 #b 171 | m = -[ mb] 172 | else 173 | error("invalid case") 174 | end 175 | 176 | mbar = vec(mean(m,dims=1)) 177 | 178 | return mbar, m 179 | 180 | end 181 | #------------------------------------------------------------------------------ 182 | 183 | 184 | #------------------------------------------------------------------------------ 185 | function OlsLStar3Par(gcKeep,theta,gcM) #extracting gc,b,par0 from theta etc 186 | 187 | vvNaN = isnan.(gcKeep) 188 | if isempty(gcKeep) || all(vvNaN) #gcKeep=[] or [NaN,NaN], estimate both g and c 189 | (g,c,b) = (abs(theta[1]),theta[2],theta[3:end]) 190 | par0 = [gcM[1];gcM[2]] 191 | EstType = 1 192 | elseif vvNaN == [false;true] #gcKeep=[1.5,NaN], don't estimate g, estimate c 193 | (g,c,b) = (gcKeep[1],theta[1],theta[2:end]) 194 | par0 = gcM[2] 195 | EstType = 2 196 | elseif vvNaN == [true;false] #gcKeep=[NaN,-0.75], estimate g, don't estimate c 197 | (g,c,b) = (theta[1],gcKeep[2],theta[2:end]) 198 | par0 = gcM[1] 199 | EstType = 3 200 | elseif !any(vvNaN) #gcKeep=[1.5,-0.75], don't estimate g or c 201 | (g,c,b) = (gcKeep[1],gcKeep[2],copy(theta)) 202 | par0 = Float64[] 203 | EstType = 4 204 | else 205 | error("invalid case") 206 | end 207 | 208 | return g, c, b, par0, EstType 209 | 210 | end 211 | #------------------------------------------------------------------------------ 212 | 213 | 214 | #------------------------------------------------------------------------------ 215 | function OlsLStar3PredPs(x0,w,z,theta,gcKeep) #predicted values 216 | 217 | k = size(x0,2) 218 | 219 | (g,c,b,) = OlsLStar3Par(gcKeep,theta,[NaN;NaN]) 220 | (G,x) = GxPs(z,c,g,x0,w) #G and x 221 | 222 | yHat = x*b 223 | yHat2 = x[:,k+1:2*k]*b[k+1:2*k] #contribution of x2 only 224 | 225 | return yHat, yHat2, G 226 | 227 | end 228 | #------------------------------------------------------------------------------ 229 | 230 | 231 | #------------------------------------------------------------------------------ 232 | #re-allocating x is wasteful, but it makes fairly little difference in timing 233 | function GxPs(z,c,g,x0,w) #G and x = [x1 x2 w] 234 | G = 1.0./(1.0.+exp.(-(z.-c)*g)) #Tx1 235 | x = [x0.*(1.0.-G) x0.*G w] 236 | return G, x 237 | end 238 | #------------------------------------------------------------------------------ 239 | 240 | -------------------------------------------------------------------------------- /LStar/jlFiles/OlsPs.jl: -------------------------------------------------------------------------------- 1 | #---------------------------------------------------------------------------- 2 | """ 3 | OlsPs(y,x,ExciseIt=false,UnExciseIt=false,SkipCovbIt=false) 4 | 5 | Do OLS of y on x, for one dependent variable or SURE with same regressors 6 | 7 | # Usage 8 | `(b,res,yhat,Covb,R2a,T) = OlsPs(y,x,ExciseIt,UnExciseIt,SkipCovbIt)` 9 | 10 | # Input 11 | - `y::Array`: Tx1 or Txn matrix of the dependent variables 12 | - `x::Array`: Txk matrix of regressors (including deterministic ones) 13 | - `ExciseIt::Bool`: (optional) bool, true to doing excise([y,x]) 14 | - `UnExciseIt::Bool`: (optional) bool, true to put residuals and fitted values in Txn matrix 15 | - `SkipCovbIt::Bool`: (optional) bool, true to skip calculation of Covb (sensitive inversion) 16 | 17 | # Output 18 | - `b::Array`: kxn matrix, regression coefficients 19 | - `res::Array`: Tx1 or Txn matrix, residuals y - yhat 20 | - `yhat::Array`: Tx1 or Txn matrix, fitted values x*b 21 | - `Covb::Array`: matrix, covariance matrix of vec(b) = [beq1;beq2;...] 22 | - `R2a::Array`: 1xn vector, R2 values 23 | - `Ty::Int`: scalar, number of obs (after excise) 24 | 25 | # Requires 26 | - FindNoNaNPs 27 | 28 | """ 29 | function OlsPs(y,x,ExciseIt=false,UnExciseIt=false,SkipCovbIt=false) 30 | 31 | Base.require_one_based_indexing(y,x) 32 | 33 | (T,n) = (size(y,1),size(y,2)) 34 | 35 | if ExciseIt 36 | vvNoNaNR = FindNNPs(y,x) #find rows with no NaNs 37 | (y,x) = (y[vvNoNaNR,:],x[vvNoNaNR,:]) 38 | end 39 | 40 | (Ty,Tx,k) = (size(y,1),size(x,1),size(x,2)) 41 | 42 | if Tx != Ty 43 | error("y and x must have same number of observations") 44 | end 45 | if any(isnan.([y x])) 46 | error("NaN in x or y") 47 | end 48 | if ndims(x) == 1 #T vector to (T,1) matrix, could also do reshape(x,T,1) 49 | x = x[:,:] 50 | end 51 | 52 | if Ty >= k 53 | b = x\y 54 | #b = (x'x)\(x'y) 55 | #ndims(x) == 1 ? yhat2 = x*b[1] : yhat2 = x*b #if? then: else. to handle x is vector 56 | yhat2 = x*b 57 | res2 = y - yhat2 58 | Covres = cov(res2)*(Ty-1)/Ty 59 | if SkipCovbIt 60 | Covb = NaN 61 | else 62 | Covb = kron(Covres,inv(x'x)) 63 | end 64 | R2a = 1 .- var(res2,dims=1)./var(y,dims=1) 65 | else 66 | (b,yhat2,res2,Covb,R2a) = (NaN,NaN,NaN,NaN,NaN) 67 | end 68 | 69 | if UnExciseIt && ExciseIt #put fitted value and residual in Tyxn matrix 70 | (yhat,res) = [fill(NaN,(T,n)) for i=1:2] 71 | yhat[vvNoNaNR,:] = yhat2 72 | res[vvNoNaNR,:] = res2 73 | else 74 | yhat = yhat2 75 | res = res2 76 | end 77 | 78 | if n == 1 #if only one regression 79 | R2a = R2a[1] 80 | end 81 | 82 | return b,res,yhat,Covb,R2a,Ty 83 | 84 | end 85 | #------------------------------------------------------------------------------ 86 | -------------------------------------------------------------------------------- /LStar/jlFiles/printmat.jl: -------------------------------------------------------------------------------- 1 | #------------------------------------------------------------------------------ 2 | """ 3 | printmat([fh::IO],x;width=10,prec=3,NoPrinting=false,StringFmt="") 4 | 5 | Print all elements of matrix with predefined formatting. 6 | 7 | # Input 8 | - `fh::IO`: (optional) file handle. If not supplied, prints to screen 9 | - `x::Array`: string, date or array to print 10 | - `width::Int`: (keyword) scalar, minimum width of printed cells 11 | - `prec::Int`: (keyword) scalar, precision of printed cells 12 | - `NoPrinting::Bool`: (keyword) bool, true: no printing, just return formatted string 13 | - `StringFmt::String`: (keyword) string, "", "html", "csv" 14 | 15 | # Output 16 | - str (if NoPrinting) string, (otherwise nothing) 17 | 18 | # Examples 19 | ``` 20 | x = [11 12;21 22] 21 | printmat(x) 22 | ``` 23 | ``` 24 | x = Any[1 "ab"; Date(2018,10,7) 3.14] 25 | printmat(x,width=20) 26 | ``` 27 | Can also call as 28 | ``` 29 | opt = Dict(:width=>10,:prec=>3,:NoPrinting=>false,:StringFmt=>"") 30 | printmat(x;opt...) #notice , and ... 31 | ``` 32 | (not all keywords are needed) 33 | 34 | # Requires 35 | - Dates 36 | - fmtNumPs 37 | 38 | # To do 39 | 40 | 41 | Paul.Soderlind@unisg.ch 42 | 43 | """ 44 | function printmat(fh::IO,x;width=10,prec=3,NoPrinting=false,StringFmt="") 45 | 46 | if isa(x,Union{String,Date,DateTime,Missing}) #eg. a single Date 47 | str = string(lpad(x,width),"\n") 48 | if NoPrinting 49 | return str 50 | else 51 | print(fh,str,"\n") 52 | return nothing 53 | end 54 | elseif isa(x,Nothing) 55 | return nothing 56 | end 57 | 58 | if ndims(x) > 2 59 | @warn("more than 2 dimensions") 60 | return nothing 61 | end 62 | 63 | (m,n) = (size(x,1),size(x,2)) 64 | 65 | iob = IOBuffer() 66 | for i = 1:m #loop over lines 67 | for j = 1:n-1 #loop over columns 1:n-1 68 | writeElementPs(iob,x,i,j,width,prec,StringFmt) 69 | end 70 | if StringFmt == "csv" #last (n) column 71 | writeElementPs(iob,x,i,n,width,prec,"") #no , at end of line 72 | else 73 | writeElementPs(iob,x,i,n,width,prec,StringFmt) 74 | end 75 | write(iob,"\n") #newline 76 | end 77 | str = String(take!(iob)) 78 | 79 | if NoPrinting #no printing, just return str 80 | return str 81 | else #print, return nothing 82 | print(fh,str,"\n") 83 | return nothing 84 | end 85 | 86 | end 87 | #when fh is not supplied: printing to screen 88 | printmat(x;width=10,prec=3,NoPrinting=false,StringFmt="") = printmat(stdout::IO, 89 | x,width=width,prec=prec,NoPrinting=NoPrinting,StringFmt=StringFmt) 90 | #------------------------------------------------------------------------------ 91 | 92 | 93 | #------------------------------------------------------------------------------ 94 | """ 95 | printTable([fh::IO],x,colNames=[],rowNames=[]; 96 | width=10,prec=3,NoPrinting=false,StringFmt="",cell00="") 97 | 98 | Print formatted table with row names (1st column) column names (1st row), 99 | and data matrix (the rest). 100 | 101 | 102 | # Input 103 | - `fh::IO`: (optional) file handle. If not supplied, prints to screen 104 | - `x::Array`: (of numbers, dates, strings, ...) to print 105 | - `colNames::Array`: of strings with column headers 106 | - `rowNames::Array`: of strings with row labels 107 | - `width::Int`: (keyword) scalar, minimum width of printed cells. [10] 108 | - `prec::Int`: (keyword) scalar, precision of printed cells. [3] 109 | - `NoPrinting::Bool`: (keyword) bool, true: no printing, just return formatted string [false] 110 | - `StringFmt::String`: (keyword) string, "", "html", "csv" 111 | - `cell00::String`: (keyword) string, for row 0, column 0 112 | 113 | # Output 114 | - `str::String`: (if NoPrinting) string, (otherwise nothing) 115 | 116 | # Example 117 | ``` 118 | xA = [1 "ab" "abc"; "ccc" 3.14 missing] 119 | printTable(xA,colNames,["1";"4"],width=12,prec=2) 120 | ``` 121 | Can also call as 122 | ``` 123 | opt = Dict(:width=>10,:prec=>3,:NoPrinting=>false,:StringFmt=>"",:cell00=>"") 124 | printTable(x;opt...) #notice , and ... 125 | ``` 126 | (not all keywords are needed) 127 | 128 | # Requires 129 | - Dates 130 | - printmat 131 | 132 | """ 133 | function printTable(fh::IO,x,colNames=[],rowNames=[]; 134 | width=10,prec=3,NoPrinting=false,StringFmt="",cell00="") 135 | 136 | isempty(x) && return nothing #do nothing is isempty(x) 137 | 138 | (m,n) = (size(x,1),size(x,2)) 139 | 140 | if isempty(rowNames) #create row names "r1" 141 | rowNames = [string("r",i) for i = 1:m] 142 | end 143 | if isempty(colNames) #create column names "c1" 144 | colNames = [string("c",i) for i = 1:n] 145 | end 146 | 147 | rNamesWidth = maximum([length(rowNames[i]) for i = 1:length(rowNames)]) #max length of rowNames 148 | rNamesWidth = max(rNamesWidth,length(cell00)) 149 | 150 | iob = IOBuffer() 151 | if StringFmt == "html" #print column names 152 | write(iob,"",lpad(cell00,rNamesWidth),"") 153 | for i = 1:n 154 | write(iob,"",lpad(colNames[i],width),"") 155 | end 156 | write(iob,"") 157 | elseif StringFmt == "csv" 158 | write(iob,lpad(string(cell00,","),rNamesWidth)) 159 | for i = 1:n-1 160 | write(iob,lpad(colNames[i],width),",") 161 | end 162 | write(iob,lpad(colNames[n],width)) #no , at line end 163 | else 164 | write(iob,lpad(cell00,rNamesWidth)) #cell 0,0 165 | for i = 1:n #create string 166 | write(iob,lpad(colNames[i],width)) 167 | end 168 | end 169 | write(iob,"\n") 170 | 171 | xStr = printmat(fh,x,width=width,prec=prec,NoPrinting=true,StringFmt=StringFmt) #body of table, one long string 172 | xStrV = split(xStr,"\n") #vector of strings (one per row of x) 173 | 174 | for i = 1:m #loop over rows in x, print rowNames[i] and x[i,:] 175 | if StringFmt == "html" 176 | write(iob,"",rpad(rowNames[i],rNamesWidth),"",xStrV[i]," \n") 177 | elseif StringFmt == "csv" 178 | write(iob,rpad(string(rowNames[i],","),rNamesWidth),xStrV[i],"\n") 179 | else 180 | write(iob,rpad(rowNames[i],rNamesWidth),xStrV[i],"\n") 181 | end 182 | end 183 | str = String(take!(iob)) 184 | 185 | if NoPrinting #no printing, just return str 186 | return str 187 | else #print, return nothing 188 | print(fh,str,"\n") 189 | return nothing 190 | end 191 | 192 | end 193 | #when fh is not supplied: printing to screen 194 | printTable(x,colNames=[],rowNames=[];width=10,prec=3,NoPrinting=false,StringFmt="",cell00="") = 195 | printTable(stdout::IO,x,colNames,rowNames,width=width,prec=prec,NoPrinting=NoPrinting, 196 | StringFmt=StringFmt,cell00=cell00) 197 | #------------------------------------------------------------------------------ 198 | 199 | 200 | #------------------------------------------------------------------------------ 201 | """ 202 | printlnPs([fh::IO],z...;width=10,prec=3) 203 | 204 | Subsitute for println, with predefined formatting. 205 | 206 | 207 | # Input 208 | - `fh::IO`: (optional) file handle. If not supplied, prints to screen 209 | - `z::String`: string, numbers and arrays to print 210 | 211 | Paul.Soderlind@unisg.ch 212 | 213 | """ 214 | function printlnPs(fh::IO,z...;width=10,prec=3) 215 | 216 | for x in z #loop over inputs in z... 217 | if isa(x,Union{String,Date,DateTime,Missing}) 218 | print(fh,lpad(x,width)) 219 | elseif isa(x,Nothing) 220 | print(fh,"") 221 | else #other types 222 | iob = IOBuffer() 223 | for i = 1:length(x) 224 | if isa(x[i],AbstractFloat) #Float 225 | write(iob,fmtNumPs(x[i],width,prec,"right")) 226 | elseif isa(x[i],Nothing) #Nothing 227 | write(iob,lpad("",width)) 228 | else #Integer, etc 229 | write(iob,lpad(x[i],width)) 230 | end 231 | end 232 | print(fh,String(take!(iob))) 233 | end 234 | end 235 | 236 | print(fh,"\n") 237 | 238 | end 239 | #when fh is not supplied: printing to screen 240 | printlnPs(z...;width=10,prec=3) = printlnPs(stdout::IO,z...,width=width,prec=prec) 241 | #------------------------------------------------------------------------------ 242 | 243 | 244 | #------------------------------------------------------------------------------ 245 | """ 246 | printmat2 247 | 248 | Call on printmat twice: to print to screen and then to an open file (IOStream) 249 | """ 250 | function printmat2(fh,x;width=10,prec=3,NoPrinting=false,StringFmt="") 251 | printmat(x,width=width,prec=prec,NoPrinting=NoPrinting,StringFmt=StringFmt) #to screen 252 | if isa(fh,IOStream) && isopen(fh) 253 | printmat(fh,x,width=width,prec=prec,NoPrinting=NoPrinting,StringFmt=StringFmt) #to file 254 | end 255 | end 256 | #------------------------------------------------------------------------------ 257 | 258 | 259 | #------------------------------------------------------------------------------ 260 | """ 261 | printTable2 262 | 263 | Call on printTable2 twice: to print to screen and then to an open file (IOStream) 264 | """ 265 | function printTable2(fh,x,colNames=[],rowNames=[];width=10,prec=3,NoPrinting=false, 266 | StringFmt="",cell00="") 267 | printTable(x,colNames,rowNames,width=width,prec=prec,NoPrinting=NoPrinting, 268 | StringFmt=StringFmt,cell00=cell00) #to screen 269 | if isa(fh,IOStream) && isopen(fh) 270 | printTable(fh,x,colNames,rowNames,width=width,prec=prec,NoPrinting=NoPrinting, 271 | StringFmt=StringFmt,cell00=cell00) #to file 272 | end 273 | end 274 | #------------------------------------------------------------------------------ 275 | 276 | 277 | #------------------------------------------------------------------------------ 278 | """ 279 | println2Ps 280 | 281 | Call on printlnPs twice: to print to screen and then to an open file (IOStream) 282 | """ 283 | function println2Ps(fh::IO,z...;width=10,prec=3) 284 | printlnPs(z...,width=width,prec=prec) #to screen 285 | if isa(fh,IOStream) && isopen(fh) 286 | printlnPs(fh::IO,z...,width=width,prec=prec) #to file 287 | end 288 | end 289 | #------------------------------------------------------------------------------ 290 | 291 | 292 | #------------------------------------------------------------------------------ 293 | """ 294 | writeElementPs(iob,x,i,j,width,prec,StringFmt) 295 | 296 | Writes one element to iob, formatting depends on type 297 | """ 298 | function writeElementPs(iob,x,i,j,width,prec,StringFmt) 299 | 300 | if isa(x[i,j],AbstractFloat) #Float 301 | write(iob,fmtNumPs(x[i,j],width,prec,"right",StringFmt)) 302 | elseif isa(x[i,j],Union{Int,String}) #Int, String 303 | write(iob,fmtNumPs(x[i,j],width,0,"right",StringFmt)) 304 | elseif isa(x[i,j],Bool) #Bool, BitArrays, as 0/1, left 305 | write(iob,fmtNumPs(x[i,j]+0,width,0,"right",StringFmt)) 306 | elseif isa(x[i,j],Nothing) #Nothing, as "" 307 | write(iob,fmtNumPs("",width,0,"right",StringFmt)) 308 | else #other types (Missing,Date,...), right 309 | write(iob,fmtNumPs(x[i,j],width,0,"right",StringFmt)) 310 | end 311 | 312 | return nothing 313 | end 314 | #------------------------------------------------------------------------------ 315 | 316 | 317 | #------------------------------------------------------------------------------ 318 | 319 | #One of the two subsequent functions is needed for handling cases like "1.5e-6" 320 | #This should not be necessary after Julia 1.6 321 | 322 | #fmtNumPsX(fmt,z) = @eval Printf.@sprintf($fmt,$z) #slow fallback solution 323 | 324 | function fmtNumPsC(fmt,z) #c fallback solution 325 | if ismissing(z) || isnan(z) || isinf(z) #asprintf does not work for these cases 326 | str = string(z) 327 | else 328 | strp = Ref{Ptr{Cchar}}(0) 329 | len = ccall(:asprintf,Cint,(Ptr{Ptr{Cchar}},Cstring,Cdouble...),strp,fmt,z) 330 | str = unsafe_string(strp[],len) 331 | Libc.free(strp[]) 332 | end 333 | return str 334 | end 335 | #------------------------------------------------------------------------------ 336 | 337 | 338 | #------------------------------------------------------------------------------ 339 | """ 340 | fmtNumPs(z,width=10,prec=2,justify="right",StringFmt="") 341 | 342 | Create a formatted string of a number. With prec=0, it can be used Bools and Strings 343 | 344 | 345 | 346 | # Remark 347 | - with prec=0, the function can be used for non-floats (incl. Bools and Strings) 348 | - The Formatting.jl package provides more elegant solutions: 349 | fmt = FormatSpec(string(">",width,".",prec,"f")) #right justified, else "<" 350 | fmt = FormatSpec(string(">",wid,"d")) #for Int 351 | str = Formatting.fmt(fmt1,z)) 352 | 353 | # Requires 354 | - Dates 355 | 356 | """ 357 | function fmtNumPs(z,width=10,prec=2,justify="right",StringFmt="") 358 | 359 | if (prec > 0) && !ismissing(z) && !isnan(z) && !isinf(z) #example: 101.0234, prec=3 360 | zRound = round(z,digits=prec) 361 | str = split(string(zRound),'.') 362 | if length(str) > 1 && !occursin("e",str[2]) #skip "1.5e-6" 363 | strR = string(".",rpad(str[2],prec,"0")) #.23 364 | strLR = string(str[1],strR) #"101" * ".23" 365 | elseif occursin("e",str[2]) #"1.5e-6" -> " 0.0000015" if prec=7 366 | fmt = "%$(width).$(prec)f" 367 | #strLR = fmtNumPsX(fmt,zRound) #slow fallback solution 368 | strLR = fmtNumPsC(fmt,zRound) #C fallback solution 369 | else 370 | strLR = string(zRound) 371 | end 372 | else 373 | (isa(z,AbstractFloat) && !isnan(z) && !isinf(z)) && (z = round(Int,z)) #Float -> Int 374 | strLR = string(z) 375 | end 376 | 377 | if justify == "left" #justification 378 | strLR = rpad(strLR,width) 379 | else 380 | strLR = lpad(strLR,width) 381 | end 382 | 383 | if StringFmt == "html" #html or csv formatting 384 | strLR = string("",strLR,"") 385 | elseif StringFmt == "csv" 386 | strLR = string(strLR,",") 387 | end 388 | 389 | return strLR 390 | 391 | end 392 | #------------------------------------------------------------------------------ 393 | 394 | 395 | #------------------------------------------------------------------------------ 396 | function printblue(x...) 397 | foreach(z->printstyled(z,color=:blue,bold=true),x) 398 | print("\n") 399 | end 400 | function printred(x...) 401 | foreach(z->printstyled(z,color=:red,bold=true),x) 402 | print("\n") 403 | end 404 | function printmagenta(x...) 405 | foreach(z->printstyled(z,color=:magenta,bold=true),x) 406 | print("\n") 407 | end 408 | function printyellow(x...) 409 | foreach(z->printstyled(z,color=:yellow,bold=true),x) 410 | print("\n") 411 | end 412 | #------------------------------------------------------------------------------ 413 | 414 | 415 | #------------------------------------------------------------------------------ 416 | function printwhere(txt) 417 | println(@__FILE__," ",@__LINE__," ",txt) 418 | end 419 | #------------------------------------------------------------------------------ 420 | 421 | -------------------------------------------------------------------------------- /NelsonSiegel/Example.jl: -------------------------------------------------------------------------------- 1 | #------------------------------------------------------------------------------ 2 | # Example.jl 3 | # 4 | # 5 | # 6 | # 7 | # 8 | # 9 | # 10 | # 11 | # 12 | # Paul.Soderlind@unisg.ch, April 2002, to Julia Nov 2015 13 | #------------------------------------------------------------------------------ 14 | 15 | using Dates, Optim 16 | 17 | include("jlFiles/BondPricePs.jl") 18 | include("jlFiles/BondNSxPs.jl") 19 | include("jlFiles/printmat.jl") 20 | 21 | 22 | ytmLoss = 0 #0: mimimize squared price errors: 1: minimize squared ytm errors 23 | weightLoss = 1 #1: 1/mat as weights for (fitted price-price)^2 in loss fn (only if ytmLoss==0) 24 | #------------------------------------------------------------------------------ 25 | 26 | #Swedish bond data for 29 Dec 1993 27 | 28 | #coupons in %/yr 29 | c = [ 0; 0; 0; 0; 11.5; 10.75; 30 | 11; 13; 10.25; 6; 9 ] 31 | 32 | #time to maturity in year 33 | tm = [ 0.00274; 0.21096; 0.46027; 0.88219; 1.67397; 3.06849; 34 | 5.06301; 7.46027; 9.34795; 11.11507; 15.30685 ] 35 | 36 | #interest rates. Bills: simple rates in %/yr; bonds: yield to maturity in %/yr 37 | y = [ 7.75; 6.835; 6.655; 6.41; 6.215; 6.195; 38 | 6.41; 6.755; 7.01; 7.21; 7.325 ] 39 | 40 | n = length(y) #number of bonds 41 | 42 | Base.require_one_based_indexing(tm,y) 43 | #---------------------------------------------------------------------------- 44 | 45 | #transform the data 46 | 47 | c = c/100 # -> column vector, coupons and yields as 0.05 rather than 5 48 | y = y/100 49 | 50 | vvc = c .== 0 #if bill, change from simple to effective rate 51 | y[vvc] = (1 .+ tm[vvc].*y[vvc]).^(1.0./tm[vvc]) .- 1 52 | 53 | P = fill(NaN,length(y)) #calculate bond prices 54 | for i = 1:n 55 | local ti 56 | ti = mod(tm[i],1):tm[i] 57 | P[i] = BondPricePs(y[i],c[i],ti) 58 | end 59 | #---------------------------------------------------------------------------- 60 | 61 | #estimating parameters in extended Nelson&Siegel model, restricted so b0 + b1 = log(1+y[1]) 62 | 63 | parX0 = [0.1045;-0.03;-0.0562;1.2;0;0.5] #starting guess 64 | 65 | if ytmLoss == 1 #loss(ytm) 66 | NSXbR = BondNSxEstPs(parX0,y,tm,c,log(1+y[1]),1) 67 | else 68 | if weightLoss == 1 #loss(P/maturity) 69 | NSXbR = BondNSxEstPs(parX0,P,tm,c,log(1+y[1]),0,1.0./tm) 70 | else #loss(P) 71 | NSXbR = BondNSxEstPs(parX0,P,tm,c,log(1+y[1])) 72 | end 73 | end 74 | 75 | println("\nParameter estimates: ") 76 | printTable(NSXbR,[""],["b0","b1","b2","tau","b3","tau2"]) 77 | #---------------------------------------------------------------------------- 78 | 79 | ytmx = fill(NaN,n) #model implied ytm 80 | for i = 1:n 81 | local ti,d,Qx 82 | ti = mod(tm[i],1):tm[i] 83 | d = BondNSxPs(ti,NSXbR...)[3] #... expands into NSXbR[1],NSXbR[2],... 84 | Qx = sum(d.*c[i]) + d[end] #model implied bond price 85 | #println(ti) 86 | ytmx[i] = BondYieldToMatPs(Qx,c[i],ti,1,1,0.05,1e-7)[1] 87 | end 88 | 89 | println("\nActual and model ytm, %: ") 90 | printTable([y ytmx]*100,["ytm actual","ytm model"],string.(tm),width=15,cell00="maturity") 91 | #---------------------------------------------------------------------------- 92 | 93 | #calculate model implied rates (spot, forward, yield to maturity) to plot 94 | 95 | tmFig = [1e-8;0.1:0.1:16] #maturities to plot 96 | (shx,fhx,) = BondNSxPs(tmFig,NSXbR...) 97 | shx = exp.(shx) .- 1 #effective interest rate 98 | fhx = exp.(fhx) .- 1 99 | 100 | println("\nmodel spot and forward rates, %: ") 101 | printTable([shx fhx]*100,["spot","forward"],string.(tmFig),width=15,cell00="maturity") 102 | #---------------------------------------------------------------------------- 103 | 104 | #Comment out this if you do not have PyPlot installed. 105 | 106 | using PyPlot 107 | #PyPlot.svg(true) #for ipynb notebooks 108 | close("all") 109 | #plotting 110 | figure() 111 | plot(tm,c,"+",tm,y,"s",tmFig,shx,"b--",tmFig,fhx,"r-",tm,ytmx,".") 112 | title("Swedish Interest Rates 29 Dec 1993") 113 | xlabel("Years to Maturity") 114 | legend(["Coupon rate","Yield to maturity","Estimated spot rate", 115 | "Estimated forward rate","Estimated yield to maturity"],loc=1) 116 | ylim(0.04,0.14) 117 | #display(gcf()) #uncomment in VsCode 118 | #---------------------------------------------------------------------------- 119 | -------------------------------------------------------------------------------- /NelsonSiegel/FinInfo199611.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PaulSoderlind/PaulSoderlindCode/00fcd5520d86575f436ea3d6b7e0a9f7981be1bc/NelsonSiegel/FinInfo199611.pdf -------------------------------------------------------------------------------- /NelsonSiegel/Readme.md: -------------------------------------------------------------------------------- 1 | Readme for NelsonSiegel 2 | ======================= 3 | 4 | Julia code for estimating an extended Nelson-Siegel model. 5 | 6 | 1. Run or just click to view the (jupyter) notebook Example.ipynb. Alternatively, use the julia script Example.jl. 7 | 8 | 2. The subfolder jlFiles contains jl files with functions used in the example. 9 | 10 | 3. FinInfo199611.pdf: paper using this approach, published as 11 | Paul Söderlind and Lars E.O. Svensson, "New Techniques to Extract Market Expectations from Financial Instruments," Journal of Monetary Economics, 40, 383-429, 1997. 12 | 13 | 4. The current version has been tested on Julia 1.9. 14 | -------------------------------------------------------------------------------- /NelsonSiegel/jlFiles/BondNSxPs.jl: -------------------------------------------------------------------------------- 1 | function BondNSxPs(m,b0,b1,b2,tau,b3=0.0,tau2=1.0) 2 | #BondNSxPs Extended Nelson and Siegel (1987) spot rate, forward rate, and discount function 3 | # 4 | # 5 | # 6 | # 7 | # Usage: (s,f,d) = BondNSxPs(m,b0,b1,b2,tau[,b3[,tau2]]) 8 | # 9 | # Input: m NxK matrix times to maturity in years (don't use less than 1e-8 or so) 10 | # b0 scalar, beta0 parameter in NS 11 | # b1 scalar, beta1 parameter in NS 12 | # b2 scalar, beta2 parameter in NS 13 | # tau scalar, tau parameter in NS 14 | # b3 (optional) scalar, beta2 parameter in extended NS [0] 15 | # tau2 (optional) scalar, tau2 parameter in extended NS [1] 16 | # 17 | # Output: s NxK matrix, spot rate (continously compounded) 18 | # f NxK matrix, forward rate (continously compounded) 19 | # d NxK matrix, discount function 20 | # 21 | # 22 | # 23 | # Note: For more details, see 24 | # (a) Svensson (1995), "Estimating Forward Interest Rates with 25 | # the Extended Nelson & Siegel Method," Quarterly Review, 26 | # Sveriges Riksbank, 1995:3, 13-26. 27 | # (b) Soderlind and Svensson (1997), "New Techniques to Extract 28 | # Market Expectations from Financial Instruments," 29 | # Journal of Monetary Economics 40, 383-429. 30 | # 31 | # 32 | # 33 | # Paul.Soderlind@unisg.ch, April 2002, to Julia 2015 34 | #----------------------------------------------------------------------------*/ 35 | 36 | #forward rate 37 | f = b0 .+ b1*exp.(-m/tau) + b2*(m/tau).*exp.(-m/tau) + b3*(m/tau2).*exp.(-m/tau2) 38 | 39 | s = b0 .+ b1* (1 .- exp.(-m/tau)) ./(m/tau) + 40 | b2*((1 .- exp.(-m/tau)) ./(m/tau) - exp.(-m/tau)) + 41 | b3*((1 .- exp.(-m/tau2))./(m/tau2) - exp.(-m/tau2)) #spot rate 42 | 43 | d = exp.(-s.*m) #discount function 44 | 45 | return s,f,d 46 | 47 | end 48 | #------------------------------------------------------------------------------ 49 | 50 | 51 | #------------------------------------------------------------------------------ 52 | function BondNSxEstPs(par0,Q,tm,c,s0,ytmLoss=0,weight=1.0) 53 | #BondNSxEstPs Estimates parameters in (extended) Nelson-Siegel yield curve model by 54 | # non-linear least squares (minimizing squared differences between 55 | # actual and fitted bond prices or yield to maturities). 56 | # 57 | # 58 | # 59 | # Usage: NSb = BondNSxEstPs(par0,Q,tm,c,s0[,ytmLoss[,weight]]) 60 | # 61 | # 62 | # Input: par0 4x1 or 6x1 vector, initial guess of paremeters 63 | # if 4x1: standard NS with par0 = [b0,b1,b2,tau] 64 | # if 6x1: extended NS with par0 = [b0,b1,b2,tau,b3,tau2] 65 | # Q nx1 vector, data on bond prices, eg. 1.01 66 | # tm nx1 vector, data on time to maturity (in years), eg. 2.54 67 | # c nx1 vector, data on bond coupons, eg. 0.06 68 | # s0 scalar, restricted value of short rate: 69 | # if [] no restriction, else b0 + b1 = s0 is imposed 70 | # ytmLoss scalar, scalar, 0: mimimize squared price errors; 71 | # 1: minimize squared ytm errors (default 0) 72 | # weight scalar or nx1 vector, weights in the loss function 73 | # 74 | # Output: NSb 4x1 or 6x1 vector, estimated parameters 75 | # 76 | # 77 | # 78 | # Note: For more details, see 79 | # (a) Svensson (1995), "Estimating Forward Interest Rates with 80 | # the Extended Neolson & Siegel Method," Quarterly Review, 81 | # Sveriges Riksbank, 1995:3, 13-26. 82 | # (b) Soderlind and Svensson (1997), "New Techniques to Extract 83 | # Market Expectations from Financial Instruments," 84 | # Journal of Monetary Economics 40, 383-429. 85 | # 86 | # 87 | # Uses: Optim 88 | # 89 | # 90 | # 91 | # Paul.Soderlind@unisg.ch, April 2002, to Julia Nov 2015 92 | #------------------------------------------------------------------------------ 93 | 94 | Base.require_one_based_indexing(par0) 95 | 96 | Qtc = [Q tm c] 97 | 98 | if in(length(par0),[4,6]) && !isempty(s0) 99 | par0 = deleteat!(par0,2) #b1 = s0 - b0 is imposed by BondNSxLossPs 100 | end 101 | 102 | Sol = optimize(b->BondNSxLossPs(b,Qtc,s0,ytmLoss,weight),par0) 103 | NSb = Optim.minimizer(Sol) 104 | if !Optim.converged(Sol) 105 | println("no convergence") 106 | return 107 | end 108 | 109 | if length(NSb) == 3 110 | NSb[[1,3]] = abs.(NSb[[1,3]]) 111 | NSb = [NSb[1]; s0-NSb[1]; NSb[2:3]] 112 | elseif length(NSb) == 4 113 | NSb[[1,4]] = abs.(NSb[[1,4]]) 114 | elseif length(NSb) == 5 115 | NSb[[1,3,5]] = abs.(NSb[[1,3,5]]) 116 | NSb = [NSb[1]; s0-NSb[1]; NSb[2:5]] 117 | elseif length(NSb) == 6 118 | NSb[[1,4,6]] = abs.(NSb[[1,4,6]]) 119 | end 120 | 121 | return NSb 122 | 123 | end 124 | #---------------------------------------------------------------------------- 125 | 126 | 127 | #------------------------------------------------------------------------------ 128 | function BondNSxLossPs(b,Qtc,s0,ytmLoss=0,weight=1.0) 129 | #BondNSxLossPs Defines loss function for bond prices in extended Nelson-Siegel model. 130 | # Used for estimation of the parameters in the model by minimizing 131 | # Loss (squared price deviations, possibly with weights). 132 | # 133 | # 134 | # Usage: Loss = BondNSxLossPs(b,Qtc,s0,ytmLoss,weight) or 135 | # = BondNSxLossPs(b,Qtc,s0,ytmLoss) or 136 | # = BondNSxLossPs(b,Qtc,s0) 137 | # 138 | # Input: b 3x1, 4x1, 5x1, or 6x1 vector with parameters in Nelson-Siegel model 139 | # if 3x1: [b0,b2,tau], NS with restriction that b1 = g_s0 - b0 140 | # if 4x1: [b0,b1,b2,tau], NS without restrictions 141 | # if 5x1: [b0,b2,tau,b3,tau2], extended NS with restriction that b1 = g_s0 - b0 142 | # if 6x1: [b0,b1,b2,tau,b3,tau2], extended NS without restrictions 143 | # Qtc nx3 matrix, data on [bond prices,time to maturity,coupons]. Use ytm instead 144 | # of bond prices if ytmLoss==1 145 | # s0 scalar, restricted value of short rate 146 | # ytmLoss scalar, 0: mimimize squared price errors; 147 | # 1: minimize squared ytm errors (default 0) 148 | # weight scalar or nx1 vector, weights in the loss function 149 | # 150 | # Output: Loss scalar, sum of squared differences between implied and actual bond 151 | # prices (or yields) 152 | # 153 | # Calls on: BondNSxPs, BondYieldToMatPs (if ytmLoss==1) 154 | # 155 | #------------------------------------------------------------------------------ 156 | 157 | Base.require_one_based_indexing(b) 158 | 159 | (Q,tm,c) = [Qtc[:,i] for i=1:3] #data on bond prices, time to maturity, coupons 160 | n = length(c) #number of bonds 161 | 162 | if length(b) == 3 #standard Nelson-Siegel with restriction b1 = s0-b0 163 | (b0,b1,b2,tau,b3,tau2) = (abs(b[1]),s0-abs(b[1]),b[2],abs(b[3]),0.0,1.0) 164 | elseif length(b) == 4 #standard Nelson-Siegel 165 | (b0,b1,b2,tau,b3,tau2) = (abs(b[1]),b[2],b[3],abs(b[4]),0.0,1.0) 166 | elseif length(b) == 5 #extended Nelson-Siegel with restriction b1 = s0 - b0 167 | (b0,b1,b2,tau,b3,tau2) = (abs(b[1]),s0-abs(b[1]),b[2],abs(b[3]),b[4],abs(b[5])) 168 | elseif length(b) == 6 #extended Nelson-Siegel 169 | (b0,b1,b2,tau,b3,tau2) = (abs(b[1]),b[2],b[3],abs(b[4]),b[5],abs(b[6])) 170 | end 171 | 172 | QNS = fill(NaN,n) 173 | for i = 1:n #loop over bonds 174 | ti = filter(z->z>0,mod(tm[i],1):tm[i]) #time to coupon payments, >0 only 175 | d = BondNSxPs(ti,b0,b1,b2,tau,b3,tau2)[3] #NSx: spot, forward, discount fn 176 | QNS[i] = sum(d.*c[i]) + d[end] #fitted bond price 177 | if ytmLoss == 1 178 | QNS[i] = BondYieldToMatPs(QNS[i],c[i],ti,1,1,0.05,1e-7) #fitted ytm 179 | end 180 | end 181 | Loss = 1.0 + 100*sum( weight.*(QNS - Q).^2 ) #weighted sum of squared deviations of fitted from actual 182 | 183 | return Loss 184 | 185 | end 186 | #------------------------------------------------------------------------------ 187 | -------------------------------------------------------------------------------- /NelsonSiegel/jlFiles/BondPricePs.jl: -------------------------------------------------------------------------------- 1 | """ 2 | BondPricePs(y,c0,t,FaceValue=1) 3 | 4 | Calculate a single coupon bond price from the spot rate curve and the payment stream 5 | (arbitrary periods and coupons), m periods 6 | 7 | 8 | # Input 9 | - `y::Vector or Number`: m vector or scalar, effective spot rates, e.g. [0.07;0.08], m periods 10 | - `c0::Vector or Number`: m vector or scalar, coupon rate, e.g. 0.06 or 0.09/2, m periods 11 | - `t::Vector`: m vector, time to the cash flows 12 | - `FaceValue::Number`: (optional) face value, [1] 13 | 14 | # Output 15 | - `Q::Number`: scalar, bond price (eg. 1.01) 16 | 17 | # Notice 18 | The face value is paid at the same time as the last coupon. 19 | Dates (t) should be expressed as fractions of the period. 20 | 21 | The following is calculated: 22 | ``` 23 | Q = c[1]/(1+y(1))^t(1) + c[2]/(1+y(2))^t(2) + ... + (1+c[m])/(1+y(m))^t(m) 24 | ``` 25 | The coupons and interest rates (optionally) depend on time to payment, so `y` and `c0` 26 | can be either scalars or m-element vectors. 27 | 28 | 29 | # Example 30 | ``` 31 | y = [0.0626;0.07] 32 | c = [0.09; 0.09] 33 | t = 1:2 34 | gives 35 | Q = 1.0367 36 | ``` 37 | 38 | Paul Soderlind (Paul.Soderlind@unisg.ch) 39 | 40 | """ 41 | function BondPricePs(y,c0,t,FaceValue=1) 42 | 43 | isa(c0,Number) ? c = fill(c0,length(t)) : c = copy(c0) 44 | c[end] = c[end] + FaceValue 45 | 46 | cdisc = c./((1.0.+y).^t) #c/(1+y(1))^t1 + c/(1+y(2))^t2 + ...+ c/(1+y(m))^tm 47 | Q = sum(cdisc) #price (sum(.,1)) to handle also m=1 48 | 49 | return Q 50 | 51 | end 52 | #----------------------------------------------------------------------------- 53 | 54 | 55 | #----------------------------------------------------------------------------- 56 | """ 57 | BondPriceQDyPs(y,c0,t,FaceValue=1) 58 | 59 | Calculate coupon bond price and derivative. 60 | 61 | # Input 62 | - see BondPricePs 63 | 64 | # Output 65 | - `Q::Number`: scalar, bond price (eg. 1.01) 66 | - `dQ_dy::Number`: scalar, derivative of bond price wrt y (valid only when y is a scalar) 67 | 68 | """ 69 | function BondPriceQDyPs(y,c0,t,FaceValue=1) 70 | 71 | isa(c0,Number) ? c = fill(c0,length(t)) : c = copy(c0) 72 | c[end] = c[end] + FaceValue 73 | 74 | cdisc = c./((1.0.+y).^t) #c/(1+y(1))^t1 + c/(1+y(2))^t2 + ...+ c/(1+y(m))^tm 75 | Q = sum(cdisc) #price (sum(.,1)) to handle also m=1 76 | 77 | dcdisc = cdisc .* (-t./(1.0.+y)) #derivative wrt ytm 78 | dQ_dy = sum(dcdisc) #only strictly valid when y is a scalar 79 | 80 | return Q, dQ_dy 81 | 82 | end 83 | #----------------------------------------------------------------------------- 84 | 85 | 86 | #----------------------------------------------------------------------------- 87 | """ 88 | BondYieldToMatPs(Q,c0,t,FaceValue=1,method=1,yLH=[-0.1;0.5],tol=1e-7) 89 | 90 | Calculate yield to maturity from bond price (several methods available). 91 | Can also be used for general IRR calculations. Works with arbitrary coupon periods. 92 | 93 | # Input 94 | - `Q::Number`: scalar 95 | - `c::Vector or Number`: see BondPricePs 96 | - `t::Vector or Number`: see BondPricePs 97 | - `FaceValue::Number`: optional, scalar or n vector, face value, [1] 98 | - `method::Number`: optional, 1: Newton-Raphson; 2: bisection [1] 99 | - `yLH::Number`: optional, if method==1: scalar, yLH[1] is initial guess of roots 100 | if method==2: 2 vector, yLH[1] is lower boundary and yLH[2] upper boundary 101 | - `tol::Number`: optional, scalar, convergence criterion for y, [1e-7] 102 | 103 | # Output 104 | - `y::Number` effective yield to maturity (per period) 105 | 106 | # Notice 107 | - method 1 (Newton-Raphson) is pretty fast. 108 | - method 2 (bisection) is a bit slow, but very robust. 109 | - To use for IRR calculations, set Q=0 and FaceValue=0 110 | - For Newton-Raphson, we could use (c+(FaceValue-B)/n)/((FaceValue+B)/2) as a good starting value 111 | 112 | # Requires 113 | - BondPricePs, BondPriceQDyPs 114 | 115 | """ 116 | function BondYieldToMatPs(Q,c0,t,FaceValue=1,method=1,yLH=[-0.1;0.5],tol=1e-7) 117 | 118 | Base.require_one_based_indexing(yLH) 119 | 120 | if method == 1 #Newton-Raphson 121 | 122 | y = yLH[1] 123 | Dy = 1e+198 124 | while abs(Dy) > tol 125 | (F0,J0) = BondPriceQDyPs(y,c0,t,FaceValue) #F(y0), derivative 126 | Dy = (Q - F0)/J0 127 | y = y + Dy 128 | end 129 | 130 | elseif method == 2 #bisection 131 | 132 | (yL,yH) = (yLH[1],yLH[2]) #lower and upper boundary for yield 133 | if yL > yH 134 | println("warning: lower bound greater than upper bound") 135 | end 136 | F0 = BondPricePs(yL,c0,t,FaceValue) #create starting value, so [yL,yH] brackets the roots 137 | while F0 < Q #as long as theoretical < actual price 138 | yL = yL - 0.01 139 | F0 = BondPricePs(yL,c0,t,FaceValue) 140 | end 141 | F0 = BondPricePs(yH,c0,t,FaceValue) 142 | while F0 > Q 143 | yH = yH + 0.01 144 | F0 = BondPricePs(yH,c0,t,FaceValue) 145 | end 146 | 147 | y = (yL + yH)/2 148 | while (yH-yL) > tol #iteration loop 149 | y = (yL + yH)/2 #mid point for yield 150 | F0 = BondPricePs(y,c0,t,FaceValue) #price at guessed yield 151 | if F0 >= Q #logical where F0 >= Q (decreasing function) 152 | yL = y # => root must be higher than y 153 | else 154 | yH = y # -> root must be lower than y 155 | end 156 | end 157 | 158 | end #end different methods 159 | 160 | return y 161 | 162 | end 163 | #------------------------------------------------------------------------------ 164 | 165 | 166 | #------------------------------------------------------------------------------ 167 | """ 168 | BondDurationPs(Q,c0,t,FaceValue=1,method=1,yLH=[-0.1;0.5],tol=1e-7) 169 | 170 | Calculate bond durations. See also BondYieldToMatPs 171 | 172 | 173 | # Input 174 | - see BondYieldToMatPs 175 | 176 | # Output 177 | - `D::Number`: scalar, (dollar) duration 178 | - `Da::Number`: scalar, adjusted (or modified) duration 179 | - `Dma::Numberc`: scalar, Macaulays duration 180 | - `ytm::Number`: scalar 181 | 182 | 183 | # Notice 184 | The bond price satisfies (with yield expressed per period) 185 | 186 | Q = c/(1+y)^t(1) + c/(1+y)^t(2) + ... + (1+c)/(1+y)^t(m) 187 | 188 | where y is the yield to maturity, c is per period coupon 189 | and Macaulay's duration is 190 | 191 | D = [t(1)*c/(1+y)^t(1) + t(2)*c/(1+y)^t(2) + ... + t(m)*(1+c)/(1+y)^t(m)]/Q 192 | 193 | 194 | # Requires 195 | - BondPricePs, BondYieldToMatPs 196 | 197 | """ 198 | function BondDurationPs(Q,c0,t,FaceValue=1,method=1,yLH=[-0.1;0.5],tol=1e-7) 199 | 200 | y = BondYieldToMatPs(Q,c0,t,FaceValue,method,yLH,tol) #ytm 201 | 202 | (_,Dy) = BondPriceQDyPs(y,c0,t,FaceValue) 203 | D = -Dy #duration 204 | Da = D / Q #adjusted duration 205 | Dmac = D*(1+y)/ Q #Macaulays duration 206 | 207 | return D, Da, Dmac, y 208 | 209 | end 210 | #------------------------------------------------------------------------------ 211 | -------------------------------------------------------------------------------- /NelsonSiegel/jlFiles/printmat.jl: -------------------------------------------------------------------------------- 1 | #------------------------------------------------------------------------------ 2 | """ 3 | printmat([fh::IO],x;width=10,prec=3,NoPrinting=false,StringFmt="") 4 | 5 | Print all elements of matrix with predefined formatting. 6 | 7 | # Input 8 | - `fh::IO`: (optional) file handle. If not supplied, prints to screen 9 | - `x::Array`: string, date or array to print 10 | - `width::Int`: (keyword) scalar, minimum width of printed cells 11 | - `prec::Int`: (keyword) scalar, precision of printed cells 12 | - `NoPrinting::Bool`: (keyword) bool, true: no printing, just return formatted string 13 | - `StringFmt::String`: (keyword) string, "", "html", "csv" 14 | 15 | # Output 16 | - str (if NoPrinting) string, (otherwise nothing) 17 | 18 | # Examples 19 | ``` 20 | x = [11 12;21 22] 21 | printmat(x) 22 | ``` 23 | ``` 24 | x = Any[1 "ab"; Date(2018,10,7) 3.14] 25 | printmat(x,width=20) 26 | ``` 27 | Can also call as 28 | ``` 29 | opt = Dict(:width=>10,:prec=>3,:NoPrinting=>false,:StringFmt=>"") 30 | printmat(x;opt...) #notice , and ... 31 | ``` 32 | (not all keywords are needed) 33 | 34 | # Requires 35 | - Dates 36 | - fmtNumPs 37 | 38 | # To do 39 | 40 | 41 | Paul.Soderlind@unisg.ch 42 | 43 | """ 44 | function printmat(fh::IO,x;width=10,prec=3,NoPrinting=false,StringFmt="") 45 | 46 | if isa(x,Union{String,Date,DateTime,Missing}) #eg. a single Date 47 | str = string(lpad(x,width),"\n") 48 | if NoPrinting 49 | return str 50 | else 51 | print(fh,str,"\n") 52 | return nothing 53 | end 54 | elseif isa(x,Nothing) 55 | return nothing 56 | end 57 | 58 | if ndims(x) > 2 59 | @warn("more than 2 dimensions") 60 | return nothing 61 | end 62 | 63 | (m,n) = (size(x,1),size(x,2)) 64 | 65 | iob = IOBuffer() 66 | for i = 1:m #loop over lines 67 | for j = 1:n-1 #loop over columns 1:n-1 68 | writeElementPs(iob,x,i,j,width,prec,StringFmt) 69 | end 70 | if StringFmt == "csv" #last (n) column 71 | writeElementPs(iob,x,i,n,width,prec,"") #no , at end of line 72 | else 73 | writeElementPs(iob,x,i,n,width,prec,StringFmt) 74 | end 75 | write(iob,"\n") #newline 76 | end 77 | str = String(take!(iob)) 78 | 79 | if NoPrinting #no printing, just return str 80 | return str 81 | else #print, return nothing 82 | print(fh,str,"\n") 83 | return nothing 84 | end 85 | 86 | end 87 | #when fh is not supplied: printing to screen 88 | printmat(x;width=10,prec=3,NoPrinting=false,StringFmt="") = printmat(stdout::IO, 89 | x,width=width,prec=prec,NoPrinting=NoPrinting,StringFmt=StringFmt) 90 | #------------------------------------------------------------------------------ 91 | 92 | 93 | #------------------------------------------------------------------------------ 94 | """ 95 | printTable([fh::IO],x,colNames=[],rowNames=[]; 96 | width=10,prec=3,NoPrinting=false,StringFmt="",cell00="") 97 | 98 | Print formatted table with row names (1st column) column names (1st row), 99 | and data matrix (the rest). 100 | 101 | 102 | # Input 103 | - `fh::IO`: (optional) file handle. If not supplied, prints to screen 104 | - `x::Array`: (of numbers, dates, strings, ...) to print 105 | - `colNames::Array`: of strings with column headers 106 | - `rowNames::Array`: of strings with row labels 107 | - `width::Int`: (keyword) scalar, minimum width of printed cells. [10] 108 | - `prec::Int`: (keyword) scalar, precision of printed cells. [3] 109 | - `NoPrinting::Bool`: (keyword) bool, true: no printing, just return formatted string [false] 110 | - `StringFmt::String`: (keyword) string, "", "html", "csv" 111 | - `cell00::String`: (keyword) string, for row 0, column 0 112 | 113 | # Output 114 | - `str::String`: (if NoPrinting) string, (otherwise nothing) 115 | 116 | # Example 117 | ``` 118 | xA = [1 "ab" "abc"; "ccc" 3.14 missing] 119 | printTable(xA,colNames,["1";"4"],width=12,prec=2) 120 | ``` 121 | Can also call as 122 | ``` 123 | opt = Dict(:width=>10,:prec=>3,:NoPrinting=>false,:StringFmt=>"",:cell00=>"") 124 | printTable(x;opt...) #notice , and ... 125 | ``` 126 | (not all keywords are needed) 127 | 128 | # Requires 129 | - Dates 130 | - printmat 131 | 132 | """ 133 | function printTable(fh::IO,x,colNames=[],rowNames=[]; 134 | width=10,prec=3,NoPrinting=false,StringFmt="",cell00="") 135 | 136 | isempty(x) && return nothing #do nothing is isempty(x) 137 | 138 | (m,n) = (size(x,1),size(x,2)) 139 | 140 | if isempty(rowNames) #create row names "r1" 141 | rowNames = [string("r",i) for i = 1:m] 142 | end 143 | if isempty(colNames) #create column names "c1" 144 | colNames = [string("c",i) for i = 1:n] 145 | end 146 | 147 | rNamesWidth = maximum([length(rowNames[i]) for i = 1:length(rowNames)]) #max length of rowNames 148 | rNamesWidth = max(rNamesWidth,length(cell00)) 149 | 150 | iob = IOBuffer() 151 | if StringFmt == "html" #print column names 152 | write(iob,"",lpad(cell00,rNamesWidth),"") 153 | for i = 1:n 154 | write(iob,"",lpad(colNames[i],width),"") 155 | end 156 | write(iob,"") 157 | elseif StringFmt == "csv" 158 | write(iob,lpad(string(cell00,","),rNamesWidth)) 159 | for i = 1:n-1 160 | write(iob,lpad(colNames[i],width),",") 161 | end 162 | write(iob,lpad(colNames[n],width)) #no , at line end 163 | else 164 | write(iob,lpad(cell00,rNamesWidth)) #cell 0,0 165 | for i = 1:n #create string 166 | write(iob,lpad(colNames[i],width)) 167 | end 168 | end 169 | write(iob,"\n") 170 | 171 | xStr = printmat(fh,x,width=width,prec=prec,NoPrinting=true,StringFmt=StringFmt) #body of table, one long string 172 | xStrV = split(xStr,"\n") #vector of strings (one per row of x) 173 | 174 | for i = 1:m #loop over rows in x, print rowNames[i] and x[i,:] 175 | if StringFmt == "html" 176 | write(iob,"",rpad(rowNames[i],rNamesWidth),"",xStrV[i]," \n") 177 | elseif StringFmt == "csv" 178 | write(iob,rpad(string(rowNames[i],","),rNamesWidth),xStrV[i],"\n") 179 | else 180 | write(iob,rpad(rowNames[i],rNamesWidth),xStrV[i],"\n") 181 | end 182 | end 183 | str = String(take!(iob)) 184 | 185 | if NoPrinting #no printing, just return str 186 | return str 187 | else #print, return nothing 188 | print(fh,str,"\n") 189 | return nothing 190 | end 191 | 192 | end 193 | #when fh is not supplied: printing to screen 194 | printTable(x,colNames=[],rowNames=[];width=10,prec=3,NoPrinting=false,StringFmt="",cell00="") = 195 | printTable(stdout::IO,x,colNames,rowNames,width=width,prec=prec,NoPrinting=NoPrinting, 196 | StringFmt=StringFmt,cell00=cell00) 197 | #------------------------------------------------------------------------------ 198 | 199 | 200 | #------------------------------------------------------------------------------ 201 | """ 202 | printlnPs([fh::IO],z...;width=10,prec=3) 203 | 204 | Subsitute for println, with predefined formatting. 205 | 206 | 207 | # Input 208 | - `fh::IO`: (optional) file handle. If not supplied, prints to screen 209 | - `z::String`: string, numbers and arrays to print 210 | 211 | Paul.Soderlind@unisg.ch 212 | 213 | """ 214 | function printlnPs(fh::IO,z...;width=10,prec=3) 215 | 216 | for x in z #loop over inputs in z... 217 | if isa(x,Union{String,Date,DateTime,Missing}) 218 | print(fh,lpad(x,width)) 219 | elseif isa(x,Nothing) 220 | print(fh,"") 221 | else #other types 222 | iob = IOBuffer() 223 | for i = 1:length(x) 224 | if isa(x[i],AbstractFloat) #Float 225 | write(iob,fmtNumPs(x[i],width,prec,"right")) 226 | elseif isa(x[i],Nothing) #Nothing 227 | write(iob,lpad("",width)) 228 | else #Integer, etc 229 | write(iob,lpad(x[i],width)) 230 | end 231 | end 232 | print(fh,String(take!(iob))) 233 | end 234 | end 235 | 236 | print(fh,"\n") 237 | 238 | end 239 | #when fh is not supplied: printing to screen 240 | printlnPs(z...;width=10,prec=3) = printlnPs(stdout::IO,z...,width=width,prec=prec) 241 | #------------------------------------------------------------------------------ 242 | 243 | 244 | #------------------------------------------------------------------------------ 245 | """ 246 | printmat2 247 | 248 | Call on printmat twice: to print to screen and then to an open file (IOStream) 249 | """ 250 | function printmat2(fh,x;width=10,prec=3,NoPrinting=false,StringFmt="") 251 | printmat(x,width=width,prec=prec,NoPrinting=NoPrinting,StringFmt=StringFmt) #to screen 252 | if isa(fh,IOStream) && isopen(fh) 253 | printmat(fh,x,width=width,prec=prec,NoPrinting=NoPrinting,StringFmt=StringFmt) #to file 254 | end 255 | end 256 | #------------------------------------------------------------------------------ 257 | 258 | 259 | #------------------------------------------------------------------------------ 260 | """ 261 | printTable2 262 | 263 | Call on printTable2 twice: to print to screen and then to an open file (IOStream) 264 | """ 265 | function printTable2(fh,x,colNames=[],rowNames=[];width=10,prec=3,NoPrinting=false, 266 | StringFmt="",cell00="") 267 | printTable(x,colNames,rowNames,width=width,prec=prec,NoPrinting=NoPrinting, 268 | StringFmt=StringFmt,cell00=cell00) #to screen 269 | if isa(fh,IOStream) && isopen(fh) 270 | printTable(fh,x,colNames,rowNames,width=width,prec=prec,NoPrinting=NoPrinting, 271 | StringFmt=StringFmt,cell00=cell00) #to file 272 | end 273 | end 274 | #------------------------------------------------------------------------------ 275 | 276 | 277 | #------------------------------------------------------------------------------ 278 | """ 279 | println2Ps 280 | 281 | Call on printlnPs twice: to print to screen and then to an open file (IOStream) 282 | """ 283 | function println2Ps(fh::IO,z...;width=10,prec=3) 284 | printlnPs(z...,width=width,prec=prec) #to screen 285 | if isa(fh,IOStream) && isopen(fh) 286 | printlnPs(fh::IO,z...,width=width,prec=prec) #to file 287 | end 288 | end 289 | #------------------------------------------------------------------------------ 290 | 291 | 292 | #------------------------------------------------------------------------------ 293 | """ 294 | writeElementPs(iob,x,i,j,width,prec,StringFmt) 295 | 296 | Writes one element to iob, formatting depends on type 297 | """ 298 | function writeElementPs(iob,x,i,j,width,prec,StringFmt) 299 | 300 | if isa(x[i,j],AbstractFloat) #Float 301 | write(iob,fmtNumPs(x[i,j],width,prec,"right",StringFmt)) 302 | elseif isa(x[i,j],Union{Int,String}) #Int, String 303 | write(iob,fmtNumPs(x[i,j],width,0,"right",StringFmt)) 304 | elseif isa(x[i,j],Bool) #Bool, BitArrays, as 0/1, left 305 | write(iob,fmtNumPs(x[i,j]+0,width,0,"right",StringFmt)) 306 | elseif isa(x[i,j],Nothing) #Nothing, as "" 307 | write(iob,fmtNumPs("",width,0,"right",StringFmt)) 308 | else #other types (Missing,Date,...), right 309 | write(iob,fmtNumPs(x[i,j],width,0,"right",StringFmt)) 310 | end 311 | 312 | return nothing 313 | end 314 | #------------------------------------------------------------------------------ 315 | 316 | 317 | #------------------------------------------------------------------------------ 318 | 319 | #One of the two subsequent functions is needed for handling cases like "1.5e-6" 320 | #This should not be necessary after Julia 1.6 321 | 322 | #fmtNumPsX(fmt,z) = @eval Printf.@sprintf($fmt,$z) #slow fallback solution 323 | 324 | function fmtNumPsC(fmt,z) #c fallback solution 325 | if ismissing(z) || isnan(z) || isinf(z) #asprintf does not work for these cases 326 | str = string(z) 327 | else 328 | strp = Ref{Ptr{Cchar}}(0) 329 | len = ccall(:asprintf,Cint,(Ptr{Ptr{Cchar}},Cstring,Cdouble...),strp,fmt,z) 330 | str = unsafe_string(strp[],len) 331 | Libc.free(strp[]) 332 | end 333 | return str 334 | end 335 | #------------------------------------------------------------------------------ 336 | 337 | 338 | #------------------------------------------------------------------------------ 339 | """ 340 | fmtNumPs(z,width=10,prec=2,justify="right",StringFmt="") 341 | 342 | Create a formatted string of a number. With prec=0, it can be used Bools and Strings 343 | 344 | 345 | 346 | # Remark 347 | - with prec=0, the function can be used for non-floats (incl. Bools and Strings) 348 | - The Formatting.jl package provides more elegant solutions: 349 | fmt = FormatSpec(string(">",width,".",prec,"f")) #right justified, else "<" 350 | fmt = FormatSpec(string(">",wid,"d")) #for Int 351 | str = Formatting.fmt(fmt1,z)) 352 | 353 | # Requires 354 | - Dates 355 | 356 | """ 357 | function fmtNumPs(z,width=10,prec=2,justify="right",StringFmt="") 358 | 359 | if (prec > 0) && !ismissing(z) && !isnan(z) && !isinf(z) #example: 101.0234, prec=3 360 | zRound = round(z,digits=prec) 361 | str = split(string(zRound),'.') 362 | if length(str) > 1 && !occursin("e",str[2]) #skip "1.5e-6" 363 | strR = string(".",rpad(str[2],prec,"0")) #.23 364 | strLR = string(str[1],strR) #"101" * ".23" 365 | elseif occursin("e",str[2]) #"1.5e-6" -> " 0.0000015" if prec=7 366 | fmt = "%$(width).$(prec)f" 367 | #strLR = fmtNumPsX(fmt,zRound) #slow fallback solution 368 | strLR = fmtNumPsC(fmt,zRound) #C fallback solution 369 | else 370 | strLR = string(zRound) 371 | end 372 | else 373 | (isa(z,AbstractFloat) && !isnan(z) && !isinf(z)) && (z = round(Int,z)) #Float -> Int 374 | strLR = string(z) 375 | end 376 | 377 | if justify == "left" #justification 378 | strLR = rpad(strLR,width) 379 | else 380 | strLR = lpad(strLR,width) 381 | end 382 | 383 | if StringFmt == "html" #html or csv formatting 384 | strLR = string("",strLR,"") 385 | elseif StringFmt == "csv" 386 | strLR = string(strLR,",") 387 | end 388 | 389 | return strLR 390 | 391 | end 392 | #------------------------------------------------------------------------------ 393 | 394 | 395 | #------------------------------------------------------------------------------ 396 | function printblue(x...) 397 | foreach(z->printstyled(z,color=:blue,bold=true),x) 398 | print("\n") 399 | end 400 | function printred(x...) 401 | foreach(z->printstyled(z,color=:red,bold=true),x) 402 | print("\n") 403 | end 404 | function printmagenta(x...) 405 | foreach(z->printstyled(z,color=:magenta,bold=true),x) 406 | print("\n") 407 | end 408 | function printyellow(x...) 409 | foreach(z->printstyled(z,color=:yellow,bold=true),x) 410 | print("\n") 411 | end 412 | #------------------------------------------------------------------------------ 413 | 414 | 415 | #------------------------------------------------------------------------------ 416 | function printwhere(txt) 417 | println(@__FILE__," ",@__LINE__," ",txt) 418 | end 419 | #------------------------------------------------------------------------------ 420 | 421 | -------------------------------------------------------------------------------- /Readme.md: -------------------------------------------------------------------------------- 1 | Readme for PaulSoderlindCode 2 | ============================ 3 | 4 | This repository has the following separate sub projects: 5 | 6 | 1. AssetPricingTest: Julia code for asset pricing test 7 | 8 | 2. DriscollKraay: Julia code for panel regressions with Driscoll-Kraay standard errors 9 | 10 | 3. FittingNfromHist: Julia code for fitting N(mu,sigma2) from a histogram 11 | 12 | 4. LStar: Julia code for LSTAR regressions 13 | 14 | 5. NelsonSiegel: Julia code for estimating the extended Nelson-Siegel model 15 | 16 | 6. SolvingReModels: Julia code for solving RE models 17 | 18 | 19 | To download use "Download ZIP" (upper right). This gives you a zip file with all the subfolders. (No, as of yet there is no simple way of downloading a single subfolder.) 20 | 21 | The code typically follows my lecture notes/papers. So far, there are few attempts at speeding up or error checking. 22 | 23 | A remark on the code (Aug 2022): much of this code was ported from Matlab in my early Julia days --- and it shows. There is plenty of room for improvements. 24 | -------------------------------------------------------------------------------- /SolvingReModels/Example.jl: -------------------------------------------------------------------------------- 1 | #-------------------------------------------------------------------------- 2 | # Example.jl 3 | # 4 | # Test program for the functions in ComItAlg.jl, DiscAlg, and SimpRulT.jl. 5 | # The program also uses VAR1SimPs to calculate impulse response functions. 6 | # 7 | # The program uses a very simplified version of the model in 8 | # Fuhrer, J. C. (1997), "Inflation/Output Variance Trade-Offs and Optimal 9 | # Monetary Policy," JMCB, 29, 214-234. 10 | # 11 | # 12 | # 13 | # This example file and the procedures were created by translating MatLab code 14 | # to Julia. 15 | # 16 | # 17 | # Paul Soderlind (Paul.Soderlind@unisg.ch), 20 June 2000, to Julia Jan 2016 18 | #---------------------------------------------------------------------------- 19 | 20 | using Dates, LinearAlgebra 21 | include("jlFiles/Fuhrer1.jl") 22 | include("jlFiles/VAR1SimPs.jl") 23 | include("jlFiles/SimpRulT.jl") 24 | include("jlFiles/ComitAlg.jl") 25 | include("jlFiles/DiscAlg.jl") 26 | include("jlFiles/printmat.jl") 27 | #----------------------------------------------------------------------- 28 | 29 | #simplified Fuhrer model, parameter values 30 | (a1,ap,Varey) = (0.85,-0.41,0.84^2) #IS equation 31 | (w,gamm,Varep) = (0.65,0.002,0.19^2) #contracting equation 32 | Dbig = 40 #arbitrage condition 33 | (qy,qpi,qf,bet) = (1,1,0.5,0.99) #Loss function 34 | 35 | #Parameters -> system matrices 36 | (A,B,K,Q,U,R) = Fuhrer1(a1,ap,Varey,w,gamm,Varep,Dbig,qy,qpi,qf,bet) 37 | (n1,n2,K) = (3,2,1) 38 | 39 | T = 12 #periods to simulate in VAR 40 | Shock0 = [sqrt(Varep);zeros(2)] #Impulse response wrt ep 41 | #----------------------------------------------------------------------- 42 | 43 | #SIMPLE RULE, u(t)=-Fx(t) 44 | (Fy,Fpi) = (0.5,1.2) #Simple decision rule: i(t) = = Fy*y(t) + Fpi*[p(t)-p(t-1)] 45 | F = [0 -Fy -Fpi*4*(1-w) 0 -Fpi*4*w ] 46 | 47 | x10 = zeros(n1) #initial state vector 48 | SigmaXX = diagm(0=>[Varep,Varey,0]) #covariance matrix of shocks 49 | (M_Simp,C_Simp,J0) = SimpRulT(A,B,Q,R,U,bet,n1,n2,F,SigmaXX,x10,1.0) 50 | 51 | x1 = VAR1SimPs(M_Simp,Shock0,T) #VAR of x1(t) 52 | x2 = x1*C_Simp' #x2(t) 53 | x = [x1 x2] #x(t) = [x1(t),x2(t)] 54 | uu = -x*F' #u(t) 55 | ypii_Simp = [x[:,2] (4*(1-w)*x[:,3]+4*w*x[:,5]) uu] 56 | 57 | println("\nSimple rule: impulse response to a one std of price shock (y,pi,i)") 58 | printTable(ypii_Simp,["y","π","i"],string.(1:T),cell00="period") 59 | #--------------------------------------- 60 | 61 | #plotting, comment out this if PyPlot is not installed 62 | using PyPlot 63 | #PyPlot.svg(true) #for ipynb notebooks 64 | figure() 65 | plot(1:T,ypii_Simp) 66 | title("Simple rule: impulse response to a one std of price shock") 67 | legend(["Output","Inflation","Short interest rate"]) 68 | #display(gcf()) #uncomment in VsCode 69 | #----------------------------------------------------------------------- 70 | 71 | #COMMITMENT 72 | (M_Commit,C_Commit) = ComItAlg(A,B,Q,R,U,bet,n1,n2,1.0) 73 | 74 | k = VAR1SimPs(M_Commit,[Shock0;zeros(2)],T) #VAR of x1(t),p2(t) 75 | lambda = k*C_Commit' #x2(t),u(t),p1(t) 76 | uu = lambda[:,n2+1:n2+1] #u(t) 77 | x = [k[:,1:n1] lambda[:,1:n2]] #x(t) = [x1(t),x2(t)] 78 | ypii_Commit = [x[:,2] (4*(1-w)*x[:,3]+4*w*x[:,5]) uu] 79 | 80 | println("\nCommitment: impulse response to a one std of price shock (y,pi,i)") 81 | printTable(ypii_Commit,["y","π","i"],string.(1:T),cell00="period") 82 | #--------------------------------------- 83 | 84 | #plotting, comment out this if PyPlot is not installed 85 | figure() 86 | plot(1:T,ypii_Commit) 87 | title("Commitment: impulse response to a one std of price shock") 88 | legend(["Output","Inflation","Short interest rate"]) 89 | #display(gcf()) #uncomment in VsCode 90 | #----------------------------------------------------------------------- 91 | 92 | #DISCRETION 93 | println("\nPlease wait, the discretionary case takes some time to solve") 94 | (M_Disc,C_Disc,V,F) = DiscAlg(A,B,Q,R,U,bet,n1,n2,Matrix(1.0I,n1,n1),zeros(n2,n1), 95 | [1e-1;1e-5],0,1,0,1,0,1e+4) 96 | 97 | x1 = VAR1SimPs(M_Disc,Shock0,T) #VAR of x1(t) 98 | x2 = x1*C_Disc' #x2(t) 99 | x = [x1 x2] #x(t) = [x1(t),x2(t)] 100 | uu = -x1*F' #u(t) 101 | ypii_Disc = [x[:,2] (4*(1-w)*x[:,3]+4*w*x[:,5]) uu] 102 | 103 | println("\nDiscretion: impulse response to a one std of price shock (y,pi,i)") 104 | printTable(ypii_Disc,["y","π","i"],string.(1:T),cell00="period") 105 | #--------------------------------------- 106 | 107 | #plotting, comment out this if PyPlot is not installed 108 | figure() 109 | plot(1:T,ypii_Disc) 110 | title("Discretion: impulse response to a one std of price shock") 111 | legend(["Output","Inflation","Short interest rate"]) 112 | #display(gcf()) #uncomment in VsCode 113 | #----------------------------------------------------------------------- 114 | -------------------------------------------------------------------------------- /SolvingReModels/MonEEA199812.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PaulSoderlind/PaulSoderlindCode/00fcd5520d86575f436ea3d6b7e0a9f7981be1bc/SolvingReModels/MonEEA199812.pdf -------------------------------------------------------------------------------- /SolvingReModels/Readme.md: -------------------------------------------------------------------------------- 1 | Readme for SolvingReModels 2 | ============================ 3 | 4 | Julia code for solve RE models. 5 | 6 | 7 | 1. Run or just click to view the (jupyter) notebook Example.ipynb. Alternatively, use the julia script Example.jl. 8 | 9 | 2. The subfolder jlFiles contains jl files with functions used in the example. 10 | 11 | 3. MonEEA199812.pdf: paper on these algorithms, published as Paul Söderlind, "Solution and Estimation of RE Macromodels with Optimal Policy," European Economic Review, 43, 813-823, 1999 12 | 13 | 4. The current version has been tested on Julia 1.9. 14 | -------------------------------------------------------------------------------- /SolvingReModels/jlFiles/ComItAlg.jl: -------------------------------------------------------------------------------- 1 | function ComItAlg(A,B,Q,R,U,bet,n1,n2,cutoff=1.0) 2 | #ComItAlg Solves for optimization problem in commitment case. 3 | # 4 | # 5 | # Usage: (M,C) = ComItAlg(A,B,Q,R,U,bet,n1,n2,cutoff) 6 | # 7 | # Input: A nxn matrix, (n=n1+n2) 8 | # B nxk matrix 9 | # Q nxn matrix, symmetric 10 | # R kxk matrix, symmetric 11 | # U nxk matrix 12 | # bet scalar, discount factor (eg 0.99) 13 | # n1 scalar, # of predetermined variables 14 | # n2 scalar, # of forward looking variables 15 | # cutoff scalar, max modulus of backward looking variables 16 | # 17 | # Output: M nxn matrix, [x1(t+1),p2(t+1)] = M*[x1(t),p2(t)] + e(t+1) 18 | # C (n2+k+n1)xn matrix, [x2(t),u(t),p1(t)] = C*[x1(t),p2(t)] 19 | # 20 | # 21 | # 22 | # Details: Solve for optimization problem in commitment case. The economy 23 | # evolves as 24 | # 25 | # x1(t+1) = A * x1(t) + Bu(t) + e(t+1) 26 | # E(t)x2(t+1) x2(t) 0 27 | # 28 | # where x1(t) ("backward looking") has n1 elements, 29 | # and x2(t) ("forward looking") has n2 elements. The initial 30 | # value of x1, x1(0), is given by history. Let n=n1+n2. 31 | # u(t) is an kx1 vector of decision variables, which follows 32 | # the decision rule. 33 | # 34 | # Define x(t)=[x1(t),x2(t)]. The loss function of the policy 35 | # maker is 36 | # 37 | # Sum{ (bet^t)*[x(t)'Q*x(t)+2x(t)'U*u(t)+u(t)'R*u(t)],t=0,1,... } 38 | # 39 | # 40 | # 41 | # Paul Söderlind, Paul.Soderlind@unisg.ch, Aug 2000, to Julia Jan 2016 42 | #---------------------------------------------------------------------------- 43 | 44 | Base.require_one_based_indexing(A,B,Q,R,U) 45 | 46 | Q = (Q + Q')/2 #to make symmetric 47 | R = (R + R')/2 48 | 49 | n = n1 + n2 50 | k = size(R,1) #No. of control variables 51 | 52 | G = [ [I zeros(n,k) zeros(n,n) ]; 53 | [zeros(n,n) zeros(n,k) (bet*A') ]; 54 | [zeros(k,n) zeros(k,k) (-B') ]] 55 | 56 | D = [ [A B zeros(n,n) ]; 57 | [(-bet*Q) (-bet*U) I ]; 58 | [U' R zeros(k,n) ]] 59 | 60 | v1 = 1:n1 #reordering 61 | v2 = n1+1:n1+n2 62 | v3 = n1+n2+1:n1+n2+k+n1 63 | v4 = n1+n2+k+n1+1:n1+n2+k+n1+n2 64 | v = [v1;v4;v2;v3] 65 | 66 | G = G[:,v] #x1,x2,(u,p1),p2 -> x1,p2,x2,(u,p1) 67 | D = D[:,v] 68 | 69 | GS = schur(G,D) 70 | logconA = abs.(GS.beta) .<= (abs.(GS.alpha)*cutoff) #selecting stable eigenvalues 71 | ordschur!(GS,logconA) #reordering, stable first 72 | 73 | if sum(logconA) < n 74 | @warn("Too few stable roots: no stable solution") 75 | return NaN,NaN 76 | elseif sum(logconA) > n 77 | @warn("Too many stable roots: inifite number of stable solutions") 78 | return NaN,NaN 79 | end 80 | 81 | Stt = GS.S[1:n,1:n] 82 | Ttt = GS.T[1:n,1:n] 83 | Zkt = GS.Z[1:n,1:n] 84 | Zlt = GS.Z[n+1:n+k+n,1:n] 85 | 86 | if cond(Zkt) > 1e+14 87 | @warn("Zkt is singular: rank condition for solution not satisfied") 88 | return NaN, NaN 89 | end 90 | 91 | Zkt_1 = inv(Zkt) #inverting 92 | Stt_1 = inv(Stt) 93 | 94 | M = real(Zkt*Stt_1*Ttt*Zkt_1) #[x1(t+1),p2(t+1)] = M*[x1(t),p2(t)]+e(t+1) 95 | C = real(Zlt*Zkt_1) #[x2(t),u(t),p1(t)] =C*[x1(t),p2(t)] 96 | 97 | return M,C 98 | 99 | end 100 | #----------------------------------------------------------------------- 101 | -------------------------------------------------------------------------------- /SolvingReModels/jlFiles/DiscAlg.jl: -------------------------------------------------------------------------------- 1 | function DiscAlg(A,B,Q,R,U,bet,n1,n2,Vt1,Ct1, 2 | ConvCrit=[1e-1;1e-5],Vweight=0,Fweight=1,CritLags=0,step=1,PrintIt=0,MaxIter=1e+4) 3 | #DiscAlg Solves the LQ problem under discretion, iterating backwards in time. 4 | # 5 | # 6 | # 7 | # Usage: (M,C,V,F) = DiscAlg( A,B,Q,R,U,bet,n1,n2,Vt1,Ct1,... 8 | # ConvCrit,Vweight,Fweight,CritLags,step,PrintIt,MaxIter ) 9 | # 10 | # Input: A,B,Q,R,U,bet,n1,n2: - see ComItAlg 11 | # Vt1 n1xn1 matrix: initial guess of value matrix 12 | # Ct1 n2xn1 matrix, initial guess of C in x2(t)=C*x1(t) 13 | # ConvCrit 1x2 convergence criteria for abs(V-Vt1)|abs(F-Ft1) 14 | # Vweight scalar or n1xn1 matrix with weights for 15 | # difference criterion for V 16 | # Fweight scalar or (n1+n2)x1 vector with weights for 17 | # difference criterion for F 18 | # CritLags no. lags of CritVar compared with ConvCrit 19 | # step scalar in (0,1): factor of updating of V and F as 20 | # in Vt1 = step*V + (1-step)*Vt1 21 | # PrintIt 1: printing iteration number 22 | # 2: printing iteration number and convergence criteria 23 | # MaxIter scalar, maximum number of iterations (eg. 10000). 24 | # 25 | # Output: M n1x1 matrix, x1(t+1) = M*x1(t) + e(t+1) 26 | # C n2xn1 matrix, x2(t) = C*x1(t) 27 | # V n1xn1 matrix, value function is x1(t)'*V*x1(t) 28 | # F kxn1 matrix, decision rule is u(t) = -F*x1(t), where 29 | # k is number of elements in u(t) 30 | # 31 | # 32 | # Paul Söderlind, Paul.Soderlind@unisg.ch, Aug 2000, to Julia Jan 2016 33 | #----------------------------------------------------------------------- 34 | 35 | Base.require_one_based_indexing(A,B,Q,R,U,Vt1,Ct1) 36 | 37 | Q = (Q + Q')/2 #to make symmetric 38 | R = (R + R')/2 39 | 40 | n = n1 + n2 41 | Ft1 = fill(1000,(1,n1)) 42 | ConvCrit = vec(collect(ConvCrit))' #to row vector 43 | 44 | (M,C,F,V) = (Float64[],Float64[],Float64[],Float64[]) #to make visible outside loop 45 | Cdiff = 1000*ones(1+CritLags,2) 46 | iter = 1 47 | while any(maximum(Cdiff,dims=1) .> ConvCrit) & (iter < MaxIter) #iterations 48 | 49 | (M,C,F,V) = DiscAlg2(A,B,Q,R,U,bet,n1,n2,Ct1,Vt1) #solve period t 50 | 51 | Vdiff = maximum(Vweight.*abs.(V-Vt1)) #changes t+1 -> t 52 | Fdiff = maximum(Fweight.*abs.(F-Ft1)) 53 | Cdiff = [ Cdiff[2:end,:]; #latest is last 54 | Vdiff Fdiff ] 55 | Vt1 = step*V + (1-step)*Vt1 #"downdating" 56 | Ct1 = copy(C) 57 | Ft1 = step*F + (1-step)*Ft1 58 | 59 | if PrintIt == 1 60 | println(iter) 61 | elseif PrintIt == 2 62 | println([iter maximum(Cdiff)]) 63 | end 64 | 65 | iter = iter + 1 66 | 67 | end #end iterations 68 | 69 | if iter >= MaxIter 70 | @warn("Maximum number of iterations reached") 71 | end 72 | 73 | return M,C,V,F 74 | 75 | end 76 | #----------------------------------------------------------------------- 77 | 78 | 79 | function DiscAlg2(A,B,Q,R,U,bet,n1,n2,Ct1,Vst1) 80 | #DiscAlg2 Solves the LQ problem under discretion in t, given C(t+1) and V(t+1). 81 | # 82 | # 83 | # 84 | # 85 | # Usage: [M,C,Fs,Vs] = DiscAlg2( A,B,Q,R,U,bet,n1,n2,Ct1,Vst1 ) 86 | # 87 | # Input: A,B,Q,R,U,bet,n1,n2: see ComItAlg 88 | # Ct1 n2xn1 matrix, C(t+1) in x2(t+1) = C(t+1)x1(t+1) 89 | # Vst1 n1xn1 matrix, V(t+1) value function matrix in t+1 90 | # 91 | # Output: M n1xn1 matrix, 92 | # C n2xn1 matrix, 93 | # Fs kxn1 matrix, 94 | # Vs n1xn1 matrix, 95 | # 96 | # Paul Söderlind, Paul.Soderlind@unisg.ch, Aug 2000, to Julia Jan 2016 97 | #----------------------------------------------------------------------- 98 | 99 | n = n1 + n2 100 | 101 | v1 = 1:n1 102 | v2 = n1+1:n 103 | 104 | #partitioning of A,Q,B,U could be moved outside of the loop 105 | (A11,A12,A21,A22) = (A[v1,v1],A[v1,v2],A[v2,v1],A[v2,v2]) 106 | (Q11,Q12,Q21,Q22) = (Q[v1,v1],Q[v1,v2],Q[v2,v1],Q[v2,v2]) 107 | (B1,B2) = (B[v1,:],B[v2,:]) 108 | (U1,U2) = (U[v1,:],U[v2,:]) 109 | 110 | d1mat = inv(A22-Ct1*A12) 111 | D = d1mat * (Ct1*A11-A21) 112 | G = d1mat * (Ct1*B1-B2) 113 | 114 | As = A11 + A12*D 115 | Bs = B1 + A12*G 116 | 117 | Qs = Q11 + Q12*D + D'Q21 + D'Q22*D 118 | Us = Q12*G + D'Q22*G + U1 + D'U2 119 | Rs = R .+ G'Q22*G + G'U2 + U2'G #R is scalar, G'Q22*G is 1x1 array 120 | 121 | Fs = inv(Rs + bet*Bs'Vst1*Bs) * (Us' + bet*Bs'Vst1*As) #u(t) = -F*x1(t) 122 | Vs = Qs - Us*Fs - Fs'Us' + Fs'Rs*Fs + bet*(As-Bs*Fs)'Vst1*(As-Bs*Fs) 123 | 124 | C = D - G*Fs #x2(t)=C*x1(t) 125 | M = A11 + A12*C - B1*Fs #x1(t+1) = M*x1(t) + e(t+1) 126 | 127 | return M,C,Fs,Vs 128 | 129 | end 130 | #----------------------------------------------------------------------- 131 | 132 | -------------------------------------------------------------------------------- /SolvingReModels/jlFiles/Fuhrer1.jl: -------------------------------------------------------------------------------- 1 | function Fuhrer1(a1,ap,Varey,w,gamm,Varep,Dbig,qy,qpi,qf,bet) 2 | #Fuhrer1 Generate A,B,K,Q,U, and R from parameter values of simplified Fuhrer model. 3 | # 4 | # 5 | # Purpose: Generate A,B,K,Q,U, and R from parameter values of simplified 6 | # Fuhrer model. 7 | # 8 | # Usage: (A,B,K,Q,U,R) = Fuhrer1(a1,ap,Varey,w,gamm,Varep,Dbig,qy,qpi,qf,bet) 9 | # 10 | # The period loss function is 11 | # 12 | # qy*y^2 + qpi*pi^2 + qf*i^2, which is rewritten here as 13 | # 14 | # x'Qx + 2x'Uu + u'Ru. 15 | # 16 | # x = [x1,x2], with x1(t) = [ep(t),y(t),Dx(t-1)] and x2(t) = [R[t],Dx(t)] 17 | # 18 | # See lecture notes for further comments. 19 | # 20 | # 21 | # 22 | # 23 | # 24 | # 25 | # Paul Soderlind, 20 August 1997 26 | #---------------------------------------------------------------------------- 27 | 28 | #model->general setup 29 | Ax = [ ( -1/(w*(1-w)^2) ); 30 | ( -gamm*a1/(w*(1-w)) - gamm/(1-w)^2 ); 31 | ( -1 ); 32 | ( -gamm*ap/(w*(1-w)) ); 33 | ( 2 ) ]' 34 | 35 | Ar = [ 0 0 0 ((1+Dbig)/Dbig) (4/Dbig*(1-w) ) ] 36 | Ar = Ar + 4/Dbig*w*Ax 37 | 38 | 39 | A = [ zeros(1,5); #x(t+1)=A*x(t)+B*u(t)+ e(t+) 40 | 0 a1 0 ap 0; 41 | 0 0 0 0 1; 42 | Ar; 43 | Ax ] 44 | 45 | B = [ 0;0;0;(-1/Dbig);0 ] 46 | 47 | K = [ 0 1 0 0 0 0; #[y,pi,f] = K*[x,u] 48 | 0 0 4*(1-w) 0 4*w 0; 49 | 0 0 0 0 0 1 ] 50 | 51 | Wbig = K'Diagonal([qy;qpi;qf])*K 52 | 53 | Q = Wbig[1:5,1:5] 54 | U = Wbig[1:5,6] 55 | R = Wbig[6,6] 56 | 57 | return A,B,K,Q,U,R 58 | 59 | end 60 | #----------------------------------------------------------------------- 61 | -------------------------------------------------------------------------------- /SolvingReModels/jlFiles/SimpRulT.jl: -------------------------------------------------------------------------------- 1 | function SimpRulT(A,B,Q,R,U,bet,n1,n2,F,SigmaXX,x10,cutoff=1.0) 2 | #SimpRulT Solving RE model for given simple rule u(t) = -F * x(t), 3 | # where x(t) = [x1(t)' x2(t)']'. 4 | # 5 | # 6 | # 7 | # Usage: (M,C,J0) = SimpRulT(A,B,Q,R,U,bet,n1,n2,F,SigmaXX,x10,cutoff) 8 | # 9 | # Input: A,B,Q,R,U,bet,n1,n2: see ComItAlg 10 | # F kxn matrix, decision rule 11 | # SigmaXX n1xn1 covariance matrix of shocks 12 | # x10 n1 vector, initial values for predetermined 13 | # variables. Not n1x1 array. 14 | # cutoff scalar, max modulus of backward looking variables 15 | # 16 | # Output: M n1xn1 matrix, x1(t+1) = M*x1(t) + e(t+1) 17 | # C n2xn1 matrix, x2(t) = C*x1(t) 18 | # J0 scalar, value of loss function 19 | # 20 | # 21 | # 22 | # Paul Soderlind, Paul.Soderlind@unisg.ch, Aug 2000, to Julia Jan 2016 23 | #----------------------------------------------------------------------- 24 | 25 | Base.require_one_based_indexing(A,B,Q,R,U,F,SigmaXX,x10) 26 | 27 | Q = (Q + Q')/2 #to make symmetric 28 | R = (R + R')/2 29 | 30 | A = A - B*F #subst for u(t) in evolution 31 | n = n1 + n2 32 | 33 | GS = schur(Matrix(1.0I,n,n),A) 34 | logconA = abs.(GS.beta) .<= (abs.(GS.alpha)*cutoff) #selecting stable eigenvalues 35 | ordschur!(GS,logconA) #reordering, stable first 36 | 37 | if sum(logconA) < n1 38 | @warn("Too few stable roots: no stable solution") 39 | return NaN,NaN,NaN 40 | elseif sum(logconA) > n1 41 | @warn("Too many stable roots: inifite number of stable solutions") 42 | return NaN,NaN,NaN 43 | end 44 | 45 | Stt = GS.S[1:n1,1:n1] 46 | Zkt = GS.Z[1:n1,1:n1] 47 | Zlt = GS.Z[n1+1:n,1:n1] 48 | Ttt = GS.T[1:n1,1:n1] 49 | 50 | if cond(Zkt) > 1e+14 51 | @warn("Zkt is singular: rank condition for solution not satisfied") 52 | return NaN,NaN,NaN 53 | end 54 | 55 | Zkt_1 = inv(Zkt) #inverting 56 | Stt_1 = inv(Stt) 57 | 58 | M = real(Zkt*Stt_1*Ttt*Zkt_1) #x1(t+1) = M*x1(t) + e(t+1) 59 | C = real(Zlt*Zkt_1) #x2(t) = C*x1(t) 60 | 61 | P = [ I; 62 | C; 63 | (-F*[I;C]) ] 64 | QUUR = [ Q U; 65 | U' R ] 66 | PQUURP = P'QUUR*P 67 | 68 | vecV = (I - kron(M',bet*M'))\vec(PQUURP) 69 | V = reshape(vecV,n1,n1) #solves V = W + bet*M'V*M 70 | 71 | J0 = x10'V*x10 + (bet/(1-bet)) * tr(V*SigmaXX) 72 | 73 | return M,C,J0 74 | 75 | end 76 | #---------------------------------------------------------------------- 77 | -------------------------------------------------------------------------------- /SolvingReModels/jlFiles/VAR1SimPs.jl: -------------------------------------------------------------------------------- 1 | """ 2 | VAR1SimPs(A,epsilon,T,x0=0.0) 3 | 4 | Calculate impulse response function of a VAR(1) system 5 | x(t) = A * x(t-1) + epsilon(t), where x(t) is nx1 6 | 7 | # Input 8 | - `A::Matrix`: nxn VAR(1) matrix, see above 9 | - `epsilon::Number or Vector`: n-vector of shocks in inital period, or Txn matrix with shocks in all periods 10 | - `T::Number`: scalar, last period to calculate for 11 | - `x0::Number or Vector`: n-vector with starting values, optional 12 | 13 | # Output 14 | - `xM::Matrix`: Txn matrix, impulse response function 15 | 16 | Paul.Soderlind@unisg.ch, to Julia Nov 2015 17 | 18 | """ 19 | function VAR1SimPs(A,epsilon,T,x0=0.0) 20 | Base.require_one_based_indexing(A,epsilon,x0) 21 | 22 | n = size(A,1) 23 | 24 | isa(x0,Number) && (x0 = fill(x0,n)) #if scalar 25 | isa(epsilon,Number) && (epsilon = fill(epsilon,n)) 26 | (length(epsilon) == n) && (epsilon = vcat(vec(epsilon)',zeros(T-1,n))) 27 | 28 | xM = fill(NaN,(T,n)) #to put results in 29 | xM[1,:] = A*vec(x0) + epsilon[1,:] 30 | for t = 2:T #loop over time periods 31 | xM[t,:] = A*xM[t-1,:] + epsilon[t,:] 32 | end 33 | 34 | return xM 35 | 36 | end 37 | #----------------------------------------------------------------------- 38 | -------------------------------------------------------------------------------- /SolvingReModels/jlFiles/printmat.jl: -------------------------------------------------------------------------------- 1 | #------------------------------------------------------------------------------ 2 | """ 3 | printmat([fh::IO],x;width=10,prec=3,NoPrinting=false,StringFmt="") 4 | 5 | Print all elements of matrix with predefined formatting. 6 | 7 | # Input 8 | - `fh::IO`: (optional) file handle. If not supplied, prints to screen 9 | - `x::Array`: string, date or array to print 10 | - `width::Int`: (keyword) scalar, minimum width of printed cells 11 | - `prec::Int`: (keyword) scalar, precision of printed cells 12 | - `NoPrinting::Bool`: (keyword) bool, true: no printing, just return formatted string 13 | - `StringFmt::String`: (keyword) string, "", "html", "csv" 14 | 15 | # Output 16 | - str (if NoPrinting) string, (otherwise nothing) 17 | 18 | # Examples 19 | ``` 20 | x = [11 12;21 22] 21 | printmat(x) 22 | ``` 23 | ``` 24 | x = Any[1 "ab"; Date(2018,10,7) 3.14] 25 | printmat(x,width=20) 26 | ``` 27 | Can also call as 28 | ``` 29 | opt = Dict(:width=>10,:prec=>3,:NoPrinting=>false,:StringFmt=>"") 30 | printmat(x;opt...) #notice , and ... 31 | ``` 32 | (not all keywords are needed) 33 | 34 | # Requires 35 | - Dates 36 | - fmtNumPs 37 | 38 | # To do 39 | 40 | 41 | Paul.Soderlind@unisg.ch 42 | 43 | """ 44 | function printmat(fh::IO,x;width=10,prec=3,NoPrinting=false,StringFmt="") 45 | 46 | if isa(x,Union{String,Date,DateTime,Missing}) #eg. a single Date 47 | str = string(lpad(x,width),"\n") 48 | if NoPrinting 49 | return str 50 | else 51 | print(fh,str,"\n") 52 | return nothing 53 | end 54 | elseif isa(x,Nothing) 55 | return nothing 56 | end 57 | 58 | if ndims(x) > 2 59 | @warn("more than 2 dimensions") 60 | return nothing 61 | end 62 | 63 | (m,n) = (size(x,1),size(x,2)) 64 | 65 | iob = IOBuffer() 66 | for i = 1:m #loop over lines 67 | for j = 1:n-1 #loop over columns 1:n-1 68 | writeElementPs(iob,x,i,j,width,prec,StringFmt) 69 | end 70 | if StringFmt == "csv" #last (n) column 71 | writeElementPs(iob,x,i,n,width,prec,"") #no , at end of line 72 | else 73 | writeElementPs(iob,x,i,n,width,prec,StringFmt) 74 | end 75 | write(iob,"\n") #newline 76 | end 77 | str = String(take!(iob)) 78 | 79 | if NoPrinting #no printing, just return str 80 | return str 81 | else #print, return nothing 82 | print(fh,str,"\n") 83 | return nothing 84 | end 85 | 86 | end 87 | #when fh is not supplied: printing to screen 88 | printmat(x;width=10,prec=3,NoPrinting=false,StringFmt="") = printmat(stdout::IO, 89 | x,width=width,prec=prec,NoPrinting=NoPrinting,StringFmt=StringFmt) 90 | #------------------------------------------------------------------------------ 91 | 92 | 93 | #------------------------------------------------------------------------------ 94 | """ 95 | printTable([fh::IO],x,colNames=[],rowNames=[]; 96 | width=10,prec=3,NoPrinting=false,StringFmt="",cell00="") 97 | 98 | Print formatted table with row names (1st column) column names (1st row), 99 | and data matrix (the rest). 100 | 101 | 102 | # Input 103 | - `fh::IO`: (optional) file handle. If not supplied, prints to screen 104 | - `x::Array`: (of numbers, dates, strings, ...) to print 105 | - `colNames::Array`: of strings with column headers 106 | - `rowNames::Array`: of strings with row labels 107 | - `width::Int`: (keyword) scalar, minimum width of printed cells. [10] 108 | - `prec::Int`: (keyword) scalar, precision of printed cells. [3] 109 | - `NoPrinting::Bool`: (keyword) bool, true: no printing, just return formatted string [false] 110 | - `StringFmt::String`: (keyword) string, "", "html", "csv" 111 | - `cell00::String`: (keyword) string, for row 0, column 0 112 | 113 | # Output 114 | - `str::String`: (if NoPrinting) string, (otherwise nothing) 115 | 116 | # Example 117 | ``` 118 | xA = [1 "ab" "abc"; "ccc" 3.14 missing] 119 | printTable(xA,colNames,["1";"4"],width=12,prec=2) 120 | ``` 121 | Can also call as 122 | ``` 123 | opt = Dict(:width=>10,:prec=>3,:NoPrinting=>false,:StringFmt=>"",:cell00=>"") 124 | printTable(x;opt...) #notice , and ... 125 | ``` 126 | (not all keywords are needed) 127 | 128 | # Requires 129 | - Dates 130 | - printmat 131 | 132 | """ 133 | function printTable(fh::IO,x,colNames=[],rowNames=[]; 134 | width=10,prec=3,NoPrinting=false,StringFmt="",cell00="") 135 | 136 | isempty(x) && return nothing #do nothing is isempty(x) 137 | 138 | (m,n) = (size(x,1),size(x,2)) 139 | 140 | if isempty(rowNames) #create row names "r1" 141 | rowNames = [string("r",i) for i = 1:m] 142 | end 143 | if isempty(colNames) #create column names "c1" 144 | colNames = [string("c",i) for i = 1:n] 145 | end 146 | 147 | rNamesWidth = maximum([length(rowNames[i]) for i = 1:length(rowNames)]) #max length of rowNames 148 | rNamesWidth = max(rNamesWidth,length(cell00)) 149 | 150 | iob = IOBuffer() 151 | if StringFmt == "html" #print column names 152 | write(iob,"",lpad(cell00,rNamesWidth),"") 153 | for i = 1:n 154 | write(iob,"",lpad(colNames[i],width),"") 155 | end 156 | write(iob,"") 157 | elseif StringFmt == "csv" 158 | write(iob,lpad(string(cell00,","),rNamesWidth)) 159 | for i = 1:n-1 160 | write(iob,lpad(colNames[i],width),",") 161 | end 162 | write(iob,lpad(colNames[n],width)) #no , at line end 163 | else 164 | write(iob,lpad(cell00,rNamesWidth)) #cell 0,0 165 | for i = 1:n #create string 166 | write(iob,lpad(colNames[i],width)) 167 | end 168 | end 169 | write(iob,"\n") 170 | 171 | xStr = printmat(fh,x,width=width,prec=prec,NoPrinting=true,StringFmt=StringFmt) #body of table, one long string 172 | xStrV = split(xStr,"\n") #vector of strings (one per row of x) 173 | 174 | for i = 1:m #loop over rows in x, print rowNames[i] and x[i,:] 175 | if StringFmt == "html" 176 | write(iob,"",rpad(rowNames[i],rNamesWidth),"",xStrV[i]," \n") 177 | elseif StringFmt == "csv" 178 | write(iob,rpad(string(rowNames[i],","),rNamesWidth),xStrV[i],"\n") 179 | else 180 | write(iob,rpad(rowNames[i],rNamesWidth),xStrV[i],"\n") 181 | end 182 | end 183 | str = String(take!(iob)) 184 | 185 | if NoPrinting #no printing, just return str 186 | return str 187 | else #print, return nothing 188 | print(fh,str,"\n") 189 | return nothing 190 | end 191 | 192 | end 193 | #when fh is not supplied: printing to screen 194 | printTable(x,colNames=[],rowNames=[];width=10,prec=3,NoPrinting=false,StringFmt="",cell00="") = 195 | printTable(stdout::IO,x,colNames,rowNames,width=width,prec=prec,NoPrinting=NoPrinting, 196 | StringFmt=StringFmt,cell00=cell00) 197 | #------------------------------------------------------------------------------ 198 | 199 | 200 | #------------------------------------------------------------------------------ 201 | """ 202 | printlnPs([fh::IO],z...;width=10,prec=3) 203 | 204 | Subsitute for println, with predefined formatting. 205 | 206 | 207 | # Input 208 | - `fh::IO`: (optional) file handle. If not supplied, prints to screen 209 | - `z::String`: string, numbers and arrays to print 210 | 211 | Paul.Soderlind@unisg.ch 212 | 213 | """ 214 | function printlnPs(fh::IO,z...;width=10,prec=3) 215 | 216 | for x in z #loop over inputs in z... 217 | if isa(x,Union{String,Date,DateTime,Missing}) 218 | print(fh,lpad(x,width)) 219 | elseif isa(x,Nothing) 220 | print(fh,"") 221 | else #other types 222 | iob = IOBuffer() 223 | for i = 1:length(x) 224 | if isa(x[i],AbstractFloat) #Float 225 | write(iob,fmtNumPs(x[i],width,prec,"right")) 226 | elseif isa(x[i],Nothing) #Nothing 227 | write(iob,lpad("",width)) 228 | else #Integer, etc 229 | write(iob,lpad(x[i],width)) 230 | end 231 | end 232 | print(fh,String(take!(iob))) 233 | end 234 | end 235 | 236 | print(fh,"\n") 237 | 238 | end 239 | #when fh is not supplied: printing to screen 240 | printlnPs(z...;width=10,prec=3) = printlnPs(stdout::IO,z...,width=width,prec=prec) 241 | #------------------------------------------------------------------------------ 242 | 243 | 244 | #------------------------------------------------------------------------------ 245 | """ 246 | printmat2 247 | 248 | Call on printmat twice: to print to screen and then to an open file (IOStream) 249 | """ 250 | function printmat2(fh,x;width=10,prec=3,NoPrinting=false,StringFmt="") 251 | printmat(x,width=width,prec=prec,NoPrinting=NoPrinting,StringFmt=StringFmt) #to screen 252 | if isa(fh,IOStream) && isopen(fh) 253 | printmat(fh,x,width=width,prec=prec,NoPrinting=NoPrinting,StringFmt=StringFmt) #to file 254 | end 255 | end 256 | #------------------------------------------------------------------------------ 257 | 258 | 259 | #------------------------------------------------------------------------------ 260 | """ 261 | printTable2 262 | 263 | Call on printTable2 twice: to print to screen and then to an open file (IOStream) 264 | """ 265 | function printTable2(fh,x,colNames=[],rowNames=[];width=10,prec=3,NoPrinting=false, 266 | StringFmt="",cell00="") 267 | printTable(x,colNames,rowNames,width=width,prec=prec,NoPrinting=NoPrinting, 268 | StringFmt=StringFmt,cell00=cell00) #to screen 269 | if isa(fh,IOStream) && isopen(fh) 270 | printTable(fh,x,colNames,rowNames,width=width,prec=prec,NoPrinting=NoPrinting, 271 | StringFmt=StringFmt,cell00=cell00) #to file 272 | end 273 | end 274 | #------------------------------------------------------------------------------ 275 | 276 | 277 | #------------------------------------------------------------------------------ 278 | """ 279 | println2Ps 280 | 281 | Call on printlnPs twice: to print to screen and then to an open file (IOStream) 282 | """ 283 | function println2Ps(fh::IO,z...;width=10,prec=3) 284 | printlnPs(z...,width=width,prec=prec) #to screen 285 | if isa(fh,IOStream) && isopen(fh) 286 | printlnPs(fh::IO,z...,width=width,prec=prec) #to file 287 | end 288 | end 289 | #------------------------------------------------------------------------------ 290 | 291 | 292 | #------------------------------------------------------------------------------ 293 | """ 294 | writeElementPs(iob,x,i,j,width,prec,StringFmt) 295 | 296 | Writes one element to iob, formatting depends on type 297 | """ 298 | function writeElementPs(iob,x,i,j,width,prec,StringFmt) 299 | 300 | if isa(x[i,j],AbstractFloat) #Float 301 | write(iob,fmtNumPs(x[i,j],width,prec,"right",StringFmt)) 302 | elseif isa(x[i,j],Union{Int,String}) #Int, String 303 | write(iob,fmtNumPs(x[i,j],width,0,"right",StringFmt)) 304 | elseif isa(x[i,j],Bool) #Bool, BitArrays, as 0/1, left 305 | write(iob,fmtNumPs(x[i,j]+0,width,0,"right",StringFmt)) 306 | elseif isa(x[i,j],Nothing) #Nothing, as "" 307 | write(iob,fmtNumPs("",width,0,"right",StringFmt)) 308 | else #other types (Missing,Date,...), right 309 | write(iob,fmtNumPs(x[i,j],width,0,"right",StringFmt)) 310 | end 311 | 312 | return nothing 313 | end 314 | #------------------------------------------------------------------------------ 315 | 316 | 317 | #------------------------------------------------------------------------------ 318 | 319 | #One of the two subsequent functions is needed for handling cases like "1.5e-6" 320 | #This should not be necessary after Julia 1.6 321 | 322 | #fmtNumPsX(fmt,z) = @eval Printf.@sprintf($fmt,$z) #slow fallback solution 323 | 324 | function fmtNumPsC(fmt,z) #c fallback solution 325 | if ismissing(z) || isnan(z) || isinf(z) #asprintf does not work for these cases 326 | str = string(z) 327 | else 328 | strp = Ref{Ptr{Cchar}}(0) 329 | len = ccall(:asprintf,Cint,(Ptr{Ptr{Cchar}},Cstring,Cdouble...),strp,fmt,z) 330 | str = unsafe_string(strp[],len) 331 | Libc.free(strp[]) 332 | end 333 | return str 334 | end 335 | #------------------------------------------------------------------------------ 336 | 337 | 338 | #------------------------------------------------------------------------------ 339 | """ 340 | fmtNumPs(z,width=10,prec=2,justify="right",StringFmt="") 341 | 342 | Create a formatted string of a number. With prec=0, it can be used Bools and Strings 343 | 344 | 345 | 346 | # Remark 347 | - with prec=0, the function can be used for non-floats (incl. Bools and Strings) 348 | - The Formatting.jl package provides more elegant solutions: 349 | fmt = FormatSpec(string(">",width,".",prec,"f")) #right justified, else "<" 350 | fmt = FormatSpec(string(">",wid,"d")) #for Int 351 | str = Formatting.fmt(fmt1,z)) 352 | 353 | # Requires 354 | - Dates 355 | 356 | """ 357 | function fmtNumPs(z,width=10,prec=2,justify="right",StringFmt="") 358 | 359 | if (prec > 0) && !ismissing(z) && !isnan(z) && !isinf(z) #example: 101.0234, prec=3 360 | zRound = round(z,digits=prec) 361 | str = split(string(zRound),'.') 362 | if length(str) > 1 && !occursin("e",str[2]) #skip "1.5e-6" 363 | strR = string(".",rpad(str[2],prec,"0")) #.23 364 | strLR = string(str[1],strR) #"101" * ".23" 365 | elseif occursin("e",str[2]) #"1.5e-6" -> " 0.0000015" if prec=7 366 | fmt = "%$(width).$(prec)f" 367 | #strLR = fmtNumPsX(fmt,zRound) #slow fallback solution 368 | strLR = fmtNumPsC(fmt,zRound) #C fallback solution 369 | else 370 | strLR = string(zRound) 371 | end 372 | else 373 | (isa(z,AbstractFloat) && !isnan(z) && !isinf(z)) && (z = round(Int,z)) #Float -> Int 374 | strLR = string(z) 375 | end 376 | 377 | if justify == "left" #justification 378 | strLR = rpad(strLR,width) 379 | else 380 | strLR = lpad(strLR,width) 381 | end 382 | 383 | if StringFmt == "html" #html or csv formatting 384 | strLR = string("",strLR,"") 385 | elseif StringFmt == "csv" 386 | strLR = string(strLR,",") 387 | end 388 | 389 | return strLR 390 | 391 | end 392 | #------------------------------------------------------------------------------ 393 | 394 | 395 | #------------------------------------------------------------------------------ 396 | function printblue(x...) 397 | foreach(z->printstyled(z,color=:blue,bold=true),x) 398 | print("\n") 399 | end 400 | function printred(x...) 401 | foreach(z->printstyled(z,color=:red,bold=true),x) 402 | print("\n") 403 | end 404 | function printmagenta(x...) 405 | foreach(z->printstyled(z,color=:magenta,bold=true),x) 406 | print("\n") 407 | end 408 | function printyellow(x...) 409 | foreach(z->printstyled(z,color=:yellow,bold=true),x) 410 | print("\n") 411 | end 412 | #------------------------------------------------------------------------------ 413 | 414 | 415 | #------------------------------------------------------------------------------ 416 | function printwhere(txt) 417 | println(@__FILE__," ",@__LINE__," ",txt) 418 | end 419 | #------------------------------------------------------------------------------ 420 | 421 | --------------------------------------------------------------------------------