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

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

% Differential Evolution with Hall of Fame (DE HOF) and Rand5/Dir4 strategy
% (DE/Rand5/Dir4) for metaheuristic optimization of risk budgeted
% equity market neutral portfolios

% Chapter 5   Secs. 5.6 B, C, D, E, F 
% The Risk budgeted equity market neutral portfolio  is represented by equations [5.14]-[5.19] for
% its objective function and equations [5.20]-[5.25] for its constraints

% The portfolio considered is a long-short portfolio of 49 long positions
% followed by 49 short positions over Nikkei225 Index 
% Sec. 5.5 Portfolio C

% The data file Nikkei225_PortfolioC.xls records the mean returns of the
% assets of Portfolio C, followed by variance-covariance matrix of returns of the assets
% and betas of the assets, with the colour coded 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

% number of long positions in the portfolio
L_col = 49;
% number of short positions in the portfolio
S_col = 49;
% portfolio size
portfolio_size = L_col+S_col;

% serial number of high volatility assets in the portfolio
Highvolat_assets = [97 98]; % Softbank Corp and Pacific Metals Co Ltd


% obtain mean returns, variance-covariance matrix of returns and asset
% betas
filename = 'Nikkei225_PortfolioC.xls';
m = xlsread(filename);

mean_data = m(1,:);
cov_data = m(2:portfolio_size+1, :);
Beta_assets = m(portfolio_size+2, :);


% input differential evolution parameters 
popln_size = 980; 
chromosm_length = portfolio_size; 
total_generations = 5000;
beta = 0.5;
pr_recombi = 0.87; 

% input portfolio parameters
Long_low_bound = 0.0001; 
Long_up_bound=1;
Short_low_bound = -1; 
Short_up_bound=-0.0001;

% initialize Hall of Fame      
 HOF_fitness = -9999;
 HOF_individual = zeros(1, portfolio_size);
 
 % generation counter
 gen_indx = 1; 
 % Hall of Fame induction counter
 i1=1; 
        

fix(clock)

% generate initial population representing long short portfolio
initial_popln_raw= EMNP_gen_longshort_popln(popln_size,  L_col, S_col, Long_low_bound, Long_up_bound, Short_low_bound, Short_up_bound);
        
% undertake weight repair of long and short positions 
initial_popln_longstd = EMNP_eqconstr_wgtstd(initial_popln_raw,  1, L_col,  Long_low_bound, Long_up_bound, 1);
initial_popln_firststd = EMNP_eqconstr_wgtstd(initial_popln_longstd,  L_col+1,  L_col+S_col,   -Short_up_bound, -Short_low_bound,0);

initial_popln = initial_popln_firststd;

% compute constraint violation functions
[psi_i, initial_G1, initial_G2]  = EMNP_compute_constr_violn_fn( initial_popln, cov_data, Beta_assets, Highvolat_assets);
[initial_popln_fitness, initial_popln_obj_val] = EMNP_comp_fitness_function(initial_popln, mean_data, psi_i);
         
% DE generation cycles begin
while (gen_indx <= total_generations)         
                                              
        gen_indx
        feas_parent_popln = initial_popln; 
        feas_parent_popln_fitness = initial_popln_fitness;
        psi_p = psi_i;
        feas_parent_G1= initial_G1;
        feas_parent_G2 = initial_G2;
        feas_parent_obj_val = initial_popln_obj_val;
        
        % perform mutation 
        trial_vector_popln = DE_Rand5Dir4_Operator(feas_parent_popln, feas_parent_popln_fitness,  beta, popln_size, chromosm_length);
        
        % perform crossover
        offsprng_popln_raw = DE_bin_Crossover(feas_parent_popln, trial_vector_popln, pr_recombi, chromosm_length);
        
        % undertake weight repair of long/short positions
        offsprng_popln_longstd = EMNP_eqconstr_wgtstd(offsprng_popln_raw,  1, L_col,  Long_low_bound, Long_up_bound, 1);
        offsprng_popln_shortstd = EMNP_eqconstr_wgtstd(offsprng_popln_longstd,  L_col+1,  L_col+S_col,   -Short_up_bound, -Short_low_bound,0);
        offsprng_popln = offsprng_popln_shortstd;
        
        % compute constraint violation functions
        [psi_o,offsprng_G1, offsprng_G2]  = EMNP_compute_constr_violn_fn( offsprng_popln, cov_data, Beta_assets, Highvolat_assets);
        
        % compute fitness functions
        [offsprng_popln_fitness, offsprng_obj_val] = EMNP_comp_fitness_function(offsprng_popln, mean_data, psi_o);
        
        % Tournament selection of individuals for the next generation
        [next_gen_pool, next_gen_pool_obj_val,  Psi_fun, G1_nextgen,G2_nextgen,  next_gen_pool_fitness] = EMNP_DE_selection(feas_parent_popln,  psi_p, feas_parent_G1,feas_parent_G2, feas_parent_obj_val, feas_parent_popln_fitness, offsprng_popln,  psi_o, offsprng_G1, offsprng_G2, offsprng_obj_val, offsprng_popln_fitness,  popln_size);
        
        % induct 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;
        
        
        % reset initial population and parameters
        initial_popln = next_gen_pool;     % move  to the next generation
        initial_popln_fitness= next_gen_pool_fitness;
        psi_i= Psi_fun;
        initial_G1=G1_nextgen;
        initial_G2 = G2_nextgen;
        initial_popln_obj_val=next_gen_pool_obj_val;
        
        
end            % while loop for DE generation cycle ends 

fix(clock)

% record the individual in the Hall of Fame as the optimal solution

x_star = HOF_individual; % optimal weights

% portfolio characteristics
portfolio_return =  261 * sum(mean_data .* x_star);
risk = sqrt( 261*x_star * cov_data * x_star');

disp('Equity Market Neutral Portfolio Optimization results:')
disp('Annualized risk')
disp(risk)
disp('Expected portfolio Annualized return')
disp(portfolio_return)
disp('Optimal weights')
disp( x_star)

disp('Successful execution!');