www.gusucode.com > GAVPai_Book_MathworksCntrlFileEx_May2019 > GAVPai_Book_MathworksCntrlFileEx_May2019/Chapter7_ESHOF_PortfolioRebalancing_TrCosts.m
% Vijayalakshmi Pai G A, Metaheuristics for Portfolio Optimization, An % Introduction using MATLAB, ISTE-Wiley, 2017. % Evolution Stategy with Hall of Fame (ES HOF)for Portfolio Rebalancing with Transaction Costs % Chapter 7 Sec. 7.3 % The constrained portfolio rebalancing model is represented by equations [7.8]-[7.9] for % its objective function and equations [7.2]-[7.6] for its constraints % The portfolio considered is a high risk portfolio of assets comprising the top 15 percentile of % high volatility stocks of S&PBSE200 Index % Sec. 7.4.1 % The data file S&PBSE200_RebalPortfolio.xls records the mean returns of the % assets of the high risk portfolio, followed by variance-covariance matrix % of returns 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 portfolio_size = 32; % 32 high risk assets comprising the portfolio % obtain mean returns and variance-covariance matrix of returns for the % portfolio file_name = 'S&PBSE200_RebalPortfolio.xls'; m = xlsread(file_name); mean_data = m(1,:); cov_data = m(2:portfolio_size+1, :); % obtain optimal weights, maximal diversification ratio, risk and return of % the original portfolio OriginalPortfolio_Optimal_Wgts = [0.0248 0.0137 0.0010 0.0010 0.0512 0.0209 0.0316 0.0576 0.0323 0.0010 0.0409 0.0010 0.0020 0.1115 0.0250 0.0010 0.0010 0.0149 0.0151 0.0316 0.0010 0.0695 0.0635 0.0687 0.0595 0.0059 0.0308 0.0617 0.0575 0.0425 0.0435 0.0171]; OriginalPortfolio_MxDR = 2.7822; OriginalPortfolio_Daily_Risk = 0.0208; OriginalPortfolio_Daily_Retrn = 0.0034; % set Transaction cost p=0.0044; % set lower and upper bounds of buy and sell weights buy_lowbounds = zeros(1, portfolio_size); buy_upbounds = ones(1,portfolio_size)*0.025; sell_lowbounds = zeros(1, portfolio_size); sell_upbounds = OriginalPortfolio_Optimal_Wgts; % Set Evolutionary algorithm parameters popln_size = 320; chromosm_length = portfolio_size; total_generations = 100; % Joines and Houck's (1994) dynamic penalty (dp) function strategy % Set parameters (C, alpha, beta) C_dp = 0.5; beta_dp=2; alpha_dp=2; epsilon = 0.0009; % initialize Hall of Fame HOF_fitness = -9999; fix(clock) % generation counter gen_indx = 1; % index for HOF fitness trace i1=1; % generate random initial population of buy sell weights subject to their respective bounds rebal_popln_raw = generate_bounded_popln(popln_size, portfolio_size,sell_lowbounds , sell_upbounds, buy_lowbounds, buy_upbounds); % determine the respective lower and upper bounds of the genes in the % population low_up_bounds = determine_bounds(rebal_popln_raw, buy_lowbounds, buy_upbounds, sell_lowbounds, sell_upbounds); % repair weights initial_rebal_popln_stdzn = PortfolioRebalancing_WeightRepair(rebal_popln_raw, low_up_bounds,p ); % compute the population of rebalanced weights initial_popln = ones(popln_size,1)*OriginalPortfolio_Optimal_Wgts + initial_rebal_popln_stdzn; % compute constraint violation function [G_parent, parent_psi] = compute_constrvioln_fn_Rebal( initial_popln, cov_data, OriginalPortfolio_Daily_Risk, C_dp, beta_dp, alpha_dp, gen_indx); %compute constraint violation functions using Joines and Houck's dynamic penalty functions % compute fitness function [parent_fitness ] = Rebal_comp_fitness(initial_popln, cov_data, parent_psi); % set parent population feasX_parent_popln = initial_rebal_popln_stdzn; feasW_parent_popln = initial_popln; feasW_parent_fitness = parent_fitness; feasW_parent_psi = parent_psi; % counter for P measure pa_count =1; % ES HOF generation cycles begin while (gen_indx <= total_generations) gen_indx % perform cross over on the parent population offsprngX_popln_raw= rand_varpt_arith_crossover(feasX_parent_popln, popln_size, chromosm_length); % perform mutation to yield offspring population offsprngX_popln_mutat = realnum_unifrm_mutation(offsprngX_popln_raw, popln_size, chromosm_length); % Normalize offspring population offsprngX_popln_norm = normalize_weight(offsprngX_popln_mutat, sell_lowbounds , sell_upbounds, buy_lowbounds, buy_upbounds); % determine lower and upper bounds of the buy sell weights low_up_bounds = determine_bounds(offsprngX_popln_norm, buy_lowbounds, buy_upbounds, sell_lowbounds , sell_upbounds); % repair weights of the offspring population offsprngX_popln = PortfolioRebalancing_WeightRepair(offsprngX_popln_norm, low_up_bounds,p ); % compute the population of rebalanced weights offsprngW_popln = ones(popln_size,1)*OriginalPortfolio_Optimal_Wgts + offsprngX_popln; % Xi % compute constraint violation function [G_offsprngW, offsprngW_psi] = compute_constrvioln_fn_Rebal(offsprngW_popln, cov_data, OriginalPortfolio_Daily_Risk, C_dp, beta_dp, alpha_dp, gen_indx); %compute constraint violation functions using Joines and Houck's dynamic penalty functions % compute fitness function [offsprngW_fitness] = Rebal_comp_fitness(offsprngW_popln, cov_data, offsprngW_psi); % construct the new generation selecting the best of parent and % offspring population [NextGenPool_X, NextGenPool_W, NextGenPool_fitness, NextGenPool_psi] = construct_newgen(feasX_parent_popln, feasW_parent_popln, feasW_parent_fitness, feasW_parent_psi , offsprngX_popln, offsprngW_popln, offsprngW_fitness, offsprngW_psi); %induct best fit individual into Hall of Fame for i=1:popln_size if (NextGenPool_psi(i)== 0) if (NextGenPool_fitness(i) > HOF_fitness) HOF_fitness = NextGenPool_fitness(i) HOF_individualW = NextGenPool_W(i,:); HOF_individualX = NextGenPool_X(i,:); HOF_genarray(i1) = gen_indx; HOF_fitarray(i1) = HOF_fitness; i1=i1+1; end else continue; end end % compute Population measure p_measure_gen = compute_Pmeasure(NextGenPool_W); perfanaly_pmeasure(pa_count, :)= [gen_indx, p_measure_gen]; pa_count=pa_count+1; % set parent population for the next generation cycle feasX_parent_popln = NextGenPool_X; feasW_parent_popln = NextGenPool_W; feasW_parent_fitness = NextGenPool_fitness; feasW_parent_psi = NextGenPool_psi; gen_indx = gen_indx + 1; end fix (clock) % extract the optimal solution (rebalanced weights) from the Hall of Fame disp('Optimal Rebalanced Portfolio Weights') Optimal_RebalWeights = HOF_individualW % compute risk, return and Diversification Ratio of the optimal rebalanced % portfolio daily_rebal_portfolio_return = sum(mean_data .* Optimal_RebalWeights); disp('Rebalanced portfolio annualized return %') ann_rebal_portfolio_return = 261 * daily_rebal_portfolio_return*100 rebal_portfolio_risk = sqrt(Optimal_RebalWeights * cov_data * Optimal_RebalWeights'); disp('Rebalanced portfolio annualized risk %') ann_rebal_portfolio_risk = sqrt(261)* rebal_portfolio_risk*100 stdev_portfolio = sqrt(diag(cov_data)); disp('Rebalanced portfolio Diversification Ratio') rebal_portfolio_DR = (sum(stdev_portfolio .* Optimal_RebalWeights') / rebal_portfolio_risk) % compare risk, return and Diversification Ratio of the original portfolio disp('Original portfolio annualized return %') original_portfolio_return = OriginalPortfolio_Daily_Retrn * 261*100 disp('Original portfolio annualized risk %') original_portfolio_risk = OriginalPortfolio_Daily_Risk * sqrt(261)*100 disp('Original portfolio Diversification Ratio') original_portfolio_DR = OriginalPortfolio_MxDR disp('Successful Execution');