{
"cells": [
{
"cell_type": "code",
"execution_count": 1,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"# Generate data for long only portfolio optimization.\n",
"srand(9);\n",
"n = 10;\n",
"mu = abs(randn(n, 1));\n",
"Sigma = randn(n, n);\n",
"Sigma = Sigma' * Sigma;"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"# Long only portfolio optimization.\n",
"using Convex, SCS, ECOS\n",
"set_default_solver(SCSSolver(verbose=0));\n",
"w = Variable(n);\n",
"ret = sum(mu' * w);\n",
"risk = sum(quad_form(w, Sigma));\n",
"\n",
"# Compute trade-off curve.\n",
"SAMPLES = 100;\n",
"risk_data = zeros(SAMPLES);\n",
"ret_data = zeros(SAMPLES);\n",
"gamma_vals = logspace(-2, 3, SAMPLES);\n",
"for i=1:SAMPLES\n",
" gamma = gamma_vals[i];\n",
" problem = maximize(ret - gamma*risk, [sum(w) == 1, w >= 0]);\n",
" solve!(problem);\n",
" risk_data[i] = sqrt(evaluate(risk));\n",
" ret_data[i] = evaluate(ret);\n",
"end"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"image/svg+xml": [
"\n",
"\n"
],
"text/html": [
"\n",
"\n"
],
"text/plain": [
"Plot(...)"
]
},
"execution_count": 3,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"using Gadfly\n",
"markers_on = [29, 40];\n",
"labels = [@sprintf(\"γ = %0.2f\", gamma_vals[marker]) for marker in markers_on];\n",
"plot(\n",
"layer(x=[sqrt(Sigma[i,i]) for i=1:n], y=mu,\n",
" Geom.point, Theme(default_color=color(\"red\"))),\n",
"layer(x=risk_data, y=ret_data,\n",
" Geom.line, Theme(default_color=color(\"green\"))),\n",
"layer(x=risk_data[markers_on], y=ret_data[markers_on], label=labels,\n",
" Geom.point, Geom.label, Theme(default_color=color(\"blue\"))),\n",
"Guide.XLabel(\"Risk\"), Guide.YLabel(\"Return\")\n",
")"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"image/svg+xml": [
"\n",
"\n"
],
"text/html": [
"\n",
"\n"
],
"text/plain": [
"Plot(...)"
]
},
"execution_count": 4,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# Plot return distributions for two points on the trade-off curve.\n",
"using DataFrames, Distributions\n",
"xdata = linspace(-2, 5, 1000);\n",
"df = DataFrame(x=xdata,\n",
" y=pdf(Normal(ret_data[markers_on[1]], risk_data[markers_on[1]]), xdata),\n",
" label=@sprintf(\"γ = %0.2f\", gamma_vals[markers_on[1]]));\n",
"for i=2:length(markers_on)\n",
" m = markers_on[i];\n",
" df = vcat(df, DataFrame(x=xdata,\n",
" y=pdf(Normal(ret_data[m], risk_data[m]), xdata),\n",
" label=@sprintf(\"γ = %0.2f\", gamma_vals[m])));\n",
"end\n",
"plot(df, x=\"x\", y=\"y\", color=\"label\", Geom.line, Guide.XLabel(\"Return\"), Guide.YLabel(\"Density\"))"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false,
"scrolled": true
},
"outputs": [],
"source": [
"# Portfolio optimization with leverage limit.\n",
"# Compute trade-off curve for each leverage limit.\n",
"L_vals = [1, 2, 4];\n",
"SAMPLES = 100;\n",
"risk_data = zeros(length(L_vals), SAMPLES);\n",
"ret_data = zeros(length(L_vals), SAMPLES);\n",
"for k=1:length(L_vals)\n",
" for i=1:SAMPLES\n",
" Lmax = L_vals[k];\n",
" gamma = gamma_vals[i];\n",
" problem = maximize(ret - gamma*risk,[sum(w) == 1, norm(w, 1) <= Lmax]);\n",
" solve!(problem);\n",
" risk_data[k, i] = sqrt(evaluate(risk));\n",
" ret_data[k, i] = evaluate(ret);\n",
" end\n",
"end"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"image/svg+xml": [
"\n",
"\n"
],
"text/html": [
"\n",
"\n"
],
"text/plain": [
"Plot(...)"
]
},
"execution_count": 6,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"df = DataFrame(x=vec(risk_data[1,:]), y=vec(ret_data[1,:]), label=@sprintf(\"Lmax = %d\", L_vals[1]));\n",
"for i=2:length(L_vals)\n",
" df = vcat(df, DataFrame(x=vec(risk_data[i,:]), y=vec(ret_data[i,:]), label=@sprintf(\"Lmax = %d\", L_vals[i])));\n",
"end\n",
"plot(df, x=\"x\", y=\"y\", color=\"label\", Geom.line, Guide.XLabel(\"Return\"), Guide.YLabel(\"Standard deviation\"))"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"# Portfolio optimization with a leverage limit and a bound on risk.\n",
"# Compute solution for different leverage limits.\n",
"w_vals = zeros(n, length(L_vals));\n",
"for i=1:length(L_vals)\n",
" problem = maximize(ret, [sum(w) == 1, norm(w, 1) <= L_vals[i], risk <= 2]);\n",
" solve!(problem);\n",
" w_vals[:, i] = evaluate(w);\n",
"end"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"# Generate data for factor model.\n",
"n = 3000;\n",
"m = 50;\n",
"mu = abs(randn(n, 1));\n",
"Sigma_tilde = randn(m, m);\n",
"Sigma_tilde = Sigma_tilde' * Sigma_tilde;\n",
"D = diagm(0.9 * rand(n));\n",
"F = randn(n, m);"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {
"collapsed": false,
"scrolled": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\n",
"ECOS 1.0.5 - (c) A. Domahidi, ETH Zurich & embotech 2012-14. Support: ecos@embotech.com\n",
"\n",
"It pcost dcost gap pres dres k/t mu step IR\n",
" 0 -7.928e-01 -1.279e+01 +2e+04 3e+01 1e+02 1e+00 3e+00 N/A 4 5 -\n",
" 1 -1.139e+01 -1.274e+01 +2e+03 4e+00 1e+01 4e-01 4e-01 0.9899 4 3 4\n",
" 2 -7.570e+00 -7.792e+00 +4e+02 6e-01 2e+00 2e-02 7e-02 0.8105 3 3 3\n",
" 3 -7.340e+00 -7.529e+00 +4e+02 5e-01 2e+00 2e-02 6e-02 0.2022 4 4 4\n",
" 4 -6.937e+00 -7.099e+00 +4e+02 4e-01 1e+00 2e-02 6e-02 0.2089 5 4 5\n",
" 5 -6.565e+00 -6.694e+00 +3e+02 3e-01 1e+00 2e-02 5e-02 0.2735 4 4 4\n",
" 6 -5.876e+00 -5.948e+00 +2e+02 2e-01 7e-01 1e-02 3e-02 0.5625 5 5 5\n",
" 7 -5.533e+00 -5.582e+00 +2e+02 1e-01 4e-01 8e-03 3e-02 0.3618 5 5 5\n",
" 8 -5.313e+00 -5.348e+00 +1e+02 1e-01 3e-01 5e-03 2e-02 0.4704 5 5 5\n",
" 9 -4.961e+00 -4.975e+00 +5e+01 4e-02 1e-01 2e-03 9e-03 0.7557 5 5 5\n",
"10 -4.989e+00 -5.003e+00 +5e+01 4e-02 1e-01 2e-03 8e-03 0.2647 5 5 5\n",
"11 -4.857e+00 -4.864e+00 +3e+01 2e-02 6e-02 8e-04 4e-03 0.5682 5 5 5\n",
"12 -4.819e+00 -4.824e+00 +2e+01 1e-02 4e-02 5e-04 3e-03 0.5266 5 5 5\n",
"13 -4.789e+00 -4.791e+00 +8e+00 5e-03 2e-02 2e-04 1e-03 0.8850 5 5 5\n",
"14 -4.774e+00 -4.775e+00 +4e+00 2e-03 8e-03 8e-05 6e-04 0.7023 5 5 5\n",
"15 -4.768e+00 -4.768e+00 +2e+00 1e-03 4e-03 4e-05 3e-04 0.6936 5 5 5\n",
"16 -4.766e+00 -4.766e+00 +1e+00 6e-04 2e-03 2e-05 2e-04 0.7589 5 5 5\n",
"17 -4.765e+00 -4.765e+00 +3e-01 2e-04 6e-04 5e-06 4e-05 0.7661 5 5 5\n",
"18 -4.764e+00 -4.764e+00 +2e-02 2e-05 5e-05 5e-07 4e-06 0.9461 5 5 5\n",
"19 -4.764e+00 -4.764e+00 +9e-04 6e-07 2e-06 2e-08 2e-07 0.9777 5 5 5\n",
"20 -4.764e+00 -4.764e+00 +1e-05 1e-08 3e-08 3e-10 2e-09 0.9845 5 5 5\n",
"21 -4.764e+00 -4.764e+00 +3e-07 2e-10 7e-10 6e-12 5e-11 0.9791 5 5 5\n",
"\n",
"OPTIMAL (within feastol=6.7e-10, reltol=6.5e-08, abstol=3.1e-07).\n",
"Runtime: 1.193969 seconds.\n",
"\n"
]
}
],
"source": [
"# Factor model portfolio optimization.\n",
"w = Variable(n);\n",
"f = F' * w;\n",
"ret = sum(mu' * w); \n",
"risk = quad_form(f, Sigma_tilde) + quad_form(w, D);\n",
"\n",
"\n",
"# Solve the factor model problem.\n",
"Lmax = 2\n",
"gamma = 0.1\n",
"factor_problem = maximize(ret - gamma*risk, [sum(w) == 1, norm(w, 1) <= Lmax]);\n",
"solve!(factor_problem, ECOSSolver())"
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"# Standard portfolio optimization with data from factor model.\n",
"risk = quad_form(w, F * Sigma_tilde * F' + D);\n",
"problem = maximize(ret - gamma*risk, [sum(w) == 1, norm(w, 1) <= Lmax]);"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"# Warning: This takes a long time.\n",
"# solve!(problem, ECOSSolver())"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Julia 0.3.9",
"language": "julia",
"name": "julia-0.3"
},
"language_info": {
"name": "julia",
"version": "0.3.9"
}
},
"nbformat": 4,
"nbformat_minor": 0
}