www.gusucode.com > GAVPai_Book_MathworksCntrlFileEx_May2019 > GAVPai_Book_MathworksCntrlFileEx_May2019/Chapter6_130_30_PortfOptmzn_DEHOF_Rand4BestDir5.m

    % Vijayalakshmi Pai G A, Metaheuristics for Portfolio Optimization, An
% Introduction using MATLAB, ISTE-Wiley, 2017.

% Differential Evolution with Hall of Fame (DE HOF), Rand4/Best/Dir5 strategy
% and dynamic scale factor bets,  for constrained optimization of 130-30
% portfolio optimization


% Chapter 6   Sec. 6.5E  
% The constrained 130-30 portfolio optimization model  is represented by equations [6.12]-[6.13] for
% its objective function and equations [6.15]-[6.19] for its constraints

% The portfolio considered is a k-portfolio of 90 assets over S&PBSE200 Index 
% Sec. 6.4.4

% The data file S&PBSE200_kPortfolio.xls records the mean returns of the
% assets of the k-portfolio, followed by variance-covariance matrix of returns of the assets
% and betas of the assets, with the  asset labels displayed in the last row


% Program coding:  Dr G A Vijayalakshmi Pai
% Note: Coding style has been kept naive and direct to favor novices in
% MATLAB. Users familiar with MATLAB are encouraged to improvise the code
%------------------------------------------------------------------------

clear all

% input mean returns, variance-covariance matrix of asset returns and asset
% betas 
portfolio_size =90;
file_name = 'S&PBSE200_kPortfolio.xls'; 
m = xlsread(file_name);
mean_data = m(1,:);
cov_data = m(2:portfolio_size+1, :);
Beta_assets = m(portfolio_size+2, :);

% general bounds
for c = 1: portfolio_size
    bounds(:,c) = [-0.3; 1.3];   
end

% bounds for the long and short positions in the portfolio
z = zeros(1,portfolio_size);
o = ones (1, portfolio_size);
long_pos_bounds(1,:)  = z ; % set lower and upper bounds for long positions as (0, 1.3)
long_pos_bounds(2,:)  =  1.3*o;
short_pos_bounds(1,:) =  -0.3*o;
short_pos_bounds(2,:) =  z;  % set lower and upper bounds for short  positions as  ( -0.3, 0)


% portfolio parameters
annriskfree = 6.5/100;
riskfree = ((1+annriskfree)^(1/360) -1)*100;

% Differential Evolution strategy parameters
popln_size = 1000; 
chromosm_length = 90;  
total_generations = 8000;  
beta = 0.5;
pr_recombi = 0.87; 
aa = -0.3;
bb= 1.3;


% Joines and Houck's (1994)  dynamic penalty (dp) function strategy
% Set parameters C, alpha, beta
C_dp = 0.5; 
alpha_dp=2;
beta_dp=2;


% initialize Hall of Fame which will finally hold the optimal weights       
HOF_fitness = -999;
HOF_individual = zeros(1, portfolio_size);
i1 = 1;
 
% generation counter
gen_indx = 1; 

fix(clock)
        
% generate initial random population within the range [-0.3, 1.3]
initial_popln_raw = aa + (bb-aa)*rand(popln_size, chromosm_length);

% repair weights
initial_popln_bound = weight_std_130_30_boundsconstr(initial_popln_raw, bounds);
initial_popln = weight_std_130_30_budgetconstr(initial_popln_bound, long_pos_bounds, short_pos_bounds);

% compute constraint violation function
[initial_popln_psi, initial_popln_G1]= ConstrViolnFun_130_30(initial_popln, Beta_assets, C_dp, alpha_dp, beta_dp, gen_indx);

% compute fitness function
initial_popln_fitness = CompFitness_130_30(initial_popln, mean_data, cov_data, riskfree,  initial_popln_psi);
                                      
       
% create parent population and compute fitness       
feas_parent_popln = initial_popln; 
feas_parent_popln_fitness = initial_popln_fitness;
feas_parent_popln_psi = initial_popln_psi;

% while loop for generation cycles begins      
        
while (gen_indx <= total_generations)         
        gen_indx                                      
        
        %dynamic beta for each generation
        dynamic_beta = 0.5+(1-0.5)*rand(1,1);
        
        % obtain trial vector population
        trial_vector_popln = DE_Rand4BestDir5_Operator(feas_parent_popln, feas_parent_popln_fitness,  dynamic_beta, popln_size, chromosm_length);
        
        % obtain offspring population
        offsprng_popln = DE_bin_Crossover(feas_parent_popln, trial_vector_popln, pr_recombi, chromosm_length);
        
        % undertake weight repair strategy Phase 1
        mutat_popln_bound = weight_std_130_30_boundsconstr(offsprng_popln, bounds);
       
        % undertake weight repair strategy Phase 2
        feas_mutat_popln = weight_std_130_30_budgetconstr(mutat_popln_bound, long_pos_bounds, short_pos_bounds);
        
        % compute constraint violation function
        [feas_mutat_popln_psi, feas_mutat_popln_G1]= ConstrViolnFun_130_30(feas_mutat_popln, Beta_assets, C_dp, alpha_dp, beta_dp, gen_indx);
       
        % compute fitness function values
        feas_mutat_popln_fitness = CompFitness_130_30(feas_mutat_popln, mean_data, cov_data, riskfree,  feas_mutat_popln_psi);
         
        
         % set the population for the next generation
        [next_gen_pool, next_gen_pool_fitness, Psi_fun ] = DE_selection_penalty_13030(feas_parent_popln, feas_parent_popln_fitness,  feas_parent_popln_psi,   feas_mutat_popln, feas_mutat_popln_fitness, feas_mutat_popln_psi,  popln_size); 
        
        
        % induce best individual into Hall of Fame
        for i=1:popln_size
            if (Psi_fun(i)== 0)
                                       
                    if (next_gen_pool_fitness(i) > HOF_fitness)
                    HOF_fitness = next_gen_pool_fitness(i)
                    HOF_individual = next_gen_pool(i,:);
                    HOF_genarray(i1) = gen_indx;
                    HOF_fitarray(i1) = HOF_fitness;
                    i1=i1+1;
                    end
            else continue;
            end
        end
        
        % increment generation counter
        gen_indx = gen_indx + 1;
        
       % form the parent population for the next generation
        feas_parent_popln = next_gen_pool;
        feas_parent_popln_fitness = next_gen_pool_fitness;
        
end    % while loop for generations ends
        
fix(clock)

% obtain optimal weights from the Hall of Fame 
x_star = HOF_individual; 
    
% compute optimal portfolio annualized risk and return            
portfolio_return =  261 * sum(mean_data .* x_star);
risk = sqrt(261 * x_star * cov_data * x_star');

   
disp('Integrated 130-30 Portfolio Optimization results:')
disp('risk    return     Sharpe ratio')
risk
portfolio_return
sharperatio = (portfolio_return-annriskfree*100)/ risk

disp('long positions       short positions')       
long = find(x_star > 0)
short = find(x_star < 0)

disp('weights: long positions   short positions      weight sum     portfolio beta')
sum (x_star(long))
sum(x_star(short))
sum(x_star)
portfoliobeta = sum(x_star.* Beta_assets)
    
disp('Successful execution!')