Main Content

Adding Constraints to Satisfy UCITS Directive

This example shows how to set up and solve a portfolio optimization problem that satisfies the Undertakings for Collective Investment in Transferable Securities (UCITS) Directive. The UCITS directive is a regulatory requirement of European investment funds. As of 2019, the UCITS asset allocation regulation states that funds can only invest only up to 10% in a single issuer, and that investments in excess of 5% must not exceed 40% of the total portfolio, with some exceptions. This rule is known as the 5/10/40 rule.

Create Portfolio Object

To solve a portfolio problem and add this requirement to the problem, start by creating a Portfolio, PortfolioCVaR, or PortfolioMAD object, depending on the desired risk measure.

% Read table of daily adjusted close prices for 2006 DJI stocks
pricesTT = readtimetable('dowPortfolio.xlsx');
% Compute the returns from the prices
returnsTT = tick2ret(pricesTT);

% Remove the DJI stock from the timetable
assetReturnsTT = returnsTT(:,2:end);
% Compute the asset returns mean and covariance matrix
mu = mean(assetReturnsTT.Variables);
Sigma = cov(assetReturnsTT.Variables);

% Create Portfolio object
p = Portfolio(AssetMean=mu',AssetCovar=Sigma);

To add the 10% upper bound on the maximum that you can invest in any individual asset, use setBounds. In this example, any chosen asset must represent at least 1% of the total portfolio.

% Weights must be either 0 or between 0.01 and 0.1
p = setBounds(p,0.01,0.1,BoundType="conditional");

To set the conditional constraint that limits the aggregate weight that you can invest in assets that exceed 5%, use setConditionalBudget.

% Assets with weights above 5% must not exceed 40% of the total
% portfolio
p = setConditionalBudget(p,0.05,0.4);

Finally, the portfolio weights must sum to one and must have between 15 and 20 active assets.

% Sum of weights must be equal to one
p = setBudget(p,1,1);

% 15-20 active assets
p = setMinMaxNumAssets(p,15,20);

Compute Minimum Variance Portfolio with Tracking Error Penalty

Given some trackingPortfolio weights allocation, find the minimum variance portfolio using estimateCustomObjectivePortfolio with a tracking error penalty that satisfies all the constraints in the previous section.

% Define tracking portfolio as the portfolio of the DJI
trackingPortfolio = returnsTT{:,2:end}\returnsTT{:,1};

% Penalized objective function
penalizedVariance = @(w) w'*Sigma*w + ...
    (w-trackingPortfolio)'*Sigma*(w-trackingPortfolio);

% Penalized variance portfolio
p = setSolverMINLP(p,"OuterApproximation",ExtendedFormulation=true, ...
    ObjectiveScalingFactor=1e4);
w = estimateCustomObjectivePortfolio(p,penalizedVariance);

The following bar chart shows the weights distribution of the portfolio.

figure
bar(assetReturnsTT.Properties.VariableNames,w);
hold on
yline(0.05,'r--',LineWidth=2)
title('Minimum Variance Portfolio with Tracking Error Penalty')
ylabel('Weight')

Figure contains an axes object. The axes object with title Minimum Variance Portfolio with Tracking Error Penalty, ylabel Weight contains 2 objects of type bar, constantline.

Only five assets are above the 5% conditional threshold and the sum of these assets are less than 40%.

conditionalBudget = sum(w(w > 0.05))
conditionalBudget = 
0.4000

See Also

|