Analyze Performance Attribution Using Brinson Model
This example shows how to prepare data, create a brinsonAttribution
object, and then analyze the performance attribution with respect to category (sector) weights and returns. In this example, you use the categoryAttribution
, categoryReturns
, categoryWeights
, totalAttribution
, and summary
functions for the analysis. Also, you can generate plots for the results, using categoryReturnsChart
, categoryWeightsChart
, and attributionsChart
.
Prepare Data
Load the stock price data into a table.
T = readtable('dowPortfolio.xlsx');
MonthIdx = [1;20;39;62;81;103;125;145;168;188;210;231;251];
MonthlyPrices = T(MonthIdx,3:end);
Compute the monthly returns using tick2ret
.
MonthlyReturns = tick2ret(MonthlyPrices.Variables)'; [NumAssets,NumPeriods] = size(MonthlyReturns);
Define the asset categories (sectors) using categorical
.
Category = categorical(["Materials";"Financials";"Financials"; ... "Industrials";"Financials";"Industrials";"Materials"; ... "Communication Services";"Industrials";"Consumer Discretionary"; ... "Consumer Discretionary";"Industrials";"Information Technology"; ... "Information Technology";"Information Technology";"Health Care"; ... "Financials";"Consumer Staples";"Consumer Discretionary"; ... "Industrials";"Consumer Staples";"Health Care"; ... "Information Technology";"Health Care";"Consumer Staples"; ... "Communication Services";"Industrials";"Communication Services"; ... "Consumer Staples";"Energy"]); Category = repmat(Category,1,NumPeriods);
Define Benchmark and Portfolio Weights
Define the benchmark weight and the portfolio weights, by quarter, for each of the stock assets.
BenchmarkWeight = 1./length(MonthlyReturns).*ones(NumAssets, NumPeriods); PortfolioWeightQ1 = [0;0;0.022;0.033;0;0.044;0.022;0.011;0.065;0.033; ... 0.055;0.072;0;0.04;0;0.05;0.08;0.042;0.03;0.043;0.055;0.036;0.111; ... 0.036;0;0.03;0;0.05;0;0.04]*ones(1,3); PortfolioWeightQ2 = [0;0;0.022;0.033;0;0.044;0.022;0.011;0.049;0.033; ... 0.055;0.074;0;0.04;0;0.05;0.08;0.042;0.03;0.02;0.055;0.036;0.148; ... 0.036;0;0.03;0;0.05;0;0.04]*ones(1,3); PortfolioWeightQ3 = [0;0;0.022;0.033;0;0.042;0.022;0.01;0.049;0.033; ... 0.05;0.07;0;0.04;0;0.05;0.08;0.042;0.03;0.02;0.055;0.036;0.16; ... 0.036;0;0.03;0;0.05;0;0.04]*ones(1,3); PortfolioWeightQ4 = [0;0;0.022;0.033;0;0.042;0.02;0.01;0.039;0.033; ... 0.05;0.07;0;0.04;0;0.05;0.08;0.042;0.03;0.02;0.055;0.036;0.198; ... 0.036;0;0.03;0;0.03;0;0.034]*ones(1,3); PortfolioWeight = [PortfolioWeightQ1 PortfolioWeightQ2 ... PortfolioWeightQ3 PortfolioWeightQ4]; Period = (1:NumPeriods).*ones(NumAssets,1); Name = repmat(string(MonthlyPrices.Properties.VariableNames(:)),1,NumPeriods);
Create AssetTable
Input
Use table
to create the AssetTable
input to use when creating a brinsonAttribution
object.
AssetTable = table(Period(:), Name(:), ... MonthlyReturns(:), Category(:), ... PortfolioWeight(:), BenchmarkWeight(:), ... VariableNames=["Period", "Name","Return","Category",... "PortfolioWeight","BenchmarkWeight"])
AssetTable=360×6 table
Period Name Return Category PortfolioWeight BenchmarkWeight
______ ______ ___________ ______________________ _______________ _______________
1 "AA" 0.053621 Materials 0 0.033333
1 "AIG" -0.05964 Financials 0 0.033333
1 "AXP" -0.00019406 Financials 0.022 0.033333
1 "BA" -0.030162 Industrials 0.033 0.033333
1 "C" -0.055015 Financials 0 0.033333
1 "CAT" 0.17956 Industrials 0.044 0.033333
1 "DD" -0.090708 Materials 0.022 0.033333
1 "DIS" 0.037221 Communication Services 0.011 0.033333
1 "GE" -0.07381 Industrials 0.065 0.033333
1 "GM" 0.27273 Consumer Discretionary 0.033 0.033333
1 "HD" -0.016838 Consumer Discretionary 0.055 0.033333
1 "HON" 0.025457 Industrials 0.072 0.033333
1 "HPQ" 0.083598 Information Technology 0 0.033333
1 "IBM" -0.009235 Information Technology 0.04 0.033333
1 "INTC" -0.1685 Information Technology 0 0.033333
1 "JNJ" -0.066351 Health Care 0.05 0.033333
⋮
Create brinsonAttribution
Object
Use brinsonAttribution
to create a brinsonAttribution
object.
BrinsonPAobj = brinsonAttribution(AssetTable)
BrinsonPAobj = brinsonAttribution with properties: NumAssets: 30 NumPortfolioAssets: 22 NumBenchmarkAssets: 30 NumPeriods: 12 NumCategories: 9 AssetName: [30x1 string] AssetReturn: [30x12 double] AssetCategory: [30x12 categorical] PortfolioAssetWeight: [30x12 double] BenchmarkAssetWeight: [30x12 double] PortfolioCategoryReturn: [9x12 double] BenchmarkCategoryReturn: [9x12 double] PortfolioCategoryWeight: [9x12 double] BenchmarkCategoryWeight: [9x12 double] PortfolioReturn: 0.2234 BenchmarkReturn: 0.2046 ActiveReturn: 0.0188
Compute Category Weights
Use the brinsonAttribution
object and categoryWeights
to compute the average and periodic category weights for the portfolio and the benchmark, as well as, the corresponding active weights.
[AverageCategoryWeights,PeriodicCategoryWeights] = categoryWeights(BrinsonPAobj)
AverageCategoryWeights=9×4 table
Category AveragePortfolioWeight AverageBenchmarkWeight AverageActiveWeight
______________________ ______________________ ______________________ ___________________
Communication Services 0.0855 0.1 -0.0145
Consumer Discretionary 0.1155 0.1 0.0155
Consumer Staples 0.097 0.13333 -0.036333
Energy 0.0385 0.033333 0.0051667
Financials 0.102 0.13333 -0.031333
Health Care 0.122 0.1 0.022
Industrials 0.22375 0.2 0.02375
Information Technology 0.19425 0.13333 0.060917
Materials 0.0215 0.066667 -0.045167
PeriodicCategoryWeights=108×5 table
Period Category PortfolioWeight BenchmarkWeight ActiveWeight
______ ______________________ _______________ _______________ ____________
1 Communication Services 0.091 0.1 -0.009
1 Consumer Discretionary 0.118 0.1 0.018
1 Consumer Staples 0.097 0.13333 -0.036333
1 Energy 0.04 0.033333 0.0066667
1 Financials 0.102 0.13333 -0.031333
1 Health Care 0.122 0.1 0.022
1 Industrials 0.257 0.2 0.057
1 Information Technology 0.151 0.13333 0.017667
1 Materials 0.022 0.066667 -0.044667
2 Communication Services 0.091 0.1 -0.009
2 Consumer Discretionary 0.118 0.1 0.018
2 Consumer Staples 0.097 0.13333 -0.036333
2 Energy 0.04 0.033333 0.0066667
2 Financials 0.102 0.13333 -0.031333
2 Health Care 0.122 0.1 0.022
2 Industrials 0.257 0.2 0.057
⋮
Compute Category Returns
Use the brinsonAttribution
object and categoryReturns
to compute the aggregate and periodic category (sector) returns for the portfolio and the benchmark.
[AggregateCategoryReturns,PeriodicCategoryReturns] = categoryReturns(BrinsonPAobj)
AggregateCategoryReturns=9×3 table
Category AggregatePortfolioReturn AggregateBenchmarkReturn
______________________ ________________________ ________________________
Communication Services 0.41756 0.42797
Consumer Discretionary 0.27772 0.34718
Consumer Staples 0.20572 0.14112
Energy 0.33598 0.33598
Financials 0.22678 0.15838
Health Care 0.19451 0.20679
Industrials 0.14132 0.14253
Information Technology 0.14339 0.13485
Materials 0.17109 0.10402
PeriodicCategoryReturns=108×4 table
Period Category PortfolioReturn BenchmarkReturn
______ ______________________ _______________ _______________
1 Communication Services 0.056262 0.052385
1 Consumer Discretionary 0.079767 0.10017
1 Consumer Staples -0.01485 -0.0033588
1 Energy 0.073093 0.073093
1 Financials -0.0021179 -0.029374
1 Health Care 0.012124 0.022297
1 Industrials 0.0018686 0.0088589
1 Information Technology 0.033481 -0.011315
1 Materials -0.090708 -0.018543
2 Communication Services 0.069253 0.078033
2 Consumer Discretionary -0.023091 -0.036416
2 Consumer Staples 0.0027749 0.00096619
2 Energy -0.0487 -0.0487
2 Financials 0.033379 0.02054
2 Health Care 0.014975 0.015929
2 Industrials 0.047732 0.041906
⋮
Compute Category Attribution
Use the brinsonAttribution
object and categoryAttribution
to compute the performance attribution of the portfolio for each category (sector).
[AggregateCategoryAttribution,PeriodicCategoryAttribution] = categoryAttribution(BrinsonPAobj)
AggregateCategoryAttribution=9×5 table
Category Allocation Selection Interaction ActiveReturn
______________________ __________ ___________ ___________ ____________
Communication Services -0.0025318 -0.00071062 0.0002061 -0.0030363
Consumer Discretionary 0.0024505 -0.00678 -0.0011609 -0.0054903
Consumer Staples 0.0023692 0.0093618 -0.0025511 0.00918
Energy 0.00038824 1.3872e-19 2.7745e-20 0.00038824
Financials 0.0013464 0.0097268 -0.0022858 0.0087874
Health Care 0.00011567 -0.0013031 -0.00028667 -0.0014741
Industrials 0.0016701 -0.00035051 -5.7623e-05 0.001262
Information Technology 0.0015686 0.0017812 0.00016898 0.0035187
Materials 0.0040725 0.0050687 -0.0034678 0.0056734
PeriodicCategoryAttribution=108×7 table
Period LinkingCoefficient Category Allocation Selection Interaction ActiveReturn
______ __________________ ______________________ ___________ ___________ ___________ ____________
1 1.1901 Communication Services -0.00034021 0.00038766 -3.489e-05 1.2564e-05
1 1.1901 Consumer Discretionary 0.0015405 -0.0020403 -0.00036725 -0.00086699
1 1.1901 Consumer Staples 0.00065192 -0.0015322 0.00041752 -0.00046274
1 1.1901 Energy 0.00039006 0 0 0.00039006
1 1.1901 Financials 0.0013774 0.0036342 -0.00085403 0.0041575
1 1.1901 Health Care 0.00016968 -0.0010173 -0.0002238 -0.0010714
1 1.1901 Industrials -0.00032634 -0.0013981 -0.00039845 -0.0021229
1 1.1901 Information Technology -0.00045756 0.0059728 0.0007914 0.0063066
1 1.1901 Materials 0.0014797 -0.004811 0.0032234 -0.00010793
2 1.1935 Communication Services -0.00058016 -0.000878 7.902e-05 -0.0013791
2 1.1935 Consumer Discretionary -0.00089975 0.0013325 0.00023985 0.00067261
2 1.1935 Consumer Staples 0.00045794 0.00024116 -6.5715e-05 0.00063338
2 1.1935 Energy -0.00041514 0 0 -0.00041514
2 1.1935 Financials -0.00021838 0.0017119 -0.0004023 0.0010912
2 1.1935 Health Care 5.19e-05 -9.5418e-05 -2.0992e-05 -6.451e-05
2 1.1935 Industrials 0.0016152 0.0011651 0.00033205 0.0031123
⋮
Compute Total Attribution
Use the brinsonAttribution
object and totalAttribution
to compute the total performance attribution of the portfolio summed up for all categories (sectors).
[AggregateTotalAttribution,PeriodicTotalAttribution] = totalAttribution(BrinsonPAobj)
AggregateTotalAttribution=1×4 table
Allocation Selection Interaction ActiveReturn
__________ _________ ___________ ____________
0.011449 0.016794 -0.0094348 0.018809
PeriodicTotalAttribution=12×6 table
Period LinkingCoefficient Allocation Selection Interaction ActiveReturn
______ __________________ ___________ ___________ ___________ ____________
1 1.1901 0.0044852 -0.00080413 0.0025538 0.0062349
2 1.1935 0.00087285 0.0032617 -0.0025973 0.0015372
3 1.1904 -6.9025e-05 0.0052394 0.00069386 0.0058643
4 1.208 -0.004707 -0.0095748 -0.0046622 -0.018944
5 1.1995 -0.00030704 -0.006091 -0.00061525 -0.0070132
6 1.1935 0.0012025 -0.00026724 0.00058932 0.0015246
7 1.1813 0.0032236 0.017541 -0.0021062 0.018658
8 1.196 0.004629 -0.004929 -0.0018038 -0.0021038
9 1.1927 0.0013046 0.00036681 0.00099195 0.0026634
10 1.1923 0.0032172 0.0023077 -0.0023663 0.0031586
11 1.194 -0.001881 0.00044958 0.0022018 0.00077039
12 1.1918 -0.0022819 0.0069324 -0.0007375 0.003913
Generate Summary for Performance Attribution
Use the brinsonAttribution
object and summary
to generate a table that summarizes the final results (aggregated over all time periods and categories) of the performance attribution using the Brinson model.
SummaryTable = summary(BrinsonPAobj)
SummaryTable=11×1 table
Brinson Attribution Summary
___________________________
Total Number of Assets 30
Number of Assets in Portfolio 22
Number of Assets in Benchmark 30
Number of Periods 12
Number of Categories 9
Portfolio Return 0.22345
Benchmark Return 0.20464
Active Return 0.018809
Allocation Effect 0.011449
Selection Effect 0.016794
Interaction Effect -0.0094348
Generate Horizontal Bar Charts for Returns, Weights, and Performance Attribution
Use the brinsonAttribution
object and categoryReturnsChart
, categoryWeightsChart
, and attributionsChart
to generate horizontal bar charts.
categoryReturnsChart(BrinsonPAobj)
categoryWeightsChart(BrinsonPAobj)
attributionsChart(BrinsonPAobj, Style="stacked")
See Also
brinsonAttribution
| categoryAttribution
| categoryReturns
| categoryWeights
| totalAttribution
| summary