В этом примере показано, как оценить торговые издержки и компоненты риска для корзины с помощью анализа операционных издержек от 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 Research Group.
[1] Kissell, Роберт. Наука об алгоритмической торговле и управлении портфелем. Кембридж, MA: нажатие Elsevier/Academic, 2013.
[2] Malamut, Роберто. “Методы оптимизации мультипериода для торгового планирования”. Представление на нью-йоркской конференции QWAFAFEW, апрель 2002.
[3] Kissell, Роберт и Мортон Глэнц. Оптимальные торговые стратегии. Нью-Йорк, Нью-Йорк: AMACOM, Inc., 2003.
krg
| liquidityFactor
| marketImpact