├── .gitattributes ├── Ch00_HowToUse.ipynb ├── Ch01_StatsReview.ipynb ├── Ch02_OLS1.ipynb ├── Ch02b_MatrixAlgebraPrimer.txt ├── Ch02c_FrischWaugh.ipynb ├── Ch03_Betas.txt ├── Ch04a_OLS_Diagnostics.ipynb ├── Ch04b_OLS_Testing.ipynb ├── Ch04c_DeltaMethod.ipynb ├── Ch05_OLS_System.ipynb ├── Ch06_TestingCAPM.txt ├── Ch07a_BinScatter.ipynb ├── Ch07b_OLS_Lasso.ipynb ├── Ch09a_MonteCarlo.ipynb ├── Ch09b_Bootstrap.ipynb ├── Ch10_PortfolioSorts.ipynb ├── Ch11_PanelRegr.ipynb ├── Ch12_IV.ipynb ├── Ch13_GMM.ipynb ├── Ch14_TimeSeries.ipynb ├── Ch15_ReturnPredictions.txt ├── Ch17_TestingDistributions.ipynb ├── Ch18_MLE.ipynb ├── Ch19_Garch.ipynb ├── Ch20_RiskMeasures.txt ├── Ch21_KernelRegression.ipynb ├── Ch22_QuantileRegression.ipynb ├── Data ├── BondPremiaPs.csv ├── FF25Ps.csv ├── FFdFactors.CSV ├── FFdSizePs.csv ├── FFmFactorsPs.csv ├── Fin1PerfEvalEmp.csv ├── MomentumSR.csv ├── Readme.md ├── RvSP500.csv ├── USCMRatesPs.csv ├── mrozEd.txt └── nls_panelEd.txt ├── FinEcmtAll.pdf ├── JuliaOnColab_OLS.ipynb ├── LICENSE.txt ├── NotebooksAsPdf.pdf ├── Readme.md └── src ├── BinScatter.jl ├── CovNW.jl ├── DeltaMethod.jl ├── DistributionTests.jl ├── FinEcmt_KernelRegression.jl ├── FinEcmt_Lasso.jl ├── FinEcmt_MLEGMM.jl ├── FinEcmt_OLS.jl ├── FinEcmt_TimeSeries.jl ├── GMM.jl ├── Garch.jl ├── KernelRegression.jl ├── LassoElasticNet.jl ├── MLE.jl ├── Ols.jl ├── OlsDiagnostics.jl ├── OlsSure.jl ├── PanelOls.jl ├── PanelRegrBasic.jl ├── PortfolioSorts.jl ├── QuantRegrIRLS.jl ├── RidgeRegression.jl ├── SimulationFunctions.jl ├── TimeSeriesExtra.jl ├── TimeSeriesFilter.jl ├── TwoSLS.jl ├── UtilityFunctions.jl └── printmat.jl /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /Ch00_HowToUse.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# How To Use the Notebooks\n", 8 | "\n", 9 | "The notebooks use various packages (which you need to install) and also some local modules (`FinEcmt_OLS` etc) which are located in the `src` subfolder.\n", 10 | "\n", 11 | "The next fell cells illustrate how to work with these notebooks." 12 | ] 13 | }, 14 | { 15 | "cell_type": "markdown", 16 | "metadata": {}, 17 | "source": [ 18 | "## Load Packages and Extra Functions\n", 19 | "\n", 20 | "The next two cells puts the `src` subfolder in the `LOAD_PATH` (if it isn't already) and then loads some modules and packages.\n", 21 | "\n", 22 | "1. The `FinEcmt_OLS` module is defined in the `src` subfolder. It uses many of the .jl files in that subfolder and exports the key functions. The cells below show two *different* ways of loading this module.\n", 23 | "\n", 24 | "2. The `Statistics` package is part of the Julia distribution, so you don't have to install it (this may change in the future). \n", 25 | "\n", 26 | "3. The `Distributions.jl` package needs to be installed. Do \n", 27 | "```import Pkg;Pkg.add(\"Distributions\")```." 28 | ] 29 | }, 30 | { 31 | "cell_type": "code", 32 | "execution_count": 1, 33 | "metadata": {}, 34 | "outputs": [], 35 | "source": [ 36 | "#approach 1 to load the FinEcmt_OLS module, precompiles so is quicker\n", 37 | "\n", 38 | "MyModulePath = joinpath(pwd(),\"src\") #add /src to module path\n", 39 | "!in(MyModulePath,LOAD_PATH) && push!(LOAD_PATH,MyModulePath);\n", 40 | "\n", 41 | "using FinEcmt_OLS: OlsGM, printmat, @doc2 #to load a few functions from module\n", 42 | "#using FinEcmt_OLS #to load all functions in module" 43 | ] 44 | }, 45 | { 46 | "cell_type": "code", 47 | "execution_count": 2, 48 | "metadata": {}, 49 | "outputs": [], 50 | "source": [ 51 | "#approach 2 to load the FinEcmt_OLS module, works also on Colab\n", 52 | "\n", 53 | "#=\n", 54 | "include(joinpath(pwd(),\"src\",\"FinEcmt_OLS.jl\"))\n", 55 | "using .FinEcmt_OLS: OlsGM, printmat, @doc2 #to load a few functions from module\n", 56 | "using .FinEcmt_OLS #to load all functions in module\n", 57 | "=#" 58 | ] 59 | }, 60 | { 61 | "cell_type": "code", 62 | "execution_count": 3, 63 | "metadata": {}, 64 | "outputs": [], 65 | "source": [ 66 | "using Statistics, Distributions" 67 | ] 68 | }, 69 | { 70 | "cell_type": "markdown", 71 | "metadata": {}, 72 | "source": [ 73 | "## See the Documentation\n", 74 | "\n", 75 | "The next cell shows the documentation of the `OLSGM` function." 76 | ] 77 | }, 78 | { 79 | "cell_type": "code", 80 | "execution_count": 4, 81 | "metadata": {}, 82 | "outputs": [ 83 | { 84 | "data": { 85 | "text/markdown": [ 86 | "```\n", 87 | "OlsGM(Y,X)\n", 88 | "```\n", 89 | "\n", 90 | "LS of Y on X; for one dependent variable, Gauss-Markov assumptions\n", 91 | "\n", 92 | "### Input\n", 93 | "\n", 94 | " * `Y::Vector`: T-vector, the dependent variable\n", 95 | " * `X::Matrix`: Txk matrix of regressors (including deterministic ones)\n", 96 | "\n", 97 | "### Output\n", 98 | "\n", 99 | " * `b::Vector`: k-vector, regression coefficients\n", 100 | " * `u::Vector`: T-vector, residuals Y - yhat\n", 101 | " * `Yhat::Vector`: T-vector, fitted values X*b\n", 102 | " * `V::Matrix`: kxk matrix, covariance matrix of b\n", 103 | " * `R²::Number`: scalar, R² value\n" 104 | ] 105 | }, 106 | "metadata": {}, 107 | "output_type": "display_data" 108 | } 109 | ], 110 | "source": [ 111 | "@doc2 OlsGM #`doc OlsGM` does not work in VS Code\n", 112 | "#println(@doc OlsGM) #plain text printing instead" 113 | ] 114 | }, 115 | { 116 | "cell_type": "markdown", 117 | "metadata": {}, 118 | "source": [ 119 | "## See the Source Code\n", 120 | "\n", 121 | "To see the source code, either open the correct file in the src subfolder, or use the\n", 122 | "[`CodeTracking.jl`](https://github.com/timholy/CodeTracking.jl) package to print the source code here in the notebook. The latter approach requires \"calling\" on the function with some valid inputs (in this case we use `[1],[1]`). In many notebooks, such printing is coded but commented out." 123 | ] 124 | }, 125 | { 126 | "cell_type": "code", 127 | "execution_count": 5, 128 | "metadata": {}, 129 | "outputs": [ 130 | { 131 | "name": "stdout", 132 | "output_type": "stream", 133 | "text": [ 134 | "function OlsGM(Y,X)\n", 135 | "\n", 136 | " T = size(Y,1)\n", 137 | "\n", 138 | " b = X\\Y\n", 139 | " Yhat = X*b\n", 140 | " u = Y - Yhat\n", 141 | "\n", 142 | " σ² = var(u)\n", 143 | " V = inv(X'X)*σ²\n", 144 | " R² = 1 - σ²/var(Y)\n", 145 | "\n", 146 | " return b, u, Yhat, V, R²\n", 147 | "\n", 148 | "end\n" 149 | ] 150 | } 151 | ], 152 | "source": [ 153 | "using CodeTracking\n", 154 | "println(@code_string OlsGM([1],[1])) #println gets the line breaks right" 155 | ] 156 | }, 157 | { 158 | "cell_type": "markdown", 159 | "metadata": {}, 160 | "source": [ 161 | "# Use the Function\n", 162 | "\n", 163 | "(here with some artificial inputs)" 164 | ] 165 | }, 166 | { 167 | "cell_type": "code", 168 | "execution_count": 6, 169 | "metadata": {}, 170 | "outputs": [ 171 | { 172 | "name": "stdout", 173 | "output_type": "stream", 174 | "text": [ 175 | " 1.000\n", 176 | " 0.500\n", 177 | "\n" 178 | ] 179 | } 180 | ], 181 | "source": [ 182 | "Y = [1,2,3]\n", 183 | "X = [1 2;1 1;1 3]\n", 184 | "b, = OlsGM(Y,X);\n", 185 | "printmat(b)" 186 | ] 187 | }, 188 | { 189 | "cell_type": "markdown", 190 | "metadata": {}, 191 | "source": [ 192 | "## Required External Packages\n", 193 | "\n", 194 | "for the different local modules. These packages need to be installed:\n", 195 | "\n", 196 | "1. FinEcmt_OLS: Distributions, StatsBase, FiniteDiff\n", 197 | "2. FinEcmt_Lasso: OSQP\n", 198 | "3. FinEcmt_TimeSeries: none\n", 199 | "4. FinEcmt_MLEGMM: Optim, NLsolve, FiniteDiff\n", 200 | "5. FinEcmt_KernelRegression: none\n", 201 | "\n", 202 | "We also use a number of standard libraries (eg. Printf), but they are typically shipped with the Julia binary. \n", 203 | "\n", 204 | "For the notebooks, some more external packages are needed, for instance, CodeTracking for printing the functions. See the different notebooks for more information. \n", 205 | "\n", 206 | "In case a package is missing, Julia will give an error message (and often tell you what you need to do)." 207 | ] 208 | }, 209 | { 210 | "cell_type": "code", 211 | "execution_count": null, 212 | "metadata": {}, 213 | "outputs": [], 214 | "source": [] 215 | } 216 | ], 217 | "metadata": { 218 | "@webio": { 219 | "lastCommId": null, 220 | "lastKernelId": null 221 | }, 222 | "anaconda-cloud": {}, 223 | "kernelspec": { 224 | "display_name": "Julia 1.11.4", 225 | "language": "julia", 226 | "name": "julia-1.11" 227 | }, 228 | "language_info": { 229 | "file_extension": ".jl", 230 | "mimetype": "application/julia", 231 | "name": "julia", 232 | "version": "1.11.4" 233 | } 234 | }, 235 | "nbformat": 4, 236 | "nbformat_minor": 4 237 | } 238 | -------------------------------------------------------------------------------- /Ch02_OLS1.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Basic OLS\n", 8 | "\n", 9 | "This notebook estimates a linear regression and reports traditional standard errors (assuming iid residuals).\n", 10 | "\n", 11 | "For a package, consider [GLM.jl](https://github.com/JuliaStats/GLM.jl) or [LinearRegression.jl](https://github.com/st--/LinearRegression.jl) (not used here)." 12 | ] 13 | }, 14 | { 15 | "cell_type": "markdown", 16 | "metadata": {}, 17 | "source": [ 18 | "## Load Packages and Extra Functions\n", 19 | "\n", 20 | "The key functions are from the `FinEcmt_OLS` module found in the `src` subfolder.\n", 21 | "\n", 22 | "The `DelimitedFiles` package is used for importing the csv data file and the `LinearAlgebra` package for some matrix operations (eg. `diag()`, which extracts the diagonal of a matrix.)" 23 | ] 24 | }, 25 | { 26 | "cell_type": "code", 27 | "execution_count": 1, 28 | "metadata": {}, 29 | "outputs": [], 30 | "source": [ 31 | "MyModulePath = joinpath(pwd(),\"src\") #add /src to module path\n", 32 | "!in(MyModulePath,LOAD_PATH) && push!(LOAD_PATH,MyModulePath)\n", 33 | "using FinEcmt_OLS" 34 | ] 35 | }, 36 | { 37 | "cell_type": "code", 38 | "execution_count": 2, 39 | "metadata": {}, 40 | "outputs": [], 41 | "source": [ 42 | "#=\n", 43 | "include(joinpath(pwd(),\"src\",\"FinEcmt_OLS.jl\"))\n", 44 | "using .FinEcmt_OLS\n", 45 | "=#" 46 | ] 47 | }, 48 | { 49 | "cell_type": "code", 50 | "execution_count": 3, 51 | "metadata": {}, 52 | "outputs": [], 53 | "source": [ 54 | "using Statistics, DelimitedFiles, LinearAlgebra" 55 | ] 56 | }, 57 | { 58 | "cell_type": "markdown", 59 | "metadata": {}, 60 | "source": [ 61 | "## Loading Data" 62 | ] 63 | }, 64 | { 65 | "cell_type": "code", 66 | "execution_count": 4, 67 | "metadata": {}, 68 | "outputs": [ 69 | { 70 | "name": "stdout", 71 | "output_type": "stream", 72 | "text": [ 73 | "Sample size: (388,)\n" 74 | ] 75 | } 76 | ], 77 | "source": [ 78 | "x = readdlm(\"Data/FFmFactorsPs.csv\",',',skipstart=1)\n", 79 | "\n", 80 | " #yearmonth, market, small minus big, high minus low\n", 81 | "(ym,Rme,RSMB,RHML) = (x[:,1],x[:,2]/100,x[:,3]/100,x[:,4]/100)\n", 82 | "x = nothing\n", 83 | "\n", 84 | "printlnPs(\"Sample size:\",size(Rme))" 85 | ] 86 | }, 87 | { 88 | "cell_type": "markdown", 89 | "metadata": {}, 90 | "source": [ 91 | "## OLS Estimates and Their Distribution\n", 92 | "\n", 93 | "Consider the linear regression\n", 94 | "\n", 95 | "$y_{t}=\\beta^{\\prime}x_{t}+u_{t},$\n", 96 | "\n", 97 | "When $x_t$ and $u_t$ are independent and $u_t$ is iid (Gauss-Markov assumptions), then the distribution of the estimates is (typically)\n", 98 | "\n", 99 | "$\\hat{\\beta} \\sim N(\\beta_{0},S_{xx}^{-1}\\sigma^2),$\n", 100 | "\n", 101 | "where $\\sigma^2$ is the variance of the residual and $S_{xx} = \\sum\\nolimits_{t=1}^{T}x_{t}x_{t}^{\\prime}$.\n", 102 | "\n", 103 | "In matrix form, these expressions are \n", 104 | "$Y = Xb + u, \\: \\text{ and } \\: S_{xx} = X'X,$\n", 105 | "where $X$ is defined below.\n", 106 | "\n", 107 | "\n", 108 | "### Matrix Form\n", 109 | "\n", 110 | "To calculate the estimates it is often convenient to work with matrices. Define $X_{T\\times k}$ by \n", 111 | "letting $x_{t}^{\\prime}$ and be the $t^{th}$ row\n", 112 | "\n", 113 | "$$\n", 114 | "X_{T\\times k}=\n", 115 | "\\begin{bmatrix}\n", 116 | "x_{1}^{\\prime}\\\\\n", 117 | "\\vdots\\\\\n", 118 | "x_{T}^{\\prime}\n", 119 | "\\end{bmatrix}\n", 120 | "$$\n", 121 | "\n", 122 | "In contrast $Y$ is a just a vector with $T$ elements (or possibly a $T \\times 1$ matrix).\n", 123 | "\n", 124 | "This is implemented in the `OlsGM()` function from the `FinEcmt_OLS` module. The source file is in the `src` subfolder. The next cells print the documentation and source code of the function. In particular, notice the `b = X\\Y` and `V = inv(X'X)*σ²`." 125 | ] 126 | }, 127 | { 128 | "cell_type": "code", 129 | "execution_count": 5, 130 | "metadata": {}, 131 | "outputs": [ 132 | { 133 | "data": { 134 | "text/markdown": [ 135 | "```\n", 136 | "OlsGM(Y,X)\n", 137 | "```\n", 138 | "\n", 139 | "LS of Y on X; for one dependent variable, Gauss-Markov assumptions\n", 140 | "\n", 141 | "### Input\n", 142 | "\n", 143 | " * `Y::Vector`: T-vector, the dependent variable\n", 144 | " * `X::Matrix`: Txk matrix of regressors (including deterministic ones)\n", 145 | "\n", 146 | "### Output\n", 147 | "\n", 148 | " * `b::Vector`: k-vector, regression coefficients\n", 149 | " * `u::Vector`: T-vector, residuals Y - yhat\n", 150 | " * `Yhat::Vector`: T-vector, fitted values X*b\n", 151 | " * `V::Matrix`: kxk matrix, covariance matrix of b\n", 152 | " * `R²::Number`: scalar, R² value\n" 153 | ] 154 | }, 155 | "metadata": {}, 156 | "output_type": "display_data" 157 | } 158 | ], 159 | "source": [ 160 | "@doc2 OlsGM" 161 | ] 162 | }, 163 | { 164 | "cell_type": "code", 165 | "execution_count": 6, 166 | "metadata": {}, 167 | "outputs": [ 168 | { 169 | "name": "stdout", 170 | "output_type": "stream", 171 | "text": [ 172 | "function OlsGM(Y,X)\n", 173 | "\n", 174 | " T = size(Y,1)\n", 175 | "\n", 176 | " b = X\\Y\n", 177 | " Yhat = X*b\n", 178 | " u = Y - Yhat\n", 179 | "\n", 180 | " σ² = var(u)\n", 181 | " V = inv(X'X)*σ²\n", 182 | " R² = 1 - σ²/var(Y)\n", 183 | "\n", 184 | " return b, u, Yhat, V, R²\n", 185 | "\n", 186 | "end\n" 187 | ] 188 | } 189 | ], 190 | "source": [ 191 | "using CodeTracking\n", 192 | "println(@code_string OlsGM([1],[1])) #print the source code" 193 | ] 194 | }, 195 | { 196 | "cell_type": "markdown", 197 | "metadata": {}, 198 | "source": [ 199 | "## OLS Regression" 200 | ] 201 | }, 202 | { 203 | "cell_type": "code", 204 | "execution_count": 7, 205 | "metadata": {}, 206 | "outputs": [ 207 | { 208 | "name": "stdout", 209 | "output_type": "stream", 210 | "text": [ 211 | "\u001b[34m\u001b[1mOLS Results:\u001b[22m\u001b[39m\n", 212 | "\n", 213 | " b std\n", 214 | "c 0.007 0.002\n", 215 | "SMB 0.217 0.073\n", 216 | "HML -0.429 0.074\n", 217 | "\n", 218 | " R²: 0.134\n" 219 | ] 220 | } 221 | ], 222 | "source": [ 223 | "Y = Rme #to get standard OLS notation\n", 224 | "T = size(Y,1)\n", 225 | "X = [ones(T) RSMB RHML]\n", 226 | "\n", 227 | "(b,_,_,V,R²) = OlsGM(Y,X)\n", 228 | "Stdb = sqrt.(diag(V)) #standard errors\n", 229 | "\n", 230 | "printblue(\"OLS Results:\\n\")\n", 231 | "xNames = [\"c\",\"SMB\",\"HML\"]\n", 232 | "printmat(b,Stdb,colNames=[\"b\",\"std\"],rowNames=xNames)\n", 233 | "\n", 234 | "printlnPs(\"R²: \",R²)" 235 | ] 236 | }, 237 | { 238 | "cell_type": "code", 239 | "execution_count": 8, 240 | "metadata": {}, 241 | "outputs": [ 242 | { 243 | "name": "stdout", 244 | "output_type": "stream", 245 | "text": [ 246 | " coef stderr t-stat p-value\n", 247 | "c 0.007 0.002 3.175 0.001\n", 248 | "SMB 0.217 0.073 2.957 0.003\n", 249 | "HML -0.429 0.074 -5.836 0.000\n", 250 | "\n" 251 | ] 252 | } 253 | ], 254 | "source": [ 255 | "RegressionTable(b,V,[\"c\",\"SMB\",\"HML\"]) #a function for printing regression results" 256 | ] 257 | }, 258 | { 259 | "cell_type": "markdown", 260 | "metadata": {}, 261 | "source": [ 262 | "# Missing Values (extra)\n", 263 | "\n", 264 | "The next cells use a simple function (`excise()`) to remove observations ($t$) where $y_t$ and/or some of the $x_t$ variables are NaN/missing. We illustrate the usage by a very simple example.\n", 265 | "\n", 266 | "An alternative approach is to fill *both* $y_t$ and $x_t$ with zeros (if any of them contains NaN/missing) by using the `OLSyxReplaceNaN` function and then do the regression. This is illustrated in the subsequent cell." 267 | ] 268 | }, 269 | { 270 | "cell_type": "code", 271 | "execution_count": 9, 272 | "metadata": {}, 273 | "outputs": [ 274 | { 275 | "name": "stdout", 276 | "output_type": "stream", 277 | "text": [ 278 | "obs 1-3 before\n", 279 | " y c SMB HML\n", 280 | " 0.042 1.000 0.037 0.023\n", 281 | " -0.034 1.000 NaN 0.012\n", 282 | " 0.058 1.000 0.032 -0.007\n", 283 | "\n", 284 | "after\n", 285 | " y c SMB HML\n", 286 | " 0.042 1.000 0.037 0.023\n", 287 | " 0.058 1.000 0.032 -0.007\n", 288 | " 0.001 1.000 0.022 0.011\n", 289 | "\n", 290 | "\u001b[34m\u001b[1mOLS using only observations without any NaN/missing:\u001b[22m\u001b[39m\n", 291 | " 0.007\n", 292 | " 0.218\n", 293 | " -0.428\n", 294 | "\n" 295 | ] 296 | } 297 | ], 298 | "source": [ 299 | "(y0,x0) = (copy(Y),copy(X)) #so we can can change some values\n", 300 | "x0[2,2] = NaN #set a value to NaN\n", 301 | "\n", 302 | "(y1,x1) = excise(y0,x0)\n", 303 | "println(\"obs 1-3 before\")\n", 304 | "printmat(y0[1:3],x0[1:3,:];colNames=vcat(\"y\",xNames))\n", 305 | "\n", 306 | "println(\"after\")\n", 307 | "printmat(y1[1:3],x1[1:3,:];colNames=vcat(\"y\",xNames))\n", 308 | "\n", 309 | "printblue(\"OLS using only observations without any NaN/missing:\")\n", 310 | "b = x1\\y1\n", 311 | "printmat(b)" 312 | ] 313 | }, 314 | { 315 | "cell_type": "code", 316 | "execution_count": 10, 317 | "metadata": {}, 318 | "outputs": [ 319 | { 320 | "name": "stdout", 321 | "output_type": "stream", 322 | "text": [ 323 | "after\n", 324 | " y c SMB HML\n", 325 | " 0.042 1.000 0.037 0.023\n", 326 | " 0.000 0.000 0.000 0.000\n", 327 | " 0.058 1.000 0.032 -0.007\n", 328 | "\n", 329 | "\u001b[34m\u001b[1mOLS from setting observations with any NaN/missing to 0:\u001b[22m\u001b[39m\n", 330 | " 0.007\n", 331 | " 0.218\n", 332 | " -0.428\n", 333 | "\n" 334 | ] 335 | } 336 | ], 337 | "source": [ 338 | "(vv,y2,x2) = OLSyxReplaceNaN(y0,x0)\n", 339 | "\n", 340 | "println(\"after\")\n", 341 | "printmat(y2[1:3],x2[1:3,:];colNames=vcat(\"y\",xNames))\n", 342 | "\n", 343 | "printblue(\"OLS from setting observations with any NaN/missing to 0:\")\n", 344 | "b = x2\\y2\n", 345 | "printmat(b)" 346 | ] 347 | }, 348 | { 349 | "cell_type": "markdown", 350 | "metadata": {}, 351 | "source": [ 352 | "# Different Ways to Calculate OLS Estimates (extra)\n", 353 | "\n", 354 | "Recall that OLS can be calculated as\n", 355 | "\n", 356 | "$\\hat{\\beta} = S_{xx}^{-1}S_{xy}, \\: \\text{ where } \\: \n", 357 | "S_{xx} = \\sum\\nolimits_{t=1}^{T}x_{t}x_{t}^{\\prime}\n", 358 | "\\: \\text{ and } \\:\n", 359 | "S_{xy} = \\sum\\nolimits_{t=1}^{T}x_{t}y_{t}.$\n", 360 | "\n", 361 | "The next cell calculates the OLS estimates in three different ways: (1) a loop to create $S_{xx}$ and $S_{xy}$ followed by $S_{xx}^{-1}S_{xy}$; (2) $(X'X)^{-1}X'Y$; (3) and `X\\Y`. They should give the same result in well-behaved data sets, but (3) is probably the most stable version." 362 | ] 363 | }, 364 | { 365 | "cell_type": "code", 366 | "execution_count": 11, 367 | "metadata": {}, 368 | "outputs": [ 369 | { 370 | "name": "stdout", 371 | "output_type": "stream", 372 | "text": [ 373 | "\u001b[34m\u001b[1mThree different ways to calculate OLS estimates:\u001b[22m\u001b[39m\n", 374 | " b1 b2 b3\n", 375 | "c 0.007 0.007 0.007\n", 376 | "SMB 0.217 0.217 0.217\n", 377 | "HML -0.429 -0.429 -0.429\n", 378 | "\n" 379 | ] 380 | } 381 | ], 382 | "source": [ 383 | "printblue(\"Three different ways to calculate OLS estimates:\")\n", 384 | "\n", 385 | "k = size(X,2)\n", 386 | "Sxx = zeros(k,k)\n", 387 | "Sxy = zeros(k,1)\n", 388 | "for t = 1:T\n", 389 | " #local x_t, y_t #local/global is needed in script\n", 390 | " #global Sxx, Sxy\n", 391 | " x_t = X[t,:] #a vector\n", 392 | " y_t = Y[t]\n", 393 | " Sxx = Sxx + x_t*x_t' #kxk, same as Sxx += x_t*x_t'\n", 394 | " Sxy = Sxy + x_t*y_t #kx1, same as Sxy += x_t*y_t\n", 395 | "end\n", 396 | "b1 = inv(Sxx)*Sxy #OLS coeffs, version 1\n", 397 | "\n", 398 | "b2 = inv(X'X)*X'Y #OLS coeffs, version 2\n", 399 | "\n", 400 | "b3 = X\\Y #OLS coeffs, version 3\n", 401 | "\n", 402 | "printmat(b1,b2,b3,colNames=[\"b1\",\"b2\",\"b3\"],rowNames=xNames)" 403 | ] 404 | }, 405 | { 406 | "cell_type": "code", 407 | "execution_count": null, 408 | "metadata": {}, 409 | "outputs": [], 410 | "source": [] 411 | } 412 | ], 413 | "metadata": { 414 | "@webio": { 415 | "lastCommId": null, 416 | "lastKernelId": null 417 | }, 418 | "anaconda-cloud": {}, 419 | "kernelspec": { 420 | "display_name": "Julia 1.11.5", 421 | "language": "julia", 422 | "name": "julia-1.11" 423 | }, 424 | "language_info": { 425 | "file_extension": ".jl", 426 | "mimetype": "application/julia", 427 | "name": "julia", 428 | "version": "1.11.5" 429 | } 430 | }, 431 | "nbformat": 4, 432 | "nbformat_minor": 4 433 | } 434 | -------------------------------------------------------------------------------- /Ch02b_MatrixAlgebraPrimer.txt: -------------------------------------------------------------------------------- 1 | See MatrixAlgebra in the Julia tutorial repository -------------------------------------------------------------------------------- /Ch02c_FrischWaugh.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# OLS, The Frisch-Waugh Theorem\n", 8 | "\n", 9 | "This notebook illustrates the Frish-Waugh theorem.\n", 10 | "\n", 11 | "In particular, it shows the following. First, we regress\n", 12 | "\n", 13 | "$y = x_1'\\beta_1 + x_2'\\beta_2 + u$\n", 14 | "\n", 15 | "Second, we run three regressions\n", 16 | "\n", 17 | "1. $y = x_1'\\gamma_1 + e_y$\n", 18 | "\n", 19 | "2. $x_2 = x_1'\\delta + e_2$\n", 20 | "\n", 21 | "3. $e_y = e_2'\\theta + v$,\n", 22 | "where $(e_y,e_2)$ are from the regressions in 1. and 2.\n", 23 | "\n", 24 | "Then, the estimates of $\\beta_2$ and $\\theta$ will be the same (as will their standard errors). This is used in, for instance, fixed effects panel regressions (where $x_1$ are dummies indicating different cross-sectional units)." 25 | ] 26 | }, 27 | { 28 | "cell_type": "markdown", 29 | "metadata": {}, 30 | "source": [ 31 | "## Load Packages and Extra Functions\n", 32 | "\n", 33 | "The `OlsGM()` function was used in ch. 2. It is from the (local) `FinEcmt_OLS` module." 34 | ] 35 | }, 36 | { 37 | "cell_type": "code", 38 | "execution_count": 1, 39 | "metadata": {}, 40 | "outputs": [], 41 | "source": [ 42 | "MyModulePath = joinpath(pwd(),\"src\")\n", 43 | "!in(MyModulePath,LOAD_PATH) && push!(LOAD_PATH,MyModulePath)\n", 44 | "using FinEcmt_OLS" 45 | ] 46 | }, 47 | { 48 | "cell_type": "code", 49 | "execution_count": 2, 50 | "metadata": {}, 51 | "outputs": [], 52 | "source": [ 53 | "#=\n", 54 | "include(joinpath(pwd(),\"src\",\"FinEcmt_OLS.jl\")) #alternative way\n", 55 | "using .FinEcmt_OLS\n", 56 | "=#" 57 | ] 58 | }, 59 | { 60 | "cell_type": "code", 61 | "execution_count": 3, 62 | "metadata": {}, 63 | "outputs": [], 64 | "source": [ 65 | "using DelimitedFiles, LinearAlgebra" 66 | ] 67 | }, 68 | { 69 | "cell_type": "markdown", 70 | "metadata": {}, 71 | "source": [ 72 | "## Loading Data" 73 | ] 74 | }, 75 | { 76 | "cell_type": "code", 77 | "execution_count": 4, 78 | "metadata": {}, 79 | "outputs": [ 80 | { 81 | "data": { 82 | "text/plain": [ 83 | "388" 84 | ] 85 | }, 86 | "execution_count": 4, 87 | "metadata": {}, 88 | "output_type": "execute_result" 89 | } 90 | ], 91 | "source": [ 92 | "x = readdlm(\"Data/FFmFactorsPs.csv\",',',skipstart=1)\n", 93 | "(Rme,SMB,HML,Rf) = (x[:,2],x[:,3],x[:,4],x[:,5])\n", 94 | "\n", 95 | "x = readdlm(\"Data/FF25Ps.csv\",',') #no header line\n", 96 | "R = x[:,2:end] #returns for 25 FF portfolios\n", 97 | "Re = R .- Rf #excess returns for the 25 FF portfolios\n", 98 | "\n", 99 | "T = size(Re,1) #number of observations" 100 | ] 101 | }, 102 | { 103 | "cell_type": "code", 104 | "execution_count": 5, 105 | "metadata": {}, 106 | "outputs": [], 107 | "source": [ 108 | "y = Re[:,6] #to the notation used in comment, use asset 6\n", 109 | "x₁ = [ones(T) Rme] #1st set of regressors (2)\n", 110 | "x₂ = [SMB HML]; #2nd set of regressors" 111 | ] 112 | }, 113 | { 114 | "cell_type": "markdown", 115 | "metadata": {}, 116 | "source": [ 117 | "## Regress y on Both x₁ and x₂" 118 | ] 119 | }, 120 | { 121 | "cell_type": "code", 122 | "execution_count": 6, 123 | "metadata": {}, 124 | "outputs": [ 125 | { 126 | "name": "stdout", 127 | "output_type": "stream", 128 | "text": [ 129 | "\u001b[34m\u001b[1mOLS Results from y regressed on x:\u001b[22m\u001b[39m\n", 130 | "\n", 131 | " b std\n", 132 | "x₁ (c) -0.337 0.121\n", 133 | "x₁ (Rme) 1.184 0.028\n", 134 | "x₂ (SMB) 0.916 0.040\n", 135 | "x₂ (HML) -0.384 0.042\n", 136 | "\n" 137 | ] 138 | } 139 | ], 140 | "source": [ 141 | "(b,_,_,V,) = OlsGM(y,[x₁ x₂])\n", 142 | "std_b = sqrt.(diag(V))\n", 143 | "\n", 144 | "printblue(\"OLS Results from y regressed on x:\\n\")\n", 145 | "rowNames=[\"x₁ (c)\",\"x₁ (Rme)\",\"x₂ (SMB)\",\"x₂ (HML)\"]\n", 146 | "printmat([b std_b];colNames=[\"b\",\"std\"],rowNames)" 147 | ] 148 | }, 149 | { 150 | "cell_type": "markdown", 151 | "metadata": {}, 152 | "source": [ 153 | "## The Three Steps in Frisch-Waugh\n", 154 | "\n", 155 | "1. Regress `y` on `x₁` and save the residuals as `e_y`. (Sorry, cannot create a symbol like $e_y$.)\n", 156 | "\n", 157 | "2. Regress `x₂` on `x₁` and save the residuals as `e₂`.\n", 158 | "\n", 159 | "3. Regress `e_y` on `e₂`." 160 | ] 161 | }, 162 | { 163 | "cell_type": "code", 164 | "execution_count": 7, 165 | "metadata": {}, 166 | "outputs": [ 167 | { 168 | "name": "stdout", 169 | "output_type": "stream", 170 | "text": [ 171 | "\u001b[34m\u001b[1mOLS Results from e_y regressed on e₂:\u001b[22m\u001b[39m\n", 172 | "\n", 173 | " b std\n", 174 | "e₂ (SMB) 0.916 0.040\n", 175 | "e₂ (HML) -0.384 0.042\n", 176 | "\n", 177 | "\u001b[31m\u001b[1mShould be same coeff and std as in multiple regression (above)\u001b[22m\u001b[39m\n" 178 | ] 179 | } 180 | ], 181 | "source": [ 182 | "(_,e_y,) = OlsGM(y,x₁); #step 1\n", 183 | "\n", 184 | "(_,e₂,) = OlsGM(x₂,x₁); #step 2\n", 185 | "\n", 186 | "(b,_,_,V,) = OlsGM(e_y,e₂) #step 3\n", 187 | "std_b = isa(V,Number) ? sqrt(V) : sqrt.(diag(V)) #diag() fails if V is a number (not a matrix)\n", 188 | "\n", 189 | "printblue(\"OLS Results from e_y regressed on e₂:\\n\")\n", 190 | "printmat([b std_b],colNames=[\"b\",\"std\"],rowNames=[\"e₂ (SMB)\",\"e₂ (HML)\"])\n", 191 | "printred(\"Should be same coeff and std as in multiple regression (above)\")" 192 | ] 193 | }, 194 | { 195 | "cell_type": "markdown", 196 | "metadata": {}, 197 | "source": [ 198 | "## A Partial Frisch-Waugh Approach (extra)\n", 199 | "\n", 200 | "Regress `y` (not `e_y`) on `e₂`. This gives the same point estimate, but wrong standard error." 201 | ] 202 | }, 203 | { 204 | "cell_type": "code", 205 | "execution_count": 8, 206 | "metadata": {}, 207 | "outputs": [ 208 | { 209 | "name": "stdout", 210 | "output_type": "stream", 211 | "text": [ 212 | "\u001b[34m\u001b[1mOLS Results from y regressed on e₂:\u001b[22m\u001b[39m\n", 213 | "\n", 214 | " b std\n", 215 | "e₂ (SMB) 0.916 0.120\n", 216 | "e₂ (HML) -0.384 0.124\n", 217 | "\n", 218 | "\u001b[31m\u001b[1mShould be same coeff (but different std) as in multiple regression (above)\u001b[22m\u001b[39m\n" 219 | ] 220 | } 221 | ], 222 | "source": [ 223 | "(b,_,_,V,) = OlsGM(y,e₂) #step 3, adjusted\n", 224 | "std_b = isa(V,Number) ? sqrt(V) : sqrt.(diag(V)) #diag() fails if V is a number (not a matrix)\n", 225 | "\n", 226 | "printblue(\"OLS Results from y regressed on e₂:\\n\")\n", 227 | "printmat([b std_b],colNames=[\"b\",\"std\"],rowNames=[\"e₂ (SMB)\",\"e₂ (HML)\"])\n", 228 | "printred(\"Should be same coeff (but different std) as in multiple regression (above)\")" 229 | ] 230 | }, 231 | { 232 | "cell_type": "code", 233 | "execution_count": null, 234 | "metadata": {}, 235 | "outputs": [], 236 | "source": [] 237 | } 238 | ], 239 | "metadata": { 240 | "@webio": { 241 | "lastCommId": null, 242 | "lastKernelId": null 243 | }, 244 | "anaconda-cloud": {}, 245 | "kernelspec": { 246 | "display_name": "Julia 1.11.4", 247 | "language": "julia", 248 | "name": "julia-1.11" 249 | }, 250 | "language_info": { 251 | "file_extension": ".jl", 252 | "mimetype": "application/julia", 253 | "name": "julia", 254 | "version": "1.11.4" 255 | } 256 | }, 257 | "nbformat": 4, 258 | "nbformat_minor": 4 259 | } 260 | -------------------------------------------------------------------------------- /Ch03_Betas.txt: -------------------------------------------------------------------------------- 1 | See the FinancialTheoryMSc repository -------------------------------------------------------------------------------- /Ch04b_OLS_Testing.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# OLS, Testing\n", 8 | "\n", 9 | "This notebook estimates a linear regression and tests various hypotheses using standard errors assuming *(a)* iid residuals (Gauss-Markov assumptions); *(b)* heteroskedasticity (White); *(c)* autocorrelation and heteroskedasticity (Newey-West).\n", 10 | "\n", 11 | "You may also consider the [HypothesisTests.jl](https://github.com/JuliaStats/HypothesisTests.jl) package (not used here)." 12 | ] 13 | }, 14 | { 15 | "cell_type": "markdown", 16 | "metadata": {}, 17 | "source": [ 18 | "## Load Packages and Extra Functions" 19 | ] 20 | }, 21 | { 22 | "cell_type": "code", 23 | "execution_count": 1, 24 | "metadata": {}, 25 | "outputs": [], 26 | "source": [ 27 | "MyModulePath = joinpath(pwd(),\"src\")\n", 28 | "!in(MyModulePath,LOAD_PATH) && push!(LOAD_PATH,MyModulePath)\n", 29 | "using FinEcmt_OLS" 30 | ] 31 | }, 32 | { 33 | "cell_type": "code", 34 | "execution_count": 2, 35 | "metadata": {}, 36 | "outputs": [], 37 | "source": [ 38 | "#=\n", 39 | "include(joinpath(pwd(),\"src\",\"FinEcmt_OLS.jl\"))\n", 40 | "using .FinEcmt_OLS\n", 41 | "=#" 42 | ] 43 | }, 44 | { 45 | "cell_type": "code", 46 | "execution_count": 3, 47 | "metadata": { 48 | "tags": [] 49 | }, 50 | "outputs": [], 51 | "source": [ 52 | "using DelimitedFiles, Statistics, LinearAlgebra, Distributions" 53 | ] 54 | }, 55 | { 56 | "cell_type": "markdown", 57 | "metadata": {}, 58 | "source": [ 59 | "## Loading Data" 60 | ] 61 | }, 62 | { 63 | "cell_type": "code", 64 | "execution_count": 4, 65 | "metadata": { 66 | "tags": [] 67 | }, 68 | "outputs": [ 69 | { 70 | "name": "stdout", 71 | "output_type": "stream", 72 | "text": [ 73 | "Sample size: (388,)\n" 74 | ] 75 | } 76 | ], 77 | "source": [ 78 | "x = readdlm(\"Data/FFmFactorsPs.csv\",',',skipstart=1)\n", 79 | "\n", 80 | " #yearmonth, market, small minus big, high minus low\n", 81 | "(ym,Rme,RSMB,RHML) = (x[:,1],x[:,2]/100,x[:,3]/100,x[:,4]/100)\n", 82 | "x = nothing\n", 83 | "\n", 84 | "printlnPs(\"Sample size:\",size(Rme))" 85 | ] 86 | }, 87 | { 88 | "cell_type": "markdown", 89 | "metadata": {}, 90 | "source": [ 91 | "## OLS under the Gauss-Markov Assumptions\n", 92 | "\n", 93 | "(assuming iid residuals)" 94 | ] 95 | }, 96 | { 97 | "cell_type": "code", 98 | "execution_count": 5, 99 | "metadata": { 100 | "tags": [] 101 | }, 102 | "outputs": [ 103 | { 104 | "name": "stdout", 105 | "output_type": "stream", 106 | "text": [ 107 | "\u001b[34m\u001b[1mOLS Results (assuming iid residuals):\u001b[22m\u001b[39m\n", 108 | "\n", 109 | " b std_iid\n", 110 | "c 0.007 0.002\n", 111 | "SMB 0.217 0.073\n", 112 | "HML -0.429 0.074\n", 113 | "\n" 114 | ] 115 | } 116 | ], 117 | "source": [ 118 | "Y = Rme\n", 119 | "T = size(Y,1)\n", 120 | "X = [ones(T) RSMB RHML]\n", 121 | "\n", 122 | "(b,u,_,V,R²) = OlsGM(Y,X)\n", 123 | "std_iid = sqrt.(diag(V))\n", 124 | "\n", 125 | "printblue(\"OLS Results (assuming iid residuals):\\n\")\n", 126 | "xNames = [\"c\",\"SMB\",\"HML\"]\n", 127 | "printmat(b,std_iid;colNames=[\"b\",\"std_iid\"],rowNames=xNames)" 128 | ] 129 | }, 130 | { 131 | "cell_type": "markdown", 132 | "metadata": {}, 133 | "source": [ 134 | "# Testing a Joint Hypothesis\n", 135 | "\n", 136 | "Since the estimator $\\hat{\\beta}_{_{k\\times1}}$ satisfies\n", 137 | "\n", 138 | "$\\hat{\\beta}-\\beta_{0} \\sim N(0,V_{k\\times k}),$\n", 139 | "\n", 140 | "we can easily apply various tests. Consider a joint linear hypothesis of the\n", 141 | "form\n", 142 | "\n", 143 | "$H_0: R\\beta=q,$\n", 144 | "\n", 145 | "where $R$ is a $J \\times k$ matrix and $q$ is a $J$-vector. To test this, use\n", 146 | "\n", 147 | "$(R\\beta-q)^{\\prime}(RVR^{\\prime}) ^{-1}(R\\beta\n", 148 | "-q)\\overset{d}{\\rightarrow}\\chi_{J}^{2}.$\n", 149 | "\n", 150 | "How we estimate $V$ depends on whether there is heteroskedasticity and/or autocorrelation (discussed below)." 151 | ] 152 | }, 153 | { 154 | "cell_type": "code", 155 | "execution_count": 6, 156 | "metadata": { 157 | "tags": [] 158 | }, 159 | "outputs": [ 160 | { 161 | "name": "stdout", 162 | "output_type": "stream", 163 | "text": [ 164 | "\u001b[34m\u001b[1mTesting Rb = a:\u001b[22m\u001b[39m\n", 165 | "test statistic 60.010\n", 166 | "10% critical value 4.605\n", 167 | "\n" 168 | ] 169 | } 170 | ], 171 | "source": [ 172 | "R = [0 1 0; #testing if b₂=0 and b₃=0\n", 173 | " 0 0 1]\n", 174 | "q = [0;0]\n", 175 | "test_stat = (R*b-q)'inv(R*V*R')*(R*b-q) #R*V*R' is 2x2\n", 176 | "\n", 177 | "printblue(\"Testing Rb = a:\")\n", 178 | "printmat([test_stat,quantile(Chisq(2),0.9)];rowNames=[\"test statistic\",\"10% critical value\"])" 179 | ] 180 | }, 181 | { 182 | "cell_type": "markdown", 183 | "metadata": {}, 184 | "source": [ 185 | "# Distribution of OLS Estimates without the Gauss-Markov Assumptions\n", 186 | "\n", 187 | "\n", 188 | "The distribution of the OLS estimates is (typically)\n", 189 | "\n", 190 | "$(\\hat{\\beta}-\\beta_{0})\\overset{d}{\\rightarrow}N(0,V)\n", 191 | "\\: \\text{ where } \\: V=S_{xx}^{-1} S S_{xx}^{-1}.$\n", 192 | "\n", 193 | "and where $S_{xx} = \\sum\\nolimits_{t=1}^{T}x_{t}x_{t}^{\\prime}$ \n", 194 | "and $S$ is the covariance matrix of $\\sum_{t=1}^{T}u_{t}x_{t}$.\n", 195 | "\n", 196 | "\n", 197 | "*When* the Gauss-Markov assumptions hold, then $S$ can be simplified to $S_{xx}\\sigma^2$, where $\\sigma^2$ is the variance of $u_t$, so $V=S_{xx}^{-1}\\sigma^2$.\n", 198 | "\n", 199 | "In contrast, with heteroskedasticity and/or autocorrelation, $S$ must be estimated differently." 200 | ] 201 | }, 202 | { 203 | "cell_type": "markdown", 204 | "metadata": {}, 205 | "source": [ 206 | "# White's Covariance Matrix\n", 207 | "\n", 208 | "If $u_{t}x_{t}$ is not autocorrelated, then $S$ simplifies to $\\sum_{t=1}^{T} x_tx_t^{\\prime}\\sigma_t^2$. White's method replaces $\\sigma_t^2$ by $\\hat{u}_{t}^{2}$. This estimate is robust to heteroskedasticity (in particular, time variation in $\\sigma_t^2$ that is related to $x_t$).\n", 209 | "\n", 210 | "## A Remark on the Code\n", 211 | "$S_{xx}$ can be calculated as `Sxx = X'X` and $S$ as `S = (X.*u)'*(X.*u)`.\n", 212 | "\n", 213 | "Clearly, these calculations can also be done in a loop like\n", 214 | "```\n", 215 | "for t = 1:T\n", 216 | " Sxx = Sxx + X[t,:]*X[t,:]' \n", 217 | " S = S + X[t,:]*X[t,:]'*u[t]^2\n", 218 | "end\n", 219 | "```" 220 | ] 221 | }, 222 | { 223 | "cell_type": "code", 224 | "execution_count": 7, 225 | "metadata": { 226 | "tags": [] 227 | }, 228 | "outputs": [ 229 | { 230 | "name": "stdout", 231 | "output_type": "stream", 232 | "text": [ 233 | "\u001b[34m\u001b[1mCoefficients and standard errors (from different methods):\u001b[22m\u001b[39m\n", 234 | "\n", 235 | " b std_iid std_White\n", 236 | "c 0.007 0.002 0.002\n", 237 | "SMB 0.217 0.073 0.113\n", 238 | "HML -0.429 0.074 0.097\n", 239 | "\n" 240 | ] 241 | } 242 | ], 243 | "source": [ 244 | "Sxx = X'X\n", 245 | "\n", 246 | "S = (X.*u)'*(X.*u) #S according to White's method\n", 247 | "V = inv(Sxx)'S*inv(Sxx) #Cov(b), White\n", 248 | "std_W = sqrt.(diag(V))\n", 249 | "\n", 250 | "printblue(\"Coefficients and standard errors (from different methods):\\n\")\n", 251 | "xx = [b std_iid std_W]\n", 252 | "printmat(xx;colNames=[\"b\",\"std_iid\",\"std_White\"],rowNames=xNames,width=12)" 253 | ] 254 | }, 255 | { 256 | "cell_type": "markdown", 257 | "metadata": {}, 258 | "source": [ 259 | "# Newey-West's Covariance Matrix\n", 260 | "\n", 261 | "Let $g_t=u_{t}x_{t}$ be a $k$-vector of data.\n", 262 | "\n", 263 | "To calculate the Newey-West covariance matrix, we first need\n", 264 | "\n", 265 | "$\\Lambda_{s} = \\sum_{t=s+1}^{T} (g_{t}-\\bar{g})(g_{t-s}-\\bar{g})^{\\prime},$\n", 266 | "\n", 267 | "which is proportional to the $s$th autocovariance matrices.\n", 268 | "\n", 269 | "Then we form a linear\n", 270 | "combination (with tent-shaped weights) of those autocovariance matrices (from\n", 271 | "lag $-m$ to $m$) as in\n", 272 | "\n", 273 | "$S = \\mathrm{Cov}(\\sum_t g_t) = \n", 274 | "\\Lambda_{0} + \\sum_{s=1}^{m}( 1-\\frac{s}{m+1}) \n", 275 | "(\\Lambda_{s}+\\Lambda_{s}^{\\prime}).$\n", 276 | "\n", 277 | "With $m=0$ this is the same as White's method.\n", 278 | "\n", 279 | "If we divide $S$ by $T$, then we get an estimate of $\\mathrm{Cov}(\\sqrt{T} \\bar{g})$, and if we instead divide by $T^2$ then we get an estimate of $\\mathrm{Cov}(\\bar{g})$.\n", 280 | "\n", 281 | "The `CovNW()` function implements this." 282 | ] 283 | }, 284 | { 285 | "cell_type": "code", 286 | "execution_count": 8, 287 | "metadata": {}, 288 | "outputs": [ 289 | { 290 | "data": { 291 | "text/markdown": [ 292 | "```\n", 293 | "CovNW(g0,m=0,DivideByT=0)\n", 294 | "```\n", 295 | "\n", 296 | "Calculates covariance matrix of sample sum (DivideByT=0), √T*(sample average) (DivideByT=1) or sample average (DivideByT=2).\n", 297 | "\n", 298 | "### Input\n", 299 | "\n", 300 | " * `g0::Matrix`: Txq matrix of data\n", 301 | " * `m::Int`: number of lags to use\n", 302 | " * `DivideByT::Int`: divide the result by T^DivideByT\n", 303 | "\n", 304 | "### Output\n", 305 | "\n", 306 | " * `S::Matrix`: qxq covariance matrix\n", 307 | "\n", 308 | "### Remark\n", 309 | "\n", 310 | " * `DivideByT=0`: Var(g₁+g₂+...), variance of sample sum\n", 311 | " * `DivideByT=1`: Var(g₁+g₂+...)/T = Var(√T gbar), where gbar is the sample average. This is the same as Var(gᵢ) if data is iid\n", 312 | " * `DivideByT=2`: Var(g₁+g₂+...)/T^2 = Var(gbar)\n" 313 | ] 314 | }, 315 | "metadata": {}, 316 | "output_type": "display_data" 317 | } 318 | ], 319 | "source": [ 320 | "@doc2 CovNW" 321 | ] 322 | }, 323 | { 324 | "cell_type": "code", 325 | "execution_count": 9, 326 | "metadata": {}, 327 | "outputs": [ 328 | { 329 | "name": "stdout", 330 | "output_type": "stream", 331 | "text": [ 332 | "function CovNW(g0,m=0,DivideByT=0)\n", 333 | "\n", 334 | " T = size(g0,1) #g0 is Txq\n", 335 | " m = min(m,T-1) #number of lags\n", 336 | "\n", 337 | " g = g0 .- mean(g0,dims=1) #normalizing to zero means\n", 338 | "\n", 339 | " S = g'g #(qxT)*(Txq)\n", 340 | " for s = 1:m\n", 341 | " Λ_s = g[s+1:T,:]'g[1:T-s,:] #same as Sum[g_t*g_{t-s}',t=s+1,T]\n", 342 | " S = S + (1 - s/(m+1))*(Λ_s + Λ_s')\n", 343 | " end\n", 344 | "\n", 345 | " (DivideByT > 0) && (S = S/T^DivideByT)\n", 346 | "\n", 347 | " return S\n", 348 | "\n", 349 | "end\n" 350 | ] 351 | } 352 | ], 353 | "source": [ 354 | "using CodeTracking\n", 355 | "println(@code_string CovNW([1],2)) #print the source code" 356 | ] 357 | }, 358 | { 359 | "cell_type": "code", 360 | "execution_count": 10, 361 | "metadata": { 362 | "tags": [] 363 | }, 364 | "outputs": [ 365 | { 366 | "name": "stdout", 367 | "output_type": "stream", 368 | "text": [ 369 | "\u001b[34m\u001b[1mCoefficients and standard errors (from different methods):\u001b[22m\u001b[39m\n", 370 | "\n", 371 | " b std_iid std_White std_NW std_NW 0 lags\n", 372 | "c 0.007 0.002 0.002 0.002 0.002\n", 373 | "SMB 0.217 0.073 0.113 0.129 0.113\n", 374 | "HML -0.429 0.074 0.097 0.118 0.097\n", 375 | "\n", 376 | "\u001b[31m\u001b[1mRemark: NW with 0 lags should be the same as White's method\u001b[22m\u001b[39m\n" 377 | ] 378 | } 379 | ], 380 | "source": [ 381 | "S = CovNW(X.*u,2) #S acccording to Newey-West, 2 lags\n", 382 | "V = inv(Sxx)'S*inv(Sxx) #Cov(b), Newey-West\n", 383 | "std_NW = sqrt.(diag(V))\n", 384 | "\n", 385 | "S = CovNW(X.*u,0) #S acccording to Newey-West, 0 lags\n", 386 | "V = inv(Sxx)'S*inv(Sxx)\n", 387 | "std_NW0 = sqrt.(diag(V))\n", 388 | "\n", 389 | "printblue(\"Coefficients and standard errors (from different methods):\\n\")\n", 390 | "xx = [b std_iid std_W std_NW std_NW0]\n", 391 | "printmat(xx,colNames=[\"b\",\"std_iid\",\"std_White\",\"std_NW\",\"std_NW 0 lags\"],rowNames=xNames,width=16)\n", 392 | "\n", 393 | "printred(\"Remark: NW with 0 lags should be the same as White's method\")" 394 | ] 395 | }, 396 | { 397 | "cell_type": "code", 398 | "execution_count": null, 399 | "metadata": {}, 400 | "outputs": [], 401 | "source": [] 402 | } 403 | ], 404 | "metadata": { 405 | "@webio": { 406 | "lastCommId": null, 407 | "lastKernelId": null 408 | }, 409 | "anaconda-cloud": {}, 410 | "kernelspec": { 411 | "display_name": "Julia 1.11.5", 412 | "language": "julia", 413 | "name": "julia-1.11" 414 | }, 415 | "language_info": { 416 | "file_extension": ".jl", 417 | "mimetype": "application/julia", 418 | "name": "julia", 419 | "version": "1.11.5" 420 | } 421 | }, 422 | "nbformat": 4, 423 | "nbformat_minor": 4 424 | } 425 | -------------------------------------------------------------------------------- /Ch04c_DeltaMethod.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# The Delta Method" 8 | ] 9 | }, 10 | { 11 | "cell_type": "markdown", 12 | "metadata": {}, 13 | "source": [ 14 | "## Load Packages and Extra Functions\n", 15 | "\n", 16 | "The notebook first implements the delta method step-by-step. At the end it also presents a the function `DeltaMethod()` from the (local) `FinEcmt_OLS` module that wraps those calculations." 17 | ] 18 | }, 19 | { 20 | "cell_type": "code", 21 | "execution_count": 1, 22 | "metadata": {}, 23 | "outputs": [], 24 | "source": [ 25 | "MyModulePath = joinpath(pwd(),\"src\")\n", 26 | "!in(MyModulePath,LOAD_PATH) && push!(LOAD_PATH,MyModulePath)\n", 27 | "using FinEcmt_OLS" 28 | ] 29 | }, 30 | { 31 | "cell_type": "code", 32 | "execution_count": 2, 33 | "metadata": {}, 34 | "outputs": [], 35 | "source": [ 36 | "#=\n", 37 | "include(joinpath(pwd(),\"src\",\"FinEcmt_OLS.jl\"))\n", 38 | "using .FinEcmt_OLS\n", 39 | "=#" 40 | ] 41 | }, 42 | { 43 | "cell_type": "code", 44 | "execution_count": 3, 45 | "metadata": {}, 46 | "outputs": [], 47 | "source": [ 48 | "using DelimitedFiles, Statistics" 49 | ] 50 | }, 51 | { 52 | "cell_type": "markdown", 53 | "metadata": {}, 54 | "source": [ 55 | "## Load Data" 56 | ] 57 | }, 58 | { 59 | "cell_type": "code", 60 | "execution_count": 4, 61 | "metadata": {}, 62 | "outputs": [ 63 | { 64 | "data": { 65 | "text/plain": [ 66 | "388" 67 | ] 68 | }, 69 | "execution_count": 4, 70 | "metadata": {}, 71 | "output_type": "execute_result" 72 | } 73 | ], 74 | "source": [ 75 | "x = readdlm(\"Data/FFmFactorsPs.csv\",',',skipstart=1)\n", 76 | "x = x[:,2] #x is an excess return in % (on the US equity market)\n", 77 | "T = size(x,1)" 78 | ] 79 | }, 80 | { 81 | "cell_type": "markdown", 82 | "metadata": {}, 83 | "source": [ 84 | "## Point Estimates of the Mean and Variance" 85 | ] 86 | }, 87 | { 88 | "cell_type": "code", 89 | "execution_count": 5, 90 | "metadata": {}, 91 | "outputs": [ 92 | { 93 | "name": "stdout", 94 | "output_type": "stream", 95 | "text": [ 96 | "\u001b[34m\u001b[1mmean and variance:\u001b[22m\u001b[39m\n", 97 | "μ 0.602\n", 98 | "σ² 21.142\n", 99 | "\n" 100 | ] 101 | } 102 | ], 103 | "source": [ 104 | "μ = mean(x) #estimates of the mean and variance\n", 105 | "σ² = var(x,corrected=false)\n", 106 | "\n", 107 | "printblue(\"mean and variance:\")\n", 108 | "momNames = [\"μ\",\"σ²\"]\n", 109 | "printmat([μ,σ²];rowNames=momNames)" 110 | ] 111 | }, 112 | { 113 | "cell_type": "markdown", 114 | "metadata": {}, 115 | "source": [ 116 | "The variance-covariance matrix (called $V$) of the point estimates depends on the distribution of the data. With a normal distribution, the form is particularly simple. We use that approximation in the next cell. Another approach is to estimate $V$ from the moment conditions (see GMM)." 117 | ] 118 | }, 119 | { 120 | "cell_type": "code", 121 | "execution_count": 6, 122 | "metadata": {}, 123 | "outputs": [ 124 | { 125 | "name": "stdout", 126 | "output_type": "stream", 127 | "text": [ 128 | " μ σ²\n", 129 | "μ 0.054 0.000\n", 130 | "σ² 0.000 2.304\n", 131 | "\n" 132 | ] 133 | } 134 | ], 135 | "source": [ 136 | "V = [σ² 0; #variance-covariance matrix of the estimates of [μ,σ²]\n", 137 | " 0 2*abs2(σ²)]/T\n", 138 | "\n", 139 | "printmat(V;rowNames=momNames,colNames=momNames)" 140 | ] 141 | }, 142 | { 143 | "cell_type": "markdown", 144 | "metadata": {}, 145 | "source": [ 146 | "## The Sharpe Ratio and Its Derivatives\n", 147 | "\n", 148 | "The Sharpe ratio and its derivatives (with respect to the parameters of the\n", 149 | "Sharpe ratio) are\n", 150 | "\n", 151 | "$SR =\\frac{\\mu}{\\sigma},\\: \\text{where}\\: \\beta=(\\mu,\\sigma^2)$\n", 152 | "\n", 153 | "Let $f(\\beta)$ denote the Sharpe ratio where $\\beta$ is a vector of parameters \n", 154 | "consisting of the mean and the variance ($\\mu,\\sigma^2$). The derivatives are then\n", 155 | "\n", 156 | "$\\frac{\\partial f(\\beta)}{\\partial\\beta^{\\prime}} \n", 157 | "= \\begin{bmatrix}\n", 158 | "\\frac{1}{\\sigma} & \\frac{-\\mu}{2 \\sigma^3}\n", 159 | "\\end{bmatrix}$\n", 160 | "\n", 161 | "We will refer to the matrix of derivatives as $P$." 162 | ] 163 | }, 164 | { 165 | "cell_type": "code", 166 | "execution_count": 7, 167 | "metadata": {}, 168 | "outputs": [ 169 | { 170 | "data": { 171 | "text/plain": [ 172 | "SRFn" 173 | ] 174 | }, 175 | "execution_count": 7, 176 | "metadata": {}, 177 | "output_type": "execute_result" 178 | } 179 | ], 180 | "source": [ 181 | "\"\"\"\n", 182 | " SRFn(μ,σ²)\n", 183 | "\n", 184 | "Calculate the Sharpe ratio from the mean μ and variance σ²\n", 185 | "\n", 186 | "\"\"\"\n", 187 | "function SRFn(μ,σ²)\n", 188 | " σ = sqrt(σ²)\n", 189 | " SR = μ/σ\n", 190 | " P = hcat(1/σ, -μ/(2*σ^3)) #Jacobian of SR, 1x2\n", 191 | " return SR, P\n", 192 | "end" 193 | ] 194 | }, 195 | { 196 | "cell_type": "code", 197 | "execution_count": 8, 198 | "metadata": {}, 199 | "outputs": [ 200 | { 201 | "name": "stdout", 202 | "output_type": "stream", 203 | "text": [ 204 | "Sharpe ratio: 0.131\n", 205 | "\n", 206 | "\u001b[34m\u001b[1mDerivatives of Sharpe ratio function wrt:\u001b[22m\u001b[39m\n", 207 | " μ σ²\n", 208 | " 0.217 -0.003\n", 209 | "\n" 210 | ] 211 | } 212 | ], 213 | "source": [ 214 | "(SR,P) = SRFn(μ,σ²)\n", 215 | "\n", 216 | "printlnPs(\"Sharpe ratio: \",SR)\n", 217 | "\n", 218 | "printblue(\"\\nDerivatives of Sharpe ratio function wrt:\")\n", 219 | "printmat(P,colNames=momNames)" 220 | ] 221 | }, 222 | { 223 | "cell_type": "markdown", 224 | "metadata": {}, 225 | "source": [ 226 | "## Applying the Delta Method\n", 227 | "\n", 228 | "\n", 229 | "Recall that if\n", 230 | "\n", 231 | "$\\hat{\\beta} \\sim N(\\beta_{0},V),$\n", 232 | "\n", 233 | "then the distribution of the function $f(\\hat{\\beta})$ is asymptotically\n", 234 | "\n", 235 | "$f(\\hat{\\beta}) \\sim N(f(\\beta_{0}),PVP')$\n", 236 | "\n", 237 | "where $P$ are the derivatives of $f(\\beta)$." 238 | ] 239 | }, 240 | { 241 | "cell_type": "code", 242 | "execution_count": 9, 243 | "metadata": {}, 244 | "outputs": [ 245 | { 246 | "name": "stdout", 247 | "output_type": "stream", 248 | "text": [ 249 | "\u001b[34m\u001b[1mResults from the delta method:\u001b[22m\u001b[39m\n", 250 | " SR Std(SR) t-stat\n", 251 | " 0.131 0.051 2.567\n", 252 | "\n" 253 | ] 254 | } 255 | ], 256 | "source": [ 257 | "Std_SR = sqrt(only(P*V*P')) #only() to convert from 1x1 matrix to scalar\n", 258 | "tstat = SR/Std_SR\n", 259 | "\n", 260 | "printblue(\"Results from the delta method:\")\n", 261 | "printmat([SR Std_SR tstat],colNames=[\"SR\",\"Std(SR)\",\"t-stat\"])" 262 | ] 263 | }, 264 | { 265 | "cell_type": "markdown", 266 | "metadata": {}, 267 | "source": [ 268 | "## A Function for the Delta Method (extra)\n", 269 | "\n", 270 | "is included below. It uses numerical derivatives from the `FiniteDiff.jl` package. \n", 271 | "\n", 272 | "To use this, first write a function that takes `(β,x)` as inputs (see `SRFn2(β,x)` below), where `β` is a vector of the parameters and `x` any data needed (for the Sharpe ratio, no data is needed). " 273 | ] 274 | }, 275 | { 276 | "cell_type": "code", 277 | "execution_count": 10, 278 | "metadata": {}, 279 | "outputs": [ 280 | { 281 | "data": { 282 | "text/markdown": [ 283 | "```\n", 284 | "DeltaMethod(fn::Function,β,V,x=NaN)\n", 285 | "```\n", 286 | "\n", 287 | "Apply the delta method on the function `fn(β,x)`\n", 288 | "\n", 289 | "### Input\n", 290 | "\n", 291 | " * `fn::Function`: of the type fn(β,x)\n", 292 | " * `β::Vector`: with parameters\n", 293 | " * `V::Matrix`: Cov(β)\n", 294 | " * `x::VecOrMat`: data (if any is needed)\n", 295 | "\n", 296 | "### Requires\n", 297 | "\n", 298 | " * `using FiniteDiff: finite_difference_jacobian as jacobian`\n" 299 | ] 300 | }, 301 | "metadata": {}, 302 | "output_type": "display_data" 303 | } 304 | ], 305 | "source": [ 306 | "@doc2 DeltaMethod" 307 | ] 308 | }, 309 | { 310 | "cell_type": "code", 311 | "execution_count": 11, 312 | "metadata": {}, 313 | "outputs": [ 314 | { 315 | "name": "stdout", 316 | "output_type": "stream", 317 | "text": [ 318 | "function DeltaMethod(fn::Function,β,V,x=NaN)\n", 319 | " P = jacobian(b->fn(b,x),β) #numerical Jacobian\n", 320 | " Cov_fn = P*V*P'\n", 321 | " return Cov_fn\n", 322 | "end\n" 323 | ] 324 | } 325 | ], 326 | "source": [ 327 | "using CodeTracking\n", 328 | "println(@code_string DeltaMethod(cos,[1],[1]))" 329 | ] 330 | }, 331 | { 332 | "cell_type": "code", 333 | "execution_count": 12, 334 | "metadata": {}, 335 | "outputs": [], 336 | "source": [ 337 | "\"\"\"\n", 338 | " SRFn2(β,x)\n", 339 | "\n", 340 | "Function for Sharpe ratio in terms of the vector β. No derivatives\n", 341 | "\"\"\"\n", 342 | "function SRFn2(β,x=NaN)\n", 343 | " (μ,σ²) = β\n", 344 | " σ = sqrt(σ²)\n", 345 | " SR = μ/σ\n", 346 | " return SR\n", 347 | "end;" 348 | ] 349 | }, 350 | { 351 | "cell_type": "code", 352 | "execution_count": 13, 353 | "metadata": {}, 354 | "outputs": [ 355 | { 356 | "name": "stdout", 357 | "output_type": "stream", 358 | "text": [ 359 | "\u001b[34m\u001b[1mStd of SR from DeltaMethod():\u001b[22m\u001b[39m\n", 360 | " 0.051\n", 361 | "\n" 362 | ] 363 | } 364 | ], 365 | "source": [ 366 | "Var_SR = DeltaMethod(SRFn2,[μ,σ²],V)\n", 367 | "\n", 368 | "printblue(\"Std of SR from DeltaMethod():\")\n", 369 | "printmat(sqrt(only(Var_SR)))" 370 | ] 371 | }, 372 | { 373 | "cell_type": "code", 374 | "execution_count": null, 375 | "metadata": {}, 376 | "outputs": [], 377 | "source": [] 378 | } 379 | ], 380 | "metadata": { 381 | "@webio": { 382 | "lastCommId": null, 383 | "lastKernelId": null 384 | }, 385 | "anaconda-cloud": {}, 386 | "kernelspec": { 387 | "display_name": "Julia 1.11.5", 388 | "language": "julia", 389 | "name": "julia-1.11" 390 | }, 391 | "language_info": { 392 | "file_extension": ".jl", 393 | "mimetype": "application/julia", 394 | "name": "julia", 395 | "version": "1.11.5" 396 | } 397 | }, 398 | "nbformat": 4, 399 | "nbformat_minor": 4 400 | } 401 | -------------------------------------------------------------------------------- /Ch05_OLS_System.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": { 6 | "tags": [] 7 | }, 8 | "source": [ 9 | "# OLS on a System of Regressions\n", 10 | "\n", 11 | "This notebook illustrates how to estimate a system of regressions with OLS - and to test (coefficients) across the regressions." 12 | ] 13 | }, 14 | { 15 | "cell_type": "markdown", 16 | "metadata": {}, 17 | "source": [ 18 | "## Load Packages and Extra Functions\n", 19 | "\n", 20 | "The key function `OlsSure()` is from the (local) `FinEcmt_OLS` module." 21 | ] 22 | }, 23 | { 24 | "cell_type": "code", 25 | "execution_count": 1, 26 | "metadata": {}, 27 | "outputs": [], 28 | "source": [ 29 | "MyModulePath = joinpath(pwd(),\"src\")\n", 30 | "!in(MyModulePath,LOAD_PATH) && push!(LOAD_PATH,MyModulePath)\n", 31 | "using FinEcmt_OLS" 32 | ] 33 | }, 34 | { 35 | "cell_type": "code", 36 | "execution_count": 2, 37 | "metadata": {}, 38 | "outputs": [], 39 | "source": [ 40 | "#=\n", 41 | "include(joinpath(pwd(),\"src\",\"FinEcmt_OLS.jl\"))\n", 42 | "using .FinEcmt_OLS\n", 43 | "=#" 44 | ] 45 | }, 46 | { 47 | "cell_type": "code", 48 | "execution_count": 3, 49 | "metadata": { 50 | "tags": [] 51 | }, 52 | "outputs": [], 53 | "source": [ 54 | "using DelimitedFiles, LinearAlgebra, Distributions" 55 | ] 56 | }, 57 | { 58 | "cell_type": "markdown", 59 | "metadata": {}, 60 | "source": [ 61 | "## Loading Data" 62 | ] 63 | }, 64 | { 65 | "cell_type": "code", 66 | "execution_count": 4, 67 | "metadata": { 68 | "tags": [] 69 | }, 70 | "outputs": [ 71 | { 72 | "data": { 73 | "text/plain": [ 74 | "(388, 5)" 75 | ] 76 | }, 77 | "execution_count": 4, 78 | "metadata": {}, 79 | "output_type": "execute_result" 80 | } 81 | ], 82 | "source": [ 83 | "x = readdlm(\"Data/FFmFactorsPs.csv\",',',skipstart=1)\n", 84 | "(Rme,Rf) = (x[:,2],x[:,5]) #market excess return, interest rate\n", 85 | "\n", 86 | "x = readdlm(\"Data/FF25Ps.csv\",',') #no header line\n", 87 | "R = x[:,2:end] #returns for 25 FF portfolios\n", 88 | "Re = R .- Rf #excess returns for the 25 FF portfolios\n", 89 | "Re = Re[:,[1,7,13,19,25]] #use just 5 assets to make the printing easier\n", 90 | "\n", 91 | "(T,n) = size(Re) #number of observations and test assets" 92 | ] 93 | }, 94 | { 95 | "cell_type": "markdown", 96 | "metadata": {}, 97 | "source": [ 98 | "## A Function for Joint Estimation of Several Regressions (OLS)\n", 99 | "\n", 100 | "Consider the linear regressions\n", 101 | "\n", 102 | "$y_{it}=x_{t}^{\\prime}\\beta_i+u_{it},$\n", 103 | "\n", 104 | "where $i=1,2,..,n$ indicates $n$ different dependent variables. The $K$ regressors are the *same* across the $n$ regressions. (This is often called SURE, Seemingly Unrelated Regression Equations.)\n", 105 | "\n", 106 | "For the case of two regressions, the variance-covariance matrix has the following structure. \n", 107 | "Stack the $\\beta$ coefficients into a vector (from equation 1 first, then from equation 2.) Then, the variance-covariance matrix is\n", 108 | "\n", 109 | "$\\mathrm{Var}\\left(\n", 110 | "\t\\begin{bmatrix}\n", 111 | "\t\t\\hat{\\beta}_{1}\\\\\n", 112 | "\t\t\\hat{\\beta}_{2}%\n", 113 | "\t\\end{bmatrix}\n", 114 | "\t\\right) =\n", 115 | "\t\\begin{bmatrix}\n", 116 | "\t\tS_{xx}^{-1} & \\mathbf{0}\\\\\n", 117 | "\t\t\\mathbf{0} & S_{xx}^{-1}\n", 118 | "\t\\end{bmatrix}\n", 119 | "\t\\Omega\n", 120 | "\t\\begin{bmatrix}\n", 121 | "\t\tS_{xx}^{-1} & \\mathbf{0}\\\\\n", 122 | "\t\t\\mathbf{0} & S_{xx}^{-1}\n", 123 | "\t\\end{bmatrix}$\n", 124 | "\n", 125 | "where \n", 126 | "\n", 127 | "$\\Omega = \\mathrm{Var}\\left(\n", 128 | "\\sum\\nolimits_{t=1}^{T}\n", 129 | "\\begin{bmatrix}\n", 130 | "\tx_{t}u_{1t}\\\\\n", 131 | "\tx_{t}u_{2t}\n", 132 | "\\end{bmatrix}\n", 133 | "\\right)$\n", 134 | "\n", 135 | "Notice that $x_{t}u_{1t}$ is a vector with $K$ elements (as many as there are regressors) and $x_{t}u_{2t}$ is similar. The $\\Omega$ matrix is thus $2K \\times 2K$.\n", 136 | "\n", 137 | "The case of $n$ regressions (rather than 2) involves creating similar matrices. This is implemented in the `OlsSure()` function." 138 | ] 139 | }, 140 | { 141 | "cell_type": "code", 142 | "execution_count": 5, 143 | "metadata": {}, 144 | "outputs": [ 145 | { 146 | "data": { 147 | "text/markdown": [ 148 | "```\n", 149 | "OlsSure(Y,X,NWQ=false,m=0)\n", 150 | "```\n", 151 | "\n", 152 | "LS of `Y` on `X`; where `Y` is Txn, and `X` is the same for all regressions\n", 153 | "\n", 154 | "### Input\n", 155 | "\n", 156 | " * `Y::Matrix`: Txn, the n dependent variables\n", 157 | " * `X::Matrix`: Txk matrix of regressors (including deterministic ones)\n", 158 | " * `NWQ:Bool`: if true, then Newey-West's covariance matrix is used, otherwise Gauss-Markov\n", 159 | " * `m::Int`: scalar, bandwidth in Newey-West\n", 160 | "\n", 161 | "### Output\n", 162 | "\n", 163 | " * `b::Matrix`: kxn, regression coefficients (one column for each `Y[:,i]`)\n", 164 | " * `u::Matrix`: Txn, residuals Y - Yhat\n", 165 | " * `Yhat::Matrix`: Txn, fitted values X*b\n", 166 | " * `V::Matrix`: covariance matrix of θ=vec(b)\n", 167 | " * `R²::Matrix`: 1xn matrix, R² values\n" 168 | ] 169 | }, 170 | "metadata": {}, 171 | "output_type": "display_data" 172 | } 173 | ], 174 | "source": [ 175 | "@doc2 OlsSure" 176 | ] 177 | }, 178 | { 179 | "cell_type": "code", 180 | "execution_count": 6, 181 | "metadata": {}, 182 | "outputs": [ 183 | { 184 | "name": "stdout", 185 | "output_type": "stream", 186 | "text": [ 187 | "function OlsSure(Y,X,NWQ=false,m=0)\n", 188 | "\n", 189 | " (T,n) = (size(Y,1),size(Y,2))\n", 190 | " k = size(X,2)\n", 191 | "\n", 192 | " b = X\\Y\n", 193 | " Yhat = X*b\n", 194 | " u = Y - Yhat\n", 195 | "\n", 196 | " Sxx = X'X\n", 197 | "\n", 198 | " if NWQ\n", 199 | " g = hcat([X.*u[:,i] for i=1:n]...) #hcat(X.*u[:,1],X.*u[:,2], etc)\n", 200 | " S = CovNW(g,m) #Newey-West covariance matrix\n", 201 | " SxxM_1 = kron(I(n),inv(Sxx))\n", 202 | " V = SxxM_1 * S * SxxM_1\n", 203 | " else\n", 204 | " V = kron(cov(u),inv(Sxx)) #traditional covariance matrix, Gauss-Markov\n", 205 | " end\n", 206 | "\n", 207 | " R² = 1 .- var(u,dims=1)./var(Y,dims=1)\n", 208 | "\n", 209 | " return b, u, Yhat, V, R²\n", 210 | "\n", 211 | "end\n" 212 | ] 213 | } 214 | ], 215 | "source": [ 216 | "using CodeTracking\n", 217 | "println(@code_string OlsSure([1],[1])) #print the source code" 218 | ] 219 | }, 220 | { 221 | "cell_type": "markdown", 222 | "metadata": {}, 223 | "source": [ 224 | "## Using the Function" 225 | ] 226 | }, 227 | { 228 | "cell_type": "code", 229 | "execution_count": 7, 230 | "metadata": { 231 | "tags": [] 232 | }, 233 | "outputs": [ 234 | { 235 | "name": "stdout", 236 | "output_type": "stream", 237 | "text": [ 238 | "\u001b[34m\u001b[1mCAPM regressions: α is the intecept, γ the coeff on Rme\u001b[22m\u001b[39m\n", 239 | "\n", 240 | "coeffs\n", 241 | " asset 1 asset 2 asset 3 asset 4 asset 5\n", 242 | "α -0.504 0.153 0.305 0.279 0.336\n", 243 | "γ 1.341 1.169 0.994 0.943 0.849\n", 244 | "\n", 245 | "t-stats\n", 246 | " asset 1 asset 2 asset 3 asset 4 asset 5\n", 247 | "α -1.720 1.045 2.436 2.094 2.070\n", 248 | "γ 22.322 30.609 28.416 23.209 17.242\n", 249 | "\n" 250 | ] 251 | } 252 | ], 253 | "source": [ 254 | "(b,u,yhat,V,R²) = OlsSure(Re,[ones(T) Rme],true)\n", 255 | "Stdb = sqrt.(reshape(diag(V),2,n)) #V = Cov(vec(b)), in vec(b) 1:2 are for asset 1, 3:4 for asset 2,...\n", 256 | "tstat = b./Stdb\n", 257 | "\n", 258 | "printblue(\"CAPM regressions: α is the intecept, γ the coeff on Rme\\n\")\n", 259 | "assetNames = [string(\"asset \",i) for i=1:n]\n", 260 | "xNames = [\"c\",\"Rme\"]\n", 261 | "\n", 262 | "println(\"coeffs\")\n", 263 | "printmat(b;colNames=assetNames,rowNames=[\"α\",\"γ\"])\n", 264 | "\n", 265 | "println(\"t-stats\")\n", 266 | "printmat(tstat;colNames=assetNames,rowNames=[\"α\",\"γ\"])" 267 | ] 268 | }, 269 | { 270 | "cell_type": "markdown", 271 | "metadata": {}, 272 | "source": [ 273 | "## Testing Across Regressions\n", 274 | "\n", 275 | "To test across regressions, we first stack the point estimates into a vector by `θ = vec(b)`.\n", 276 | "\n", 277 | "The test below applies the usual $\\chi^2$ test, where \n", 278 | "\n", 279 | "$H_0: R\\theta=q,$\n", 280 | "\n", 281 | "where $R$ is a $J \\times k$ matrix and $q$ is a $J$-vector. To test this, use\n", 282 | "\n", 283 | "$(R\\theta-q)^{\\prime}(RVR^{\\prime}) ^{-1}(R\\theta-q)\\overset{d}{\\rightarrow}\\chi_{J}^{2}.$\n", 284 | "\n", 285 | "The $R$ matrix clearly depends on which hypotheses that we want to test.\n", 286 | "\n", 287 | "The next cell creates a matrix of coefficient names that will help us see how the results are organised." 288 | ] 289 | }, 290 | { 291 | "cell_type": "code", 292 | "execution_count": 8, 293 | "metadata": { 294 | "tags": [] 295 | }, 296 | "outputs": [ 297 | { 298 | "name": "stdout", 299 | "output_type": "stream", 300 | "text": [ 301 | " α₁ α₂ α₃ α₄ α₅\n", 302 | " γ₁ γ₂ γ₃ γ₄ γ₅\n", 303 | "\n" 304 | ] 305 | } 306 | ], 307 | "source": [ 308 | "bNames = fill(\"\",2,n) #matrix of coef names, subscript for the asset number\n", 309 | "for i = 1:n\n", 310 | " bNames[:,i] = [string(\"α\",'₀'+i),string(\"γ\",'₀'+i)] #'₀'+1 to get ₁\n", 311 | "end\n", 312 | "printmat(bNames)" 313 | ] 314 | }, 315 | { 316 | "cell_type": "code", 317 | "execution_count": 9, 318 | "metadata": { 319 | "tags": [] 320 | }, 321 | "outputs": [ 322 | { 323 | "name": "stdout", 324 | "output_type": "stream", 325 | "text": [ 326 | "\u001b[34m\u001b[1mstacking the coeffs into a vector:\u001b[22m\u001b[39m\n", 327 | "α₁ -0.504\n", 328 | "γ₁ 1.341\n", 329 | "α₂ 0.153\n", 330 | "γ₂ 1.169\n", 331 | "α₃ 0.305\n", 332 | "γ₃ 0.994\n", 333 | "α₄ 0.279\n", 334 | "γ₄ 0.943\n", 335 | "α₅ 0.336\n", 336 | "γ₅ 0.849\n", 337 | "\n" 338 | ] 339 | } 340 | ], 341 | "source": [ 342 | "θ = vec(b)\n", 343 | "\n", 344 | "printblue(\"stacking the coeffs into a vector:\")\n", 345 | "printmat(θ;rowNames=vec(bNames))" 346 | ] 347 | }, 348 | { 349 | "cell_type": "code", 350 | "execution_count": 10, 351 | "metadata": { 352 | "tags": [] 353 | }, 354 | "outputs": [ 355 | { 356 | "name": "stdout", 357 | "output_type": "stream", 358 | "text": [ 359 | "\u001b[34m\u001b[1mThe R matrix:\u001b[22m\u001b[39m\n", 360 | "hypothesis 1 1 0 0 0 0 0 0 0 0 0\n", 361 | "hypothesis 2 0 0 1 0 0 0 0 0 0 0\n", 362 | "hypothesis 3 0 0 0 0 1 0 0 0 0 0\n", 363 | "hypothesis 4 0 0 0 0 0 0 1 0 0 0\n", 364 | "hypothesis 5 0 0 0 0 0 0 0 0 1 0\n", 365 | "\n", 366 | "The number of hypotheses that we test: 5 \n", 367 | "\n", 368 | "\u001b[34m\u001b[1mR*vec(b) - q:\u001b[22m\u001b[39m\n", 369 | "hypothesis 1 -0.504\n", 370 | "hypothesis 2 0.153\n", 371 | "hypothesis 3 0.305\n", 372 | "hypothesis 4 0.279\n", 373 | "hypothesis 5 0.336\n", 374 | "\n" 375 | ] 376 | } 377 | ], 378 | "source": [ 379 | "#R = [1 0 -1 0 zeros(1,2*n-4)] #are intercepts the same for assets 1 and 2?\n", 380 | "R = zeros(n,2*n) #are all intercepts == 0?\n", 381 | "for i in 1:n\n", 382 | " R[i,(i-1)*2+1] = 1\n", 383 | "end\n", 384 | "\n", 385 | "printblue(\"The R matrix:\")\n", 386 | "hypNames = string.(\"hypothesis \",1:size(R,1))\n", 387 | "printmat(R;colNames=bNames,rowNames=hypNames,width=4,prec=0)\n", 388 | "\n", 389 | "J = size(R,1)\n", 390 | "printlnPs(\"The number of hypotheses that we test: $J \\n\")\n", 391 | "\n", 392 | "q = zeros(J)\n", 393 | "\n", 394 | "printblue(\"R*vec(b) - q:\")\n", 395 | "printmat(R*θ-q;rowNames=hypNames)" 396 | ] 397 | }, 398 | { 399 | "cell_type": "code", 400 | "execution_count": 11, 401 | "metadata": { 402 | "tags": [] 403 | }, 404 | "outputs": [ 405 | { 406 | "name": "stdout", 407 | "output_type": "stream", 408 | "text": [ 409 | "Joint test of all hypotheses\n", 410 | "test statistic 10.707\n", 411 | "10% crit value 9.236\n", 412 | "\n" 413 | ] 414 | } 415 | ], 416 | "source": [ 417 | "println(\"Joint test of all hypotheses\")\n", 418 | "\n", 419 | "Γ = R*V*R'\n", 420 | "test_stat = (R*θ - q)'inv(Γ)*(R*θ - q)\n", 421 | "\n", 422 | "critval = quantile(Chisq(J),0.9) #10% critical value\n", 423 | "\n", 424 | "printmat([test_stat,critval];rowNames=[\"test statistic\",\"10% crit value\"])" 425 | ] 426 | }, 427 | { 428 | "cell_type": "code", 429 | "execution_count": null, 430 | "metadata": {}, 431 | "outputs": [], 432 | "source": [] 433 | } 434 | ], 435 | "metadata": { 436 | "@webio": { 437 | "lastCommId": null, 438 | "lastKernelId": null 439 | }, 440 | "anaconda-cloud": {}, 441 | "kernelspec": { 442 | "display_name": "Julia 1.11.5", 443 | "language": "julia", 444 | "name": "julia-1.11" 445 | }, 446 | "language_info": { 447 | "file_extension": ".jl", 448 | "mimetype": "application/julia", 449 | "name": "julia", 450 | "version": "1.11.5" 451 | } 452 | }, 453 | "nbformat": 4, 454 | "nbformat_minor": 4 455 | } 456 | -------------------------------------------------------------------------------- /Ch06_TestingCAPM.txt: -------------------------------------------------------------------------------- 1 | See the FinancialTheoryMSc repository -------------------------------------------------------------------------------- /Ch09b_Bootstrap.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Bootstrapping a Linear Regression\n", 8 | "\n", 9 | "This notebook implements both a traditional bootstrap and a block bootstrap in order to get more robust standard errors of OLS coefficients." 10 | ] 11 | }, 12 | { 13 | "cell_type": "markdown", 14 | "metadata": {}, 15 | "source": [ 16 | "## Load Packages and Extra Functions\n", 17 | "\n", 18 | "The key functions (for doing OLS and block bootstrap) are from the (local) `FinEcmt_OLS` module." 19 | ] 20 | }, 21 | { 22 | "cell_type": "code", 23 | "execution_count": 1, 24 | "metadata": {}, 25 | "outputs": [], 26 | "source": [ 27 | "MyModulePath = joinpath(pwd(),\"src\")\n", 28 | "!in(MyModulePath,LOAD_PATH) && push!(LOAD_PATH,MyModulePath)\n", 29 | "using FinEcmt_OLS" 30 | ] 31 | }, 32 | { 33 | "cell_type": "code", 34 | "execution_count": 2, 35 | "metadata": {}, 36 | "outputs": [], 37 | "source": [ 38 | "#=\n", 39 | "include(joinpath(pwd(),\"src\",\"FinEcmt_OLS.jl\"))\n", 40 | "using .FinEcmt_OLS\n", 41 | "=#" 42 | ] 43 | }, 44 | { 45 | "cell_type": "code", 46 | "execution_count": 3, 47 | "metadata": { 48 | "tags": [] 49 | }, 50 | "outputs": [], 51 | "source": [ 52 | "using DelimitedFiles, Statistics, LinearAlgebra, Random" 53 | ] 54 | }, 55 | { 56 | "cell_type": "markdown", 57 | "metadata": {}, 58 | "source": [ 59 | "## Loading Data\n", 60 | "\n", 61 | "The regressions used below are of the type\n", 62 | "\n", 63 | "$y_t = x_t'b + u_t$\n", 64 | "\n", 65 | "where $y_t$ is monthly data on 1-year excess returns on a 5-year bond (so there is an 11-month overlap between two data points) and $x_t$ includes a constant and the lagged 1-year forward rates for investments starting (0,1,2,3,4) years ahead." 66 | ] 67 | }, 68 | { 69 | "cell_type": "code", 70 | "execution_count": 4, 71 | "metadata": { 72 | "tags": [] 73 | }, 74 | "outputs": [ 75 | { 76 | "name": "stdout", 77 | "output_type": "stream", 78 | "text": [ 79 | "T = 580, n = 1, K = 6\n" 80 | ] 81 | } 82 | ], 83 | "source": [ 84 | "xx = readdlm(\"Data/BondPremiaPs.csv\",',',skipstart=1)\n", 85 | "rx = xx[:,5] #bond excess returns\n", 86 | "f = xx[:,6:end] #forward rates, several columns\n", 87 | "\n", 88 | "x = [ones(size(f,1)-12) f[1:end-12,:]] #regressors\n", 89 | "y = rx[13:end] #dependent variable\n", 90 | "\n", 91 | "\n", 92 | "(T,n) = (size(y,1),size(y,2)) #no. obs and no. test assets\n", 93 | "K = size(x,2) #no. regressors\n", 94 | "\n", 95 | "println(\"T = $T, n = $n, K = $K\")" 96 | ] 97 | }, 98 | { 99 | "cell_type": "markdown", 100 | "metadata": {}, 101 | "source": [ 102 | "## Point Estimates" 103 | ] 104 | }, 105 | { 106 | "cell_type": "code", 107 | "execution_count": 5, 108 | "metadata": { 109 | "tags": [] 110 | }, 111 | "outputs": [ 112 | { 113 | "name": "stdout", 114 | "output_type": "stream", 115 | "text": [ 116 | "\u001b[34m\u001b[1mOLS estimates:\u001b[22m\u001b[39m\n", 117 | "\n", 118 | " coeff std (trad.)\n", 119 | "x₁ -3.306 0.824\n", 120 | "x₂ -4.209 0.712\n", 121 | "x₃ 10.627 4.513\n", 122 | "x₄ -14.397 12.896\n", 123 | "x₅ 7.096 15.876\n", 124 | "x₆ 1.284 6.904\n", 125 | "\n" 126 | ] 127 | } 128 | ], 129 | "source": [ 130 | "(bLS,u,yhat,Covb,) = OlsGM(y,x) #OLS estimate and traditional std errors\n", 131 | "StdbLS = sqrt.(diag(Covb))\n", 132 | "\n", 133 | "printblue(\"OLS estimates:\\n\")\n", 134 | "rowNames = [string(\"x\",'₀'+i) for i=1:K] #'₀'+1 to get ₁\n", 135 | "printmat(bLS,StdbLS;colNames=[\"coeff\",\"std (trad.)\"],rowNames=rowNames,width=15)" 136 | ] 137 | }, 138 | { 139 | "cell_type": "markdown", 140 | "metadata": {}, 141 | "source": [ 142 | "## Standard Bootstrap (I)\n", 143 | "\n", 144 | "In each loop, a new series of residuals, $\\tilde{u}_{t}$, is created by drawing (with replacement) values from the fitted residuals (from the estimates in earlier cells). Then, simulated values of the dependent variable are created as \n", 145 | "\n", 146 | "$\\tilde{y}_{t}=x_{t}^{\\prime}\\beta+\\tilde{u}_{t}$ \n", 147 | "\n", 148 | "and we redo the estimation on ($\\tilde{y}_{t},x_{t}$). Notice that $x_t$ is the same as in the data.\n", 149 | "\n", 150 | "This is repeated `NSim` times." 151 | ] 152 | }, 153 | { 154 | "cell_type": "code", 155 | "execution_count": 6, 156 | "metadata": { 157 | "tags": [] 158 | }, 159 | "outputs": [ 160 | { 161 | "name": "stdout", 162 | "output_type": "stream", 163 | "text": [ 164 | "\u001b[34m\u001b[1mCoefficients:\u001b[22m\u001b[39m\n", 165 | " OLS avg. bootstr\n", 166 | "x₁ -3.306 -3.315\n", 167 | "x₂ -4.209 -4.225\n", 168 | "x₃ 10.627 10.693\n", 169 | "x₄ -14.397 -14.619\n", 170 | "x₅ 7.096 7.403\n", 171 | "x₆ 1.284 1.150\n", 172 | "\n", 173 | "\u001b[34m\u001b[1mStd:\u001b[22m\u001b[39m\n", 174 | " trad. bootstrap 1\n", 175 | "x₁ 0.824 0.828\n", 176 | "x₂ 0.712 0.722\n", 177 | "x₃ 4.513 4.576\n", 178 | "x₄ 12.896 13.011\n", 179 | "x₅ 15.876 15.924\n", 180 | "x₆ 6.904 6.891\n", 181 | "\n", 182 | "\u001b[31m\u001b[1mThe results from these bootstrap are similar to standard OLS, but...see below\u001b[22m\u001b[39m\n" 183 | ] 184 | } 185 | ], 186 | "source": [ 187 | "NSim = 2000 #no. of simulations\n", 188 | "Random.seed!(123)\n", 189 | "\n", 190 | "bBoot = fill(NaN,NSim,K)\n", 191 | "for i = 1:NSim #loop over simulations\n", 192 | " #local t_i, utilde, ytilde #local/global is needed in script\n", 193 | " t_i = rand(1:T,T) #T random numbers from 1:T (with replacement)\n", 194 | " #println(t_i) #uncomment to see which rows that are picked out\n", 195 | " utilde = u[t_i]\n", 196 | " ytilde = x*bLS + utilde[1:T]\n", 197 | " bBoot[i,:] = OlsGM(ytilde,x)[1]\n", 198 | "end\n", 199 | "\n", 200 | "printblue(\"Coefficients:\")\n", 201 | "xx = [bLS mean(bBoot,dims=1)']\n", 202 | "printmat(xx;colNames=[\"OLS\",\"avg. bootstr\"],rowNames=rowNames,width=20)\n", 203 | "\n", 204 | "printblue(\"Std:\")\n", 205 | "xx = [StdbLS std(bBoot,dims=1)']\n", 206 | "printmat(xx;colNames=[\"trad.\",\"bootstrap 1\"],rowNames=rowNames,width=20)\n", 207 | "\n", 208 | "printred(\"The results from these bootstrap are similar to standard OLS, but...see below\")" 209 | ] 210 | }, 211 | { 212 | "cell_type": "markdown", 213 | "metadata": {}, 214 | "source": [ 215 | "## Block Bootstrap (II)\n", 216 | "\n", 217 | "To handle autocorrelated residuals, we now consider a *block bootstrap*.\n", 218 | "\n", 219 | "\n", 220 | "In each loop, we initially define a random starting point (observation number) of each block (by using the `rand()` function). For instance, if we randomly draw that the blocks should start with observations $27$ and $35$ and have decided that each block should contain $10$ data points, then the artificial sample will pick out observations $27-36$ and $35-44$. Clearly, some observations can be in several blocks. This is done by the `DrawBlocks(T,BlockSize)` function, included above.\n", 221 | "\n", 222 | "Once we have $T$ data points, we define a new series of residuals, $\\tilde{u}_{t}$.\n", 223 | "\n", 224 | "Then, new values of the dependent variable are created as \n", 225 | "\n", 226 | "$\\tilde{y}_{t}=x_{t}^{\\prime}\\beta+\\tilde{u}_{t}$ \n", 227 | "\n", 228 | "and we redo the estimation on ($\\tilde{y}_{t},x_{t}$)." 229 | ] 230 | }, 231 | { 232 | "cell_type": "code", 233 | "execution_count": 7, 234 | "metadata": {}, 235 | "outputs": [ 236 | { 237 | "data": { 238 | "text/markdown": [ 239 | "```\n", 240 | "DrawBlocks(T,BlockSize)\n", 241 | "```\n", 242 | "\n", 243 | "Draw a T-vector of indices `v` that can be used to create bootstrap residuals. The indices are such that they form blocks of length `BlockSize`.\n" 244 | ] 245 | }, 246 | "metadata": {}, 247 | "output_type": "display_data" 248 | } 249 | ], 250 | "source": [ 251 | "@doc2 DrawBlocks" 252 | ] 253 | }, 254 | { 255 | "cell_type": "code", 256 | "execution_count": 8, 257 | "metadata": {}, 258 | "outputs": [], 259 | "source": [ 260 | "#using CodeTracking\n", 261 | "#println(@code_string DrawBlocks(1,1)) #print the source code" 262 | ] 263 | }, 264 | { 265 | "cell_type": "code", 266 | "execution_count": 9, 267 | "metadata": { 268 | "tags": [] 269 | }, 270 | "outputs": [ 271 | { 272 | "name": "stdout", 273 | "output_type": "stream", 274 | "text": [ 275 | "\u001b[34m\u001b[1millustrating how to draw 30 observations, in blocks of 10:\u001b[22m\u001b[39m\n", 276 | "\n", 277 | " block 1 block 2 block 3\n", 278 | " 7 11 19 \n", 279 | " 8 12 20 \n", 280 | " 9 13 21 \n", 281 | " 10 14 22 \n", 282 | " 11 15 23 \n", 283 | " 12 16 24 \n", 284 | " 13 17 25 \n", 285 | " 14 18 26 \n", 286 | " 15 19 27 \n", 287 | " 16 20 28 \n", 288 | "\n" 289 | ] 290 | } 291 | ], 292 | "source": [ 293 | "Random.seed!(1234567)\n", 294 | "BlockSize = 10 #size of blocks\n", 295 | "\n", 296 | "printblue(\"illustrating how to draw 30 observations, in blocks of $BlockSize:\\n\")\n", 297 | "t_i = DrawBlocks(30,BlockSize)\n", 298 | "\n", 299 | "printmat(reshape(t_i,BlockSize,:);colNames=[\"block 1\",\"block 2\",\"block 3\"])" 300 | ] 301 | }, 302 | { 303 | "cell_type": "code", 304 | "execution_count": 10, 305 | "metadata": { 306 | "tags": [] 307 | }, 308 | "outputs": [ 309 | { 310 | "name": "stdout", 311 | "output_type": "stream", 312 | "text": [ 313 | "\u001b[34m\u001b[1mStd:\u001b[22m\u001b[39m\n", 314 | " trad. bootstrap 1 block bootstr\n", 315 | "x₁ 0.824 0.828 2.102\n", 316 | "x₂ 0.712 0.722 1.407\n", 317 | "x₃ 4.513 4.576 8.327\n", 318 | "x₄ 12.896 13.011 23.881\n", 319 | "x₅ 15.876 15.924 29.839\n", 320 | "x₆ 6.904 6.891 13.219\n", 321 | "\n", 322 | "\u001b[31m\u001b[1mThe block bootstrap accounts for autocorrelation, so the stds tend to be higher (since there is indeed autocorrelation)\u001b[22m\u001b[39m\n" 323 | ] 324 | } 325 | ], 326 | "source": [ 327 | "BlockSize = 10 #size of blocks\n", 328 | "NSim = 2000 #no. of simulations\n", 329 | "Random.seed!(123)\n", 330 | "\n", 331 | "bBoot2 = fill(NaN,NSim,K*n)\n", 332 | "for i = 1:NSim #loop over simulations\n", 333 | " #local t_i, utilde, ytilde #local/global is needed in script\n", 334 | " t_i = DrawBlocks(T,BlockSize)\n", 335 | " utilde = u[t_i]\n", 336 | " ytilde = x*bLS + utilde[1:T]\n", 337 | " bBoot2[i,:] = OlsGM(ytilde,x)[1]\n", 338 | "end\n", 339 | "\n", 340 | "printblue(\"Std:\")\n", 341 | "xx = [StdbLS std(bBoot,dims=1)' std(bBoot2,dims=1)']\n", 342 | "printmat(xx;colNames=[\"trad.\",\"bootstrap 1\",\"block bootstr\"],rowNames=rowNames,width=20)\n", 343 | "\n", 344 | "printred(\"The block bootstrap accounts for autocorrelation, so the stds tend to be higher (since there is indeed autocorrelation)\")" 345 | ] 346 | }, 347 | { 348 | "cell_type": "code", 349 | "execution_count": null, 350 | "metadata": {}, 351 | "outputs": [], 352 | "source": [] 353 | } 354 | ], 355 | "metadata": { 356 | "@webio": { 357 | "lastCommId": null, 358 | "lastKernelId": null 359 | }, 360 | "anaconda-cloud": {}, 361 | "kernelspec": { 362 | "display_name": "Julia 1.11.5", 363 | "language": "julia", 364 | "name": "julia-1.11" 365 | }, 366 | "language_info": { 367 | "file_extension": ".jl", 368 | "mimetype": "application/julia", 369 | "name": "julia", 370 | "version": "1.11.5" 371 | } 372 | }, 373 | "nbformat": 4, 374 | "nbformat_minor": 4 375 | } 376 | -------------------------------------------------------------------------------- /Ch12_IV.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Instrumental Variables\n", 8 | "\n", 9 | "This notebook uses a function for 2SLS and illustrates it by redoing an example from Ch 10.3.3 in \"Principles of Econometrics\", 3rd edition (Hill, Griffiths and Lim)." 10 | ] 11 | }, 12 | { 13 | "cell_type": "markdown", 14 | "metadata": {}, 15 | "source": [ 16 | "## Load Packages and Extra Functions\n", 17 | "\n", 18 | "The key functions used for OLS and IV/2SLS are from the (local) `FinEcmt_OLS` module." 19 | ] 20 | }, 21 | { 22 | "cell_type": "code", 23 | "execution_count": 1, 24 | "metadata": {}, 25 | "outputs": [], 26 | "source": [ 27 | "MyModulePath = joinpath(pwd(),\"src\")\n", 28 | "!in(MyModulePath,LOAD_PATH) && push!(LOAD_PATH,MyModulePath)\n", 29 | "using FinEcmt_OLS" 30 | ] 31 | }, 32 | { 33 | "cell_type": "code", 34 | "execution_count": 2, 35 | "metadata": {}, 36 | "outputs": [], 37 | "source": [ 38 | "#=\n", 39 | "include(joinpath(pwd(),\"src\",\"FinEcmt_OLS.jl\"))\n", 40 | "using .FinEcmt_OLS\n", 41 | "=#" 42 | ] 43 | }, 44 | { 45 | "cell_type": "code", 46 | "execution_count": 3, 47 | "metadata": { 48 | "tags": [] 49 | }, 50 | "outputs": [], 51 | "source": [ 52 | "using DelimitedFiles, LinearAlgebra" 53 | ] 54 | }, 55 | { 56 | "cell_type": "markdown", 57 | "metadata": {}, 58 | "source": [ 59 | "# Loading the Data\n", 60 | "\n", 61 | "The next cells replicates an old example from Hill et al (2008). See the lecture notes for more details.\n", 62 | "\n", 63 | "### A remark on the code\n", 64 | "The data set contains many different variables. To import them with their correct names, we create a named tuple of them by using the function `PutDataInNT()` from the `FinEcmt_OLS` module. (This is convenient, but not important for the focus of this notebook. An alternative is to use the `DataFrames.jl` package.)" 65 | ] 66 | }, 67 | { 68 | "cell_type": "code", 69 | "execution_count": 4, 70 | "metadata": { 71 | "tags": [] 72 | }, 73 | "outputs": [ 74 | { 75 | "name": "stdout", 76 | "output_type": "stream", 77 | "text": [ 78 | "The variables in X (use as, for instance, X.wage): \n", 79 | "(:taxableinc, :federaltax, :hsiblings, :hfathereduc, :hmothereduc, :siblings, :lfp, :hours, :kidsl6, :kids618, :age, :educ, :wage, :wage76, :hhours, :hage, :heduc, :hwage, :faminc, :mtr, :mothereduc, :fathereduc, :unemployment, :bigcity, :exper)\n", 80 | "\n" 81 | ] 82 | } 83 | ], 84 | "source": [ 85 | "(x,header) = readdlm(\"Data/mrozEd.txt\",header=true)\n", 86 | "X = PutDataInNT(x,header) #NamedTuple with X.wage, X.exper, etc\n", 87 | "\n", 88 | "c = ones(size(x,1)) #constant, used in the regressions\n", 89 | "\n", 90 | "println(\"The variables in X (use as, for instance, X.wage): \")\n", 91 | "printmat(keys(X))" 92 | ] 93 | }, 94 | { 95 | "cell_type": "markdown", 96 | "metadata": {}, 97 | "source": [ 98 | "## OLS\n", 99 | "\n", 100 | "estimation of the log wage on education, experience and experience^2. Only data points where wage > 0 are used." 101 | ] 102 | }, 103 | { 104 | "cell_type": "code", 105 | "execution_count": 5, 106 | "metadata": { 107 | "tags": [] 108 | }, 109 | "outputs": [ 110 | { 111 | "name": "stdout", 112 | "output_type": "stream", 113 | "text": [ 114 | "\u001b[34m\u001b[1mOLS estimates:\u001b[22m\u001b[39m\n", 115 | "\n", 116 | " coef std\n", 117 | "c -0.522 0.198\n", 118 | "educ 0.107 0.014\n", 119 | "exper 0.042 0.013\n", 120 | "exper^2 -0.001 0.000\n", 121 | "\n" 122 | ] 123 | } 124 | ], 125 | "source": [ 126 | "vv = X.wage .> 0 #find data points where X.wage > 0\n", 127 | " #OLS on wage>0\n", 128 | "(b_OLS,_,_,Covb,) = OlsGM(log.(X.wage[vv]),[c X.educ X.exper X.exper.^2][vv,:])\n", 129 | "Stdb_ols = sqrt.(diag(Covb))\n", 130 | "\n", 131 | "colNames = [\"coef\",\"std\"]\n", 132 | "rowNames = [\"c\",\"educ\",\"exper\",\"exper^2\"]\n", 133 | "printblue(\"OLS estimates:\\n\")\n", 134 | "printmat(b_OLS,Stdb_ols;colNames,rowNames)" 135 | ] 136 | }, 137 | { 138 | "cell_type": "markdown", 139 | "metadata": {}, 140 | "source": [ 141 | "## IV (2SLS)\n", 142 | "\n", 143 | "using the function `TwoSLS()` function.\n", 144 | "\n", 145 | "In this application, the mother's education is used as an instrument for the person's education." 146 | ] 147 | }, 148 | { 149 | "cell_type": "code", 150 | "execution_count": 6, 151 | "metadata": {}, 152 | "outputs": [ 153 | { 154 | "data": { 155 | "text/markdown": [ 156 | "```\n", 157 | "TwoSLS(y,x,z,NWQ=false,m=0)\n", 158 | "```\n", 159 | "\n", 160 | "### Input\n", 161 | "\n", 162 | " * `y::VecOrMat`: Tx1 or T-vector of the dependent variable\n", 163 | " * `x::VecOrMat`: Txk matrix (or vector) of regressors\n", 164 | " * `z::VecOrMat`: TxL matrix (or vector) of instruments\n", 165 | " * `NWQ:Bool`: if true, then Newey-West's covariance matrix is used, otherwise Gauss-Markov\n", 166 | " * `m::Int`: scalar, bandwidth in Newey-West; 0 means White's method\n", 167 | "\n", 168 | "### Output\n", 169 | "\n", 170 | " * `b::Vector`: k-vector, regression coefficients\n", 171 | " * `fnOutput::NamedTuple`: with\n", 172 | "\n", 173 | " * res Tx1 or Txn matrix, residuals y - yhat\n", 174 | " * yhat Tx1 or Txn matrix, fitted values\n", 175 | " * Covb matrix, covariance matrix of vec(b) = [beq1;beq2;...]\n", 176 | " * R2 1xn, R2\n", 177 | " * R2_stage1 k-vector, R2 of each x[:,i] in first stage regression on z\n", 178 | " * δ_stage1 Lxk matrix, coeffs from 1st stage x = z'δ\n", 179 | " * Stdδ_stage1 Lxk matrix, std of δ\n", 180 | "\n", 181 | "### Requires\n", 182 | "\n", 183 | " * Statistics, LinearAlgebra\n", 184 | " * CovNW\n" 185 | ] 186 | }, 187 | "metadata": {}, 188 | "output_type": "display_data" 189 | } 190 | ], 191 | "source": [ 192 | "@doc2 TwoSLS" 193 | ] 194 | }, 195 | { 196 | "cell_type": "code", 197 | "execution_count": 7, 198 | "metadata": {}, 199 | "outputs": [], 200 | "source": [ 201 | "#using CodeTracking\n", 202 | "#println(@code_string TwoSLS([1],[1],[1])) #print the source code" 203 | ] 204 | }, 205 | { 206 | "cell_type": "code", 207 | "execution_count": 8, 208 | "metadata": { 209 | "tags": [] 210 | }, 211 | "outputs": [ 212 | { 213 | "name": "stdout", 214 | "output_type": "stream", 215 | "text": [ 216 | "\u001b[34m\u001b[1mfirst-stage estimates: coeffs (each regression in its own column)\u001b[22m\u001b[39m\n", 217 | " c educ exper exper^2\n", 218 | "c 1.000 9.775 -0.000 0.000\n", 219 | "exper 0.000 0.049 1.000 -0.000\n", 220 | "exper^2 -0.000 -0.001 0.000 1.000\n", 221 | "mothereduc 0.000 0.268 -0.000 -0.000\n", 222 | "\n", 223 | "\u001b[34m\u001b[1mfirst-stage estimates: std errors\u001b[22m\u001b[39m\n", 224 | " c educ exper exper^2\n", 225 | "c 0.000 0.422 0.000 0.000\n", 226 | "exper 0.000 0.042 0.000 0.000\n", 227 | "exper^2 0.000 0.001 0.000 0.000\n", 228 | "mothereduc 0.000 0.031 0.000 0.000\n", 229 | "\n", 230 | "\u001b[34m\u001b[1mfirst-stage estimates: R²\u001b[22m\u001b[39m\n", 231 | " c educ exper exper^2\n", 232 | " NaN 0.153 1.000 1.000\n", 233 | "\n" 234 | ] 235 | } 236 | ], 237 | "source": [ 238 | "(b_iv,fO2) = TwoSLS(log.(X.wage[vv]),[c X.educ X.exper X.exper.^2][vv,:],\n", 239 | " [c X.exper X.exper.^2 X.mothereduc][vv,:])\n", 240 | "\n", 241 | "zNames = [\"c\",\"exper\",\"exper^2\",\"mothereduc\"]\n", 242 | "\n", 243 | "printblue(\"first-stage estimates: coeffs (each regression in its own column)\")\n", 244 | "printmat(fO2.δ_stage1;colNames=rowNames,rowNames=zNames)\n", 245 | "\n", 246 | "printblue(\"first-stage estimates: std errors\")\n", 247 | "printmat(fO2.Stdδ_stage1;colNames=rowNames,rowNames=zNames)\n", 248 | "\n", 249 | "printblue(\"first-stage estimates: R²\")\n", 250 | "printmat(fO2.R2_stage1';colNames=rowNames)" 251 | ] 252 | }, 253 | { 254 | "cell_type": "code", 255 | "execution_count": 9, 256 | "metadata": { 257 | "tags": [] 258 | }, 259 | "outputs": [ 260 | { 261 | "name": "stdout", 262 | "output_type": "stream", 263 | "text": [ 264 | "\u001b[34m\u001b[1mIV estimates\u001b[22m\u001b[39m\n", 265 | " coef std\n", 266 | "c 0.198 0.471\n", 267 | "educ 0.049 0.037\n", 268 | "exper 0.045 0.014\n", 269 | "exper^2 -0.001 0.000\n", 270 | "\n", 271 | "\u001b[31m\u001b[1mThe results should be very close to Hill et al, 10.3.3,\u001b[22m\u001b[39m\n", 272 | "\u001b[31m\u001b[1mbut with small differences due to how df adjustments are made to variances\u001b[22m\u001b[39m\n" 273 | ] 274 | } 275 | ], 276 | "source": [ 277 | "Stdb_iv = sqrt.(diag(fO2.Covb))\n", 278 | "printblue(\"IV estimates\")\n", 279 | "printmat(b_iv,Stdb_iv;colNames,rowNames)\n", 280 | "\n", 281 | "printred(\"The results should be very close to Hill et al, 10.3.3,\n", 282 | "but with small differences due to how df adjustments are made to variances\")" 283 | ] 284 | }, 285 | { 286 | "cell_type": "code", 287 | "execution_count": null, 288 | "metadata": {}, 289 | "outputs": [], 290 | "source": [] 291 | } 292 | ], 293 | "metadata": { 294 | "@webio": { 295 | "lastCommId": null, 296 | "lastKernelId": null 297 | }, 298 | "anaconda-cloud": {}, 299 | "kernelspec": { 300 | "display_name": "Julia 1.11.4", 301 | "language": "julia", 302 | "name": "julia-1.11" 303 | }, 304 | "language_info": { 305 | "file_extension": ".jl", 306 | "mimetype": "application/julia", 307 | "name": "julia", 308 | "version": "1.11.4" 309 | } 310 | }, 311 | "nbformat": 4, 312 | "nbformat_minor": 4 313 | } 314 | -------------------------------------------------------------------------------- /Ch15_ReturnPredictions.txt: -------------------------------------------------------------------------------- 1 | See the FinancialTheoryMSc repository -------------------------------------------------------------------------------- /Ch20_RiskMeasures.txt: -------------------------------------------------------------------------------- 1 | See the FinancialTheoryMSc repository -------------------------------------------------------------------------------- /Data/FFmFactorsPs.csv: -------------------------------------------------------------------------------- 1 | date,Mkt-RF,SMB,HML,RF,Mom,ST_Rev,LT_Rev 2 | 197901,4.18,3.69,2.28,0.77,-1.26,5.49,-0.75 3 | 197902,-3.41,0.47,1.17,0.73,-1.08,1.28,0.94 4 | 197903,5.75,3.19,-0.67,0.81,2.91,1.38,-0.35 5 | 197904,0.05,2.18,1.06,0.8,0.81,-0.37,-0.4 6 | 197905,-2.18,0.34,1.62,0.82,-0.36,0.99,0.75 7 | 197906,3.88,1.17,1.42,0.81,0.84,1.2,-2.71 8 | 197907,0.73,1.31,1.75,0.77,-1.07,0.57,-2.02 9 | 197908,5.7,2.07,-1.53,0.77,-0.24,0.81,-1.74 10 | 197909,-0.69,-0.29,-0.91,0.83,5.33,-1.56,0.04 11 | 197910,-8.14,-3.33,-1.87,0.87,2.15,-1.96,1.52 12 | 197911,5.37,2.75,-3.34,0.99,7.95,1.37,-2.28 13 | 197912,1.87,4.24,-2.04,0.95,4.76,-1.93,-0.34 14 | 198001,5.76,1.68,1.78,0.8,7.47,-3.38,-0.85 15 | 198002,-0.79,-1.79,0.58,0.89,7.9,-4.94,-0.09 16 | 198003,-13.23,-6.64,-1.02,1.21,-9.61,8.38,2.61 17 | 198004,3.97,0.99,1.09,1.26,-0.43,1.36,-0.13 18 | 198005,5.2,2.13,0.38,0.81,-1.13,2.87,0.78 19 | 198006,3.16,1.69,-0.91,0.61,1.59,2.15,-2.92 20 | 198007,6.41,4.21,-6.27,0.53,0.36,2.93,-1.74 21 | 198008,1.72,3.91,-2.69,0.64,3.2,-0.99,-1.55 22 | 198009,2.2,0.87,-4.71,0.75,5.44,-1.44,-1.79 23 | 198010,1.06,2.45,-2.75,0.95,7.33,-1.99,-2.83 24 | 198011,9.54,-3.46,-8.52,0.96,15.21,-9.86,-7.79 25 | 198012,-4.75,-0.23,2.67,1.31,-6.63,6.36,3.43 26 | 198101,-5.05,3.02,6.88,1.04,-7.91,-2.29,7.51 27 | 198102,0.48,-0.29,1,1.07,-1.39,-2.22,2.65 28 | 198103,3.41,3.61,0.74,1.21,0.78,1.62,1.59 29 | 198104,-2.21,4.4,2.28,1.08,-0.96,-1.53,2.83 30 | 198105,0.21,2.05,-0.45,1.15,3.73,-3.74,1.55 31 | 198106,-2.37,-0.86,5.13,1.35,-5.9,4.53,1.01 32 | 198107,-1.55,-2.26,-0.53,1.24,-2.53,-0.58,-3.51 33 | 198108,-6.91,-1.93,4.78,1.28,-1.11,-0.67,1.27 34 | 198109,-7.62,-2.64,5.19,1.24,1.93,-1.11,5.23 35 | 198110,4.81,2.24,-4.36,1.21,4.06,4.62,-4.92 36 | 198111,3.51,-0.93,1.86,1.07,-0.26,2.58,0.62 37 | 198112,-3.68,1.2,0.72,0.87,1.32,1.63,1.4 38 | 198201,-3.42,-1.24,3.07,0.8,1.71,-1.22,6.42 39 | 198202,-6.03,0.5,6.03,0.92,4.94,-4.36,5.93 40 | 198203,-1.99,-0.22,3.86,0.98,2.98,-1.77,3.97 41 | 198204,3.2,1.46,-2.72,1.13,-0.41,1.62,-1.67 42 | 198205,-3.88,0.5,1.8,1.06,2.53,1.93,1.58 43 | 198206,-3.35,-0.39,1.57,0.96,4.99,0.16,1.94 44 | 198207,-3.1,0.89,0.23,1.05,4.47,-2.89,2.35 45 | 198208,11.14,-4.13,1.17,0.76,-3.52,1.1,-0.97 46 | 198209,1.17,2.94,0.34,0.51,4.18,4.3,-0.47 47 | 198210,11.27,2.34,-3.72,0.59,0.05,2.83,-0.95 48 | 198211,4.56,4.77,-1.93,0.63,5.89,-4.48,1.05 49 | 198212,0.78,-0.17,0.04,0.67,0.03,3.78,1.07 50 | 198301,3.5,2.66,-0.87,0.69,-1.67,3.17,0.06 51 | 198302,2.4,3.26,0.7,0.62,3.8,2.72,-0.46 52 | 198303,2.84,1.76,2.08,0.63,0.92,0.35,0.9 53 | 198304,6.71,0.53,0.58,0.71,1.8,-0.54,3.19 54 | 198305,0.63,6.12,-1.4,0.69,-1.48,2.76,-2.1 55 | 198306,3.11,0.92,-3.85,0.67,1.78,0.2,-0.91 56 | 198307,-3.9,1.51,5.65,0.74,-3.12,2.02,1.01 57 | 198308,-0.41,-4.3,5.46,0.76,-5.44,-0.61,0.09 58 | 198309,0.85,0.55,1.05,0.76,-0.11,2.33,0.82 59 | 198310,-3.56,-3.61,4.94,0.76,-4.56,-1.68,1.15 60 | 198311,2.26,2.03,-0.63,0.7,-0.11,4.88,-1.33 61 | 198312,-1.78,-0.29,1.64,0.73,0.79,1.9,1.36 62 | 198401,-2.06,-0.4,7.56,0.76,-2.52,0.67,4.24 63 | 198402,-4.62,-1.72,3.39,0.71,0.17,-2.02,0.22 64 | 198403,0.61,0.14,0.52,0.73,1.1,2.42,0.71 65 | 198404,-0.56,-1.2,1.28,0.81,2.08,1.54,-1.56 66 | 198405,-6.01,0.08,0.2,0.78,1.53,0.84,-0.22 67 | 198406,1.59,-0.27,-2.59,0.75,-0.7,0.94,-3.6 68 | 198407,-2.88,-2.28,0.28,0.82,2.93,-1.49,-1.63 69 | 198408,10.44,-0.22,-1.75,0.83,-5.74,7.28,-1.69 70 | 198409,-0.82,0.24,5.33,0.86,3.66,4.35,1.78 71 | 198410,-1.01,-1.17,0.46,1,3.23,-1.26,-1.79 72 | 198411,-1.8,-0.63,4.01,0.73,1.7,-0.66,1.02 73 | 198412,1.73,-0.57,-0.11,0.64,1.5,0.56,-3.1 74 | 198501,7.92,3.27,-5.35,0.65,-6.93,2.34,-1.93 75 | 198502,1.11,0.79,-0.23,0.58,1.82,2.42,-0.12 76 | 198503,-0.79,-1.12,3.98,0.62,1.69,-1.3,-0.69 77 | 198504,-0.94,0.18,3.72,0.72,3.05,-2.46,0.15 78 | 198505,4.92,-2.28,-0.91,0.66,3.97,-0.51,-4 79 | 198506,1.16,0.49,0.42,0.55,3.63,-0.63,-2.35 80 | 198507,-0.65,2.85,-1.63,0.62,-3.92,3.62,1.67 81 | 198508,-1.03,-0.37,2.2,0.55,1.79,1.82,0.11 82 | 198509,-4.58,-1.61,1.25,0.6,1.48,-1.81,-0.8 83 | 198510,3.79,-1.58,0.72,0.65,4.87,0.72,-2.46 84 | 198511,6.31,0.24,-2.87,0.61,-0.39,2.31,-2.39 85 | 198512,3.66,-0.46,-1.52,0.65,-0.13,-0.63,-3.13 86 | 198601,0.42,1.21,0.53,0.56,2.97,0.72,-2.83 87 | 198602,6.72,-0.59,-0.84,0.53,2.76,-1.64,-3.67 88 | 198603,4.79,-0.48,-0.44,0.6,2.45,-0.21,-2.24 89 | 198604,-1.31,2.82,-2.91,0.52,-0.5,2.83,-1.17 90 | 198605,4.59,-1.3,-0.11,0.49,2.03,0.97,-1.35 91 | 198606,0.9,-0.89,1.38,0.52,5.15,-2.36,-6.44 92 | 198607,-6.49,-3.43,4.71,0.52,1.8,-3.05,-4.05 93 | 198608,6.16,-4.17,3.53,0.46,-5.02,1.16,4.82 94 | 198609,-8.35,2.3,3.22,0.45,-5.86,-0.3,3.83 95 | 198610,4.47,-2.59,-1.48,0.46,2.7,3.55,0.64 96 | 198611,1.12,-1.96,-0.16,0.39,-0.31,0.66,0.12 97 | 198612,-3.13,0.07,0.36,0.49,0.37,0.56,0.53 98 | 198701,12.43,-1.73,-3.15,0.42,2.07,0.45,3.12 99 | 198702,4.36,3.45,-5.95,0.43,-2.16,-1.06,-0.16 100 | 198703,1.9,0.44,1.65,0.47,1.6,1.82,3.92 101 | 198704,-2.14,-1.69,-0.29,0.44,0.26,-1.89,3.92 102 | 198705,0.13,-0.56,0.17,0.38,-0.69,-0.28,2.22 103 | 198706,3.89,-2.1,1.13,0.48,-0.2,0.11,-1.42 104 | 198707,3.96,-0.68,0.67,0.46,2.69,-0.15,2.33 105 | 198708,3.24,-0.77,-0.94,0.47,-0.89,2.55,-3.05 106 | 198709,-2.53,0.62,0.28,0.45,0.61,-0.38,3.08 107 | 198710,-23.14,-8.41,4.17,0.6,-7.92,0.1,-6.26 108 | 198711,-7.58,2.61,3.18,0.35,-1.17,-0.77,-0.42 109 | 198712,6.64,0.18,-4.48,0.39,5.78,5.96,2.87 110 | 198801,4.2,-0.66,5.22,0.29,-7.63,7.9,-1.63 111 | 198802,4.71,3.34,-1.66,0.46,-1.54,4.35,1.53 112 | 198803,-2.1,6.15,0.77,0.44,0.64,-0.9,1.21 113 | 198804,0.64,0.96,1.73,0.46,2.25,0.33,0.45 114 | 198805,-0.47,-2.62,2.31,0.51,0.5,0.57,-0.13 115 | 198806,4.66,2.12,-1.14,0.49,-2.91,1.83,1.75 116 | 198807,-1.24,-0.19,2.28,0.51,0.64,3.4,-1.35 117 | 198808,-3.39,0.08,2.09,0.59,0.32,-1.95,-2.03 118 | 198809,3.1,-1.3,-0.74,0.62,0.24,-0.15,-1.95 119 | 198810,1.15,-2.94,1.66,0.61,1.32,-0.92,-0.12 120 | 198811,-2.21,-1.74,1.26,0.57,0.41,-0.67,-0.84 121 | 198812,1.48,1.93,-1.55,0.63,0.28,2.29,0.79 122 | 198901,6.06,-2.15,0.52,0.55,-0.14,1.12,2.81 123 | 198902,-2.25,2.74,0.87,0.61,0.87,1.06,0.9 124 | 198903,1.48,0.7,0.47,0.67,3.56,-0.87,0.15 125 | 198904,4.15,-0.53,-1.38,0.67,1.7,-0.72,-1.1 126 | 198905,3.14,-0.03,-0.84,0.79,1.54,-2.74,-1.7 127 | 198906,-1.2,-1.01,2.18,0.71,0.65,2.26,-0.71 128 | 198907,7.01,-3.98,-2.8,0.7,5.39,1.3,-1.8 129 | 198908,1.47,0.5,0.67,0.74,-0.14,1.89,0.17 130 | 198909,-0.8,0.34,-1.3,0.65,3.39,1.18,-2.83 131 | 198910,-3.61,-3.23,-0.98,0.68,1.43,-4.26,-3.55 132 | 198911,1.09,-1.26,-1.12,0.69,2.57,-1.77,-1.25 133 | 198912,1.22,-2.35,0.29,0.61,2.78,-2.54,-0.83 134 | 199001,-7.58,-1.25,0.87,0.57,-3.36,1.1,3.23 135 | 199002,0.92,1.15,0.66,0.57,-0.53,0.43,1.9 136 | 199003,1.77,1.5,-2.86,0.64,1.68,0.21,-0.17 137 | 199004,-3.52,-0.44,-2.48,0.69,2.47,-2.04,-1.12 138 | 199005,8.21,-2.48,-3.63,0.68,3.02,-0.44,0.93 139 | 199006,-1.05,1.37,-2.11,0.63,2.41,-0.17,-1.47 140 | 199007,-1.62,-3.18,-0.05,0.68,5.95,-0.56,-1.79 141 | 199008,-9.85,-3.57,1.49,0.66,1.79,-3.51,1.62 142 | 199009,-5.98,-3.63,0.67,0.6,5.52,-6,0.71 143 | 199010,-1.93,-5.56,0.26,0.68,6.73,-2.64,-3.5 144 | 199011,6,0.32,-2.96,0.57,-5.69,5.91,-0.64 145 | 199012,2.35,0.78,-1.49,0.6,0.01,-2.98,-2.39 146 | 199101,4.39,3.85,-1.73,0.52,-6.52,-2.04,6.15 147 | 199102,7.1,3.9,-0.58,0.48,-4.83,1.97,1.12 148 | 199103,2.45,3.92,-1.19,0.44,2.73,0.49,-0.23 149 | 199104,-0.2,0.53,1.43,0.53,-2.42,1.6,-1.19 150 | 199105,3.6,-0.31,-0.56,0.47,-0.12,0.35,1.4 151 | 199106,-4.82,0.06,1.23,0.42,0.4,2.14,-1.69 152 | 199107,4.19,-0.97,-1.29,0.49,4.34,2.06,0.82 153 | 199108,2.22,1.59,-0.8,0.46,1.59,-2.92,-0.43 154 | 199109,-1.56,1.68,-1.06,0.46,1.74,-0.81,-0.82 155 | 199110,1.36,0.85,-0.39,0.42,3.21,-1.28,2.25 156 | 199111,-4.12,-0.55,-1.77,0.39,1.26,-0.4,-2.67 157 | 199112,10.3,-2.26,-4.02,0.38,8.3,1.02,-0.85 158 | 199201,-0.46,8.43,4.63,0.34,-2.47,5.29,9.48 159 | 199202,1.06,0.87,6.37,0.28,-0.66,-2.69,5.41 160 | 199203,-2.71,-1.08,3.72,0.34,-0.35,-1.09,1.41 161 | 199204,1.02,-6.08,4.33,0.32,-2.6,-3.37,0.71 162 | 199205,0.36,0.42,1.17,0.28,0.11,-0.18,-0.47 163 | 199206,-2.25,-3.07,3.32,0.32,-0.61,0.86,1.32 164 | 199207,3.68,-0.39,-0.48,0.31,1.43,2.05,-1.26 165 | 199208,-2.34,-0.11,-1.09,0.26,-0.51,-1.57,-4.1 166 | 199209,0.98,0.58,-0.2,0.26,1.44,-1.12,-0.02 167 | 199210,0.87,2.07,-2.05,0.23,2.74,-0.22,-1.06 168 | 199211,3.79,3.63,-1.53,0.23,-0.32,-1.07,0.27 169 | 199212,1.5,1.63,2.53,0.28,4.47,1.21,0.8 170 | 199301,1.03,2.03,5.83,0.23,4.82,-0.52,5.54 171 | 199302,0.32,-3.36,6.5,0.22,3.11,-1.41,4.23 172 | 199303,2.26,0.23,1.23,0.25,3.74,-0.92,1.74 173 | 199304,-2.78,-0.64,2.65,0.24,0.33,-1.77,2.46 174 | 199305,2.74,1.97,-3.45,0.22,0.28,1.45,1.29 175 | 199306,0.29,-0.31,2.61,0.25,4.59,2.25,1.64 176 | 199307,-0.32,0.95,3.24,0.24,3.24,-2.7,0.99 177 | 199308,3.7,0.22,-0.4,0.25,2.58,1.3,1.23 178 | 199309,-0.2,3.08,-0.45,0.26,3.31,0.67,0.5 179 | 199310,1.59,1.45,-1.59,0.22,-2.7,1.96,1.78 180 | 199311,-2.01,-1.41,-0.31,0.25,-4.71,-1.37,1.49 181 | 199312,1.72,1.24,0.6,0.23,2.37,1.15,0.48 182 | 199401,2.9,0.11,2.15,0.25,0.09,1.75,3.78 183 | 199402,-2.63,2.72,-1.37,0.21,-0.27,0.42,-0.18 184 | 199403,-4.85,-0.9,1.29,0.27,-1.31,0.13,0.54 185 | 199404,0.68,-0.88,1.66,0.27,0.39,-0.35,0.17 186 | 199405,0.62,-2.05,0.12,0.32,-2.22,0.07,1.64 187 | 199406,-3.1,-0.49,1.71,0.31,-0.83,0.18,0.46 188 | 199407,2.78,-1.78,0.98,0.28,0.18,1.4,0.5 189 | 199408,3.89,1.45,-3.47,0.37,1.54,1.47,2.35 190 | 199409,-2.21,2.7,-1.83,0.37,1.29,-0.74,1.71 191 | 199410,1.07,-2.21,-2.35,0.38,1.48,-0.25,0.54 192 | 199411,-4.09,-0.16,-0.07,0.37,-0.19,-2.1,-1.63 193 | 199412,0.82,0.04,0.22,0.44,3.51,0.82,0.1 194 | 199501,1.62,-2.95,1.67,0.42,-1.82,4.05,-0.65 195 | 199502,3.56,-0.33,0.37,0.4,-0.33,2.38,-1.01 196 | 199503,2.24,-0.35,-2.04,0.46,0.38,-0.13,1.11 197 | 199504,2.06,-0.41,1.73,0.44,1.85,-0.58,0.36 198 | 199505,2.86,-2.24,1.97,0.54,-0.43,-0.44,-1.13 199 | 199506,2.65,3.07,-2.99,0.47,2.92,1.21,-1.85 200 | 199507,3.63,2.22,-2.15,0.45,2.57,-2.24,-0.97 201 | 199508,0.46,1.84,1.89,0.47,-0.02,1.32,-1.14 202 | 199509,3.21,-2.02,-0.92,0.43,2.63,-0.86,-1.01 203 | 199510,-1.6,-3.99,-0.08,0.47,4.14,-1.05,0.51 204 | 199511,3.85,-0.81,0.34,0.42,-0.6,0.56,0.55 205 | 199512,1.03,0.42,1.41,0.49,2.56,-0.95,3.96 206 | 199601,2.38,-2.44,0.36,0.43,0.55,1.08,1.34 207 | 199602,1.24,2.06,-2.32,0.39,0.58,2.27,-1.39 208 | 199603,0.7,1.31,1.23,0.39,-1.89,-0.08,-0.24 209 | 199604,2.09,4.89,-3.98,0.46,-0.93,0.7,-0.78 210 | 199605,2.26,3.22,-1.38,0.42,1.55,-1.08,1.16 211 | 199606,-1.23,-3.68,1.93,0.4,0.95,-0.22,-0.13 212 | 199607,-5.83,-3.57,4.39,0.45,-0.14,-2.48,0 213 | 199608,2.84,2.31,-0.59,0.41,-0.12,2.55,-1.47 214 | 199609,4.86,-0.82,-3.83,0.44,2.7,0.54,-2.12 215 | 199610,0.95,-4.11,4.81,0.42,3.82,-1.1,0.06 216 | 199611,6.15,-3.6,0.21,0.41,-2.39,0.17,-2.49 217 | 199612,-1.6,3.15,0.94,0.46,0.6,0.54,-0.57 218 | 199701,4.9,-1.51,-2.3,0.45,1.95,2.71,-1.58 219 | 199702,-0.5,-2.57,4.72,0.39,-2.02,1.27,0.84 220 | 199703,-4.92,-0.3,3.88,0.43,0.98,0.89,2.11 221 | 199704,3.81,-5.14,-1,0.43,4.81,2.39,-4.09 222 | 199705,6.67,4.79,-4.35,0.49,-5.2,2.83,-2.18 223 | 199706,4.04,1.52,0.7,0.37,2.67,0.81,0.19 224 | 199707,7.22,-2.42,-0.38,0.43,3.84,3.81,-1.16 225 | 199708,-4.04,7.48,1.03,0.41,-2.53,-0.07,3.18 226 | 199709,5.41,2.68,-0.28,0.44,1.46,1.68,-0.4 227 | 199710,-3.86,-0.81,2.31,0.42,-0.44,-0.97,0.35 228 | 199711,2.65,-5.05,1.03,0.39,0.29,-2.01,1.01 229 | 199712,1.3,-2.34,3.82,0.48,3.84,-3.05,0.12 230 | 199801,0.02,-1.01,-1.82,0.43,0.08,4.98,-1.11 231 | 199802,6.94,0.21,-0.72,0.39,-1.1,1.96,-1.18 232 | 199803,4.74,-1.18,1.67,0.39,2.14,1.84,2.3 233 | 199804,0.66,0.46,0.31,0.43,0.78,1.72,-0.93 234 | 199805,-2.97,-3.58,4.27,0.4,1.86,0.7,1.49 235 | 199806,2.78,-3.28,-1.84,0.41,7.26,-1.48,-0.75 236 | 199807,-2.74,-4.88,-1.08,0.4,3.69,-1.99,0.46 237 | 199808,-16.21,-5.7,5.14,0.43,1.91,-2.66,4.47 238 | 199809,5.92,-0.16,-3.96,0.46,-0.61,2.82,0.24 239 | 199810,7.12,-3.19,-2.71,0.32,-5.36,9.86,-4.23 240 | 199811,5.89,1.12,-3.29,0.31,1.18,1.22,-0.38 241 | 199812,5.93,-0.27,-4.8,0.38,9.03,-1.63,-1 242 | 199901,3.5,0.67,-5.61,0.35,3.02,-2.28,1.09 243 | 199902,-4.16,-5.68,1.71,0.35,-0.13,2.34,0.37 244 | 199903,3.36,-3.89,-2.88,0.43,-1.36,0.21,-1.09 245 | 199904,4.54,3.37,2.45,0.37,-9.14,2.36,5.14 246 | 199905,-2.41,3.69,2.69,0.34,-5.25,1.12,3.39 247 | 199906,4.68,3.37,-4.3,0.4,4.96,1.58,0.36 248 | 199907,-3.45,2.23,0.54,0.38,1.6,1.4,1.93 249 | 199908,-1.39,-1.24,-0.99,0.39,3.06,-3.51,-1.55 250 | 199909,-2.67,3.25,-3.08,0.39,6.49,-0.82,0.23 251 | 199910,5.82,-6.78,-3.26,0.39,5.48,-1.18,-2.76 252 | 199911,3.32,7.66,-7.99,0.36,5.57,0.09,5.14 253 | 199912,7.94,6.82,-9.19,0.44,13.2,-14.05,5.66 254 | 200001,-4.37,4.39,0.23,0.41,1.9,2.71,1.87 255 | 200002,2.75,22.06,-12.87,0.43,18.4,-13.35,7.59 256 | 200003,4.88,-16.62,7.91,0.47,-6.85,10.08,-5.17 257 | 200004,-6.41,-7.64,9.26,0.46,-8.47,-1.95,0.35 258 | 200005,-4.4,-4.66,3.8,0.5,-9.1,-8.73,-1.71 259 | 200006,4.76,13.74,-9.92,0.4,16.55,12.34,2.36 260 | 200007,-2.19,-2.79,8.45,0.48,-0.08,6.48,-3.27 261 | 200008,7.09,-0.9,-1.29,0.5,5.77,0.62,1.04 262 | 200009,-5.62,-1.84,6.87,0.51,2.18,2.49,-2.64 263 | 200010,-3.02,-3.63,4.8,0.56,-4.7,-4.74,-1.1 264 | 200011,-10.76,-3.07,12.39,0.51,-2.49,-14.52,0.35 265 | 200012,1.54,1.59,6.13,0.5,6.83,-6.63,2.91 266 | 200101,3.41,6.98,-5.67,0.54,-25.01,16.29,-2.61 267 | 200102,-10.32,-1.14,13.88,0.39,12.56,12.34,11 268 | 200103,-7.47,0.53,6.37,0.44,8.4,-7.67,3.9 269 | 200104,7.99,0.28,-4.39,0.39,-8.12,9.97,-3.79 270 | 200105,0.74,3.01,2.82,0.32,2.13,3.67,3.85 271 | 200106,-2.03,6.39,-2.11,0.28,0.3,0.46,2.08 272 | 200107,-2.13,-4.18,5.61,0.3,5.58,1.07,2.8 273 | 200108,-6.21,2.18,3.32,0.31,5.61,-3.96,5.92 274 | 200109,-9.43,-6.53,1.63,0.28,11.54,-4.9,0.05 275 | 200110,2.56,6.83,-6.99,0.22,-8.42,14.85,-1.66 276 | 200111,7.71,0.39,0.82,0.17,-8.62,-3.11,0.24 277 | 200112,1.64,5.12,0.39,0.15,0.01,1.68,1.26 278 | 200201,-1.74,1.15,3.46,0.14,3.73,1.59,3.52 279 | 200202,-2.3,-1.67,3.92,0.13,6.81,-0.11,4.09 280 | 200203,4.34,4.34,1.14,0.13,-1.68,2.85,2.11 281 | 200204,-5.11,5.84,4.21,0.15,7.92,2.08,6.12 282 | 200205,-1.19,-3.68,2.46,0.14,3.05,-2.7,2.4 283 | 200206,-7.16,3.55,1.47,0.13,6.19,-3.38,2.15 284 | 200207,-8.26,-5.16,-3.65,0.15,3.4,1.48,-2.94 285 | 200208,0.66,-2.19,2.17,0.14,1.73,1.39,-0.59 286 | 200209,-10.14,2.69,1.16,0.14,9.14,-1.8,-0.59 287 | 200210,7.35,-3.01,-6.51,0.14,-5.49,7.53,-0.38 288 | 200211,6.01,3.18,-1.54,0.12,-16.31,0.27,4.05 289 | 200212,-5.44,-0.52,3.86,0.11,9.65,10.58,2.26 290 | 200301,-2.44,1.4,-0.9,0.1,1.56,0.25,0.41 291 | 200302,-1.63,-0.27,-1.46,0.09,1.22,-0.8,-1.9 292 | 200303,0.93,0.83,-1.73,0.1,1.51,-0.22,-2.66 293 | 200304,8.18,1.11,-0.02,0.1,-9.44,3.17,-0.92 294 | 200305,6.26,4.69,0.16,0.09,-10.77,-1.44,3.47 295 | 200306,1.53,1.48,0.66,0.1,-0.97,-0.18,1.38 296 | 200307,2.24,5.62,-2.08,0.07,-0.29,2.59,0.37 297 | 200308,2.43,2.65,1.79,0.07,-0.54,-1.47,-0.35 298 | 200309,-0.99,0.57,0.92,0.08,-0.07,4.59,1.09 299 | 200310,5.96,2.87,1.84,0.07,3.88,2.04,2.02 300 | 200311,1.59,2.2,1.46,0.07,1.59,-1.44,1.93 301 | 200312,4.47,-2.78,2.64,0.08,-5.69,1.7,2.06 302 | 200401,2.23,2.61,1.66,0.07,2.58,2.24,1.91 303 | 200402,1.49,-1.15,0.34,0.06,-1.13,1.45,-2.95 304 | 200403,-1.16,1.87,-0.01,0.09,0.19,-2.17,-1.7 305 | 200404,-2.5,-2.56,-1.7,0.08,-5.38,-0.22,-2.36 306 | 200405,1.35,-0.15,-0.26,0.06,1.65,2.27,0.89 307 | 200406,2.08,2.28,1.68,0.08,2.08,0.31,1.79 308 | 200407,-3.87,-3.82,4.39,0.1,-2.31,-1.37,-2.51 309 | 200408,0.16,-1.54,1.12,0.11,-1.52,-2.41,-2.77 310 | 200409,1.94,2.85,0.34,0.11,5.26,3.05,-1.25 311 | 200410,1.67,0.42,-0.89,0.11,-1.5,0.14,0.98 312 | 200411,4.67,4.12,1.91,0.15,3.22,1.46,-1.16 313 | 200412,3.36,0.19,-0.35,0.16,-2.83,0.92,0.87 314 | 200501,-2.82,-1.62,2.49,0.16,3.12,1.57,-2.9 315 | 200502,2.11,-0.75,2.78,0.16,3.24,-2.33,-1.49 316 | 200503,-1.9,-1.3,1.65,0.21,0.92,0.16,-0.72 317 | 200504,-2.73,-3.96,-0.48,0.21,-0.83,-1.82,-1.48 318 | 200505,3.56,2.95,-1.17,0.24,0.43,3.18,0.48 319 | 200506,0.92,2.56,2.75,0.23,2.06,0.11,-1.49 320 | 200507,4.09,2.76,-0.46,0.24,0.04,-0.17,0.99 321 | 200508,-0.89,-0.89,1.42,0.3,2.21,-1.46,0.35 322 | 200509,0.77,-0.63,1.17,0.29,3.47,-3.7,-0.05 323 | 200510,-2.35,-1.04,-0.7,0.27,-1.29,1.56,-1.03 324 | 200511,3.73,1,-1.81,0.31,0.37,0.15,0.28 325 | 200512,0.03,-0.48,0.48,0.32,0.76,1.94,-0.86 326 | 200601,3.65,5.39,1.14,0.35,2.75,-1.09,1.16 327 | 200602,-0.5,-0.36,-0.83,0.34,-1.8,3.3,1.26 328 | 200603,1.54,3.54,-0.07,0.37,1.23,0.06,0.44 329 | 200604,0.94,-1.23,3.08,0.36,0.66,-0.34,-0.42 330 | 200605,-3.53,-2.99,2.78,0.43,-3.72,0.02,-0.16 331 | 200606,-0.44,-0.49,1.5,0.4,1.48,-0.55,-1.11 332 | 200607,-0.59,-3.94,3.3,0.4,-2.18,0.25,1.37 333 | 200608,2.09,0.81,-1.73,0.42,-3.46,1.74,2.92 334 | 200609,1.53,-1.21,-0.43,0.41,-0.94,0.74,1.65 335 | 200610,3.3,1.65,0.48,0.41,-0.23,-0.21,-0.46 336 | 200611,1.95,0.73,0.51,0.42,-1.01,-0.95,-1.93 337 | 200612,0.68,-0.89,2.54,0.4,0.83,2.38,1.93 338 | 200701,1.5,0.06,-0.1,0.44,0.26,1.07,-0.68 339 | 200702,-1.78,1.43,0.24,0.38,-1.32,0.3,-0.64 340 | 200703,0.87,-0.23,0.43,0.43,2.49,-2.02,-1.18 341 | 200704,3.55,-2.09,-0.96,0.44,-0.17,-0.28,0.28 342 | 200705,3.48,-0.06,-0.09,0.41,-0.32,-1.09,-2.48 343 | 200706,-1.87,0.67,-1.03,0.4,0.25,-0.84,-0.29 344 | 200707,-3.57,-2.7,-2.93,0.4,2.79,-3.35,-2.06 345 | 200708,0.75,-0.14,-2.37,0.42,0.11,-2.57,-0.24 346 | 200709,3.77,-2.47,-2.13,0.32,4.61,0.31,-2.78 347 | 200710,2.26,0.09,-1.92,0.32,4.89,-3.92,-1.58 348 | 200711,-5.27,-2.73,-1.02,0.34,0.89,-1.73,0.45 349 | 200712,-0.7,0.07,-0.05,0.27,6.51,-2.09,-2.28 350 | 200801,-6.44,-0.76,3.01,0.21,-7.84,6.97,1.76 351 | 200802,-2.33,-0.55,0.05,0.13,6.14,5.05,-2.18 352 | 200803,-1.21,0.86,0.17,0.17,4.14,-0.31,2.73 353 | 200804,4.94,-1.55,0.07,0.18,-0.21,3.13,-4.53 354 | 200805,2.21,2.84,-0.26,0.18,3.2,-2.31,-4.52 355 | 200806,-8.03,1.05,-1.06,0.17,12.52,-7.09,-3.18 356 | 200807,-1.47,3.74,3.59,0.15,-5.15,8.21,7.84 357 | 200808,0.99,3.79,1.48,0.13,-3.81,-0.63,1.06 358 | 200809,-9.97,-0.23,4.42,0.15,0.39,-3.74,5.8 359 | 200810,-18.55,-2.17,-3.07,0.08,7.81,-9.47,2.45 360 | 200811,-8.56,-3.57,-4.99,0.03,7.18,-10.22,-2.4 361 | 200812,2.06,3.99,-1.18,0.09,-5.03,5.3,0.3 362 | 200901,-7.75,-0.9,-9.93,0,-1.92,0.49,-7.12 363 | 200902,-10.12,-0.41,-6.75,0.01,4.25,-6.69,1.15 364 | 200903,8.75,0.75,2.57,0.02,-11.51,3.35,3.92 365 | 200904,11.04,5.16,5.68,0.01,-34.75,-6.94,-0.35 366 | 200905,6.73,-2.64,0.45,0,-12.49,-2.82,-1.97 367 | 200906,-0.28,2.65,-2.45,0.01,5.37,5.07,1.32 368 | 200907,8.23,2.47,4.82,0.01,-5.51,4.39,5.04 369 | 200908,3.18,-0.56,7.68,0.01,-8.87,-2.1,5.48 370 | 200909,4.52,2.33,1.47,0.01,-4.97,1.23,-1.78 371 | 200910,-2.84,-4.28,-4.37,0,2.65,2.12,-4.76 372 | 200911,5.74,-2.84,0.13,0,0.41,0.38,1.44 373 | 200912,2.91,5.89,0.72,0.01,2.94,1.57,0.7 374 | 201001,-3.71,0.43,0.57,0,-5.34,3.66,1.64 375 | 201002,3.53,1.39,2.75,0,3.61,1.83,2.58 376 | 201003,6.44,1.57,2.01,0.01,3.72,0.87,4.3 377 | 201004,2.02,5.01,3.14,0,3.2,-1.81,4.8 378 | 201005,-8,-0.01,-2.36,0.01,-0.26,0.55,-3.03 379 | 201006,-5.21,-2.08,-4.31,0.01,-2.88,-4.88,-5.34 380 | 201007,7.1,0.13,0.23,0.01,1.95,4.05,0.65 381 | 201008,-4.4,-2.91,-1.71,0.01,-0.12,1.06,-3.82 382 | 201009,9.24,3.96,-3.05,0.01,1.35,3.2,1.97 383 | 201010,3.88,0.94,-2.21,0.01,1.59,-1.37,-2.23 384 | 201011,0.56,3.78,-0.66,0.01,2.5,-0.91,-0.73 385 | 201012,6.77,0.78,3.53,0.01,-3.18,2.34,4.8 386 | 201101,2.01,-2.46,0.96,0.01,-0.22,0.02,1.03 387 | 201102,3.85,1.79,1.38,0.01,1.99,-0.99,1.29 388 | 201103,0.28,2.73,-1.31,0.01,3.55,-0.89,-1.91 389 | 201104,2.82,-0.23,-2.31,0,0.07,-1,-2.15 390 | -------------------------------------------------------------------------------- /Data/Readme.md: -------------------------------------------------------------------------------- 1 | Readme for EmpiricalFinance/jl 2 | ============================== 3 | 4 | This folder contains data used in the FinancialEconometrics notebooks. 5 | The data is taken from internet sources (see the lecture notes for detailed references). -------------------------------------------------------------------------------- /Data/RvSP500.csv: -------------------------------------------------------------------------------- 1 | 1970.0,2.0,2.52351 2 | 1970.0,3.0,2.37335 3 | 1970.0,4.0,2.62981 4 | 1970.0,5.0,3.42307 5 | 1970.0,6.0,2.86661 6 | 1970.0,7.0,2.7344 7 | 1970.0,8.0,2.66761 8 | 1970.0,9.0,2.39748 9 | 1970.0,10.0,2.39592 10 | 1970.0,11.0,2.31199 11 | 1970.0,12.0,2.02459 12 | 1971.0,1.0,2.04573 13 | 1971.0,2.0,2.08378 14 | 1971.0,3.0,1.98867 15 | 1971.0,4.0,1.76201 16 | 1971.0,5.0,2.13071 17 | 1971.0,6.0,2.28925 18 | 1971.0,7.0,2.15775 19 | 1971.0,8.0,2.81477 20 | 1971.0,9.0,2.07942 21 | 1971.0,10.0,2.19859 22 | 1971.0,11.0,2.68509 23 | 1971.0,12.0,2.41983 24 | 1972.0,1.0,2.00821 25 | 1972.0,2.0,1.7887 26 | 1972.0,3.0,2.06631 27 | 1972.0,4.0,1.9966 28 | 1972.0,5.0,2.23315 29 | 1972.0,6.0,1.8898 30 | 1972.0,7.0,2.12161 31 | 1972.0,8.0,2.01634 32 | 1972.0,9.0,2.02758 33 | 1972.0,10.0,2.29172 34 | 1972.0,11.0,2.05816 35 | 1972.0,12.0,2.0419 36 | 1973.0,1.0,2.1272 37 | 1973.0,2.0,2.50708 38 | 1973.0,3.0,2.59297 39 | 1973.0,4.0,2.6516 40 | 1973.0,5.0,2.93484 41 | 1973.0,6.0,2.77793 42 | 1973.0,7.0,2.68201 43 | 1973.0,8.0,2.34449 44 | 1973.0,9.0,2.37716 45 | 1973.0,10.0,2.51761 46 | 1973.0,11.0,3.12784 47 | 1973.0,12.0,3.22866 48 | 1974.0,1.0,2.98494 49 | 1974.0,2.0,2.72319 50 | 1974.0,3.0,2.64046 51 | 1974.0,4.0,2.6759 52 | 1974.0,5.0,2.74695 53 | 1974.0,6.0,2.79776 54 | 1974.0,7.0,3.17242 55 | 1974.0,8.0,3.16048 56 | 1974.0,9.0,3.46652 57 | 1974.0,10.0,3.52059 58 | 1974.0,11.0,3.06175 59 | 1974.0,12.0,3.0418 60 | 1975.0,1.0,3.05622 61 | 1975.0,2.0,2.86378 62 | 1975.0,3.0,2.80349 63 | 1975.0,4.0,2.7836 64 | 1975.0,5.0,2.7516 65 | 1975.0,6.0,2.60053 66 | 1975.0,7.0,2.49901 67 | 1975.0,8.0,2.7999 68 | 1975.0,9.0,2.79917 69 | 1975.0,10.0,2.71289 70 | 1975.0,11.0,2.35655 71 | 1975.0,12.0,2.51701 72 | 1976.0,1.0,2.69778 73 | 1976.0,2.0,2.5921 74 | 1976.0,3.0,2.47986 75 | 1976.0,4.0,2.40298 76 | 1976.0,5.0,2.35755 77 | 1976.0,6.0,2.34325 78 | 1976.0,7.0,2.03232 79 | 1976.0,8.0,2.22674 80 | 1976.0,9.0,2.33804 81 | 1976.0,10.0,2.49755 82 | 1976.0,11.0,2.49433 83 | 1976.0,12.0,2.06644 84 | 1977.0,1.0,2.23209 85 | 1977.0,2.0,1.89367 86 | 1977.0,3.0,2.1251 87 | 1977.0,4.0,2.43154 88 | 1977.0,5.0,2.16065 89 | 1977.0,6.0,2.05964 90 | 1977.0,7.0,2.1879 91 | 1977.0,8.0,2.10939 92 | 1977.0,9.0,2.00435 93 | 1977.0,10.0,2.26032 94 | 1977.0,11.0,2.53234 95 | 1977.0,12.0,2.14244 96 | 1978.0,1.0,2.34705 97 | 1978.0,2.0,2.23221 98 | 1978.0,3.0,2.12226 99 | 1978.0,4.0,2.63675 100 | 1978.0,5.0,2.41096 101 | 1978.0,6.0,2.39074 102 | 1978.0,7.0,2.27099 103 | 1978.0,8.0,2.36483 104 | 1978.0,9.0,2.35052 105 | 1978.0,10.0,2.75687 106 | 1978.0,11.0,3.00934 107 | 1978.0,12.0,2.71201 108 | 1979.0,1.0,2.35898 109 | 1979.0,2.0,2.3755 110 | 1979.0,3.0,2.23794 111 | 1979.0,4.0,2.17083 112 | 1979.0,5.0,2.34104 113 | 1979.0,6.0,2.07044 114 | 1979.0,7.0,2.19537 115 | 1979.0,8.0,1.98718 116 | 1979.0,9.0,2.47838 117 | 1979.0,10.0,2.8454 118 | 1979.0,11.0,2.60753 119 | 1979.0,12.0,2.02574 120 | 1980.0,1.0,2.68369 121 | 1980.0,2.0,2.73701 122 | 1980.0,3.0,3.15713 123 | 1980.0,4.0,2.90405 124 | 1980.0,5.0,2.57159 125 | 1980.0,6.0,2.54822 126 | 1980.0,7.0,2.51038 127 | 1980.0,8.0,2.6446 128 | 1980.0,9.0,2.85716 129 | 1980.0,10.0,2.72041 130 | 1980.0,11.0,2.84987 131 | 1980.0,12.0,2.91577 132 | 1981.0,1.0,2.61738 133 | 1981.0,2.0,2.60427 134 | 1981.0,3.0,2.73041 135 | 1981.0,4.0,2.37324 136 | 1981.0,5.0,2.38358 137 | 1981.0,6.0,2.37279 138 | 1981.0,7.0,2.42058 139 | 1981.0,8.0,2.69503 140 | 1981.0,9.0,2.90535 141 | 1981.0,10.0,2.72893 142 | 1981.0,11.0,2.72794 143 | 1981.0,12.0,2.33327 144 | 1982.0,1.0,2.84078 145 | 1982.0,2.0,2.89667 146 | 1982.0,3.0,2.66491 147 | 1982.0,4.0,2.47403 148 | 1982.0,5.0,2.3633 149 | 1982.0,6.0,2.57518 150 | 1982.0,7.0,2.37409 151 | 1982.0,8.0,3.29366 152 | 1982.0,9.0,2.80072 153 | 1982.0,10.0,3.27993 154 | 1982.0,11.0,3.21916 155 | 1982.0,12.0,2.82512 156 | 1983.0,1.0,2.96239 157 | 1983.0,2.0,2.78424 158 | 1983.0,3.0,2.46274 159 | 1983.0,4.0,2.58044 160 | 1983.0,5.0,2.451 161 | 1983.0,6.0,2.51658 162 | 1983.0,7.0,2.80776 163 | 1983.0,8.0,2.52063 164 | 1983.0,9.0,2.44804 165 | 1983.0,10.0,2.45337 166 | 1983.0,11.0,2.27478 167 | 1983.0,12.0,2.13578 168 | 1984.0,1.0,2.26064 169 | 1984.0,2.0,2.74226 170 | 1984.0,3.0,2.51967 171 | 1984.0,4.0,2.39322 172 | 1984.0,5.0,2.35831 173 | 1984.0,6.0,2.626 174 | 1984.0,7.0,2.30789 175 | 1984.0,8.0,2.84077 176 | 1984.0,9.0,2.35153 177 | 1984.0,10.0,2.46521 178 | 1984.0,11.0,2.39908 179 | 1984.0,12.0,2.47502 180 | 1985.0,1.0,2.60202 181 | 1985.0,2.0,2.2815 182 | 1985.0,3.0,2.26677 183 | 1985.0,4.0,2.02391 184 | 1985.0,5.0,2.25951 185 | 1985.0,6.0,2.27193 186 | 1985.0,7.0,2.20905 187 | 1985.0,8.0,2.14732 188 | 1985.0,9.0,2.32197 189 | 1985.0,10.0,2.13744 190 | 1985.0,11.0,2.32938 191 | 1985.0,12.0,2.46468 192 | 1986.0,1.0,2.69675 193 | 1986.0,2.0,2.46254 194 | 1986.0,3.0,2.56712 195 | 1986.0,4.0,2.82261 196 | 1986.0,5.0,2.65979 197 | 1986.0,6.0,2.60462 198 | 1986.0,7.0,2.82011 199 | 1986.0,8.0,2.47076 200 | 1986.0,9.0,3.09603 201 | 1986.0,10.0,2.29891 202 | 1986.0,11.0,2.6883 203 | 1986.0,12.0,2.49527 204 | 1987.0,1.0,2.8134 205 | 1987.0,2.0,2.55407 206 | 1987.0,3.0,2.70582 207 | 1987.0,4.0,3.09649 208 | 1987.0,5.0,2.86779 209 | 1987.0,6.0,2.39073 210 | 1987.0,7.0,2.25153 211 | 1987.0,8.0,2.65243 212 | 1987.0,9.0,2.85175 213 | 1987.0,10.0,4.50243 214 | 1987.0,11.0,3.52386 215 | 1987.0,12.0,3.32935 216 | 1988.0,1.0,3.48615 217 | 1988.0,2.0,2.80613 218 | 1988.0,3.0,2.62904 219 | 1988.0,4.0,3.00132 220 | 1988.0,5.0,2.84482 221 | 1988.0,6.0,2.79444 222 | 1988.0,7.0,2.72288 223 | 1988.0,8.0,2.54529 224 | 1988.0,9.0,2.4556 225 | 1988.0,10.0,2.61301 226 | 1988.0,11.0,2.52575 227 | 1988.0,12.0,2.20539 228 | 1989.0,1.0,2.35072 229 | 1989.0,2.0,2.51098 230 | 1989.0,3.0,2.49186 231 | 1989.0,4.0,2.36257 232 | 1989.0,5.0,2.3959 233 | 1989.0,6.0,2.55169 234 | 1989.0,7.0,2.52528 235 | 1989.0,8.0,2.5102 236 | 1989.0,9.0,2.08443 237 | 1989.0,10.0,3.23525 238 | 1989.0,11.0,2.40654 239 | 1989.0,12.0,2.37342 240 | 1990.0,1.0,2.90986 241 | 1990.0,2.0,2.54047 242 | 1990.0,3.0,2.37959 243 | 1990.0,4.0,2.37537 244 | 1990.0,5.0,2.50351 245 | 1990.0,6.0,2.52391 246 | 1990.0,7.0,2.50336 247 | 1990.0,8.0,3.25711 248 | 1990.0,9.0,2.83444 249 | 1990.0,10.0,3.0211 250 | 1990.0,11.0,2.80883 251 | 1990.0,12.0,2.43185 252 | 1991.0,1.0,2.94701 253 | 1991.0,2.0,2.86353 254 | 1991.0,3.0,2.5872 255 | 1991.0,4.0,2.73524 256 | 1991.0,5.0,2.59382 257 | 1991.0,6.0,2.53012 258 | 1991.0,7.0,2.40812 259 | 1991.0,8.0,2.72363 260 | 1991.0,9.0,2.02287 261 | 1991.0,10.0,2.42272 262 | 1991.0,11.0,2.74023 263 | 1991.0,12.0,2.71597 264 | 1992.0,1.0,2.31101 265 | 1992.0,2.0,2.41881 266 | 1992.0,3.0,2.01048 267 | 1992.0,4.0,2.61917 268 | 1992.0,5.0,2.24836 269 | 1992.0,6.0,2.23775 270 | 1992.0,7.0,2.30332 271 | 1992.0,8.0,1.89672 272 | 1992.0,9.0,2.30284 273 | 1992.0,10.0,2.34213 274 | 1992.0,11.0,2.04606 275 | 1992.0,12.0,1.98992 276 | 1993.0,1.0,1.91713 277 | 1993.0,2.0,2.44616 278 | 1993.0,3.0,2.36185 279 | 1993.0,4.0,2.3828 280 | 1993.0,5.0,2.26755 281 | 1993.0,6.0,2.09431 282 | 1993.0,7.0,2.12774 283 | 1993.0,8.0,1.69956 284 | 1993.0,9.0,2.01398 285 | 1993.0,10.0,1.78785 286 | 1993.0,11.0,2.10426 287 | 1993.0,12.0,1.70712 288 | 1994.0,1.0,1.94784 289 | 1994.0,2.0,2.44126 290 | 1994.0,3.0,2.3112 291 | 1994.0,4.0,2.689 292 | 1994.0,5.0,2.23203 293 | 1994.0,6.0,2.26974 294 | 1994.0,7.0,1.88747 295 | 1994.0,8.0,2.02866 296 | 1994.0,9.0,2.27461 297 | 1994.0,10.0,2.439 298 | 1994.0,11.0,2.30427 299 | 1994.0,12.0,2.20072 300 | 1995.0,1.0,1.76087 301 | 1995.0,2.0,2.01702 302 | 1995.0,3.0,1.97511 303 | 1995.0,4.0,1.6965 304 | 1995.0,5.0,2.36535 305 | 1995.0,6.0,2.18128 306 | 1995.0,7.0,2.23304 307 | 1995.0,8.0,1.53459 308 | 1995.0,9.0,1.861 309 | 1995.0,10.0,2.01664 310 | 1995.0,11.0,2.05551 311 | 1995.0,12.0,2.27742 312 | 1996.0,1.0,2.52595 313 | 1996.0,2.0,2.5493 314 | 1996.0,3.0,2.66094 315 | 1996.0,4.0,2.37382 316 | 1996.0,5.0,2.4237 317 | 1996.0,6.0,1.96116 318 | 1996.0,7.0,2.80571 319 | 1996.0,8.0,2.42319 320 | 1996.0,9.0,2.29417 321 | 1996.0,10.0,2.1033 322 | 1996.0,11.0,2.18841 323 | 1996.0,12.0,2.64478 324 | 1997.0,1.0,2.51022 325 | 1997.0,2.0,2.65965 326 | 1997.0,3.0,2.77519 327 | 1997.0,4.0,2.91455 328 | 1997.0,5.0,2.73 329 | 1997.0,6.0,2.70924 330 | 1997.0,7.0,2.70752 331 | 1997.0,8.0,2.83046 332 | 1997.0,9.0,2.85173 333 | 1997.0,10.0,3.48634 334 | 1997.0,11.0,2.93269 335 | 1997.0,12.0,2.77384 336 | 1998.0,1.0,2.8833 337 | 1998.0,2.0,2.45057 338 | 1998.0,3.0,2.42035 339 | 1998.0,4.0,2.62421 340 | 1998.0,5.0,2.49362 341 | 1998.0,6.0,2.73514 342 | 1998.0,7.0,2.77336 343 | 1998.0,8.0,3.51316 344 | 1998.0,9.0,3.71109 345 | 1998.0,10.0,3.18708 346 | 1998.0,11.0,2.78691 347 | 1998.0,12.0,2.96008 348 | 1999.0,1.0,3.00445 349 | 1999.0,2.0,3.06239 350 | 1999.0,3.0,2.94977 351 | 1999.0,4.0,2.89111 352 | 1999.0,5.0,2.94891 353 | 1999.0,6.0,2.80311 354 | 1999.0,7.0,2.68393 355 | 1999.0,8.0,2.87365 356 | 1999.0,9.0,2.87356 357 | 1999.0,10.0,3.17085 358 | 1999.0,11.0,2.5949 359 | 1999.0,12.0,2.4242 360 | 2000.0,1.0,3.19963 361 | 2000.0,2.0,3.11201 362 | 2000.0,3.0,3.30917 363 | 2000.0,4.0,3.42282 364 | 2000.0,5.0,3.1949 365 | 2000.0,6.0,2.79677 366 | 2000.0,7.0,2.76989 367 | 2000.0,8.0,2.36021 368 | 2000.0,9.0,2.65284 369 | 2000.0,10.0,3.22937 370 | 2000.0,11.0,3.03769 371 | 2000.0,12.0,3.24339 372 | 2001.0,1.0,3.17828 373 | 2001.0,2.0,2.87008 374 | 2001.0,3.0,3.3564 375 | 2001.0,4.0,3.37862 376 | 2001.0,5.0,2.83548 377 | 2001.0,6.0,2.59334 378 | 2001.0,7.0,2.90496 379 | 2001.0,8.0,2.77695 380 | 2001.0,9.0,3.4295 381 | 2001.0,10.0,2.9571 382 | 2001.0,11.0,2.75154 383 | 2001.0,12.0,2.69032 384 | 2002.0,1.0,2.79292 385 | 2002.0,2.0,3.03328 386 | 2002.0,3.0,2.71768 387 | 2002.0,4.0,2.80059 388 | 2002.0,5.0,3.07705 389 | 2002.0,6.0,3.03441 390 | 2002.0,7.0,3.73776 391 | 2002.0,8.0,3.49104 392 | 2002.0,9.0,3.37452 393 | 2002.0,10.0,3.51972 394 | 2002.0,11.0,3.12638 395 | 2002.0,12.0,2.86563 396 | 2003.0,1.0,3.1935 397 | 2003.0,2.0,2.9704 398 | 2003.0,3.0,3.27865 399 | 2003.0,4.0,2.97361 400 | 2003.0,5.0,2.7644 401 | 2003.0,6.0,2.76421 402 | 2003.0,7.0,2.7264 403 | 2003.0,8.0,2.35144 404 | 2003.0,9.0,2.69195 405 | 2003.0,10.0,2.31208 406 | 2003.0,11.0,2.33405 407 | 2003.0,12.0,2.29678 408 | 2004.0,1.0,2.35643 409 | 2004.0,2.0,2.27697 410 | 2004.0,3.0,2.69345 411 | 2004.0,4.0,2.48014 412 | 2004.0,5.0,2.40588 413 | 2004.0,6.0,2.2344 414 | 2004.0,7.0,2.26897 415 | 2004.0,8.0,2.55395 416 | 2004.0,9.0,2.20626 417 | 2004.0,10.0,2.47142 418 | 2004.0,11.0,2.28231 419 | 2004.0,12.0,2.19856 420 | 2005.0,1.0,2.28526 421 | 2005.0,2.0,2.31733 422 | 2005.0,3.0,2.30367 423 | 2005.0,4.0,2.67542 424 | 2005.0,5.0,2.3584 425 | 2005.0,6.0,2.06595 426 | 2005.0,7.0,2.18259 427 | 2005.0,8.0,2.19643 428 | 2005.0,9.0,2.22547 429 | 2005.0,10.0,2.67318 430 | 2005.0,11.0,2.08576 431 | 2005.0,12.0,2.00417 432 | 2006.0,1.0,2.36984 433 | 2006.0,2.0,2.2094 434 | 2006.0,3.0,1.99915 435 | 2006.0,4.0,2.16381 436 | 2006.0,5.0,2.52933 437 | 2006.0,6.0,2.74194 438 | 2006.0,7.0,2.69266 439 | 2006.0,8.0,1.94795 440 | 2006.0,9.0,2.03056 441 | 2006.0,10.0,1.95062 442 | 2006.0,11.0,2.09992 443 | 2006.0,12.0,1.9487 444 | 2007.0,1.0,1.993 445 | 2007.0,2.0,2.59411 446 | 2007.0,3.0,2.6001 447 | 2007.0,4.0,2.0878 448 | 2007.0,5.0,2.17577 449 | 2007.0,6.0,2.56862 450 | 2007.0,7.0,2.81915 451 | 2007.0,8.0,3.183 452 | 2007.0,9.0,2.81882 453 | 2007.0,10.0,2.57561 454 | 2007.0,11.0,3.24969 455 | 2007.0,12.0,2.81029 456 | 2008.0,1.0,3.16775 457 | 2008.0,2.0,3.00348 458 | 2008.0,3.0,3.35612 459 | 2008.0,4.0,2.89838 460 | 2008.0,5.0,2.62173 461 | 2008.0,6.0,2.99511 462 | 2008.0,7.0,3.11956 463 | 2008.0,8.0,3.01408 464 | 2008.0,9.0,3.96014 465 | 2008.0,10.0,4.40219 466 | 2008.0,11.0,4.18003 467 | 2008.0,12.0,3.87036 468 | 2009.0,1.0,3.64519 469 | 2009.0,2.0,3.64502 470 | 2009.0,3.0,3.87593 471 | 2009.0,4.0,3.38815 472 | 2009.0,5.0,3.32903 473 | 2009.0,6.0,2.99309 474 | 2009.0,7.0,3.02796 475 | 2009.0,8.0,2.75496 476 | 2009.0,9.0,2.70738 477 | 2009.0,10.0,3.05256 478 | 2009.0,11.0,2.96202 479 | 2009.0,12.0,2.33087 480 | 2010.0,1.0,2.74833 481 | 2010.0,2.0,2.85349 482 | 2010.0,3.0,2.02506 483 | 2010.0,4.0,2.64778 484 | 2010.0,5.0,3.44705 485 | 2010.0,6.0,3.23447 486 | 2010.0,7.0,2.98455 487 | 2010.0,8.0,2.8742 488 | 2010.0,9.0,2.78319 489 | 2010.0,10.0,2.40413 490 | 2010.0,11.0,2.64795 491 | 2010.0,12.0,2.25399 492 | 2011.0,1.0,2.29152 493 | 2011.0,2.0,2.55087 494 | 2011.0,3.0,2.7394 495 | 2011.0,4.0,2.16638 496 | 2011.0,5.0,2.34439 497 | 2011.0,6.0,2.78883 498 | 2011.0,7.0,2.7185 499 | 2011.0,8.0,3.84891 500 | 2011.0,9.0,3.34248 501 | 2011.0,10.0,3.40852 502 | 2011.0,11.0,3.42929 503 | 2011.0,12.0,3.13431 504 | 2012.0,1.0,2.22713 505 | 2012.0,2.0,2.12168 506 | 2012.0,3.0,2.43458 507 | 2012.0,4.0,2.58653 508 | 2012.0,5.0,2.58675 509 | 2012.0,6.0,2.98522 510 | 2012.0,7.0,2.75342 511 | 2012.0,8.0,2.19577 512 | 2012.0,9.0,2.42689 513 | 2012.0,10.0,2.39525 514 | 2012.0,11.0,2.69235 515 | 2012.0,12.0,2.39413 516 | 2013.0,1.0,2.4412 517 | 2013.0,2.0,2.49633 518 | 2013.0,3.0,2.12988 519 | 2013.0,4.0,2.6277 520 | 2013.0,5.0,2.37247 521 | 2013.0,6.0,2.82556 522 | 2013.0,7.0,1.99528 523 | 2013.0,8.0,2.35718 524 | 2013.0,9.0,2.1312 525 | 2013.0,10.0,2.52151 526 | 2013.0,11.0,2.17212 527 | 2013.0,12.0,2.21541 528 | 2014.0,1.0,2.51785 529 | 2014.0,2.0,2.57456 530 | 2014.0,3.0,2.30227 531 | 2014.0,4.0,2.54513 532 | 2014.0,5.0,2.07207 533 | 2014.0,6.0,1.72306 534 | 2014.0,7.0,2.35079 535 | 2014.0,8.0,2.33802 536 | 2014.0,9.0,2.22159 537 | 2014.0,10.0,2.87553 538 | 2014.0,11.0,1.77481 539 | 2014.0,12.0,2.71641 540 | 2015.0,1.0,2.80606 541 | 2015.0,2.0,2.47531 542 | 2015.0,3.0,2.64568 543 | 2015.0,4.0,2.23094 544 | 2015.0,5.0,2.37448 545 | 2015.0,6.0,2.40356 546 | 2015.0,7.0,2.43985 547 | 2015.0,8.0,3.25772 548 | 2015.0,9.0,3.08185 549 | 2015.0,10.0,2.59529 550 | 2015.0,11.0,2.43921 551 | 2015.0,12.0,2.89445 552 | 2016.0,1.0,3.13293 553 | 2016.0,2.0,2.95662 554 | 2016.0,3.0,2.47546 555 | 2016.0,4.0,2.27348 556 | 2016.0,5.0,2.37869 557 | 2016.0,6.0,2.89682 558 | 2016.0,7.0,2.32353 559 | 2016.0,8.0,1.73376 560 | 2016.0,9.0,2.63079 561 | 2016.0,10.0,1.95728 562 | 2016.0,11.0,2.33216 563 | 2016.0,12.0,2.04648 564 | 2017.0,1.0,1.84695 565 | 2017.0,2.0,1.66678 566 | 2017.0,3.0,1.91228 567 | 2017.0,4.0,1.913 568 | 2017.0,5.0,2.02161 569 | 2017.0,6.0,1.9675 570 | 2017.0,7.0,1.81532 571 | 2017.0,8.0,2.2272 572 | 2017.0,9.0,1.75841 573 | 2017.0,10.0,1.58031 574 | 2017.0,11.0,1.8303 575 | 2017.0,12.0,1.77178 576 | -------------------------------------------------------------------------------- /FinEcmtAll.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PaulSoderlind/FinancialEconometrics/1971ec498566eaa41f27bca5eb72c76726aa25b3/FinEcmtAll.pdf -------------------------------------------------------------------------------- /JuliaOnColab_OLS.ipynb: -------------------------------------------------------------------------------- 1 | {"cells":[{"cell_type":"markdown","metadata":{"id":"71-TZ-kkQity"},"source":["# A Julia Note at Colab\n","\n","This notebook gives instructions for getting started with using Julia at Colab. The basic issues are: (1) how to make Colab aware of my files located at \"My Drive\" (2) how to load packages and (3) how to load a local module?"]},{"cell_type":"markdown","metadata":{"id":"UpFAlwlJQit0"},"source":["## Mounting My Drive\n","\n","There is currently no Julia command for this, but can be done in Python. Therefore, change the \"Runtime type\" (see \"Connect\" at the top right menu bar) to Python. Run the next cell, and then change back to Julia."]},{"cell_type":"code","source":["from google.colab import drive #do this in Python, then switch to Julia\n","drive.mount('/content/drive')"],"metadata":{"id":"BBVGw412QkuE","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1742630086173,"user_tz":-60,"elapsed":23380,"user":{"displayName":"Paul Soderlind","userId":"17308914881026729518"}},"outputId":"6af4548a-80d7-4c33-b495-713cbdf9ac70"},"execution_count":1,"outputs":[{"output_type":"stream","name":"stdout","text":["Mounted at /content/drive\n"]}]},{"cell_type":"markdown","source":["## Import Packages\n","\n","Colab has a very short list of installed packages, so you probably have to add some. This has (currently) to be done for each session. For the ?\n","`FinEcmt_OLS` module, you need the packes added in the next cell."],"metadata":{"id":"zZKifsZU2PYB"}},{"cell_type":"code","source":["import Pkg\n","Pkg.add([\"Distributions\",\"StatsBase\",\"FiniteDiff\"])"],"metadata":{"id":"B8h-t_4KR6fm","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1742630332326,"user_tz":-60,"elapsed":57298,"user":{"displayName":"Paul Soderlind","userId":"17308914881026729518"}},"outputId":"57f88ef2-0203-4b44-de17-3b76cba63074"},"execution_count":1,"outputs":[{"output_type":"stream","name":"stderr","text":["\u001b[32m\u001b[1m Updating\u001b[22m\u001b[39m registry at `~/.julia/registries/General.toml`\n","\u001b[32m\u001b[1m Resolving\u001b[22m\u001b[39m package versions...\n","\u001b[32m\u001b[1m Installed\u001b[22m\u001b[39m FiniteDiff ─ v2.27.0\n","\u001b[32m\u001b[1m Updating\u001b[22m\u001b[39m `~/.julia/environments/v1.10/Project.toml`\n"," \u001b[90m[31c24e10] \u001b[39m\u001b[92m+ Distributions v0.25.118\u001b[39m\n"," \u001b[90m[6a86dc24] \u001b[39m\u001b[92m+ FiniteDiff v2.27.0\u001b[39m\n"," \u001b[90m[2913bbd2] \u001b[39m\u001b[92m+ StatsBase v0.34.4\u001b[39m\n","\u001b[32m\u001b[1m Updating\u001b[22m\u001b[39m `~/.julia/environments/v1.10/Manifest.toml`\n"," \u001b[90m[6a86dc24] \u001b[39m\u001b[92m+ FiniteDiff v2.27.0\u001b[39m\n","\u001b[32m\u001b[1mPrecompiling\u001b[22m\u001b[39m packages...\n"," 2644.3 ms\u001b[32m ✓ \u001b[39mFiniteDiff\n"," 2109.5 ms\u001b[32m ✓ \u001b[39mFiniteDiff → FiniteDiffSparseArraysExt\n"," 2264.9 ms\u001b[32m ✓ \u001b[39mFiniteDiff → FiniteDiffStaticArraysExt\n"," 3 dependencies successfully precompiled in 16 seconds. 460 already precompiled.\n"]}]},{"cell_type":"markdown","source":["# Load the `FinEcmt_OLS` module. It is on \"My Drive\"\n","\n","Then load some extra packages that actually are installed on Colab."],"metadata":{"id":"76s3lcY93e-Z"}},{"cell_type":"code","execution_count":2,"metadata":{"id":"pViIYEstQit0","executionInfo":{"status":"ok","timestamp":1742630503611,"user_tz":-60,"elapsed":14694,"user":{"displayName":"Paul Soderlind","userId":"17308914881026729518"}}},"outputs":[],"source":["myfolder = \"/content/drive/My Drive/Test\" #Julia code\n","readdir(myfolder)\n","\n","include(joinpath(myfolder,\"src\",\"FinEcmt_OLS.jl\"))\n","using .FinEcmt_OLS"]},{"cell_type":"code","execution_count":3,"metadata":{"id":"-n1bRNC5Qit1","executionInfo":{"status":"ok","timestamp":1742630520451,"user_tz":-60,"elapsed":10,"user":{"displayName":"Paul Soderlind","userId":"17308914881026729518"}}},"outputs":[],"source":["using Statistics, DelimitedFiles, LinearAlgebra"]},{"cell_type":"markdown","metadata":{"id":"Qc8W2TFEQit1"},"source":["# Start Working..."]},{"cell_type":"code","execution_count":4,"metadata":{"id":"P2oCwkV1Qit1","outputId":"ce1916f1-27cf-45c3-95b2-bf322ce37da9","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1742630527846,"user_tz":-60,"elapsed":2466,"user":{"displayName":"Paul Soderlind","userId":"17308914881026729518"}}},"outputs":[{"output_type":"stream","name":"stdout","text":["Sample size: (388,)\n"]}],"source":["x = readdlm(joinpath(myfolder,\"Data/FFmFactorsPs.csv\"),',',skipstart=1)\n","\n"," #yearmonth, market, small minus big, high minus low\n","(ym,Rme,RSMB,RHML) = (x[:,1],x[:,2]/100,x[:,3]/100,x[:,4]/100)\n","x = nothing\n","\n","printlnPs(\"Sample size:\",size(Rme))"]},{"cell_type":"code","execution_count":5,"metadata":{"id":"872lBnZvQit2","outputId":"ebee9fe4-9157-4988-b4bb-e2aba80b7329","colab":{"base_uri":"https://localhost:8080/","height":271},"executionInfo":{"status":"ok","timestamp":1742630540726,"user_tz":-60,"elapsed":2147,"user":{"displayName":"Paul Soderlind","userId":"17308914881026729518"}}},"outputs":[{"output_type":"display_data","data":{"text/markdown":"```\nOlsGM(Y,X)\n```\n\nLS of Y on X; for one dependent variable, Gauss-Markov assumptions\n\n### Input\n\n * `Y::Vector`: T-vector, the dependent variable\n * `X::Matrix`: Txk matrix of regressors (including deterministic ones)\n\n### Output\n\n * `b::Vector`: k-vector, regression coefficients\n * `u::Vector`: T-vector, residuals Y - yhat\n * `Yhat::Vector`: T-vector, fitted values X*b\n * `V::Matrix`: kxk matrix, covariance matrix of b\n * `R²::Number`: scalar, R² value\n"},"metadata":{}}],"source":["@doc2 OlsGM"]},{"cell_type":"markdown","metadata":{"id":"Krl0zCQiQit2"},"source":["## OLS Regression"]},{"cell_type":"code","execution_count":6,"metadata":{"id":"QYlUhHxpQit2","outputId":"3ef051f9-bd9c-422b-e022-adbfa66bc965","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1742630562214,"user_tz":-60,"elapsed":5838,"user":{"displayName":"Paul Soderlind","userId":"17308914881026729518"}}},"outputs":[{"output_type":"stream","name":"stdout","text":["\u001b[34m\u001b[1mOLS Results:\u001b[22m\u001b[39m\n","\n"," b std\n","c 0.007 0.002\n","SMB 0.217 0.073\n","HML -0.429 0.074\n","\n"," R²: 0.134\n"]}],"source":["Y = Rme #to get standard OLS notation\n","T = size(Y,1)\n","X = [ones(T) RSMB RHML]\n","\n","(b,_,_,V,R²) = OlsGM(Y,X)\n","Stdb = sqrt.(diag(V)) #standard errors\n","\n","printblue(\"OLS Results:\\n\")\n","xNames = [\"c\",\"SMB\",\"HML\"]\n","printmat(b,Stdb,colNames=[\"b\",\"std\"],rowNames=xNames)\n","\n","printlnPs(\"R²: \",R²)"]},{"cell_type":"code","execution_count":7,"metadata":{"id":"0Ql-pKR2Qit2","outputId":"88f1feb0-6485-40b6-f30d-88874a5c00de","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1742630565249,"user_tz":-60,"elapsed":631,"user":{"displayName":"Paul Soderlind","userId":"17308914881026729518"}}},"outputs":[{"output_type":"stream","name":"stdout","text":[" coef stderr t-stat p-value\n","c 0.007 0.002 3.175 0.001\n","SMB 0.217 0.073 2.957 0.003\n","HML -0.429 0.074 -5.836 0.000\n","\n"]}],"source":["RegressionTable(b,V,[\"c\",\"SMB\",\"HML\"]) #a function for printing regression results"]},{"cell_type":"code","execution_count":null,"metadata":{"id":"3gDimuusQit3"},"outputs":[],"source":[]}],"metadata":{"@webio":{"lastCommId":null,"lastKernelId":null},"anaconda-cloud":{},"kernelspec":{"display_name":"Julia","name":"julia"},"language_info":{"name":"julia"},"colab":{"provenance":[]}},"nbformat":4,"nbformat_minor":0} -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | Copyright (c) 2019 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 | -------------------------------------------------------------------------------- /NotebooksAsPdf.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PaulSoderlind/FinancialEconometrics/1971ec498566eaa41f27bca5eb72c76726aa25b3/NotebooksAsPdf.pdf -------------------------------------------------------------------------------- /Readme.md: -------------------------------------------------------------------------------- 1 | # Introduction 2 | 3 | This repository contains Julia code for a Financial Econometrics (MSc) course at UNISG. 4 | 5 | 6 | # Instructions 7 | 8 | 1. Most files are jupyter notebooks. Click one of them to see it online. If GitHub fails to render the notebook or messes up the LaTeX in the Markdown cells, then use [nbviewer](https://nbviewer.jupyter.org/). Instructions: try to open the notebook at GitHub, copy the link and paste it in the address field of nbviewer. 9 | 10 | 2. A pdf file contains print-outs of all notebooks. 11 | 12 | 3. To download this repository, use the Download (as zip) in the Github menu. Otherwise, clone it. 13 | 14 | 4. To get started, please check the *Ch00_HowToUse.ipynb* notebook first. 15 | 16 | 17 | # On the Files 18 | 19 | 1. ChapterNumber_Topic.ipynb are notebooks organised around different topics. The chapter numbers correspond to the lecture notes (pdf), where more details are given (and the notation is explained). 20 | 21 | 2. Most statistical/econometric functions are organised in local modules, typically loaded at the top of the notebooks. The source code is in the src subfolder. 22 | 23 | 3. NotebooksAsPDF.pdf is a print-out of all notebooks. 24 | 25 | 4. The pdf file contains the lecture notes. 26 | 27 | 5. The folder Data contains some data sets used in the notebooks. 28 | 29 | 6. The plots are in png format. If you want sharper plots, change `default(fmt = :png)` to `default(fmt = :svg)` in one of the top cells. 30 | 31 | 7. The current version is tested on Julia 1.11. 32 | 33 | 34 | # Relation to Other Julia Econometrics Codes 35 | 36 | The notebooks are closely tied to my lecture notes. The focus is on learning, so most methods are built from scratch. For instance, to estimate a GARCH model, the notebook builds the likelihood function, calls on a routine for optimisation (for the point estimates) and then differentiation (for the standard errors). 37 | 38 | See [Michael Creel's code](https://github.com/mcreel/Econometrics) 39 | for a similar approach (also focused on teaching) 40 | 41 | The following packages provide more convenient (and often more powerful) routines: 42 | 43 | [GLM.jl](https://github.com/JuliaStats/GLM.jl) 44 | for regressions 45 | 46 | [CovarianceMatrices.jl](https://github.com/gragusa/CovarianceMatrices.jl) 47 | for robust (heteroskedasticity and/or autocorrelation) covariance estimates 48 | 49 | [HypothesisTests.jl](https://github.com/JuliaStats/HypothesisTests.jl) 50 | for testing residuals and distributions 51 | 52 | [ARCHModels.jl](https://github.com/s-broda/ARCHModels.jl) 53 | for estimating ARCH and GARCH models 54 | 55 | [KernelDensity.jl](https://github.com/JuliaStats/KernelDensity.jl) 56 | for kernel density estimation 57 | 58 | [QuantileRegressions.jl](https://github.com/pkofod/QuantileRegressions.jl) 59 | for quantile regressions 60 | -------------------------------------------------------------------------------- /src/BinScatter.jl: -------------------------------------------------------------------------------- 1 | """ 2 | BinScatter(y,x₁,x₂,L=[],U=[],N=20,critval=1.645) 3 | 4 | Do a regression `y = x₁'γ + d'β + u`, where `d` is an N-vector indicating 5 | membership in a certain `x₂` bin. Plotting `β` against those bins is a binscatter plot. 6 | 7 | ### Input: 8 | - `y::Vector`: dependent variable 9 | - `x₁::VecOrMat`: control variables 10 | - `x₂::Vector`: main regressor of interest 11 | - `L::Vector`: lower bin boundaries, if [] then quantiles (see N) 12 | - `U::Vector`: upper bin boundaries, if [] then quantiles (see N) 13 | - `N::Vector`: number of quantiles, giving N+1 bins. Used if `L=U=[]` 14 | - `critval::Vector`: for calculation of confidence band 15 | 16 | ### Output 17 | - `β::Vector`: N-vector of coeffs on the bin (x₂) dummies 18 | - `stdβ::Vector`: N-vector of std of β 19 | - `fnO::NamedTuple`: with (LU,confBand) 20 | 21 | """ 22 | function BinScatter(y,x₁,x₂,L=[],U=[],N=20,critval=1.645) 23 | 24 | size(x₂,2) > 1 && error("x₂ must be a vector") 25 | 26 | if isempty(L) && isempty(U) 27 | p = quantile(x₂,range(0,1,1+N)) 28 | L = p[1:end-1] 29 | L[1] -= eps(L[1]) #to make sure minimum(x₂) is in first bin 30 | U = p[2:end] 31 | end 32 | N = length(L) 33 | 34 | (D,D_colchk,y_binchk) = BinDummies(x₂,L,U) 35 | 36 | if any(==(true),y_binchk) || any(==(true),D_colchk) #checking if bins are correct 37 | println("the following x₂ indices are in no bin:") 38 | printmat(findall(==(true),y_binchk)) 39 | println("the following bins are empty:") 40 | printmat(findall(==(true),D_colchk)) 41 | error("some x₂ are in no bin or some bins are empty") 42 | end 43 | 44 | if any(allequal,eachcol(x₁)) && all(==(1),sum(D,dims=2)) 45 | error("don't include a constant in x₁ if the x₂ dummies sum to 1") 46 | end 47 | 48 | if isempty(x₁) #no x₁ controls 49 | (β,_,_,Covβ,) = OlsNW(y,D) 50 | else #with x₁ controls 51 | (b,_,_,Covb,) = OlsNW(y,[D x₁]) 52 | β = b[1:N] #coefs on the dummies in D (for x₂) 53 | Covβ = Covb[1:N,1:N] 54 | #γ = b[N+1:end] #coefs on control variables x₁ 55 | end 56 | stdβ = sqrt.(diag(Covβ)) 57 | confBand = hcat(β - critval*stdβ,β + critval*stdβ) 58 | 59 | LU = [L U] 60 | 61 | fnO = (;LU,confBand) 62 | 63 | return β, stdβ, fnO 64 | 65 | end 66 | 67 | 68 | """ 69 | BinDummies(y::Vector,L,U) 70 | 71 | Creates TxK BitArray `D` where `D[i,k]=true` if `L[k] U) && error("Must have L <= U") 87 | (!issorted(L) || !issorted(U)) && error("L and U must be sorted") 88 | 89 | (T,K) = (length(y),length(L)) 90 | _CompareFn(j,yi,L,U) = L[j]_CompareFn(j,yi,L,U),1:K) #can only be in one bin, findfirst 95 | !isnothing(k) && (D[i,k] = true) 96 | end 97 | (K==1) && (D=vec(D)) #to vector if K == 1 98 | 99 | D_colchk = [all(==(false),col) for col in eachcol(D)] #true if D[:,j] is empty 100 | y_binchk = vec(sum(D,dims=2) .== 0) #true if y[i] is in no group 101 | 102 | return D, D_colchk, y_binchk 103 | 104 | end 105 | -------------------------------------------------------------------------------- /src/CovNW.jl: -------------------------------------------------------------------------------- 1 | """ 2 | CovNW(g0,m=0,DivideByT=0) 3 | 4 | Calculates covariance matrix of sample sum (DivideByT=0), √T*(sample average) (DivideByT=1) 5 | or sample average (DivideByT=2). 6 | 7 | 8 | ### Input 9 | - `g0::Matrix`: Txq matrix of data 10 | - `m::Int`: number of lags to use 11 | - `DivideByT::Int`: divide the result by T^DivideByT 12 | 13 | ### Output 14 | - `S::Matrix`: qxq covariance matrix 15 | 16 | ### Remark 17 | - `DivideByT=0`: Var(g₁+g₂+...), variance of sample sum 18 | - `DivideByT=1`: Var(g₁+g₂+...)/T = Var(√T gbar), where gbar is the sample average. This is 19 | the same as Var(gᵢ) if data is iid 20 | - `DivideByT=2`: Var(g₁+g₂+...)/T^2 = Var(gbar) 21 | 22 | 23 | """ 24 | function CovNW(g0,m=0,DivideByT=0) 25 | 26 | T = size(g0,1) #g0 is Txq 27 | m = min(m,T-1) #number of lags 28 | 29 | g = g0 .- mean(g0,dims=1) #normalizing to zero means 30 | 31 | S = g'g #(qxT)*(Txq) 32 | for s = 1:m 33 | Λ_s = g[s+1:T,:]'g[1:T-s,:] #same as Sum[g_t*g_{t-s}',t=s+1,T] 34 | S = S + (1 - s/(m+1))*(Λ_s + Λ_s') 35 | end 36 | 37 | (DivideByT > 0) && (S = S/T^DivideByT) 38 | 39 | return S 40 | 41 | end 42 | -------------------------------------------------------------------------------- /src/DeltaMethod.jl: -------------------------------------------------------------------------------- 1 | """ 2 | DeltaMethod(fn::Function,β,V,x=NaN) 3 | 4 | Apply the delta method on the function `fn(β,x)` 5 | 6 | ### Input 7 | - `fn::Function`: of the type fn(β,x) 8 | - `β::Vector`: with parameters 9 | - `V::Matrix`: Cov(β) 10 | - `x::VecOrMat`: data (if any is needed) 11 | 12 | ### Requires 13 | - `using FiniteDiff: finite_difference_jacobian as jacobian` 14 | 15 | """ 16 | function DeltaMethod(fn::Function,β,V,x=NaN) 17 | P = jacobian(b->fn(b,x),β) #numerical Jacobian 18 | Cov_fn = P*V*P' 19 | return Cov_fn 20 | end 21 | -------------------------------------------------------------------------------- /src/DistributionTests.jl: -------------------------------------------------------------------------------- 1 | """ 2 | JarqueBeraTest(x) 3 | 4 | Calculate the JB test for each column in a matrix. Reports `(skewness,kurtosis,JB)`. 5 | 6 | """ 7 | function JarqueBeraTest(x) 8 | (T,n) = (size(x,1),size(x,2)) #number of columns in x 9 | μ = mean(x,dims=1) 10 | σ = std(x,dims=1) 11 | xStd = (x .- μ)./σ #first normalize to a zero mean, unit std variable 12 | skewness = mean(z->z^3,xStd,dims=1) 13 | kurtosis = mean(z->z^4,xStd,dims=1) 14 | JB = (T/6)*abs2.(skewness) + (T/24)*abs2.(kurtosis.-3) #Jarque-Bera, Chisq(2) 15 | if n == 1 16 | (skewness,kurtosis,JB) = (only(skewness),only(kurtosis),only(JB)) #to numbers if n=1 17 | end 18 | 19 | pskew = 2*ccdf.(Normal(0,sqrt(6/T)), abs.(skewness)) 20 | pkurt = 2*ccdf.(Normal(3,sqrt(24/T)),abs.(kurtosis)) 21 | pJB = ccdf.(Chisq(2),JB) 22 | pvals = (;pskew,pkurt,pJB) 23 | 24 | return skewness, kurtosis, JB, pvals 25 | end 26 | 27 | 28 | """ 29 | KolSmirTest(x1,TheoryCdf::Function) 30 | 31 | Calculate the Kolmogorov-Smirnov test 32 | 33 | ### Output 34 | - `KSstat::Float64`: KS test statistic 35 | - `xD::Number`: x value with the largest diff beteen empirical and theoretical cdf 36 | 37 | """ 38 | function KolSmirTest(x1,TheoryCdf::Function) 39 | T = length(x1) 40 | x1Sorted = sort(x1) 41 | TheoryCdf_x = TheoryCdf.(x1Sorted) 42 | edfH = 1/T:1/T:1 #empirical cdf for x1Sorted 43 | edfL = 0:1/T:(1-1/T) 44 | D_candidates = abs.([edfH;edfL] - repeat(TheoryCdf_x,2)) 45 | (D,vD) = findmax(D_candidates) 46 | KSstat = sqrt(T)*D 47 | xD = repeat(x1Sorted,2)[vD] 48 | return KSstat, xD 49 | end 50 | -------------------------------------------------------------------------------- /src/FinEcmt_KernelRegression.jl: -------------------------------------------------------------------------------- 1 | module FinEcmt_KernelRegression 2 | 3 | using Statistics 4 | 5 | export EpanechnikovKernel, GaussianKernel, KernelDensity, KernelRegression, 6 | LocalLinearRegression, UniformKernel, hRuleOfThumb 7 | 8 | include("CovNW.jl") 9 | include("KernelRegression.jl") 10 | include("Ols.jl") 11 | 12 | end 13 | -------------------------------------------------------------------------------- /src/FinEcmt_Lasso.jl: -------------------------------------------------------------------------------- 1 | 2 | module FinEcmt_Lasso 3 | 4 | using LinearAlgebra, SparseArrays, OSQP 5 | 6 | export LassoEN 7 | 8 | include("LassoElasticNet.jl") 9 | 10 | end 11 | -------------------------------------------------------------------------------- /src/FinEcmt_MLEGMM.jl: -------------------------------------------------------------------------------- 1 | 2 | module FinEcmt_MLEGMM 3 | 4 | using Statistics, LinearAlgebra, Optim, NLsolve 5 | using FiniteDiff: finite_difference_hessian as hessian, finite_difference_jacobian as jacobian 6 | 7 | export MLE, GMMAgbar, GMMExactlyIdentified, GMMgbarWgbar, meanV 8 | 9 | include("MLE.jl") 10 | include("CovNW.jl") 11 | include("GMM.jl") 12 | 13 | end 14 | -------------------------------------------------------------------------------- /src/FinEcmt_OLS.jl: -------------------------------------------------------------------------------- 1 | module FinEcmt_OLS 2 | 3 | using Statistics, LinearAlgebra, DelimitedFiles, Distributions, StatsBase 4 | import Printf 5 | using FiniteDiff: finite_difference_jacobian as jacobian 6 | 7 | export BinScatter, BinDummies, 8 | JarqueBeraTest, CompanionFormAR, CovNW, CovToCor, 9 | DeltaMethod, DrawBlocks, EMA, EWportf, 10 | FindNNPanel, FindNN, FirstDiff, 11 | IndividualDemean, KolSmirTest, 12 | NWCovPs, OLSyxReplaceNaN, OlsAutoCorr, OlsBasic, OlsGM, OlsNW, RegressionTable, 13 | OlsR2Test, OlsSure, OlsWhitesTest,RegressionFit, VIF, DiagnosticsTable, 14 | PanelOls, PanelReshuffle, DummiesCreate, TimeDummiesTTN, 15 | FixedIndivEffects,FixedTimeEffects, FixedIndivTimeEffects, FixedTimeIndivEffects, FWonZRepeated!, 16 | PutDataInNT, Readcsv, 17 | QuantRegrIRLS, ReturnStats, RidgeRegression, StandardiseYX, 18 | TwoSLS, excise, lag, 19 | printblue, printlnPs, printmagenta, printmat, printred, printyellow, @doc2, 20 | rankPs, sortLoHi, logpdfNorm 21 | 22 | include("BinScatter.jl") 23 | include("CovNW.jl") 24 | include("DeltaMethod.jl") 25 | include("DistributionTests.jl") 26 | include("Ols.jl") 27 | include("OlsDiagnostics.jl") 28 | include("OlsSure.jl") 29 | include("PanelOls.jl") 30 | include("PanelRegrBasic.jl") 31 | include("PortfolioSorts.jl") 32 | include("printmat.jl") 33 | include("QuantRegrIRLS.jl") 34 | include("RidgeRegression.jl") 35 | include("SimulationFunctions.jl") 36 | include("TwoSLS.jl") 37 | include("UtilityFunctions.jl") 38 | 39 | end 40 | -------------------------------------------------------------------------------- /src/FinEcmt_TimeSeries.jl: -------------------------------------------------------------------------------- 1 | module FinEcmt_TimeSeries 2 | 3 | using Statistics, LinearAlgebra 4 | 5 | export ARMAFilter, VARFilter, 6 | CompanionFormAR, ARpEst, MAqLL, 7 | garch11LL, egarch11LL, DccLL, DccParTrans 8 | 9 | include("Garch.jl") 10 | include("TimeSeriesExtra.jl") 11 | include("TimeSeriesFilter.jl") 12 | include("UtilityFunctions.jl") 13 | 14 | end 15 | -------------------------------------------------------------------------------- /src/GMM.jl: -------------------------------------------------------------------------------- 1 | """ 2 | meanV(x) 3 | 4 | Calculate the sample average of each column of `x` and return a vector of them. 5 | 6 | """ 7 | meanV(x) = vec(mean(x,dims=1)); #mean of each column, transformed into a vector 8 | 9 | 10 | """ 11 | GMMExactlyIdentified(GmmMomFn::Function,x,par0,m) 12 | 13 | Estimates GMM coeffs and variance-covariance matrix from an exactly identified model. The Jacobian 14 | is calculated numerically. 15 | 16 | ### Input 17 | - `GmmMomFn::Function`: for the moment conditions, called as `GmmMomFn(p,x)` where `p` 18 | are the coefficients and `x` is the data. 19 | - `x::VecOrMat`: data 20 | - `par0::Vector`: initial guess 21 | - `m::Int`: number of lags in NW covariance matrix 22 | 23 | """ 24 | function GMMExactlyIdentified(GmmMomFn::Function,x,par0,m) 25 | 26 | T = size(x,1) 27 | 28 | Sol = nlsolve(p->meanV(GmmMomFn(p,x)),par0) #numerically solve for the estimates 29 | par1 = Sol.zero 30 | 31 | g = GmmMomFn(par1,x) #Tx2, moment conditions 32 | S = CovNW(g,m,1) #variance of sqrt(T)*gbar, NW with m lags 33 | 34 | D = jacobian(par->meanV(GmmMomFn(par,x)),par1) #Numerical Jacobian 35 | V = inv(D'inv(S)*D)/T 36 | StdErr = sqrt.(diag(V)) 37 | 38 | return par1, StdErr, V, S 39 | 40 | end 41 | 42 | 43 | """ 44 | GMMgbarWgbar(GmmMomFn::Function,W,x,par0,m;SkipCovQ=false) 45 | 46 | Estimates GMM coeffs and variance-covariance matrix from A*gbar. The Jacobian 47 | is calculated numerically. 48 | 49 | ### Input 50 | - `GmmMomFn::Function`: for the moment conditions, called as `GmmMomFn(p,x)` where `p` 51 | are the coefficients and `x` is the data. 52 | - `W::Matrix`: length(gbar)xlength(gbar) 53 | - `x::VecOrMat`: data 54 | - `par0::Vector`: initial guess 55 | - `m::Int`: number of lags in NW covariance matrix 56 | - `SkipCovQ::Bool`: if true: the Jacobian and variance-covariance matrix are 57 | not calculated. This can be used to speed up calculations in iterative computations. 58 | 59 | """ 60 | function GMMgbarWgbar(GmmMomFn::Function,W,x,par0,m;SkipCovQ=false) 61 | 62 | function GmmMomLossFn(GmmMomFn::Function,p,x,W=1) 63 | gbar = meanV(GmmMomFn(p,x)) 64 | Loss = gbar'W*gbar #to be minimized 65 | return Loss 66 | end 67 | 68 | T = size(x,1) 69 | 70 | Sol = optimize(p->GmmMomLossFn(GmmMomFn,p,x,W),par0) 71 | par1 = Optim.minimizer(Sol) 72 | 73 | g = GmmMomFn(par1,x) #Tx2, moment conditions 74 | S = CovNW(g,m,1) #variance of sqrt(T)*gbar, NW with m lags 75 | 76 | if SkipCovQ 77 | (D,V,StdErr) = (NaN,NaN,NaN) 78 | else 79 | D = jacobian(par->meanV(GmmMomFn(par,x)),par1) #Numerical Jacobian 80 | V = inv(D'W*D)*D'W*S*W'D*inv(D'W*D)/T 81 | StdErr = sqrt.(diag(V)) 82 | end 83 | 84 | return par1, StdErr, V, S, D 85 | 86 | end 87 | 88 | 89 | """ 90 | GMMAgbar(GmmMomFn::Function,A,x,par0,m) 91 | 92 | Estimates GMM coeffs and variance-covariance matrix from A*gbar. The Jacobian 93 | is calculated numerically. 94 | 95 | ### Input 96 | - `GmmMomFn::Function`: for the moment conditions, called as `GmmMomFn(p,x)` where `p` 97 | are the coefficients and `x` is the data. 98 | - `A::Matrix`: length(p) x length(gbar) 99 | - `x::VecOrMat`: data 100 | - `par0::Vector`: initial guess 101 | - `m::Int`: number of lags in NW covariance matrix 102 | 103 | """ 104 | function GMMAgbar(GmmMomFn::Function,A,x,par0,m) 105 | 106 | T = size(x,1) 107 | 108 | Sol = nlsolve(p->A*meanV(GmmMomFn(p,x)),par0) #numerically solve for the estimates 109 | par1 = Sol.zero 110 | 111 | g = GmmMomFn(par1,x) #Tx2, moment conditions 112 | S = CovNW(g,m,1) #variance of sqrt(T)*gbar, NW with m lags 113 | 114 | D = jacobian(par->meanV(GmmMomFn(par,x)),par1) #Numerical Jacobian 115 | V = inv(A*D)*A*S*A'inv(A*D)'/T 116 | StdErr = sqrt.(diag(V)) 117 | 118 | return par1, StdErr, V, S 119 | 120 | end 121 | -------------------------------------------------------------------------------- /src/Garch.jl: -------------------------------------------------------------------------------- 1 | """ 2 | garch11LL(par,y,x) 3 | 4 | Calculate `(LL_t,σ²,yhat,u)` for regression `y = x'b + u` where 5 | `u` follows a GARCH(1,1) process with paramaters `(ω,α,β)`. 6 | 7 | ### Input 8 | - `par::Vector`: parameters, `[b;ω;α;β]` 9 | - `y::VecOrMat`: Tx1 10 | - `x::VecOrMat`: Txk. 11 | 12 | """ 13 | function garch11LL(par,y,x) 14 | 15 | (T,k) = (size(x,1),size(x,2)) 16 | 17 | b = par[1:k] #mean equation, y = x'*b 18 | (ω,α,β) = par[k+1:k+3] #GARCH(1,1) equation: σ²(t) = ω + α*u(t-1)^2 + β*σ²(t-1) 19 | 20 | yhat = x*b 21 | u = y - yhat #fitted regression residuals 22 | σ²_0 = var(u) 23 | 24 | σ² = zeros(typeof(α),T) #works with ForwardDiff too 25 | σ²[1] = ω + α*σ²_0 + β*σ²_0 26 | for t = 2:T 27 | σ²[t] = ω + α*u[t-1]^2 + β*σ²[t-1] 28 | end 29 | 30 | #LL_t = -(1/2)*log(2*π) .- (1/2)*log.(σ²) .- (1/2)*(u.^2)./σ² 31 | σ = sqrt.(σ²) 32 | LL_t = logpdfNorm.(u./σ) - log.(σ) 33 | LL_t[1] = 0.0 #effectively skip the first observation 34 | 35 | return LL_t, σ², yhat, u 36 | 37 | end 38 | 39 | 40 | """ 41 | egarch11LL(par,y,x) 42 | 43 | Calculate `(LL_t,σ²,yhat,u)` for regression `y = x'b + u` where 44 | `u` follows an eGARCH(1,1) process with paramaters `(ω,α,β,γ)`. 45 | 46 | ### Input 47 | - `par::Vector`: parameters, `[b;ω;α;β;γ]` 48 | - `y::VecOrMat`: Tx1 49 | - `x::VecOrMat`: Txk. 50 | 51 | 52 | """ 53 | function egarch11LL(par,y,x) 54 | 55 | (T,k) = (size(x,1),size(x,2)) 56 | 57 | #lnσ²(t) = ω + α*abs(u(t-1)/s[t-1]) + β*lnσ²(t-1) + γ*u(t-1)/s[t-1] 58 | b = par[1:k] #mean equation, y = x'*b 59 | (ω,α,β,γ) = par[k+1:k+4] 60 | yhat = x*b 61 | u = y - yhat 62 | σ²_0 = var(u) 63 | 64 | lnσ² = zeros(typeof(α),T) 65 | lnσ²[1] = log(σ²_0) 66 | for t = 2:T 67 | σₜ₋₁ = sqrt(exp(lnσ²[t-1])) #lagged std 68 | lnσ²[t] = ω + α*abs(u[t-1])/σₜ₋₁ + β*lnσ²[t-1] + γ*u[t-1]/σₜ₋₁ 69 | end 70 | σ² = exp.(lnσ²) 71 | 72 | #LL_t = -(1/2)*log(2*π) .- (1/2)*log.(σ²) - (1/2)*(u.^2)./σ² 73 | σ = sqrt.(σ²) 74 | LL_t = logpdfNorm.(u./σ) - log.(σ) 75 | LL_t[1] = 0 76 | 77 | #LL = sum(LL_t) 78 | 79 | return LL_t,σ²,yhat,u 80 | 81 | end 82 | 83 | 84 | """ 85 | DccLL(par,data) 86 | 87 | Calculate `(LL_t,Σ)` for a DCC model. `LL_t` is a vector with LL values 88 | `Σ` an (n,n,T) array with T covariance matrices (for `n` variables). 89 | 90 | ### Input 91 | - `par::Vector`: transformed parameters (a,b), will be transformed into (α,β) below 92 | - `data::Vector`: of arrays: v = data[1], σ² = data[2], Qbar = data[3] 93 | 94 | """ 95 | function DccLL(par,data) 96 | 97 | #(α,β) = par 98 | (α,β) = DccParTrans(par) #restrict 99 | 100 | (v,σ²,Qbar) = (data[1],data[2],data[3]) #unpack data 101 | 102 | (T,n) = (size(v,1),size(v,2)) 103 | 104 | u = v .* sqrt.(σ²) 105 | 106 | Σ = fill(NaN,n,n,T) 107 | Q_t = copy(Qbar) #starting guess 108 | LL_t = zeros(T) 109 | for t = 2:T 110 | Q_t = (1-α-β)*Qbar + α*v[t-1,:]*v[t-1,:]' + β*Q_t 111 | q_t = diag(Q_t) 112 | R_t = Q_t./sqrt.(q_t*q_t') 113 | d_t = σ²[t,:] 114 | Σ_t = R_t.*sqrt.(d_t*d_t') 115 | LL_t[t] = -n*log(2*π) - logdet(Σ_t) - u[t,:]'*inv(Σ_t)*u[t,:] 116 | Σ[:,:,t] = Σ_t 117 | end 118 | 119 | LL_t = 0.5*LL_t 120 | #LL = sum(LL_t) 121 | 122 | return LL_t, Σ 123 | 124 | end 125 | 126 | 127 | """ 128 | DccParTrans(par) 129 | 130 | Transform the parameters so that `(α,β)` are guaranteed to be positive and 131 | sum to less than 1. 132 | 133 | """ 134 | function DccParTrans(par) 135 | (a,b) = par 136 | α = exp(a)/(1+exp(a)+exp(b)) 137 | β = exp(b)/(1+exp(a)+exp(b)) 138 | return α,β 139 | end 140 | -------------------------------------------------------------------------------- /src/KernelRegression.jl: -------------------------------------------------------------------------------- 1 | """ 2 | Four different kernels for use with the kernel density and regression 3 | """ 4 | GaussianKernel(z) = exp(-abs2(z)/2)/sqrt(2*pi) 5 | UniformKernel(z) = ifelse(abs(z) < sqrt(3),1/(2*sqrt(3)),0.0) #[-sqrt(3),sqrt(3)] 6 | EpanechnikovKernel(z) = ifelse(abs(z) < sqrt(5),(1-abs2(z)/5)*3/(4*sqrt(5)),0.0) #[-sqrt(5),sqrt(5)] 7 | TriangularKernel(z) = ifelse(abs(z) < sqrt(6),(1-abs(z)/sqrt(6))/sqrt(6),0.0) #[-sqrt(6),sqrt(6)] 8 | 9 | 10 | """ 11 | KernelDensity(x,xGrid,h=[],KernelFun=GaussianKernel) 12 | 13 | Compute a kernel density estimate at each value of the grid `xGrid`, using the data in vector `x`. 14 | The bandwidth `h` can be specified (otherwise a default value is used). The kernel function 15 | defaults to a standard normal density function, but other choices are available. 16 | 17 | """ 18 | function KernelDensity(x,xGrid,h=[],KernelFun=GaussianKernel) 19 | 20 | T = length(x) 21 | if isempty(h) 22 | h = 1.06*std(x)/T^0.2 23 | end 24 | 25 | Ngrid = length(xGrid) #number of grid points 26 | fx = fill(NaN,Ngrid) 27 | for j = 1:Ngrid #loop over elements in xGrid 28 | xa = (x .- xGrid[j])/h 29 | Kh = KernelFun.(xa) 30 | fx[j] = mean(Kh)/h 31 | end 32 | 33 | Varfx = fx./(T*h) * 1/(2*sqrt(π)) 34 | Stdfx = sqrt.(Varfx) #std[f(x)] 35 | 36 | return fx, Stdfx 37 | 38 | end 39 | 40 | 41 | """ 42 | KernelRegression(y,x,xGrid,h,vv = :all,DoCovb=true,KernelFun=GaussianKernel) 43 | 44 | Do kernel regression `y[vv] = b(x[vv])`, evaluated at 45 | each point in the `xGrid` vector, using bandwidth `h`. 46 | Implemented as weighted least squares (WLS), which also provide heteroskedasticity 47 | robust standard errors. 48 | 49 | ### Input 50 | - `y::Vector`: T-vector with data for the dependent variable 51 | - `x::Vector`: T-vector with data for the regressor 52 | - `xGrid::Vector`: Ngrid-vector with grid points where the estimates are done 53 | - `vv::Symbol or Vector`: If `vv = :all`, then all data points are used, otherwise supply indices. 54 | - `DoCovb::Bool`: If true, the standard error of the estimate is also calculated 55 | - `KernelFun::Function`: Function used as kernel. 56 | 57 | ### Remark 58 | - The `vv` and `DoCovb=false` options are useful for speeding up the cross-validation below. 59 | 60 | """ 61 | function KernelRegression(y,x,xGrid,h,vv = :all,DoCovb=true,KernelFun=GaussianKernel) 62 | 63 | if vv != :all 64 | (y,x) = (y[vv],x[vv]) 65 | end 66 | 67 | Ngrid = length(xGrid) #number of grid points 68 | 69 | (bHat,StdbHat) = (fill(NaN,Ngrid),fill(NaN,Ngrid)) #b[x(t)] 70 | for i = 1:Ngrid #loop over elements in xGrid 71 | zi = (x .- xGrid[i])/h 72 | w = KernelFun.(zi) 73 | w05 = sqrt.(w) 74 | if DoCovb #point estimate and standard error 75 | (b_i,_,_,Covb_i,) = OlsNW(w05.*y,w05,0) 76 | bHat[i] = b_i 77 | StdbHat[i] = sqrt(Covb_i) 78 | else #point estimate only 79 | bHat[i] = w05\(w05.*y) 80 | end 81 | end 82 | 83 | return bHat, StdbHat 84 | 85 | end 86 | 87 | 88 | """ 89 | hRuleOfThumb(y,x) 90 | 91 | Rule of thumb bandwidth for regressing `y` on `x`. 92 | 93 | """ 94 | function hRuleOfThumb(y,x) 95 | 96 | T = length(y) 97 | (b,res,) = OlsGM(y,[x.^2 x ones(T)]) 98 | (σ,γ) = (std(res), b[1]) 99 | (x_10,x_90) = quantile(x,[0.1,0.9]) #10th and 90th percentiles 100 | 101 | h_rot = 0.6*σ^(2/5)*abs(γ)^(-2/5)*(x_90-x_10)^(1/5)*T^(-1/5) 102 | 103 | return h_rot 104 | end 105 | 106 | 107 | """ 108 | LocalLinearRegression(y,x,xGrid,h,vv = :all,DoCovb=true,KernelFun=GaussianKernel) 109 | 110 | Do local linear regression `y = a + b(x-xGrid[i])`, where both `a` and `b` will differ 111 | across `xGrid[i]` values. The estimates of `a` and their standard errors are 112 | exported. 113 | 114 | See `KernRegrFn()` for further comments 115 | 116 | """ 117 | function LocalLinearRegression(y,x,xGrid,h,vv = :all,DoCovb=true,KernelFun=GaussianKernel) 118 | 119 | if vv != :all 120 | (y,x) = (y[vv],x[vv]) 121 | end 122 | c = ones(length(y)) 123 | 124 | Ngrid = length(xGrid) #number of grid points 125 | 126 | (aHat,StdaHat) = (fill(NaN,Ngrid),fill(NaN,Ngrid)) #b[x(t)] 127 | for i = 1:Ngrid #loop over elements in xGrid 128 | zi = (x .- xGrid[i])/h 129 | w = KernelFun.(zi) 130 | w05 = sqrt.(w) 131 | x2 = hcat(c,x .- xGrid[i]) 132 | if DoCovb 133 | (b_i,_,_,Covb_i,) = OlsNW(w05.*y,w05.*x2,0) 134 | aHat[i] = b_i[1] 135 | StdaHat[i] = sqrt(Covb_i[1,1]) 136 | else 137 | b_i = (w05.*x2)\(w05.*y) 138 | aHat[i] = b_i[1] 139 | end 140 | end 141 | 142 | return aHat, StdaHat 143 | 144 | end 145 | -------------------------------------------------------------------------------- /src/LassoElasticNet.jl: -------------------------------------------------------------------------------- 1 | """ 2 | LassoEN(Y,X,γM=0,λ=0,β₀=0) 3 | 4 | Do Lasso (set γ>0,λ=0), ridge (set γ=0,λ>0) or elastic net regression (set γ>0,λ>0). 5 | The function loops over the values in a vector γM, but requires λ to be a number (scalar). 6 | 7 | ### Input 8 | - `Y::Vector`:: T-vector, zero mean dependent variable 9 | - `X::Matrix`: TxK matrix, zero mean regressors 10 | - `γM::Vector`: nγ-vector with different values of γ (could also be a number) 11 | - `λ::Number`: value of λ (a number) 12 | - `β₀::Vector`: K-vector of target levels for the coeffs (could also be a common number) 13 | 14 | 15 | ### Remark (details on the coding) 16 | 17 | Choice variables `z = [b;t]` with lengths K and K respectively 18 | 19 | The objective 20 | 21 | `0.5*z'P*z + q'z` 22 | 23 | effectively involves 24 | 25 | `0.5*z'P*z = b'(X'X/T+λI)b` and 26 | 27 | `q'z = (-2X'Y/T-2λβ₀)'b + γ1't` 28 | 29 | The restrictions `lb <= Az <= ub` imply 30 | 31 | `-∞ <= β-t <= β₀` 32 | 33 | `β₀ <= β-t <= ∞` 34 | 35 | ### Requires 36 | using OSQP, SparseArrays, LinearAlgebra 37 | 38 | """ 39 | function LassoEN(Y,X,γM=0,λ=0,β₀=0) 40 | 41 | (T,K) = (size(X,1),size(X,2)) 42 | nγ = length(γM) 43 | 44 | b_ls = X\Y 45 | βM₀ = isa(β₀,Number) ? fill(β₀,K) : β₀ #exand to vector, if needed 46 | 47 | P1 = X'X/T + λ*I #from (Xb-Y)'(Xb-Y) and λb'b 48 | P2 = -2X'Y/T 49 | 50 | P = blockdiag(sparse(2*P1),spzeros(K,K)) #2* to cancel the 0.5 in 0.5z'Pz 51 | q = [P2-2*λ*βM₀;zeros(K)] #we replace zeros(K) by γ (see below) 52 | A = [sparse(I,K,K) -sparse(I,K,K); 53 | sparse(I,K,K) sparse(I,K,K)] 54 | lb = [fill(-Inf,K); βM₀] 55 | ub = [βM₀; fill(Inf,K)] 56 | prob = OSQP.Model() 57 | 58 | settings = Dict(:verbose => false) 59 | OSQP.setup!(prob;P=P,q=q,A=A,l=lb,u=ub,settings...) 60 | 61 | bM = fill(NaN,K,nγ) #loop over γ values 62 | for i = 1:nγ 63 | q[end-K+1:end] .= γM[i] #change q 64 | OSQP.update!(prob;q=q) 65 | res = OSQP.solve!(prob) 66 | (res.info.status == :Solved) && (bM[:,i] = res.x[1:K]) 67 | end 68 | 69 | return bM, b_ls 70 | 71 | end 72 | -------------------------------------------------------------------------------- /src/MLE.jl: -------------------------------------------------------------------------------- 1 | """ 2 | MLE(LLtFun,par0,y,x,lower,upper) 3 | 4 | Calculate ML point estimates of K parameters and three different types of standard errors: 5 | from the Information matrix, from the gradients and the sandwich approach. 6 | 7 | ### Input 8 | - `LLtFun::Function`: name of log-likelihood function 9 | - `par0::Vector`: K-vector, starting guess of the parameters 10 | - `y::VecOrMat`: vector or matrix with the dependent variable 11 | - `x::VecOrMat`: vector or matrix with data, use `nothing` if not needed 12 | - `lower::Vector`: lower bounds on the parameters, nothing or fill(-Inf,K) if no bounds 13 | - `upper::Vector`: upper bounds on the parameters, nothing or fill(Inf,K) if no bounds 14 | 15 | ### Requires 16 | - `using FiniteDiff: finite_difference_hessian as hessian, finite_difference_jacobian as jacobian` 17 | 18 | ### Notice 19 | The `LLtFun` should take `(par,y,x)` as inputs and generate a T-vector `LLt` as output. 20 | 21 | """ 22 | function MLE(LLtFun::Function,par0,y,x,lower=nothing,upper=nothing) 23 | 24 | LL_t = LLtFun(par0,y,x) #trying the LLtFun 25 | T = length(LL_t) 26 | 27 | NoBounds = (isnothing(lower) && isnothing(upper)) || (all(!isfinite,lower) && all(!isfinite,upper)) 28 | 29 | if NoBounds 30 | Sol = optimize(par->-sum(LLtFun(par,y,x)),par0) #minimize -sum(LLt) 31 | else 32 | Sol = optimize(par->-sum(LLtFun(par,y,x)),lower,upper,par0) 33 | end 34 | parHat = Optim.converged(Sol) ? Optim.minimizer(Sol) : fill(NaN,length(par0)) #the optimal solution 35 | 36 | Ia = -hessian(par->mean(LLtFun(par,y,x)),parHat) #2nd derivatives of mean(LLt) 37 | Ia = (Ia+Ia')/2 #to guarantee symmetry 38 | vcv = inv(Ia)/T 39 | std_hess = sqrt.(diag(vcv)) 40 | 41 | δL = jacobian(par->LLtFun(par,y,x),parHat) #TxK 42 | J = δL'δL/T #KxT * TxK 43 | vcv = inv(J)/T 44 | std_grad = sqrt.(diag(vcv)) 45 | 46 | vcv = inv(Ia) * J * inv(Ia)/T 47 | std_sandw = sqrt.(diag(vcv)) #std from sandwich 48 | 49 | return parHat, std_hess, std_grad, std_sandw 50 | 51 | end 52 | -------------------------------------------------------------------------------- /src/Ols.jl: -------------------------------------------------------------------------------- 1 | """ 2 | OlsGM(Y,X) 3 | 4 | LS of Y on X; for one dependent variable, Gauss-Markov assumptions 5 | 6 | ### Input 7 | - `Y::Vector`: T-vector, the dependent variable 8 | - `X::Matrix`: Txk matrix of regressors (including deterministic ones) 9 | 10 | ### Output 11 | - `b::Vector`: k-vector, regression coefficients 12 | - `u::Vector`: T-vector, residuals Y - yhat 13 | - `Yhat::Vector`: T-vector, fitted values X*b 14 | - `V::Matrix`: kxk matrix, covariance matrix of b 15 | - `R²::Number`: scalar, R² value 16 | 17 | """ 18 | function OlsGM(Y,X) 19 | 20 | T = size(Y,1) 21 | 22 | b = X\Y 23 | Yhat = X*b 24 | u = Y - Yhat 25 | 26 | σ² = var(u) 27 | V = inv(X'X)*σ² 28 | R² = 1 - σ²/var(Y) 29 | 30 | return b, u, Yhat, V, R² 31 | 32 | end 33 | 34 | 35 | """ 36 | OlsNW(Y,X,m=0) 37 | 38 | LS of Y on X; for one dependent variable, using Newey-West covariance matrix 39 | 40 | ### Input 41 | - `Y::Vector`: T-vector, the dependent variable 42 | - `X::Matrix`: Txk matrix of regressors (including deterministic ones) 43 | - `m::Int`: scalar, bandwidth in Newey-West 44 | 45 | ### Output 46 | - `b::Vector`: k-vector, regression coefficients 47 | - `u::Vector`: T-vector, residuals Y - Yhat 48 | - `Yhat::Vector`: T-vector, fitted values X*b 49 | - `V::Matrix`: kxk matrix, covariance matrix of b 50 | - `R²::Number`: scalar, R² value 51 | 52 | """ 53 | function OlsNW(Y,X,m=0) 54 | 55 | T = size(Y,1) 56 | 57 | b = X\Y 58 | Yhat = X*b 59 | u = Y - Yhat 60 | 61 | S = CovNW(X.*u,m) #Newey-West covariance matrix 62 | Sxx = X'X 63 | V = inv(Sxx)'S*inv(Sxx) #covariance matrix of b 64 | R² = 1 - var(u)/var(Y) 65 | 66 | return b, u, Yhat, V, R² 67 | 68 | end 69 | 70 | 71 | """ 72 | 73 | OLSyxReplaceNaN(Y,X) 74 | 75 | Replaces any rows in Y and X with zeros if there is any NaN/missing in any of them. 76 | 77 | """ 78 | function OLSyxReplaceNaN(Y,X) 79 | 80 | vv = FindNN(Y,X) #vv[t] = true if no missing/NaN i (y[t],x[t,:]) 81 | 82 | (Yb,Xb) = (copy(Y),copy(X)) #set both y[t] and x[t,:] to 0 if any missing/NaN for obs. t 83 | Yb[.!vv] .= 0 84 | Xb[.!vv,:] .= 0 85 | 86 | return vv, Yb, Xb 87 | 88 | end 89 | 90 | 91 | """ 92 | OlsBasic(Y,X,ExciseQ=false) 93 | 94 | LS of Y on X; for one dependent variable, only point estimates, fitted values and residuals. 95 | Optionally (`ExciseQ=true`) handles missing values/NaNs. 96 | 97 | ### Input 98 | - `Y::Vector`: T-vector, the dependent variable 99 | - `X::Matrix`: Txk matrix of regressors (including deterministic ones) 100 | - `ExciseQ::Bool`: true: get rid of missing/NaN cases in estimation, but put them back in (u,Yhat) 101 | 102 | ### Output 103 | - `b::Vector`: k-vector, regression coefficients 104 | - `u::Vector`: T-vector, residuals Y - yhat 105 | - `Yhat::Vector`: T-vector, fitted values X*b 106 | 107 | """ 108 | function OlsBasic(Y,X,ExciseQ=false) 109 | 110 | if ExciseQ 111 | (vv,Y,X) = OLSyxReplaceNaN(Y,X) #creates new (Y,X) 112 | end 113 | b = X\Y 114 | Yhat = X*b 115 | ExciseQ && (Yhat[.!vv] .= NaN) #puts obs with missings/NaN to NaN 116 | u = Y - Yhat 117 | 118 | return b, u, Yhat 119 | 120 | end 121 | 122 | 123 | """ 124 | RegressionTable(b,V,xNames="") 125 | 126 | ### Input 127 | - `b::Vector`: of k point estimates 128 | - `V::Matrix`: kxk variance-covariance matrix of b 129 | - `xNames::Vector`: of k strings, variable names 130 | 131 | ### Requires 132 | - Distributions, LinearAlgebra, Printf 133 | 134 | """ 135 | function RegressionTable(b,V,xNames="") 136 | 137 | k = length(b) 138 | isempty(xNames) && (xNames = [string("x",'₀'+i) for i=1:k]) #create rowNames 139 | 140 | stderr = sqrt.(diag(V)) 141 | tstat = b./stderr 142 | pval = 2*ccdf.(Normal(0,1),abs.(tstat)) # ccdf(x) = 1-cdf(x) 143 | 144 | colNames = ["coef","stderr","t-stat","p-value"] 145 | printmat(b,stderr,tstat,pval;rowNames=xNames,colNames) 146 | 147 | end 148 | -------------------------------------------------------------------------------- /src/OlsDiagnostics.jl: -------------------------------------------------------------------------------- 1 | """ 2 | OlsR2Test(R²,T,df) 3 | 4 | Test of all slope coefficients. Notice that the regression must contain 5 | an intercept for R² to be useful. 6 | 7 | ### Input 8 | - `R²::Number`: R² value 9 | - `T::Int`: number of observations 10 | - `df::Number`: number of (non-constant) regressors 11 | 12 | ### Output 13 | - `RegrStat::Number`: test statistic 14 | - `pval::Number`: p-value 15 | 16 | """ 17 | function OlsR2Test(R²,T,df) 18 | RegrStat = T*R²/(1-R²) #R\^2[TAB] 19 | pval = ccdf(Chisq(df),RegrStat) #same as 1-cdf() 20 | return RegrStat, pval 21 | end 22 | 23 | 24 | """ 25 | OlsWhitesTest(u,x) 26 | 27 | Test of heteroskedasticity. Notice that the regression must contain 28 | an intercept for the test to be useful. 29 | 30 | ### Input 31 | - `u::Vector`: T-vector, residuals 32 | - `x::Matrix`: Txk, regressors 33 | 34 | ### Output 35 | - `RegrStat::Number`: test statistic 36 | - `pval::Number`: p-value 37 | 38 | """ 39 | function OlsWhitesTest(u,x) 40 | 41 | (T,k) = (size(x,1),size(x,2)) 42 | 43 | w = zeros(T,round(Int,k*(k+1)/2)) #matrix of cross products of x 44 | vv = 1 45 | for i = 1:k, j = i:k 46 | w[:,vv] = x[:,i].*x[:,j] #eg. x1*x1, x1*x2, x2*x2 47 | vv = vv + 1 48 | end 49 | 50 | R² = OlsGM(u.^2,w)[5] #[5] picks out output 5 51 | df = rank(w) - 1 #number of independent regressors in w 52 | 53 | WhiteStat = T*R²/(1-R²) 54 | pval = ccdf(Chisq(df),WhiteStat) 55 | 56 | return WhiteStat, pval 57 | 58 | end 59 | 60 | 61 | """ 62 | OlsAutoCorr(u,L=1) 63 | 64 | Test the autocorrelation of OLS residuals 65 | 66 | ### Input 67 | - `u::Vector`: T-vector, residuals 68 | - `L::Int`: scalar, number of lags in autocorrelation and Box-Pierce test 69 | 70 | ### Output 71 | - `AutoCorr::Matrix`: Lx3, autocorrelation, t-stat and p-value 72 | - `BoxPierce::Matrix`: 1x2, Box-Pierce statistic and p-value 73 | - `DW::Number`: DW statistic 74 | 75 | ### Requires 76 | - StatsBase, Distributions 77 | 78 | """ 79 | function OlsAutoCorr(u,L=1) 80 | 81 | T = size(u,1) 82 | 83 | Stdu = std(u) 84 | ρ = autocor(u,1:L) 85 | t_ρ = sqrt(T)*ρ #t-stat of ρ 86 | 87 | pval = 2*ccdf.(Normal(0,1),abs.(t_ρ)) 88 | AutoCorr = [ρ t_ρ pval] 89 | 90 | BPStat = T*sum(ρ.^2) 91 | pval = ccdf(Chisq(L),BPStat) 92 | BoxPierce = [BPStat pval] 93 | 94 | DWStat = mean(diff(u).^2)/Stdu^2 95 | 96 | return AutoCorr, BoxPierce, DWStat 97 | 98 | end 99 | 100 | 101 | """ 102 | RegressionFit(u,R²,k) 103 | 104 | Calculate adjusted R², AIC and BIC from regression residuals. 105 | 106 | ### Input 107 | - `u::Vector`: T-vector of residuals 108 | - `R²::Float`: the R² value 109 | - `k::Int`: number of regressors 110 | 111 | """ 112 | function RegressionFit(u,R²,k) 113 | T = length(u) 114 | σ² = var(u) 115 | R²adj = 1 - (1-R²)*(T-1)/(T-k) 116 | AIC = log(σ²) + 2*k/T 117 | BIC = log(σ²) + k/T * log(T) 118 | return R²adj, AIC, BIC 119 | end 120 | 121 | 122 | """ 123 | VIF(X) 124 | 125 | Calculate the variance inflation factor 126 | 127 | ### Input 128 | - `x::Matrix`: Txk matrix with regressors 129 | 130 | ### Output 131 | - `maxVIF::Float`: highest VIF value 132 | - `allVIF::Vector`: a k VIF values 133 | 134 | """ 135 | function VIF(X) 136 | 137 | k = size(X,2) 138 | 139 | intercept_cols = [first(col) != 0 && allequal(col) for col in eachcol(X)] 140 | !any(intercept_cols) && throw(ArgumentError("one of the colums of X must be a non-zero constant")) 141 | 142 | R2 = fill(NaN,k) 143 | for i = 1:k 144 | if !intercept_cols[i] #if X[:,i] is not a constant 145 | v = filter(!=(i),1:k) #exclude i from 1:k 146 | R2[i] = OlsGM(X[:,i],X[:,v])[5] 147 | else #if X[:,i] is a constant 148 | R2[i] = 0 149 | end 150 | end 151 | 152 | allVIF = 1.0./(1.0 .- R2) 153 | maxVIF = maximum(allVIF) 154 | 155 | return maxVIF, allVIF 156 | 157 | end 158 | 159 | """ 160 | DiagnosticsTable(X,u,R²,nlags,xNames="") 161 | 162 | Compute and print a number of regression diagnostic tests. 163 | 164 | ### Input 165 | - `X::Matrix`: Txk matrix of regressors 166 | - `u::Vector`: T-vector of residuals 167 | - `R²::Float`: the R² value 168 | - `nlags::Int`: number of lags to use in autocorrelation test 169 | - `xNames::Vector`: of strings, regressor names 170 | 171 | """ 172 | function DiagnosticsTable(X,u,R²,nlags,xNames="") 173 | 174 | (T,k) = size(X) 175 | 176 | isempty(xNames) && (xNames = [string("x",'₀'+i) for i=1:k]) #create rowNames 177 | 178 | printblue("Test of all slopes = 0") 179 | df = k - 1 #number of slope coefficients 180 | (RegrStat,pval) = OlsR2Test(R²,T,df) 181 | printmat([RegrStat,pval],rowNames=["stat","p-val"]) 182 | 183 | printblue("White's test (H₀: heteroskedasticity is not correlated with regressors)") 184 | (WhiteStat,pval) = OlsWhitesTest(u,X) 185 | printmat([WhiteStat,pval],rowNames=["stat","p-val"]) 186 | 187 | printblue("Testing autocorrelation of residuals (lag 1 to $nlags)") 188 | (ρStats,BoxPierce,DW) = OlsAutoCorr(u,nlags) 189 | printmat(ρStats,colNames=["autocorr","t-stat","p-val"],rowNames=1:nlags,cell00="lag") 190 | 191 | printblue("BoxPierce ($nlags lags) ") 192 | printmat(BoxPierce',rowNames=["stat","p-val"]) 193 | 194 | printblue("DW statistic") 195 | printlnPs(DW,"\n") 196 | 197 | for i = 1:k #iterate over different regressors 198 | ρStats, = OlsAutoCorr(X[:,i].*u,nlags) 199 | printblue("Autocorrelations of $(xNames[i])*u (lag 1 to $nlags)") 200 | printmat(ρStats,colNames=["autocorr","t-stat","p-val"],rowNames=1:nlags,cell00="lag") 201 | end 202 | 203 | printblue("Measures of fit") 204 | (R²adj,AIC,BIC) = RegressionFit(u,R²,k) 205 | printmat([R²,R²adj,AIC,BIC];rowNames=["R²","R²adj","AIC","BIC"]) 206 | 207 | printblue("Test of normality") 208 | (skewness,kurtosis,JB,pvals) = JarqueBeraTest(u) 209 | xut = vcat(skewness,kurtosis,JB) 210 | printmat(xut,collect(pvals);rowNames=["skewness","kurtosis","Jarque-Bera"],colNames=["stat","p-value"]) 211 | 212 | printblue("Correlation matrix (checking multicollinearity)") 213 | printmat(cor(X);colNames=xNames,rowNames=xNames) 214 | 215 | (maxVIF,allVIF) = VIF(X) 216 | printblue("VIF (checking multicollinearity)") 217 | printmat(allVIF;rowNames=xNames) 218 | 219 | return nothing 220 | 221 | end 222 | -------------------------------------------------------------------------------- /src/OlsSure.jl: -------------------------------------------------------------------------------- 1 | """ 2 | OlsSure(Y,X,NWQ=false,m=0) 3 | 4 | LS of `Y` on `X`; where `Y` is Txn, and `X` is the same for all regressions 5 | 6 | ### Input 7 | - `Y::Matrix`: Txn, the n dependent variables 8 | - `X::Matrix`: Txk matrix of regressors (including deterministic ones) 9 | - `NWQ:Bool`: if true, then Newey-West's covariance matrix is used, otherwise Gauss-Markov 10 | - `m::Int`: scalar, bandwidth in Newey-West 11 | 12 | ### Output 13 | - `b::Matrix`: kxn, regression coefficients (one column for each `Y[:,i]`) 14 | - `u::Matrix`: Txn, residuals Y - Yhat 15 | - `Yhat::Matrix`: Txn, fitted values X*b 16 | - `V::Matrix`: covariance matrix of θ=vec(b) 17 | - `R²::Matrix`: 1xn matrix, R² values 18 | 19 | """ 20 | function OlsSure(Y,X,NWQ=false,m=0) 21 | 22 | (T,n) = (size(Y,1),size(Y,2)) 23 | k = size(X,2) 24 | 25 | b = X\Y 26 | Yhat = X*b 27 | u = Y - Yhat 28 | 29 | Sxx = X'X 30 | 31 | if NWQ 32 | g = hcat([X.*u[:,i] for i=1:n]...) #hcat(X.*u[:,1],X.*u[:,2], etc) 33 | S = CovNW(g,m) #Newey-West covariance matrix 34 | SxxM_1 = kron(I(n),inv(Sxx)) 35 | V = SxxM_1 * S * SxxM_1 36 | else 37 | V = kron(cov(u),inv(Sxx)) #traditional covariance matrix, Gauss-Markov 38 | end 39 | 40 | R² = 1 .- var(u,dims=1)./var(Y,dims=1) 41 | 42 | return b, u, Yhat, V, R² 43 | 44 | end 45 | -------------------------------------------------------------------------------- /src/PanelRegrBasic.jl: -------------------------------------------------------------------------------- 1 | """ 2 | IndividualDemean(y,x,id,ϑ=1) 3 | 4 | Demean `y` and `x` by individuals (cross-sectional units), assuming `y` is a NT vector 5 | and `x` is NTxK and both are organised according to the NT-vector `id`. The code handles both 6 | the case where data is organised according to id or according to time. 7 | 8 | `ϑ=1` is used for the FE estimator, but the GLS estimator uses `0<ϑ<1` (see below). 9 | 10 | """ 11 | function IndividualDemean(y,x,id,ϑ=1) 12 | 13 | id_uniq = unique(id) #which id values are in data set 14 | N = length(id_uniq) 15 | K = size(x,2) 16 | 17 | (yˣ,xˣ) = (fill(NaN,size(y)),fill(NaN,size(x))) 18 | (ȳ,x̄) = (fill(NaN,N),fill(NaN,N,K)) 19 | 20 | for i = 1:N #loop over individuals 21 | vv_i = id .== id_uniq[i] #locate rows which refer to individual i 22 | ȳ[i] = mean(y[vv_i]) #averages for individual i 23 | x̄[i,:] = mean(x[vv_i,:],dims=1) 24 | yˣ[vv_i] = y[vv_i] .- ϑ*ȳ[i] 25 | xˣ[vv_i,:] = x[vv_i,:] .- ϑ*x̄[i:i,:] #i:i to keep it a row vector 26 | end 27 | 28 | return yˣ,xˣ,ȳ,x̄ 29 | 30 | end 31 | 32 | 33 | """ 34 | FirstDiff(y,x,id) 35 | 36 | Calculate first differences (for each individual) of `y` and `x`, 37 | assuming `y` is a NT vector and `x` is NTxK and both are 38 | organised according to the NT-vector `id`. 39 | It is important, however, that obs (i,t+1) is below that of (i,t). 40 | 41 | """ 42 | function FirstDiff(y,x,id) 43 | 44 | id_uniq = unique(id) #which id values are in data set 45 | N = length(id_uniq) 46 | K = size(x,2) 47 | 48 | (Δy,Δx) = (fill(NaN,size(y)),fill(NaN,size(x))) 49 | 50 | for i = 1:N #individual first-differencing, loop over individuals 51 | vv_i = id .== id_uniq[i] ##locate rows which refer to individual i 52 | Δy[vv_i,:] = y[vv_i] - lag(y[vv_i,:]) #y[t] -y[t-1] 53 | Δx[vv_i,:] = x[vv_i,:] - lag(x[vv_i,:]) #x[t,:] -x[t-1,:] 54 | end 55 | 56 | (Δy,Δx) = (excise(Δy),excise(Δx)) #cut out rows with NaNs 57 | 58 | return Δy,Δx 59 | 60 | end 61 | -------------------------------------------------------------------------------- /src/PortfolioSorts.jl: -------------------------------------------------------------------------------- 1 | """ 2 | rankPs(x) 3 | 4 | Calculates the ordinal rank of eack element in a vector `x`. As an aternative, 5 | use `ordinalrank` from the `StatsBase.jl` package. 6 | 7 | """ 8 | rankPs(x) = invperm(sortperm(x)) 9 | 10 | 11 | """ 12 | sortLoHi(x,v,m) 13 | 14 | Create vectors `vL` and `vH` with trues/falses indicating membership of the Lo and Hi 15 | groups. It sorts according to `x[v]`, setting the m lowest (in `vL`) and m 16 | highest values (in `vH`) to `true`. All other elements 17 | (also those in `x[.!v]`) are set to false. 18 | 19 | ### Input 20 | - `x::Vector`: n-vector, sorting variable 21 | - `v::Vector`: n-vector of true/false. Sorting is done within x[v] 22 | - `m::Int`: number of assets in Lo/Hi portfolio 23 | 24 | ### Output 25 | - `vL::Vector`: n-vector of true/false, indicating membership of Lo portfolio 26 | - `vH::Vector`: n-vector of true/false, indicating membership of Hi portfolio 27 | 28 | """ 29 | function sortLoHi(x,v,m) 30 | 31 | x = Float64.(x) #cindependent copy of the input (x), float 32 | nv = sum(v) 33 | (nv < 2m) && error("sum(v) < 2m") 34 | 35 | (vL,vH) = [falses(length(x)) for i=1:2] 36 | x[.!v] .= Inf #v[i] = false are put to Inf to sort last 37 | r = rankPs(x) #lowest are first 38 | vL[r.<=m] .= true #eg. 1:5, with m=5 39 | vH[(nv-m+1).<=r.<=nv] .= true #eg. 8:12, with nv=12 40 | 41 | return vL, vH 42 | end 43 | 44 | 45 | """ 46 | EWportf(v) 47 | 48 | Create (equal) portfolio weights from a vector of trues/falses. If all elements are falses, 49 | then the weights are NaNs. 50 | 51 | ### Examples 52 | - EWportf([true,false,true]) gives [0.5,0.0,0.5]. 53 | - EWportf([false,false]) gives [NaN,NaN] 54 | 55 | """ 56 | function EWportf(v) 57 | w = ifelse( all(.!v), fill(NaN,length(v)), v/sum(v) ) 58 | return w 59 | end 60 | -------------------------------------------------------------------------------- /src/QuantRegrIRLS.jl: -------------------------------------------------------------------------------- 1 | """ 2 | QuantRegrIRLS(y,x,q=0.5;prec=1e-8,epsu=1e-6,maxiter=1000) 3 | 4 | Estimate a quantile regression for quantile `q`. The outputs are the point estimates 5 | and three different variance-covariance matrices of the estimates. 6 | 7 | ### Input 8 | - `y::Vector`: T vector, dependent variable 9 | - `x::VecOrMat`: TXK, regressors (including any constant) 10 | - `q::Number`: quantile to estimate at, 0 prec ...end` creates a loop that continues as long as 24 | the new and previous estimates differ more than `prec`. However, once the number of 25 | iterations exceed `maxiter` then the execution is stopped. 26 | 27 | 2. `u .= max.(u,epsu)` limits how small `u` can become which makes the algorithm 28 | more stable (recall: the next command is `x./u`). 29 | 30 | """ 31 | function QuantRegrIRLS(y,x,q=0.5;prec=1e-8,epsu=1e-6,maxiter=1000) 32 | 33 | (T,K) = (size(x,1),size(x,2)) 34 | xw = copy(x) 35 | 36 | (b_old,b,u,iter) = (zeros(K),fill(1e+6,K) .+ prec,zeros(T),0) 37 | 38 | while maximum(abs,b - b_old) > prec 39 | copyto!(b_old, b) 40 | b .= (xw'*x)\(xw'*y) 41 | u .= y .- x*b 42 | #u .= ifelse.(u.>0,1-q,q).*abs.(u) #as in Python code, divide loss fn by q(1-q) to get it 43 | u .= ifelse.(u.>0,1/q,1/(1-q)).*abs.(u) #abs(u)/q if u>0, abs(u)/(1-q) if u<0 44 | u .= max.(u,epsu) #not smaller than epsu 45 | xw .= x./u 46 | iter = iter + 1 47 | if iter > maxiter 48 | @warn("$iter > maxiter") 49 | b = NaN 50 | break 51 | end 52 | end 53 | 54 | res = y - x*b 55 | 56 | D = x'x/T 57 | h = 1.06*std(res)/T^0.2 #Silverman (1986) recommendation 58 | fx = exp.(-0.5*((res/h).^2))./(h*sqrt(2*pi)) #Green 7th ed, using N() kernel 59 | f0 = mean(fx) 60 | C = f0*x'x/T 61 | C_1 = inv(C) 62 | vcv = q*(1-q)*C_1*D*C_1/T #variance-covariance matrix 63 | 64 | C = (fx.*x)'x/T #Wooldrige 2dn ed, Powell 1991 65 | C_1 = inv(C) #but with Gaussian kernel 66 | vcv2 = q*(1-q)*C_1*D*C_1/T #caputures (x,res) dependence 67 | 68 | fx = (abs.(res) .<= h/2)/h #Wooldrige 2nd ed, Powell 1991 69 | C = (fx.*x)'x/T #uniform kernel 70 | C_1 = inv(C) 71 | vcv3 = q*(1-q)*C_1*D*C_1/T 72 | 73 | return b, vcv, vcv2, vcv3 74 | 75 | end 76 | -------------------------------------------------------------------------------- /src/RidgeRegression.jl: -------------------------------------------------------------------------------- 1 | """ 2 | RidgeRegression(Y,X,λ,β₀=0) 3 | 4 | Calculate ridge regression estimate with target vector `β₀`. 5 | """ 6 | function RidgeRegression(Y,X,λ,β₀=0) 7 | (T,K) = (size(X,1),size(X,2)) 8 | isa(β₀,Number) && (β₀=fill(β₀,K)) 9 | b = (X'X/T+λ*I)\(X'Y/T+λ*β₀) #same as inv(X'X/T+λ*I)*(X'Y/T+λ*β₀) 10 | return b 11 | end 12 | 13 | 14 | """ 15 | StandardiseYX(Y0,X0) 16 | 17 | Demean and make std=1 for `Y` and `X` (vector or matrices) 18 | 19 | """ 20 | function StandardiseYX(Y0,X0) 21 | Y = (Y0 .- mean(Y0,dims=1))./std(Y0,dims=1) 22 | X = (X0 .- mean(X0,dims=1))./std(X0,dims=1) 23 | return Y,X 24 | end 25 | -------------------------------------------------------------------------------- /src/SimulationFunctions.jl: -------------------------------------------------------------------------------- 1 | """ 2 | DrawBlocks(T,BlockSize) 3 | 4 | Draw a T-vector of indices `v` that can be used to create bootstrap residuals. 5 | The indices are such that they form blocks of length `BlockSize`. 6 | 7 | """ 8 | function DrawBlocks(T,BlockSize) 9 | nBlocks = cld(T,BlockSize) #number of blocks, rounded up 10 | v0 = rand(1:T,nBlocks) #nBlocks, random starting obs of blocks 11 | v = vec(v0' .+ vec(0:BlockSize-1)) #each block in a column 12 | v = replace(z -> z>T ? z-T : z,v) #wrap around if index > T 13 | #println(v) #uncomment to see result 14 | return v 15 | end 16 | -------------------------------------------------------------------------------- /src/TimeSeriesExtra.jl: -------------------------------------------------------------------------------- 1 | """ 2 | CompanionFormAR(a) 3 | 4 | Companion form of AR(p), that is, write an AR(p) as a VAR(1) 5 | """ 6 | function CompanionFormAR(a) 7 | p = length(a) 8 | if p > 1 #if order > 1 9 | A1 = vcat(a',[I zeros(p-1)]) 10 | else #if already VAR(1) 11 | A1 = copy(a) 12 | end 13 | return A1 14 | end 15 | 16 | 17 | """ 18 | ARpEst(y,p) 19 | 20 | Estimate an AR(p) model (with an intercept) on the data in a vector `y`. 21 | 22 | Output: the slope coefficients (not the intercept). 23 | 24 | """ 25 | function ARpEst(y,p) 26 | 27 | T = length(y) 28 | 29 | xAll = fill(NaN,T,p) #build matrix of regressors 30 | for s = 1:p #or reduce(hcat,lag(y,s) for s=1:p) 31 | xAll[:,s] = lag(y,s) 32 | end 33 | xAll = [xAll ones(T)] #add constant last 34 | #printmat([y xAll][1:10,:]) #uncomment to see the regressors 35 | 36 | b = xAll[p+1:end,:]\y[p+1:end] #OLS, cut the first p observatioms 37 | a = b[1:end-1] #slopes 38 | 39 | return a 40 | 41 | end 42 | 43 | 44 | """ 45 | MAqLL(par,y) 46 | 47 | Log likelihood function for MA(q) process. Same as 48 | `LL_i = -1/2*log(2*π) .- 1/2*log(σ^2) .- 1/2*ϵ.^2/σ^2` 49 | 50 | """ 51 | function MAqLL(par::Vector,y) 52 | (θ,σ) = (par[1:end-1],par[end]) 53 | q = length(θ) 54 | ϵ = ARMAFilter(y,-θ) #ϵ is AR(q) with coefs -θ 55 | LL_i = logpdfNorm.(ϵ./σ) .- log(σ) #log of N(0,1) pdf - log(σ) 56 | return LL_i, ϵ 57 | end 58 | -------------------------------------------------------------------------------- /src/TimeSeriesFilter.jl: -------------------------------------------------------------------------------- 1 | """ 2 | EMA(x,m=1) 3 | 4 | Equally weighted moving average (over the current and m-1 lagged values) of each column 5 | in a matrix `x`. 6 | 7 | """ 8 | function EMA(x,m=1) 9 | 10 | (T,n) = (size(x,1),size(x,2)) 11 | q = m - 1 #m=2, q=1 (avg over [t-1,t]) 12 | 13 | (q < 0) && error("q must be >= 0") 14 | 15 | y = fill(NaN,T,n) #y[t] = (x[t-1] + x[t])/2 16 | for t = 1:T 17 | vv = max(1,t-q):t #with q=2; 1:1,1:2,1:3,2:4 18 | y[t,:] = sum(x[vv,:],dims=1)/m 19 | end 20 | 21 | return y 22 | 23 | end 24 | 25 | 26 | """ 27 | ARMAFilter(ϵ,rho=[],θ=[],θ₀=1.0,y₀=[]) 28 | 29 | Calculate ARMA(p,q) transformation of an input series ϵ. Uses explicit loop (instead of 30 | DSP.filt). 31 | 32 | 33 | ### Input 34 | - `ϵ::Vector`: T-vector with an input series 35 | - `rho::Vector`: (optional) p-vector of autoregression coefficients, could be [] 36 | - `θ::Vector`: (optional) q-vector of moving average coefficients (lag 1 to q), could be [] 37 | - `θ₀::Number`: (optional) scalar, coefficient on ϵ[t] in MA part, [1] 38 | - `y₀::Vector`: (optional) p-vector, initial values of y, eg. [y(-1);y(0)], default: zeros(p) 39 | 40 | ### Output 41 | - `y::Vector`: T-vector with output from the filter 42 | 43 | ### Notice 44 | 1. The process is 45 | `y[t] = rho[1]*y[t-1] + ... + rho[p]*y[t-p] + θ₀*ϵ[t] + θ[1]*ϵ[t-1] + ... + θ[q]*ϵ[t-q]` 46 | 2. The initial values of `ϵ` are assumed to be zero 47 | 3. To calculate impulse response functions, use `ϵ = [1;zeros(T-1,1)]` 48 | 4. There are no initial values in a pure MA and the case of `q > p` 49 | is handled with padding with zeros (see the code below) 50 | 51 | """ 52 | function ARMAFilter(ϵ,rho=[],θ=[],θ₀=1,y₀=[]) 53 | 54 | T = length(ϵ) 55 | (q,p) = (length(θ),length(rho)) 56 | r = max(p,q) #r obs are needed for start-up 57 | 58 | if (p > 0) && isempty(y₀) #default y₀ 59 | y₀ = zeros(p) 60 | end 61 | (length(y₀) != p) && error("length of y₀ must equal p") 62 | 63 | θ_ud = q > 0 ? reverse([θ₀;θ]) : θ₀ #flip upside down 64 | ρ_ud = p > 1 ? reverse(rho) : rho 65 | 66 | ϵ = [zeros(r);ϵ] #pad with zeros, clumsy but easy 67 | Tb = length(ϵ) #effective sample with padding 68 | 69 | y = r > p ? [zeros(r-p);y₀;zeros(T)] : [y₀;zeros(T)] #to store output in 70 | 71 | for t = r+1:Tb 72 | if p == 0 #pure MA 73 | y[t] = dot(θ_ud,ϵ[t-q:t]) 74 | else #AR or ARMA 75 | y[t] = dot(ρ_ud,y[t-p:t-1]) + dot(θ_ud,ϵ[t-q:t]) 76 | end 77 | end 78 | y = y[r+1:Tb] #cut padded part 79 | 80 | return y 81 | 82 | end 83 | 84 | 85 | """ 86 | VARFilter(ϵ,A,y₀) 87 | 88 | Create y Txn matrix from VAR model where 89 | `y[t,:] = A1*y[t-1,:] +...+Ap*y[t-p,:] + ϵ[t,:]` 90 | 91 | A is an `nxnxp` array with `cat(A1,A2,...,dims=3)` 92 | `y₀` is `pxn` initial values of y (for [t=-2;t=-1;t=0] for a VAR(3)) 93 | """ 94 | function VARFilter(ϵ,A,y₀) 95 | 96 | p = size(A,3) #lag order 97 | (T,n) = (size(ϵ,1),size(ϵ,2)) 98 | (p != size(y₀,1)) && error("y₀ must be $p x $n") 99 | 100 | y = [y₀;zeros(T,n)] 101 | ϵ = [zeros(p,n);ϵ] 102 | Tb = size(y,1) 103 | for t = p+1:Tb #loop over t 104 | for s = 1:p #loop over lags, y[t-1],y[t-2],...,y[t-p] 105 | y[t,:] = y[t,:] + A[:,:,s]*y[t-s,:] 106 | end 107 | y[t,:] = y[t,:] + ϵ[t,:] 108 | end 109 | #printmat(y) 110 | y = y[p+1:end,:] #cut padded part 111 | 112 | return y 113 | 114 | end 115 | 116 | -------------------------------------------------------------------------------- /src/TwoSLS.jl: -------------------------------------------------------------------------------- 1 | """ 2 | TwoSLS(y,x,z,NWQ=false,m=0) 3 | 4 | ### Input 5 | - `y::VecOrMat`: Tx1 or T-vector of the dependent variable 6 | - `x::VecOrMat`: Txk matrix (or vector) of regressors 7 | - `z::VecOrMat`: TxL matrix (or vector) of instruments 8 | - `NWQ:Bool`: if true, then Newey-West's covariance matrix is used, otherwise Gauss-Markov 9 | - `m::Int`: scalar, bandwidth in Newey-West; 0 means White's method 10 | 11 | ### Output 12 | - `b::Vector`: k-vector, regression coefficients 13 | - `fnOutput::NamedTuple`: with 14 | - res Tx1 or Txn matrix, residuals y - yhat 15 | - yhat Tx1 or Txn matrix, fitted values 16 | - Covb matrix, covariance matrix of vec(b) = [beq1;beq2;...] 17 | - R2 1xn, R2 18 | - R2_stage1 k-vector, R2 of each x[:,i] in first stage regression on z 19 | - δ_stage1 Lxk matrix, coeffs from 1st stage x = z'δ 20 | - Stdδ_stage1 Lxk matrix, std of δ 21 | 22 | ### Requires 23 | - Statistics, LinearAlgebra 24 | - CovNW 25 | 26 | 27 | """ 28 | function TwoSLS(y,x,z,NWQ=false,m=0) 29 | 30 | (Ty,n) = (size(y,1),size(y,2)) 31 | (k,L) = (size(x,2),size(z,2)) 32 | 33 | δ = z\x #stage 1 estimates, Lxk, one column per regression 34 | xhat = z*δ #TxL * Lxk - > Txk 35 | resx = x - xhat #Txk 36 | R2_stage1 = [cor(x[:,i],xhat[:,i])^2 for i=1:k] 37 | 38 | Szz_1 = inv(z'z) #stage 1 standard errors 39 | Stdδ = similar(δ) #Lxk standard errors of δ 40 | for i = 1:k #loop over columns in x 41 | if NWQ #NW standard errors 42 | S = CovNW(resx[:,i].*z,m) 43 | Covδ_i = Szz_1*S*Szz_1 44 | else #standard errors assuming iid 45 | Covδ_i = Szz_1*var(resx[:,i]) 46 | end 47 | Stdδ[:,i] = sqrt.(diag(Covδ_i)) 48 | end 49 | 50 | b = xhat\y #stage 2 estimates 51 | yhat = x*b #notice: from y=x'b+u, not 2nd stage regression 52 | res = y - yhat 53 | 54 | R2 = cor(y,yhat)^2 55 | Sxz = x'z #stage 2 standard errors 56 | if NWQ #Cov(b) using Newey-West 57 | S = CovNW(res.*z,m) 58 | B = inv(Sxz*Szz_1*Sxz')*Sxz*Szz_1 59 | Covb = B*S*B' 60 | else #Cov(b) assuming iid residuals, independent of z 61 | Covb = var(res)*inv(Sxz*Szz_1*Sxz') 62 | end 63 | 64 | fnOutput = (;res,yhat,Covb,R2,R2_stage1,δ_stage1=δ,Stdδ_stage1=Stdδ) 65 | 66 | return b, fnOutput 67 | 68 | end 69 | -------------------------------------------------------------------------------- /src/UtilityFunctions.jl: -------------------------------------------------------------------------------- 1 | """ 2 | ReturnStats(Re,Annfactor=252) 3 | 4 | Calculate average excess return, the std and the SR ratio - and annualise. 5 | Returns a 3xn matrix with (annualised) `[μ;σ;SR]`, where `n=size(Re,2)`. 6 | """ 7 | function ReturnStats(Re,Annfactor=252) 8 | μ = mean(Re,dims=1)*Annfactor 9 | σ = std(Re,dims=1)*sqrt(Annfactor) 10 | SR = μ./σ 11 | stats = [μ;σ;SR] 12 | return stats 13 | end 14 | 15 | 16 | """ 17 | PutDataInNT(x,header) 18 | 19 | Creates a NamedTuple with, for instance, `N.X`, `N.Y` and `N.Z` where `x` is a matrix 20 | and `header = ["X" "Y" "Z"]` or `["X","Y","Z"]`. 21 | 22 | """ 23 | function PutDataInNT(x,header) 24 | namesB = tuple(Symbol.(header)...) #a tuple (:X,:Y,:Z) 25 | N = NamedTuple{namesB}([x[:,i] for i=1:size(x,2)]) #NamedTuple with N.X, N.Y and N.Z 26 | return N 27 | end 28 | 29 | 30 | """ 31 | 32 | Readcsv(DataFile,SkipCols=1,NaNCode="NA";ToFloat=false,delim=',') 33 | 34 | 35 | Read a csv file and create a named tuple with variables, with the names 36 | taken from the header. 37 | 38 | ### Input 39 | - `DataFile::String`: file path 40 | - `SkipCols::Int`: number of leading columns to skip (often 1) 41 | - `NaNCode::String or Number`: indicator for missing value in the file ("NA",-999.99, etc) 42 | - `ToFloat::Bool`: if true: convert all Ints and Floats to Float64 43 | - `delim::Char`: typically ',' or '\t' 44 | 45 | ### Output 46 | - `d::NamedTuple`: with data, as d.X, d.Y, etc 47 | 48 | ### Remark 49 | - The conversion of Ints and Floats is to Int64 (with missing) and Float64 (with NaN), respectively, 50 | but with `ToFloat=true` all Ints and Floats are converted to Float64 (wih NaN). 51 | 52 | 53 | """ 54 | function Readcsv(DataFile,SkipCols=1,NaNCode="NA";ToFloat=false,delim=',') 55 | 56 | (xx,header) = readdlm(DataFile,delim;header=true) 57 | n = size(xx,2) 58 | xx = replace(z -> z==NaNCode ? missing : z,xx) 59 | namesB = tuple(Symbol.(header[SkipCols+1:end])...) #a tuple (:X,:Y,:Z) 60 | 61 | dx = Vector{Any}(undef,n) 62 | for i in 1:n 63 | xx_i = xx[:,i] 64 | intQ = all(z->isa(z,Union{Integer,Missing}),xx_i) #all are integers 65 | fltQ = any(z->isa(z,AbstractFloat),xx_i) && all(z->isa(z,Union{Real,Missing}),xx_i) #all are real and some are floats 66 | misQ = any(ismissing,xx_i) 67 | #println(i," ",xx_i[1]," ",intQ," ",fltQ," ",misQ) 68 | if intQ && !ToFloat 69 | dx[i] = misQ ? convert.(Union{Int,Missing},xx_i) : convert.(Int,xx_i) 70 | elseif (intQ && ToFloat) || fltQ 71 | misQ && (xx_i = replace(z -> ismissing(z) ? NaN : z,xx_i)) 72 | dx[i] = convert.(Float64,xx_i) 73 | else 74 | dx[i] = xx_i 75 | end 76 | end 77 | d = NamedTuple{namesB}(dx[SkipCols+1:end]) 78 | 79 | return d 80 | 81 | end 82 | 83 | 84 | """ 85 | lag(x,n=1) 86 | 87 | Create a matrix or vector of lagged values. 88 | 89 | ### Input 90 | - `x::VecOrMat`: T Vector or Txk matrix 91 | - `n::Int`: scalar, order of lag. For instance, 2 puts x[t-2,:] on row t 92 | 93 | ### Output 94 | - `z::Array`: Txk matrix of lags 95 | 96 | """ 97 | function lag(x,n=1) 98 | 99 | (T,k) = (size(x,1),size(x,2)) 100 | 101 | if n < 0 #leads 102 | z = [ x[1-n:T,:]; fill(NaN,(abs(n),k)) ] 103 | elseif n == 0 #no lag or lead 104 | z = copy(x) 105 | elseif n > 0 #lags 106 | z = [ fill(NaN,(n,k)); x[1:T-n,:] ] 107 | end 108 | 109 | isa(x,AbstractVector) && (z = z[:,1]) #z should be vector if x is 110 | 111 | return z 112 | 113 | end 114 | 115 | 116 | """ 117 | excise(x...;xtype=Any) 118 | 119 | Remove all lines where the is a NaN/missing in any of the x arrays 120 | 121 | ### Input 122 | - `xtype::Type`: type to convert the data to 123 | 124 | ### Examples 125 | - `x1 = excise(x)` 126 | - `(y1,x1) = excise(y,x;xtype=Float64)` 127 | 128 | """ 129 | function excise(x...;xtype=Any) 130 | n = length(x) 131 | vv = FindNN(x...) #find rows with NaN/missing 132 | if xtype != Any 133 | z = ntuple(i->convert.(xtype,copy(selectdim(x[i],1,vv))),n) #create a tuple of arrays 134 | else 135 | z = ntuple(i->copy(selectdim(x[i],1,vv)),n) #create a tuple of arrays 136 | end 137 | (n==1) && (z = z[1]) #if a single array in the tuple 138 | return z 139 | end 140 | 141 | 142 | """ 143 | FindNN(x...;Keepdim=1) 144 | 145 | Find rows (if Keepdim==1) which have no NaNs missing in other dimensions (eg. in no columns). 146 | 147 | ### Input 148 | - `z::Array`: one or several numerical arrays 149 | - `Keepdim::Int`: (keyword) 1 if check rows, 2 if check columns, etc 150 | 151 | ### Output 152 | - `vvb::BitVector`: vector, element t is true if row (if Keepdim==1) t has no NaN or missing 153 | 154 | ### Notice 155 | - Set Keepdim=2 if we should instead look for NaNs/missings along rows (and other dimensions). 156 | - For heterogenous arrays like `x=[x1,x1]`, use `FindNN(x...)` 157 | 158 | Paul.Soderlind@unisg.ch 159 | 160 | """ 161 | function FindNN(x...;Keepdim=1) 162 | 163 | N = length(x) 164 | T = size(x[1],Keepdim) #length of output 165 | 166 | xDims = maximum(ndims,x) #max of ndims(x[i]) for i=1:N 167 | dims = setdiff(1:xDims,Keepdim) #dimensions to check 168 | 169 | vvM = falses(T,N) 170 | for i = 1:N #loop over inputs 171 | vvM[:,i] = any(isunordered,x[i],dims=dims) 172 | end 173 | 174 | vvb = vec(.!any(vvM,dims=2)) #rows witout NaN/missing in any of the x matrices 175 | 176 | return vvb 177 | 178 | end 179 | 180 | 181 | """ 182 | CovToCor(covMat) 183 | 184 | Compute correlation matrix from covariance matrix. 185 | 186 | """ 187 | function CovToCor(covMat) 188 | d = diag(covMat) #variances 189 | corMat = covMat./sqrt.(d*d') 190 | return corMat 191 | end 192 | 193 | 194 | """ 195 | logpdfNorm(x) 196 | 197 | Calculate the log pdf of a N(0,1) variable at x. 198 | Should give the same as `Distributions.logpdf(Normal(0,1),x)` 199 | 200 | """ 201 | function logpdfNorm(x) 202 | f = -0.5*log(2*π) - 0.5*x^2 203 | return f 204 | end 205 | 206 | -------------------------------------------------------------------------------- /src/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 | --------------------------------------------------------------------------------