Создание сводки корзин и эффективная торговая граница

В этом примере показано, как оценить торговую стоимость и компоненты риска для корзины с помощью анализа транзакционных издержек от Kissell Research Group. Чтобы создать сводные данные корзин, оцените торговые затраты для всей корзины с помощью методов оптимизации корзины, а затем вычислите статистику рисков для корзины. Используя сводные данные корзин, вы можете предоставить брокерам и третьим лицам достаточно информации для оценки общих затрат на выполнение и торговых трудностей корзины. Сводные данные корзин позволяют предоставлять информацию о транзакциях, не раскрывая фактические порядки. Другой способ использования брокерами сводных данных корзин - оценить оценку основной ставки справедливого значения. Основная ставка - это сделка, в которой брокер взимает премию, которая выше, чем связанная с ней комиссия. Брокеры представляют эту сделку с гарантированным завершением по заданной цене.

В этом примере можно увидеть таблицу итогового анализа корзины и сводные данные основного предложения. Сводные данные корзин предоставляют оценки торговых затрат для корзины по различным категориям, таким как сторона, рыночная капитализация и рыночный сектор. Основные сводные данные предложения содержат эффективную торговую границу, которая обеспечивает различные предполагаемые торговые затраты для различных периодов времени. Эффективная торговая граница показывает, как стоимость и риск изменяются путем торговли более агрессивно или пассивно. При пассивной торговле влияние на рынок уменьшается по мере увеличения временных рисков. При агрессивной торговле влияние рынка возрастает по мере снижения риска времени.

Код в этом примере зависит от выходных данных из примера Оптимизация торговой стратегии для корзины. Сначала запустите код в этом примере, а затем запустите код в этом примере.

Для доступа к коду примера введите edit KRGBasketAnalysisExample.m в командной строке.

После выполнения кода в этом примере можно отправить порядок на выполнение с помощью Bloomberg®, для примера.

Оценка торговых издержек в корзине

Определите ковариационную матрицу. Ковариация указывает, как цены на акции в корзине связаны друг с другом.

% Covariance matrix is annualized covariance matrix in decimals.
% Convert to ($/Shares)^2 units for the trade period, this matrix is for a
% two-sided portfolio, buys and sells or long and short.
diagPrice = diag(TradeDataTradeOpt.Price);
C1 = TradeDataTradeOpt.SideIndicator * TradeDataTradeOpt.SideIndicator' .* ...
    diagPrice * CovarianceTradeOpt * diagPrice;

% Covariance Matrix in $/Share^2 by Day
CD = diagPrice * CovarianceTradeOpt * diagPrice;    % compute Covariance Matrix in ($/share)^2
CD = CD / k.TradeDaysInYear;                        % scale to 1-day
CD = TradeDataTradeOpt.SideIndicator * TradeDataTradeOpt.SideIndicator' ...
    .* CD;

Добавьте предполагаемые торговые затраты из оптимизации торгового графика к данным корзины.

% Market impact in basis points
TradeDataTradeOpt.MI = MI ./ (TradeDataTradeOpt.Shares .* ... 
    TradeDataTradeOpt.Price) .* 10000;  

% Timing risk in basis points
TradeDataTradeOpt.TR = TR ./ (TradeDataTradeOpt.Shares .* ...
    TradeDataTradeOpt.Price) .* 10000;   

% Percentage of volume, price appreciation and liquidity factor
TradeDataTradeOpt.POV = POV;
TradeDataTradeOpt.PA = PA;
TradeDataTradeOpt.LF = liquidityFactor(k,TradeDataTradeOpt);

Рассчитать торговые издержки в базисных точках, центах за акцию и долларах.

% Build optimal cost table
OptimalCostTable = table(cell(3,1),zeros(3,1),zeros(3,1),zeros(3,1), ...
    zeros(3,1),'VariableNames',{'CostUnits','MI','PA','TotalCost','TR'});
OptimalCostTable.CostUnits(1) = {'Basis Points'};
OptimalCostTable.CostUnits(2) = {'Cents per Share'};
OptimalCostTable.CostUnits(3) = {'Dollars'};

