Trying to optimize weights of series of combinations (250 in total) of 10-stock portfolios for Omega Ratio, with weights bound from 0<->1, and total of weights = 1.

So I know MATLAB has a function for Omega Ratio: Omega = lpm(-Data, -MAR, 1) / lpm(Data, MAR, 1), that uses "lpm". That is my objective function. I believe I can use "fmincon" - or a linear optimizer for this exercise. My constraints are as per above.
The question I have is, does anyone know of any scripts that I can begin with so I'm not reinventing the wheel?
I want to output the 1 of the 250 combinations with the highest Omega Ratio, its weights (for each of the 10 stocks)

6 Comments

Andrew, can you specify what you mean by having 250 combinations of the 10-stock portfolios? Do you mean you have 250 combinations of 10 different stocks or do you mean you have 250 combinations of weights for the same 10 stocks?
I.e., do you already know the possible weights or is that part of what you are trying to calculate?
Also, can you specify what data it is with which you are starting. E.g., do you have a 10 x 250 matrix of doubles, 250 Portfolio objects, etc?
Thanks for following up Brandon. What I have is a population of 13 stocks from which I'm choosing combinations of 10 (so 286 combinations - it's a combination without replacement exercise, i.e., I can't have IBM in the group of 10 more than twice, and order doesn't matter).
So I've created a matrix of the 286 combinations already - works fine (it's a single matrix of column numbers - i.e., 1 to 13) in the rows, and 10 columns, 286 rows).
So the objective function is the Omega Ratio (which you point out in your previous message - you have it exactly right.
The constraints for this simple initial exercise are a "long only" portfolio - i.e., no short selling or leverage. So each of the 10 stocks's weight is bounded by 0 and 1. Also the total weights of the 10 stocks must equal 1.
I'm having real trouble understanding all the arguments to the fmincon() function (I'm new to MATLAB). I know you have to set an initial guess - i.e., X0=0 (or your equal weight of 0.1).
When you think of the exercise in general, at this stage it's not really an optimization problem (but I will need to use the optimization engine as I add constraints so need/want to use it now. By that I mean, each stock has it's own Omega Ratio. The portfolio (i.e., group of 10) is also a simple linear combination of the 10 Omega Ratios. Therefore the weights should be "1" for the stock with the highest Omega, and "0" for the other 9.
% (optimize_omega.Vn); Vn - nth version
% Start the processing time clock:
tic()
% Import the return data from Excel file names
% input_return_data_matrix(1).xlsx'. Returns are in rows, holdings in columns:
[num, txt, raw] = xlsread('input_return_data_matrix(1)');
% format short g;
% Count of number of securities (removes date column):
num_securities = size(num, 2) - 1;
% Count of number of periods:
num_periods = size(num, 1);
% Combinations in portfolio of 10 securities chosen amoung a sample of 13:
combinations_matrix = combnk(1:num_securities, 10);
% Skew the column number of the combination forward by one (for date field):
combinations_matrix = combinations_matrix + 1;
% Total number of combinations:
total_number_combinations = size(combinations_matrix, 1);
% Initialize weights matrix:
optimal_weights = zeros(10, total_number_combinations);
% Initialize omegas matrix:
optimal_omegas = zeros(1, total_number_combinations);
for k = 1 : total_number_combinations
% Set constraints for each optimization of total number of combinations:
% Lower-bound and upper-bound for each weight is 0 and 1, respectively:
lb = zeros(1, 10);
ub = ones(1, 10);
% Total weight equals 1:
Aeq = ones(1, 10);
beq = 1;
% Use a equal weighting as the initial guess:
% x0 = 0.1 * ones(10,1);
x0 = zeros(1, 10)';
A = [];
b = [];
% Create and save the combination data matrix:
r = num(:, combinations_matrix(k, 1:end));
save('returns.mat', 'r')
% The non-linear optimization:
options = optimset('Display', 'off');
nonlcon = [];
[optimal_weights(:, k), optimal_omegas(k)] = fmincon(@f_omega_02, x0, A, b, Aeq, beq, lb, ub, nonlcon, options);
% Write portfolio combination to command window:
fprintf('\nPortfolio Combination: ');
fprintf('%d', k);
pause(0.05);
% Write optimal omega ratio to command window:
fprintf('\tOptimal Omega: ');
fprintf('%f', optimal_omegas(k));
pause(0.05);
end
fprintf('\n')
% [max_omega, array_max_omega] = max(optimal_omegas);
% Data(:,indexOfMax)
% Stop the processing time clock:
toc()
function [negative_omegas] = f_omega_02(x)
% In this function, i.e., "negative_omegas", the objective function to maximize the omega ratio is multiplied by (-1) given that "fmincon()" seeks a minimimum:
load('returns.mat')
negative_omegas = -1 * lpm(-r * x, -0.04, 1) / lpm(r * x, 0.04, 1);
end
Effectively what's going on with the function is it's giving me the right weights (one of the 10 is fully weighted at "1", the other 9 are "0", but when I compare it to Excel, it's not applying the right full "1" weight to the right stock (it should be the one with the highest individual Omega Ratio).
I think it has to do with the input parameters I'm passing fmincon()?

Sign in to comment.

 Accepted Answer

Hey Andrew, it's hard to answer your question precisely without knowing about your Data variable. One would need to know the datatype and what information it contains to know how to pass it and the weights appropriately to "lpm" and "fmincon". Below is essentially psuedo code that you can adjust to meet your needs. What I have provided definitely will not work (specifically because of how weights and Data are passed to "lpm".
%
%data and mars initialized somehow and stored in Data and MAR variables, respectively
%
optimalWeights = zeros(10:250);
optimalOmegas = zeros(1:250);
%Lower bound and upper bound for each weight is 0 and 1, respectively.
lb = zeros(1:10);
up = ones(1:10);
%All weights should add together to equal 1.
Aeq = ones(1:10);
beq=1;
%use even distribution as initial guess
w0 = 0.1*ones(10,1);
for k = 1:250
%The function is multiplied by -1 because fmincon is a minimizer
func = @(weights)-1*lpm(-weights*Data(:,k),-MAR(k),1)/lpm(weights*Data(:,k),MAR(k),1);
[optimalWeights(:,k), optimalOmegas(k)] = fmincon(func,w0,[],[],Aeq,beq,lb,ub);
end
[maxOmega, indexOfMax] = max(optimalOmegas);
Data(:,indexOfMax)
It sounds like you are aware of these documentation pages but, just in case, I have provided links below to "lpm" and "fmincon" so you can see the appropriate way to pass arguments to these functions.

1 Comment

Thanks so much Brandon. I appreciate your input. I'll be working on this over the weekend. Let me employ your suggestions and show you what I come up with - any more input would be hugely appreciated then. Cheers.

Sign in to comment.

More Answers (0)

Tags

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!