- #1
member 428835
Hi PF!
I'm going through a backtracking tutorial here. That code runs well for me, and is below:
I've shortened it substantially, where I only go until we get initial portfolio weights. Now I try to run this code with different data, so the code slightly changes to this:
but my code is choking at line 28. I've read the error message, compared my table T to the tutorial's, but can't seem to figure out the issue. Any help is greatly appreciated.
I'm going through a backtracking tutorial here. That code runs well for me, and is below:
Matlab:
%% LOAD DATA
% Read a table of daily adjusted close prices for 2006 DJIA stocks.
T = readtable('dowPortfolio.xlsx');
% For readability, use only 15 of the 30 DJI component stocks.
assetSymbols = ["AA","CAT","DIS","GM","HPQ","JNJ","MCD","MMM","MO","MRK","MSFT","PFE","PG","T","XOM"];
% Prune the table to hold only the dates and selected stocks.
timeColumn = "Dates";
T = T(:,[timeColumn assetSymbols]);
% Convert to the table to a timetable.
pricesTT = table2timetable(T,'RowTimes','Dates');
% View the structure of the prices timetable.
head(pricesTT)
% View the size of the asset price data set.
numSample = size(pricesTT.Variables, 1);
numAssets = size(pricesTT.Variables, 2);
table(numSample, numAssets)
% USE FIRST 40 DAYS
% This example uses the first 40 days of the data set (about 2 months) to initialize the strategies
% The backtest is then run over the remaining data (about 10 months).
warmupPeriod = 40;
% No current weights (100% cash position).
current_weights = zeros(1,numAssets);
% Warm-up partition of data set timetable.
warmupTT = pricesTT(1:warmupPeriod,:);
%%
% Compute the initial portfolio weights for each strategy.
equalWeight_initial = equalWeightFcn(current_weights,warmupTT);
maxSharpeRatio_initial = maxSharpeRatioFcn(current_weights,warmupTT);
inverseVariance_initial = inverseVarianceFcn(current_weights,warmupTT);
markowitz_initial = markowitzFcn(current_weights,warmupTT);
robustOptim_initial = robustOptimFcn(current_weights,warmupTT);
%% LOCAL FUNCTIONS
function new_weights = equalWeightFcn(current_weights, pricesTT)
% Equal-weighted portfolio allocation
nAssets = size(pricesTT, 2);
new_weights = ones(1,nAssets);
new_weights = new_weights / sum(new_weights);
end
function new_weights = maxSharpeRatioFcn(current_weights, pricesTT)
% Mean-variance portfolio allocation
nAssets = size(pricesTT, 2);
assetReturns = tick2ret(pricesTT); % tick2ret GIVES PERCENT RETURN AS DECIMAL FROM ONE DAY TO THE NEXT
% Max 25% into a single asset (including cash)
p = Portfolio('NumAssets',nAssets,...
'LowerBound',0,'UpperBound',0.1,...
'LowerBudget',1,'UpperBudget',1); % Portfolio IS DICTIONARY WITH PREDEFINED KEYS
p = estimateAssetMoments(p, assetReturns{:,:}); % estimates mean & covariance of assetReturns from data for a Portfolio object
new_weights = estimateMaxSharpeRatio(p); % outputs sharp ratio
end
function new_weights = inverseVarianceFcn(current_weights, pricesTT)
% Inverse-variance portfolio allocation
% Risk averse by weighting prop to inverse variance, or inverse uncertainty
assetReturns = tick2ret(pricesTT); % tick2ret GIVES PERCENT RETURN AS DECIMAL FROM ONE DAY TO THE NEXT
assetCov = cov(assetReturns{:,:}); % cov calculates covariance, measures amount two quantities move together or inversed
new_weights = 1 ./ diag(assetCov);
new_weights = new_weights / sum(new_weights);
end
function new_weights = robustOptimFcn(current_weights, pricesTT)
% Robust portfolio allocation
% maximizing return and minimizing risk with fixed risk-aversion
% coefficient (lambda)
nAssets = size(pricesTT, 2);
assetReturns = tick2ret(pricesTT); % tick2ret GIVES PERCENT RETURN AS DECIMAL FROM ONE DAY TO THE NEXT
Q = cov(table2array(assetReturns));
SIGMAx = diag(diag(Q)); % make matrix of zeros with diag the cov_ii
% Robust aversion coefficient
k = 1.1;
% Robust aversion coefficient
lambda = 0.05;
rPortfolio = mean(table2array(assetReturns))'; % mean of assetReturns
% Create the optimization problem
pRobust = optimproblem('Description','Robust Portfolio');
% Define the variables
% xRobust - x allocation vector
xRobust = optimvar('x',nAssets,1,'Type','continuous','LowerBound',0.0,'UpperBound',0.1);
zRobust = optimvar('z','LowerBound',0);
% Define the budget constraint
pRobust.Constraints.budget = sum(xRobust) == 1;
% Define the robust constraint
pRobust.Constraints.robust = xRobust'*SIGMAx*xRobust - zRobust*zRobust <=0;
pRobust.Objective = -rPortfolio'*xRobust + k*zRobust + lambda*xRobust'*Q*xRobust;
x0.x = zeros(nAssets,1);
x0.z = 0;
opt = optimoptions('fmincon','Display','off');
[solRobust,~,~] = solve(pRobust,x0,'Options',opt);
new_weights = solRobust.x;
end
function new_weights = markowitzFcn(current_weights, pricesTT)
% Robust portfolio allocation
nAssets = size(pricesTT, 2);
assetReturns = tick2ret(pricesTT);
Q = cov(table2array(assetReturns));
% Risk aversion coefficient
lambda = 0.05;
rPortfolio = mean(table2array(assetReturns))';
% Create the optimization problem
pMrkwtz = optimproblem('Description','Markowitz Mean Variance Portfolio ');
% Define the variables
% xRobust - x allocation vector
xMrkwtz = optimvar('x',nAssets,1,'Type','continuous','LowerBound',0.0,'UpperBound',0.1);
% Define the budget constraint
pMrkwtz.Constraints.budget = sum(xMrkwtz) == 1;
% Define the Markowitz objective
pMrkwtz.Objective = -rPortfolio'*xMrkwtz + lambda*xMrkwtz'*Q*xMrkwtz;
x0.x = zeros(nAssets,1);
opt = optimoptions('quadprog','Display','off');
[solMrkwtz,~,~] = solve(pMrkwtz,x0,'Options',opt);
new_weights = solMrkwtz.x;
end
function [buy, sell] = variableTransactionCosts(deltaPositions)
Matlab:
load('T.csv')
% Convert to the table to a timetable.
pricesTT = table2timetable(T,'RowTimes','Dates');
% View the structure of the prices timetable.
head(pricesTT)
% View the size of the asset price data set.
numSample = size(pricesTT.Variables, 1);
numAssets = size(pricesTT.Variables, 2);
table(numSample, numAssets)
% USE FIRST 40 DAYS
% This example uses the first 40 days of the data set (about 2 months) to initialize the strategies
% The backtest is then run over the remaining data (about 10 months).
warmupPeriod = 40;
% No current weights (100% cash position).
current_weights = zeros(1,numAssets);
% Warm-up partition of data set timetable.
warmupTT = pricesTT(1:warmupPeriod,:);
%%
% Compute the initial portfolio weights for each strategy.
equalWeight_initial = equalWeightFcn(current_weights,warmupTT);
maxSharpeRatio_initial = maxSharpeRatioFcn(current_weights,warmupTT);
inverseVariance_initial = inverseVarianceFcn(current_weights,warmupTT);
markowitz_initial = markowitzFcn(current_weights,warmupTT);
robustOptim_initial = robustOptimFcn(current_weights,warmupTT);
%% LOCAL FUNCTIONS
function new_weights = equalWeightFcn(current_weights, pricesTT)
% Equal-weighted portfolio allocation
nAssets = size(pricesTT, 2);
new_weights = ones(1,nAssets);
new_weights = new_weights / sum(new_weights);
end
function new_weights = maxSharpeRatioFcn(current_weights, pricesTT)
% Mean-variance portfolio allocation
nAssets = size(pricesTT, 2);
assetReturns = tick2ret(pricesTT); % tick2ret GIVES PERCENT RETURN AS DECIMAL FROM ONE DAY TO THE NEXT
% Max 25% into a single asset (including cash)
p = Portfolio('NumAssets',nAssets,...
'LowerBound',0,'UpperBound',0.1,...
'LowerBudget',1,'UpperBudget',1); % Portfolio IS DICTIONARY WITH PREDEFINED KEYS
p = estimateAssetMoments(p, assetReturns{:,:}); % estimates mean & covariance of assetReturns from data for a Portfolio object
new_weights = estimateMaxSharpeRatio(p); % outputs sharp ratio
end
function new_weights = inverseVarianceFcn(current_weights, pricesTT)
% Inverse-variance portfolio allocation
% Risk averse by weighting prop to inverse variance, or inverse uncertainty
assetReturns = tick2ret(pricesTT); % tick2ret GIVES PERCENT RETURN AS DECIMAL FROM ONE DAY TO THE NEXT
assetCov = cov(assetReturns{:,:}); % cov calculates covariance, measures amount two quantities move together or inversed
new_weights = 1 ./ diag(assetCov);
new_weights = new_weights / sum(new_weights);
end
function new_weights = robustOptimFcn(current_weights, pricesTT)
% Robust portfolio allocation
% maximizing return and minimizing risk with fixed risk-aversion
% coefficient (lambda)
nAssets = size(pricesTT, 2);
assetReturns = tick2ret(pricesTT); % tick2ret GIVES PERCENT RETURN AS DECIMAL FROM ONE DAY TO THE NEXT
Q = cov(table2array(assetReturns));
SIGMAx = diag(diag(Q)); % make matrix of zeros with diag the cov_ii
% Robust aversion coefficient
k = 1.1;
% Robust aversion coefficient
lambda = 0.05;
rPortfolio = mean(table2array(assetReturns))'; % mean of assetReturns
% Create the optimization problem
pRobust = optimproblem('Description','Robust Portfolio');
% Define the variables
% xRobust - x allocation vector
xRobust = optimvar('x',nAssets,1,'Type','continuous','LowerBound',0.0,'UpperBound',0.1);
zRobust = optimvar('z','LowerBound',0);
% Define the budget constraint
pRobust.Constraints.budget = sum(xRobust) == 1;
% Define the robust constraint
pRobust.Constraints.robust = xRobust'*SIGMAx*xRobust - zRobust*zRobust <=0;
pRobust.Objective = -rPortfolio'*xRobust + k*zRobust + lambda*xRobust'*Q*xRobust;
x0.x = zeros(nAssets,1);
x0.z = 0;
opt = optimoptions('fmincon','Display','off');
[solRobust,~,~] = solve(pRobust,x0,'Options',opt);
new_weights = solRobust.x;
end
function new_weights = markowitzFcn(current_weights, pricesTT)
% Robust portfolio allocation
nAssets = size(pricesTT, 2);
assetReturns = tick2ret(pricesTT);
Q = cov(table2array(assetReturns));
% Risk aversion coefficient
lambda = 0.05;
rPortfolio = mean(table2array(assetReturns))';
% Create the optimization problem
pMrkwtz = optimproblem('Description','Markowitz Mean Variance Portfolio ');
% Define the variables
% xRobust - x allocation vector
xMrkwtz = optimvar('x',nAssets,1,'Type','continuous','LowerBound',0.0,'UpperBound',0.1);
% Define the budget constraint
pMrkwtz.Constraints.budget = sum(xMrkwtz) == 1;
% Define the Markowitz objective
pMrkwtz.Objective = -rPortfolio'*xMrkwtz + lambda*xMrkwtz'*Q*xMrkwtz;
x0.x = zeros(nAssets,1);
opt = optimoptions('quadprog','Display','off');
[solMrkwtz,~,~] = solve(pMrkwtz,x0,'Options',opt);
new_weights = solMrkwtz.x;
end
function [buy, sell] = variableTransactionCosts(deltaPositions)