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

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

% Differential Evolution with Hall of Fame (DE HOF) for metaheuristic risk
% budgeted portfolio optimization, employing Joines and Houck's dynamic
% penalty functions for constraint handling

% Chapter 4  Secs. 4.8 A, B, C, D  
% Risk budgeted Portfolio optimization model is represented by equations [4.19]-[4.20] for
% its objective function and equations [4.10]-[4.13] for its constraints

% The portfolio considered is a case study global portfolio described in
% Table 4.1

% 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 risk budgeted portfolio problem parameters and inputs

% load the premia and variance-covariance matrix of returns of the assets
% in the portfolio
load   optim_input_export.mat  cv premia; 

risk_budget = 12.5;                                       
positive_premia_assets_indx=  1:23;                      
zero_premia_assets_indx= 24:27;                          
zero_premia_splasset_indx = 28;                          
default_low_bound= -3;                                   
default_up_bound =  3; 
low_bound_positive_premia= 0.001;                      
low_bound_zerprsplasset = 0;
bound_asset_indx = [positive_premia_assets_indx,zero_premia_splasset_indx]; 

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

% set Differential Evolution strategy parameters
popln_size = 300;                                        
total_generations = 1000; 
beta = 0.5;
pr_recombi = 0.87;
[row, portfolio_size]=size(premia);                                        
chromosm_length = portfolio_size;  

% set bounds for the categories of assets in the portfolio
bounds(1,:)= zeros(1, portfolio_size);                       
bounds(2,:)= zeros(1, portfolio_size);
bounds(1,positive_premia_assets_indx)= zeros(1, length(positive_premia_assets_indx))+ low_bound_positive_premia;  
bounds(1,zero_premia_assets_indx)= zeros(1, length(zero_premia_assets_indx))+default_low_bound;
bounds(1,zero_premia_splasset_indx)= zeros(1, length(zero_premia_splasset_indx))+low_bound_zerprsplasset;
bounds(2,positive_premia_assets_indx) = zeros(1, length(positive_premia_assets_indx))+default_up_bound;
bounds(2,zero_premia_assets_indx) = zeros(1, length(zero_premia_assets_indx))+default_up_bound; 
bounds(2,zero_premia_splasset_indx)= zeros(1, length(zero_premia_splasset_indx))+default_up_bound;


% initialize Hall of Fame which will ultimately hold the optimal weights
HOF_fitness = 9999;
HOF_individual = zeros(1, portfolio_size);

fix(clock)

% generation cycle counter
gen_indx = 1;

% generate initial random population of individuals, the parent population
initial_popln_raw= default_low_bound + (default_up_bound-default_low_bound)*rand(popln_size, chromosm_length);%generate initial random population within default bounds
initial_popln_lev = satisfy_lowbounds(initial_popln_raw, bounds,bound_asset_indx);
initial_popln = weightstdzn(initial_popln_lev, bounds, bound_asset_indx);
[GI, psi_i]  = compute_constrvioln_fn( initial_popln, cv, risk_budget, C_dp, beta_dp, alpha_dp, gen_indx  );
initial_popln_fitness = comp_fitness(initial_popln, premia, cv, psi_i);


% beginning of generation cycles

 while (gen_indx <= total_generations)         
       
        % set parent population, fitness and constraint violation functions
        feas_parent_popln = initial_popln;                 
        feas_parent_popln_fitness = initial_popln_fitness;
        
        GP = GI;
        psi_p = psi_i;
        
        %perform mutation to generate trial vectors 
        trial_vector_popln = DE_mutation(feas_parent_popln, beta, popln_size);
        
        %generate offspring population using the parent and trial vector populations
        offsprng_popln_raw = DE_bin_Crossover(feas_parent_popln, trial_vector_popln, pr_recombi, chromosm_length);
        
        % undertake weight repair of offspring population 
        offsprng_popln_lev = satisfy_lowbounds(offsprng_popln_raw, bounds, bound_asset_indx);
        offsprng_popln = weightstdzn(offsprng_popln_lev, bounds, bound_asset_indx);
               
        %compute constraint violation function for the offspring population
        [GO, psi_o]  = compute_constrvioln_fn( offsprng_popln, cv, risk_budget, C_dp, beta_dp, alpha_dp, gen_indx);
        
        %compute fitness of the offspring population
        offsprng_popln_fitness = comp_fitness(offsprng_popln,premia, cv, psi_o);
        
        %set the population for the next generation
        [next_gen_pool, next_gen_pool_fitness,  Penalty, Psi_fun] = DE_selection_penalty(feas_parent_popln, GP, psi_p, feas_parent_popln_fitness, offsprng_popln, GO,  psi_o, offsprng_popln_fitness, popln_size);  
        
        % individuals compete to enter Hall of Fame
        for i=1:popln_size
            if (isequal(Penalty(i,:), zeros(1, portfolio_size)))
                 if (next_gen_pool_fitness(i)< HOF_fitness)
                     
                    HOF_fitness = next_gen_pool_fitness(i);          
                    HOF_individual = next_gen_pool(i,:); 
                                   
                 end
            else continue;
            end
        end
        gen_indx = gen_indx + 1
        
        % move  to the next generation
        initial_popln = next_gen_pool;     
        initial_popln_fitness= next_gen_pool_fitness;
        
        GI = Penalty;
        psi_i= Psi_fun;
 end                                       % end of a generation cycle

fix(clock)

% extract optimal weights from the individual in the Hall of Fame
optimal_weights = HOF_individual;          

% compute risk budgeted portfolio characteristics: Sharpe Ratio, return and
% risk
portfolio_sharperatio =  ((premia * optimal_weights')/ sqrt(optimal_weights*cv * optimal_weights'));
portfolio_return= (premia * optimal_weights');
portfolio_risk = sqrt( optimal_weights * cv * optimal_weights');


% check if the optimal risk budgeted portfolio satisfies its risk budget
% constraint
mcr =  (cv * optimal_weights')/portfolio_risk; 
mcr_status = (optimal_weights.*mcr')-(risk_budget/100)*portfolio_risk;

% display portfolio characteristics 
disp('Optimization results:')
optimal_weights
portfolio_return
portfolio_risk
portfolio_sharperatio


disp('Successful execution!');