%% KRG Trade Performance Ranking and Broker Pre Trade Example.
% This example computes the broker rankings by trade by calculating the
% average arrival cost per broker and estimates the trading cost by broker 
% for a specified order or trade list

%   Copyright 2016-2020 The MathWorks, Inc.

% Load the market impact data provided by the Kissell Research Group
f = ftp('ftp.kissellresearch.com','username','password');  
cd(f,'MI_Parameters');

% Note that market impact data with additional broker codes is used in this
% example
mget(f,'MI_Broker.csv');
close(f)

% Create KRG object
miData = readtable('MI_Broker.csv','Format','auto','delimiter',',','ReadRowNames',false,'ReadVariableNames',true);
k = krg(miData,datetime('today'),1,250);


% Load example data
load KRGExampleData.mat TradeData Basket BrokerNames

% User selects the trade categories.  The specified trade categories are 
% extracted and the average arrival cost for each broker's category is
% calculated.

% Arrival cost for the category for each broker.
TradeData.TradeSize = TradeData.Shares ./ TradeData.ADV;
TradeData.ArrivalCost = TradeData.SideIndicator .* (TradeData.AvgExecPrice ./ TradeData.ArrivalPrice-1) * 10000;
TradeData.MI = marketImpact(k,TradeData);
TradeData.ValueAdd = TradeData.MI - TradeData.ArrivalCost;

% Get brokers and preallocate average cost output
uniqueBrokers = unique(TradeData.Broker);
numBrokers = length(uniqueBrokers);
avgCost = NaN(numBrokers,1);
avgMI = NaN(numBrokers,1);
avgValueAdd = NaN(numBrokers,1);

% Compute Broker Rankings by Trade Size between 5% and 10% average daily
% volume (ADV)
indBroker = (TradeData.TradeSize >= 0.05) & (TradeData.TradeSize <= 0.10);

if any(indBroker)
  TD = TradeData(indBroker,:);
  for i = 1:numBrokers
    j = strcmp(TD.Broker,uniqueBrokers(i));
    if any(j)
      avgCost(i) = mean(TD.ArrivalCost(j));
      avgMI(i) = mean(TD.MI(j));
      avgValueAdd(i) = mean(TD.ValueAdd(j));
    end
  end
end

% Get valid average cost values (non NaN's)
indAvgCost = ~isnan(avgCost);

% Create table with broker rankings and sort by average cost
BrokerRankings = table(uniqueBrokers(indAvgCost),(1:sum(indAvgCost))',avgCost(indAvgCost),avgMI(indAvgCost),avgValueAdd(indAvgCost),'VariableNames',{'Broker','Rank','AvgArrivalCost','AvgMI','AvgValueAdd'});
BrokerRankings = sortrows(BrokerRankings,-5);
BrokerRankings.Rank = (1:sum(indAvgCost))';  % Reset rank

% Plot broker average value add 
bar(BrokerRankings.AvgValueAdd)
set(gca,'XTickLabel',BrokerRankings.Broker)
ylabel('Average Value Add (bp)')
title('Average Value Add by Broker')
grid

%% Broker Selection
%
% Investors can estimate the trading cost by broker for a specified order 
% or trade list.
             
% Get the number of orders from the trade list table
numOrders = size(Basket.Symbols,1);

% Calculate pre trade cost for each broker for each order
BrokerPreTrade = zeros(numOrders,numBrokers);
for i = 1:numBrokers

  % Market impact code for broker corresponds to the MICode in the market
  % impact data, for example, Broker1 = 1.
  k.MiCode = i;
   
  % Calculate market impact cost for each broker
  BrokerPreTrade(:,i) = marketImpact(k,Basket);

end

% Convert output to a table with the symbols used as the row names.
BrokerPreTrade = array2table(BrokerPreTrade,'VariableNames',BrokerNames.Broker,'RowNames',Basket.Symbols);

% Plot best broker for given stock
bar(table2array(BrokerPreTrade(1,:)))
set(gca,'XTickLabel',BrokerNames.Broker)
ylabel('Market Impact Cost (bp)')
title(['Market Impact Cost by Broker for Symbol ' BrokerPreTrade.Properties.RowNames{1}])
grid
