portf = {"AAPL", "BA", "IBM", "BMW.DE", "DIS", "R", "PEP", "BRBY.L", "AXP", "BTI"};
prices = FinancialData[#, "Price", {{2004}, {2011}, "Month"}] & /@ portf;
Returns are often calculated as the difference of the logarithms of the prices:
Differences[Log@#] &[prices[[1, All, 2]]]
This works because $\log(\text{price}_{new})-\log(\text{price}_{old})=\log(\text{price}_{old}(1+r))-\log(\text{price}_{old})=\log(1+r)$, which is
Series[Log[o (1 + r)] - Log[o], {r, 0, 2}]
that is, approximately $r$.
But we can get returns from FiancialData
right away using "FractionalChange" instead of "Price":
portReturns = FinancialData[#, "FractionalChange", {{2004}, {2011}, "Month"}] & /@ portf;
Can't hurt to check the data a bit. Let's see if we have data from the same dates:
Outer[
Length[Intersection[#1, #2]] &,
portReturns[[All, All, 1]],
portReturns[[All, All, 1]],
1
] // MatrixForm
It appears not all periods are exactly the same. So, if we want to be prudent we could use only the data for the periods that match.
overlappingDates = Intersection @@ (#[[All, 1]] & /@ portReturns);
portReturnsCleaned = Select[#, MemberQ[overlappingDates, #[[1]]] &][[All, 2]] & /@ portReturns;
Now, introduce symbolic weights and define portfolio return and variance in terms of them. The portfolio variance is the sum of the covariance matrix elements.
weights = {w1, w2, w3, w4, w5, w6, w7, w8, w9, w10};
portAverageReturns = 12 weights (Mean /@ portReturnsCleaned) // Total
portVar = 12 Total[Outer[Times, weights, weights] Covariance[portReturnsCleaned\[Transpose]], 2]
Let's find the lowest variance for a bunch of given returns (the so-called efficient frontier). The range of this will lie between:
12 Min@(Mean /@ portReturnsCleaned)
0.08960473674
12 Max@(Mean /@ portReturnsCleaned)
0.7151653802
(should have bought Apple stock)
The no short selling, no borrowing/lending case (weights sum to 1 and each weight is between 0 and 1):
effFrontier =
Table[
{Sqrt[
NMinimize[
{portVar,
Total[weights] == 1 &&
portAverageReturns == i &&
And @@ (0 <= # <= 1 & /@ weights)
}, weights
][[1]]
], i},
{i, 0.09, 0.7, .02}] // Quiet
I collected the square root of the variance (the standard deviations) here as this is usually considered as the measure of risk.
Find the minimum variance portfolio:
minimumVariance1 = {Sqrt[portVar], portAverageReturns} /.
NMinimize[{portVar, Total[weights] == 1 && And @@ (0 <= # <= 1 & /@ weights)}, weights][[2]]
{0.1292044085, 0.127437124}
Plotting this with 10,000 randomly selected portfolios:
Show[
ListLinePlot[effFrontier,
Epilog -> {Red, PointSize -> Large, Point[minimumVariance]},
Frame -> True,
FrameLabel->{"σ","Expected portfolio return","No short selling, no borrowing/lending",""},
PlotRange -> {{0, Automatic}, Automatic}, BaseStyle -> 16,
ImageSize -> 500],
ListPlot[
Table[{Sqrt[portVar], portAverageReturns} /.
Thread[weights -> #/Total[#] &[RandomReal[{0, 1}, 10]]], {10000}]]
]
It appears pretty difficult to blindly guess an optimal portfolio.
Dropping the constraint of no short selling (positive weights) gets us better results:
effFrontier2 =
Table[{Sqrt[
NMinimize[{portVar, Total[weights] == 1 && portAverageReturns == i}, weights][[
1]]], i},
{i, 0.09, 0.7, .02}] // Quiet;
minimumVariance2 = {Sqrt[portVar], portAverageReturns} /.
NMinimize[{portVar, Total[weights] == 1}, weights][[2]]
One more step is to introduce lending/borrowing at the risk free rate:
portAverageReturns2 = α rf + 12 Total[(1 - α) weights (Mean /@ portReturnsCleaned)]
portVar2 = 12 Total[Outer[Times, (1 - α) weights, (1 - α) weights]
Covariance[portReturnsCleaned\[Transpose]], 2]
Assuming a risk free rate of 1%:
Block[{rf = .01},
effFrontier3 =
Table[{Sqrt[
NMinimize[{portVar2,
Total[weights] == 1 && portAverageReturns2 == i &&
And @@ (0 <= # <= 1 & /@ weights)},
Join[weights, {α}]][[1]]], i}, {i, 0.01, 0.7, .05}];
effFrontier4 =
Table[{Sqrt[
NMinimize[{portVar2,
Total[weights] == 1 && portAverageReturns2 == i &&
And @@ (# <= 1 & /@ weights)}, Join[weights, {α}]][[
1]]], i}, {i, 0.01, 0.7, .05}];
]
Show[
ListLinePlot[effFrontier,
Epilog -> {Red, PointSize -> Large, Point[minimumVariance],
Point[minimumVariance2]}, Frame -> True, PlotStyle -> Dashed,
PlotRange -> {{0, Automatic}, Automatic}, BaseStyle -> 16,
ImageSize -> 500,
FrameLabel -> {"σ", "Expected portfolio return", "", ""},
PlotLegends ->
Placed[LineLegend[{Blue, Directive[Blue, Dashed], Darker@Green,
Directive[Darker@Green,
Dashed]}, {"Short & no borrowing/lending",
"No short & no borrowing/lending",
"Short & with borrowing/lending",
"No short & with borrowing/lending"}, LabelStyle -> 12],
Scaled[{0.25, 0.8}]]],
ListLinePlot[effFrontier2, Frame -> True,
PlotRange -> {{0, Automatic}, Automatic}, BaseStyle -> 16,
ImageSize -> 500],
ListLinePlot[effFrontier3, Frame -> True,
PlotRange -> {{0, Automatic}, Automatic}, BaseStyle -> 16,
ImageSize -> 500, PlotStyle -> Directive[Green, Dashed]],
ListLinePlot[effFrontier4, Frame -> True,
PlotRange -> {{0, Automatic}, Automatic}, BaseStyle -> 16,
ImageSize -> 500, PlotStyle -> Green],
ListPlot[Table[{Sqrt[portVar], portAverageReturns} /.
Thread[weights -> #/Total[#] &[RandomReal[{0, 1}, 10]]], {10000}]]
]