В этом примере показано, как оценить торговые затраты и компоненты риска для корзины с помощью анализа операционных затрат Исследовательской группы Kissell. Чтобы создать сводку по корзине, оцените торговые затраты для всей корзины с помощью методов оптимизации корзины, а затем вычислите статистику рисков для корзины. С помощью сводки по корзине можно предоставить брокерам и третьим лицам достаточно информации для оценки общих затрат на выполнение и торговых трудностей корзины. Сводка корзины позволяет предоставлять информацию о транзакциях без раскрытия фактических заказов. Другой способ, которым брокеры используют сводку по корзине, заключается в оценке оценки основных предложений по справедливой стоимости. Основное предложение - это транзакция, в которой брокер взимает надбавку за предложение, которая выше, чем связанная комиссия. Брокеры представляют данную сделку с гарантированным завершением по заданной цене.
В этом примере можно просмотреть таблицу анализа сводки корзины и сводку основного предложения. В сводке корзины представлены оценки торговых затрат для корзины по различным категориям, таким как сторона, рыночная капитализация и рыночный сектор. Резюме основных предложений содержит эффективную торговую границу, которая обеспечивает различные оценочные торговые затраты для различных периодов времени. Эффективная торговая граница показывает, как стоимость и риск меняются, торговая более агрессивно или пассивно. При пассивной торговле влияние на рынок уменьшается по мере увеличения риска. При агрессивной торговле влияние на рынок увеличивается по мере снижения риска.
Код в этом примере зависит от выходных данных из примера Оптимизация торговой стратегии графика торговли для корзины. Сначала выполните код в этом примере, а затем выполните код в этом примере.
Для вызова кода примера введите 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
OptimalCostTableOptimalCostTable =
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] Кисселл, Роберт. Наука алгоритмической торговли и управления портфелем. Кембридж, Массачусетс: Elsevier/Академическая пресса, 2013.
[2] Маламут, Роберто. «Методы многопериодной оптимизации для планирования торговли». Выступление на Нью-Йоркской конференции QWAFAFEW, апрель 2002 года.
[3] Кисселл, Роберт и Мортон Гланц. Оптимальные торговые стратегии. Нью-Йорк, Нью-Йорк: AMACOM, Inc., 2003.
krg | liquidityFactor | marketImpact