{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Mean Variance Frontier with Short Sales Constraints" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Load Packages and Utility Functions" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "printyellow (generic function with 1 method)" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "using Printf, LinearAlgebra, Optim\n", "\n", "include(\"jlFiles/printmat.jl\")" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "using Plots\n", "\n", "#pyplot(size=(600,400)) #use pyplot or gr\n", "gr(size=(480,320))\n", "default(fmt = :svg)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Traditional MV Calculations \n", "\n", "(no constraints)" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "3" ] }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "source": [ "μ = [11.5, 9.5, 6]/100 #expected returns\n", "Σ = [166 34 58; #covariance matrix\n", " 34 64 4;\n", " 58 4 100]/100^2\n", "\n", "assetNames = [\"A\",\"B\",\"C\"];\n", "n = length(μ)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## A Function for Calculating the (traditional) Mean-Variance Frontier\n" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "MVCalc" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "\"\"\"\n", " MVCalc(μstar,μ,Σ)\n", "\n", "Calculate the std and weights of a portfolio (with mean return μstar) on MVF of risky assets.\n", "\n", "# Remark\n", "- Only (λ,δ) and thus (w,stdRp) depend on μstar. We could therefore speed up the computations a bit\n", "by doing the loop over different μstar values inside the function (and thus not recalculate Σ_1,a,b,c).\n", "\"\"\"\n", "function MVCalc(μstar,μ,Σ)\n", " n = length(μ)\n", " Σ_1 = inv(Σ)\n", " a = μ'Σ_1*μ\n", " b = μ'Σ_1*ones(n)\n", " c = ones(n)'Σ_1*ones(n)\n", " λ = (c*μstar - b)/(a*c-b^2)\n", " δ = (a-b*μstar)/(a*c-b^2)\n", " w = Σ_1 *(μ*λ.+δ)\n", " StdRp = sqrt(w'Σ*w)\n", " return StdRp,w\n", "end" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "data": { "image/svg+xml": [ "\n", "\n", "\n", " \n", " \n", " \n", "\n", "\n", "\n", " \n", " \n", " \n", "\n", "\n", "\n", " \n", " \n", " \n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "μstar_range = range(0.04,0.15,length=201)\n", "L = length(μstar_range)\n", "\n", "StdRp = fill(NaN,L)\n", "for i = 1:L\n", " StdRp[i] = MVCalc(μstar_range[i],μ,Σ)[1]\n", "end\n", "\n", "p1 = plot( StdRp*100,μstar_range*100,\n", " linecolor = :red,\n", " linewidth = 2,\n", " label = \"MVF\",\n", " legend = :topleft,\n", " xlim = (0,15),\n", " ylim = (0,15),\n", " title = \"MVF (no portfolio constraints)\",\n", " xlabel = \"Std(Rp), %\",\n", " ylabel = \"ERp, %\" )\n", "scatter!(sqrt.(diag(Σ))*100,μ*100,color=:red,label=\"assets\")\n", "display(p1)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# The Maximization Problem\n", "\n", "The investor maximizes:\n", "\n", "$\\text{E}R_{p}-\\frac{k}{2} \\text{Var}(R_{p})$,\n", "\n", "where $\\text{E}R_{p}= w'\\mu$ and $\\text{Var}(R_{p}=w'\\Sigma w$\n", "\n", "subject to $\\Sigma_{i=1}^n w_{i} = 1$.\n", "\n", "We can trace out the mean-variance frontier by solving this problem for different values of $k$.\n", "\n", "To impose the restriction, optimise over `v` and let `w=[v;1-sum(v)]`" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "objfun1 (generic function with 1 method)" ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "function objfun1(v,k,μ,Σ)\n", " w = [v;1-sum(v)]\n", " ERp = w'μ\n", " VarRp = w'Σ*w\n", " StdRp = sqrt(VarRp)\n", " U = ERp - k/2*VarRp\n", " loss = -U #minimise this\n", " return loss, w, ERp, StdRp\n", "end" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "A 0.313\n", "B 0.695\n", "C -0.008\n", "\n", "σₚ 0.079\n", "μₚ 0.102\n", "\n" ] } ], "source": [ "k = 10\n", "Sol = optimize(v -> objfun1(v,k,μ,Σ)[1],zeros(n-1))\n", "\n", "v = Optim.minimizer(Sol)\n", "(_,w,ERp,StdRp) = objfun1(v,k,μ,Σ)\n", "\n", "printmat(w,rowNames=assetNames)\n", "printmat([StdRp,ERp],rowNames=[\"σₚ\",\"μₚ\"])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Task 1\n", "\n", "Redo the optimisation for the following range of $k$ values:\n", "`k = [range(0.1,1.9,length=30);range(1,30,length=25)]`\n", "\n", "Then plot the resulting \"efficient frontier\" (similar to the MV plot above). Is is the same as the plot above?" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Task 2\n", "\n", "Change the optimisation problem to `U = ERp + cost - k/2*VarRp` where `cost` is (sum of the *negative* portfolio weights)*0.05. This is a (crude/dramatic) attaempt to illustrate the impact of costs of short selling ($w_i<0$) assets. Plot the new \"effecient frontier\" together with the old one." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Task 3\n", "\n", "Compare the portfolio weights (with/without the extra `cost`)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "@webio": { "lastCommId": null, "lastKernelId": null }, "anaconda-cloud": {}, "kernelspec": { "display_name": "Julia 1.6.3", "language": "julia", "name": "julia-1.6" }, "language_info": { "file_extension": ".jl", "mimetype": "application/julia", "name": "julia", "version": "1.6.3" } }, "nbformat": 4, "nbformat_minor": 4 }