% Market impact, 
OptimalCostTable.MI(1) = TotMI;
OptimalCostTable.MI(2) = TotMI / 100 * mean(TradeDataTradeOpt.Price); 
OptimalCostTable.MI(3) = TotMI / 100 * (TradeDataTradeOpt.Shares' * ...
    TradeDataTradeOpt.Price);

% Price appreciation
OptimalCostTable.PA(1) = TotPA;
OptimalCostTable.PA(2) = TotPA / 100 * mean(TradeDataTradeOpt.Price);
OptimalCostTable.PA(3) = TotPA / 100 * (TradeDataTradeOpt.Shares' * ...
    TradeDataTradeOpt.Price);

% Total cost
OptimalCostTable.TotalCost(1) = TotMI + TotPA;
OptimalCostTable.TotalCost(2) = (TotMI + TotPA) / 100 * mean(TradeDataTradeOpt.Price);
OptimalCostTable.TotalCost(3) = (TotMI + TotPA) / 100 * ...
    (TradeDataTradeOpt.Shares' * TradeDataTradeOpt.Price);

% Timing risk
OptimalCostTable.TR(1) = TotTR;
OptimalCostTable.TR(2) = TotTR / 100 * mean(TradeDataTradeOpt.Price);
OptimalCostTable.TR(3) = TotTR / 100 * ...
    (TradeDataTradeOpt.Shares' * TradeDataTradeOpt.Price);

Отобразите оптимальные затраты для корзины. Отформатируйте отображаемый вывод, чтобы показать центы и доллары. Оптимальными затратами являются влияние на рынок, повышение цен, общая стоимость и временные риски.

format bank
OptimalCostTable
OptimalCostTable =

  3×5 table array

        CostUnits             MI          PA      TotalCost           TR     
    _________________    ____________    ____    ____________    ____________

    'Basis Points'              38.30    0.00           38.30           26.57
    'Cents per Share'           14.88    0.00           14.88           10.32
    'Dollars'            171134479.73    0.00    171134479.73    118710304.48

Определите компоненты риска в корзине

Вычислим статистику рисков. Предельный вклад в риск отражает риск изменения одного из компонентов корзины, например количества акций. Вклад риска представляет собой риск для каждой торговли в корзине.

% Portfolio Risk in Dollars
PortfolioRisk = sqrt(TradeDataTradeOpt.Shares' * CD * ...
    TradeDataTradeOpt.Shares);

% MCR and RC calculations
PortfolioRiskMCR = zeros(numberStocks,1);
PortfolioRiskRC =zeros(numberStocks,1);
SharesMCR = TradeDataTradeOpt.Shares;
SharesRC = TradeDataTradeOpt.Shares;  
for i = 1:numberStocks
  SharesMCR(i) = TradeDataTradeOpt.Shares(i) * 0.90;
  SharesRC(i) = 0;
  PortfolioRiskMCR(i) = sqrt(SharesMCR' * CD * SharesMCR);
  PortfolioRiskRC(i) = sqrt(SharesRC' * CD * SharesRC);
end
TradeDataTradeOpt.MCR = PortfolioRisk ./ PortfolioRiskMCR - 1;
TradeDataTradeOpt.RC = PortfolioRisk ./ PortfolioRiskRC - 1;

Отображение стороны, символа и количества акций для самой безопасной торговли в корзине с помощью вклада риска.

minrisk = min(TradeDataTradeOpt.RC);
for i = 1:25
    if TradeDataTradeOpt.RC(i) == minrisk
        idx = i;
    end
end
[TradeDataTradeOpt.Side(idx) TradeDataTradeOpt.Symbol(idx) ...
    TradeDataTradeOpt.Shares(idx)]
ans =

  1×3 cell array

    'B'    'ABC'    [100000]

Покупка порядка 100 000 акций фондовых ABC способствует наибольшему общему портфельному риску.

Создание сводных данных отчетов о корзинах

Составьте таблицу для сводных данных отчетов о корзине.

% Get sector identifiers
uniqueSectors = unique(TradeDataTradeOpt.Sector);
numSectors = size(uniqueSectors,1);
numGroups = 14 + size(uniqueSectors,1);  % Using 14 categories plus number of sectors

% Preallocate BasketReport table
BasketReport = table;
BasketReport.BasketCategory = cell(numGroups,1);
BasketReport.Number = zeros(numGroups,1);
BasketReport.Weight = zeros(numGroups,1);
BasketReport.MI = zeros(numGroups,1);
BasketReport.TR = zeros(numGroups,1);
BasketReport.POV = zeros(numGroups,1);
BasketReport.TradeTime = zeros(numGroups,1);
BasketReport.PctADV = zeros(numGroups,1);
BasketReport.Price = zeros(numGroups,1);
BasketReport.Volatility = zeros(numGroups,1);
BasketReport.Risk = zeros(numGroups,1);
BasketReport.RC = zeros(numGroups,1);
BasketReport.MCR = zeros(numGroups,1);
BasketReport.Beta = zeros(numGroups,1);
BasketReport.LF = zeros(numGroups,1);
BasketReport.TotalValue = zeros(numGroups,1);
BasketReport.BuyValue = zeros(numGroups,1);
BasketReport.SellValue = zeros(numGroups,1);
BasketReport.NetValue = zeros(numGroups,1);
BasketReport.Shares = zeros(numGroups,1);
BasketReport.BuyShares = zeros(numGroups,1);
BasketReport.SellShares = zeros(numGroups,1);

Вычислите сводные данные отчета о корзине.

Разделите сделки в корзине на следующие категории:

  • Total - Все сделки в корзине

  • Buy - Покупка сделок

  • Cover - Покупайте сделки, которые покрывают короткую позицию

  • Sell - Продажа сделок

  • Short - Короткие сделки

  • <=1% - Сделки, которые имеют процент от среднесуточного объема меньше или равный 1%

  • 1%-3% - Сделки, которые имеют процент от среднесуточного объема от 1% до 3%

  • 3%-5% - Сделки, которые имеют процент от среднесуточного объема от 3% до 5%

  • 5%-10% - Сделки, которые имеют процент от среднесуточного объема от 5% до 10%

  • 10%-20% - Сделки, которые имеют процент от среднесуточного объема от 10% до 20%

  • >20% - Сделки, которые имеют процент от среднесуточного объема более 20%

  • LC - Биржевые торги с большой капитализацией

  • MC - Торги акциями средней капитализации

  • SC - Торги акциями с малой капитализацией

  • Consumer Discretionary - Торговля в дискреционной индустрии потребителей

  • Consumer Staples - Торговля в отрасли потребительских товаров

  • Energy - Сделки в энергетической отрасли

  • Financials - Сделки в финансовой отрасли

  • Health Care - Сделки в сфере здравоохранения

  • Industrials - Торговля промышленностью

  • Information Technology - Сделки в сфере информационных технологий

  • Materials - Торговля материалами

  • Telecommunication Services - Сделки в сфере телекоммуникационных услуг

  • Utilities - Сделки в коммунальной промышленности

Для запасов в каждой категории вычислите следующие значения:

  • Weight - Общий вес торгового значения

  • MI - средневзвешенная рыночная стоимость

  • TR - Риск синхронизации

  • POV - Средневзвешенный процент от объемной ставки

  • TradeTime - Средневзвешенное время выполнения порядка

  • PctADV - Средневзвешенный размер порядка (в процентах от среднесуточного объема)

  • Price - Средневзвешенная цена акций

  • Volatility - Средневзвешенная волатильность

  • Risk - Портфельный риск

  • RC - Вклад риска в общий портфельный риск (показывает величину риска, который вносит порядок в корзину)

  • MCR - Предельный вклад в риск (показывает величину риска, которую вносят в корзину 10% акций в порядке)

  • Beta - Средневзвешенная бета-версия

  • LF - Средневзвешенный коэффициент ликвидности

  • TotalValue - Общее торговое значение

  • BuyValue - Общее торговое значение сделок покупки

  • SellValue - Общее торговое значение сделок продажи

  • NetValue - Различие между общим торговым значением сделок покупки и продажи

  • Shares - Количество акций

  • BuyShares - Количество акций для покупки

  • SellShares - Количество проданных акций

% Fill table, indRecord is index of matching TradeData rows
j = 0;
for i = 1:24
 
    switch i
 
      % Total
      case 1
 
        indRecord = true(numberStocks,1);
        BasketReport.BasketCategory(i) = {'Total'};
    
      % Side
      case 2
        indRecord = strcmp(TradeDataTradeOpt.Side,'B') | ...
            strcmp(TradeDataTradeOpt.Side,'Buy');
        BasketReport.BasketCategory(i) = {'Buy'};
    
      case 3
        indRecord = strcmp(TradeDataTradeOpt.Side,'C') | ...
            strcmp(TradeDataTradeOpt.Side,'Cover');
        BasketReport.BasketCategory(i) = {'Cover'};
        
      case 4
        indRecord = strcmp(TradeDataTradeOpt.Side,'S') | ...
            strcmp(TradeDataTradeOpt.Side,'Sell');
        BasketReport.BasketCategory(i) = {'Sell'};
    
      case 5
        indRecord = strcmp(TradeDataTradeOpt.Side,'SS') | ...
            strcmp(TradeDataTradeOpt.Side,'Short') | ...
            strcmp(TradeDataTradeOpt.Side,'Sell Short');
        BasketReport.BasketCategory(i) = {'Short'};
   
      % Liquidity Category
      case 6
        
        % Percentage of average daily volume is less than 1 %
        indRecord = (TradeDataTradeOpt.PctADV <= 0.01);
        BasketReport.BasketCategory(i) = {'<=1%'};
        
      case 7
        
        % Percentage of average daily volume is between 1 and 3 %
        indRecord = (TradeDataTradeOpt.PctADV > 0.01 & ...
            TradeDataTradeOpt.PctADV <= 0.03);
        BasketReport.BasketCategory(i) = {'1%-3%'};
    
      case 8
        
        % Percentage of average daily volume is between 3 and 5 %
        indRecord = (TradeDataTradeOpt.PctADV > 0.03 & ...
            TradeDataTradeOpt.PctADV <= 0.05);
        BasketReport.BasketCategory(i) = {'3%-5%'};
    
      case 9
        
        % Percentage of average daily volume is between 5 and 10 %
        indRecord = (TradeDataTradeOpt.PctADV > 0.05 & ...
            TradeDataTradeOpt.PctADV <= 0.10);
        BasketReport.BasketCategory(i) = {'5%-10%'};
    
      case 10
        
        % Percentage of average daily volume is between 10 and 20 %
        indRecord = (TradeDataTradeOpt.PctADV > 0.10 & ...
            TradeDataTradeOpt.PctADV <= 0.20);
        BasketReport.BasketCategory(i) = {'10%-20%'};
    
      case 11
        
        % Percentage of average daily volume is greater than 20 %
        indRecord = (TradeDataTradeOpt.PctADV > 0.20);
        BasketReport.BasketCategory(i) = {'>20%'};
    
      % Market cap
      case 12
        
        % Large cap
        indRecord = (TradeDataTradeOpt.MktCap > 10000000000);
        BasketReport.BasketCategory(i) = {'LC'};
    
      case 13
        
        % Mid cap
        indRecord = (TradeDataTradeOpt.MktCap > 1000000000 & ...
            TradeDataTradeOpt.MktCap <= 10000000000);
        BasketReport.BasketCategory(i) = {'MC'};
    
      case 14
        
        % Small cap
        indRecord = (TradeDataTradeOpt.MktCap <= 1000000000);
        BasketReport.BasketCategory(i)={'SC'};

      % Sectors
      % Description of basket category
      case {15, 16, 17, 18, 19, 20, 21, 22, 23, 24}
        j = j + 1;
        if j <= numSectors
          indRecord = strcmp(TradeDataTradeOpt.Sector,uniqueSectors(j));
          BasketReport.BasketCategory(i) = uniqueSectors(j);
        end
    
    end

    % Get subset of TradeData
    TD = TradeDataTradeOpt(indRecord,:);
    
    if ~isempty(TD)
    
         % Covariance Matrix in $/Shares^2
      CC2 = CC(indRecord,indRecord);    %Trading Period Covariance Matrix in $/Shares^2
      C2 = C1(indRecord,indRecord);     %Annualized Covariance Matrix in $/Shares^2
      RR = R(indRecord,:);              %Residuals for Stocks in group
    
      % Basket Summary Calculations
      Weight2 = TD.Value / sum(TD.Value);

      % Side
      I_Buy = (TD.SideIndicator == 1);
      I_Sell = (TD.SideIndicator == -1);
    
      % Fill basket report table
      BasketReport.Number(i) = size(TD,1);                     % Number of records that match criteria
      BasketReport.Weight(i) = sum(TD.Value)/PortfolioValue;   % Weight of assets in criteria
      BasketReport.MI(i) = Weight2' * TD.MI;                   % Market impact of assets
      BasketReport.TR(i) = sqrt(trace(RR'*CC2*RR)) / sum(TD.Value) * 10000;   % Timing risk of assets
      BasketReport.POV(i) = Weight2' * TD.POV;                 % POV of assets
      BasketReport.TradeTime(i) = Weight2' * TD.TradeTime;     % Tradetime of assets
      BasketReport.PctADV(i) = Weight2' * TD.PctADV;           % Percentage of ADV
      BasketReport.Price(i) = Weight2' * TD.Price;             % Total price of assets
      BasketReport.Volatility(i) = Weight2' * TD.Volatility;   % Volatility
      BasketReport.Risk(i) = sqrt(TD.Shares' * C2 * TD.Shares) / ...
          sum(TD.Value);   % Risk value
 
      % RC and MCR 
      Shares2 = TradeDataTradeOpt.Shares;
      Shares3 = TradeDataTradeOpt.Shares;
      Shares2(indRecord) = 0;
      Shares3(indRecord) = Shares3(indRecord) * 0.90;
    
      if sum(Shares2) > 0
        BasketReport.RC(i) = PortfolioRisk / sqrt(Shares2' * CD * Shares2) - 1;
      else
        BasketReport.RC(i) = 0;
      end
      BasketReport.MCR(i) = PortfolioRisk / sqrt(Shares3' * CD * Shares3) - 1;

      % Beta value, liquidity factor and total value
      BasketReport.Beta(i) = sum(Weight2 .* TD.SideIndicator .* TD.Beta);
      BasketReport.LF(i) = Weight2' * TD.LF;
      BasketReport.TotalValue(i) = sum(TD.Value);
    
      % Calculate buy share values
      if sum(I_Buy) > 0
        BasketReport.BuyValue(i) = sum(TD.Value(I_Buy));
        BasketReport.BuyShares(i) = sum(TD.Shares(I_Buy));
      else
        BasketReport.BuyValue(i) = 0;
        BasketReport.BuyShares(i) = 0;
      end
      
      % Calculate sell share values
      if sum(I_Sell) > 0
        BasketReport.SellValue(i) = sum(TD.Value(I_Sell));
        BasketReport.SellShares(i) = sum(TD.Shares(I_Sell));
      else
        BasketReport.SellValue(i) = 0;
        BasketReport.SellShares(i) = 0;
      end
      
      % Calculate net value of criteria and number of shares
      BasketReport.NetValue(i) = BasketReport.BuyValue(i) - ...
          BasketReport.SellValue(i);
      BasketReport.Shares(i) = sum(TD.Shares);
      
    end 
end

% Remove rows with no stocks
indRecord = (BasketReport.Number > 0);
BasketReport = BasketReport(indRecord,:);

Отобразите рыночную капитализацию по волатильности как круговую диаграмму.

pie(BasketReport.Volatility(8:10),BasketReport.BasketCategory(8:10))
title('Market Capitalization by Volatility')

Создание сводных данных основных предложений

Определите эффективную торговую границу по времени. Используйте различные сценарии торгового времени. Оценка затрат на торговлю для повышения цены, влияния на рынок и факторного риска для каждого сценария.

ScenarioTime = [0.10;0.25;0.50;0.75;1.0;1.50;2.0;2.5;3.0;3.5;4.0;4.5;5.0];
numScenarios = size(ScenarioTime,1);
ETFCosts = zeros(numScenarios,5);

TableVariableNames = TradeDataTradeOpt.Properties.VariableNames;
if sum(strcmp(TableVariableNames,'DeltaP')) > 0
    DeltaP = TradeDataTradeOpt.DeltaP;
elseif sum(strcmp(TableVariableNames,'Alpha_bp')) > 0
    DeltaP = TradeDataTradeOpt.Alpha_bp;
else
    DeltaP = zeros(NumberStocks,1);
end

% Convert DeltaP from basis points per day to cents/share per period
DeltaP = DeltaP / 1000 .* TradeDataTradeOpt.Price / totalNumberPeriods;

for i = 1:numScenarios
    
    TradeTime = ScenarioTime(i);
    TradeDataTradeOpt.POV = TradeDataTradeOpt.Shares ./ ...
        (TradeDataTradeOpt.Shares + TradeTime .* TradeDataTradeOpt.ADV);
    
    % Price Appreciations in Dollars
    PA = 1/2 * TradeDataTradeOpt.Shares .* DeltaP .* TradeTime;
    TotPA = sum(PA) / (TradeDataTradeOpt.Shares' * ...
        TradeDataTradeOpt.Price) .* 10000;          % bp
    PA = PA ./ (TradeDataTradeOpt.Shares .* ...
        TradeDataTradeOpt.Price) * 10000;           % bp

    % Market Impact in Dollars
    MI = marketImpact(k,TradeDataTradeOpt) .* TradeDataTradeOpt.Shares .* ...
        TradeDataTradeOpt.Price ./ 10000; %dollars;
    TotMI = sum(MI) / (TradeDataTradeOpt.Shares' * ...
        TradeDataTradeOpt.Price) .* 10000;          % bp
    MI = MI ./ (TradeDataTradeOpt.Shares .* ...
        TradeDataTradeOpt.Price) * 10000;           % bp

    % Timing Risk in Dollars
    TotTR = sqrt(1/3 * TradeDataTradeOpt.Shares' * ...
        (CD * TradeTime) * TradeDataTradeOpt.Shares) / ...
        (TradeDataTradeOpt.Shares' * TradeDataTradeOpt.Price) * 10000;

    % Total Cost Dollars
    TotTC = (TotMI + TotPA);

    % ETF Cost Table
    ETFCosts(i,1) = TradeTime;
    ETFCosts(i,2) = TotMI;
    ETFCosts(i,3) = TotPA;
    ETFCosts(i,4) = TotTC;
    ETFCosts(i,5) = TotTR;
    
end

% Save as Table
ETFCosts = table(ETFCosts(:,1),ETFCosts(:,2),ETFCosts(:,3),ETFCosts(:,4), ...
    ETFCosts(:,5),'VariableNames',{'Days','MI_bp','PA_bp','TotalCost_bp', ...
    'TR_bp'});

Определите время торговли с самой низкой общей стоимостью.

mintotcost = min(ETFCosts.TotalCost_bp);
for i = 1:numScenarios
    if(ETFCosts.TotalCost_bp(i) == mintotcost)
        scenario = ETFCosts.Days(i);
    end
end
scenario
scenario =

     5

Для получения дополнительной информации о предыдущих расчетах обратитесь в исследовательскую группу Kissell.

Ссылки

[1] Кисселл, Роберт. Наука об алгоритмической торговле и управлении портфелем. Cambridge, MA: Elsevier/Academic Press, 2013.

[2] Маламут, Роберто. «Многопериодические методы оптимизации для планирования торговли». Презентация на Нью-Йоркской конференции КВАФАФЬЮ, апрель 2002 года.

[3] Кисселл, Роберт и Мортон Гланц. Оптимальные торговые стратегии. Нью-Йорк, Нью-Йорк: AMACOM, Inc., 2003.

См. также

| |

Похожие темы