exponenta event banner

резюме

Создание сводной таблицы результатов обратного тестирования

Описание

пример

summaryTable = summary(backtester) создает таблицу метрик для суммирования обратного теста. Каждая строка таблицы является вычисляемой метрикой, и каждый столбец представляет стратегию. Вы должны запустить функцию сводки только после выполнения runBacktest функция.

Примеры

свернуть все

Механизм обратного тестирования MATLAB ® выполняет обратные тесты стратегий портфельных инвестиций на основе временных рядов данных о ценах на активы. Вы можете использоватьsummary сравнение нескольких стратегий по одному и тому же рыночному сценарию. В этом примере показано, как проанализировать результаты бэктеста с помощью двух стратегий.

Загрузить данные

Загрузите данные цены запаса за один год. Для удобства чтения в этом примере используется подмножество запасов DJIA.

% Read table of daily adjusted close prices for 2006 DJIA stocks
T = readtable('dowPortfolio.xlsx');

% Prune the table to include only the dates and selected stocks
timeColumn = "Dates";
assetSymbols = ["BA", "CAT", "DIS", "GE", "IBM", "MCD", "MSFT"];
T = T(:,[timeColumn assetSymbols]);

% Convert to timetable
pricesTT = table2timetable(T,'RowTimes','Dates');

% View the final asset price timetable
head(pricesTT)
ans=8×7 timetable
       Dates        BA       CAT      DIS      GE       IBM      MCD     MSFT 
    ___________    _____    _____    _____    _____    _____    _____    _____

    03-Jan-2006    68.63    55.86    24.18     33.6    80.13    32.72    26.19
    04-Jan-2006    69.34    57.29    23.77    33.56    80.03    33.01    26.32
    05-Jan-2006    68.53    57.29    24.19    33.47    80.56    33.05    26.34
    06-Jan-2006    67.57    58.43    24.52     33.7    82.96    33.25    26.26
    09-Jan-2006    67.01    59.49    24.78    33.61    81.76    33.88    26.21
    10-Jan-2006    67.33    59.25    25.09    33.43     82.1    33.91    26.35
    11-Jan-2006     68.3    59.28    25.33    33.66    82.19     34.5    26.63
    12-Jan-2006     67.9    60.13    25.41    33.25    81.61    33.96    26.48

Стратегия обратного отклонения требует инициализации некоторой истории цен, чтобы можно было распределить часть данных для установки начальных весов. Сделав это, можно «разогреть начало» бэктеста.

warmupRange = 1:20;
testRange = 21:height(pricesTT);

Создание стратегий

Определение инвестиционной стратегии с помощью backtestStrategy функция. В этом примере используются две стратегии:

  • Равные взвешенные

  • Обратная дисперсия

В этом примере не приводится подробная информация о построении стратегий. Дополнительные сведения о создании стратегий см. в разделе backtestStrategy. Функции перебалансировки стратегии реализованы в разделе Функции перебалансировки.

% Create the strategies
ewInitialWeights = equalWeightFcn([],pricesTT(warmupRange,:));
ewStrategy = backtestStrategy("EqualWeighted",@equalWeightFcn,...
    'RebalanceFrequency',20,...
    'TransactionCosts',[0.0025 0.005],...
    'LookbackWindow',0,...
    'InitialWeights',ewInitialWeights);

ivInitialWeights = inverseVarianceFcn([],pricesTT(warmupRange,:));
ivStrategy = backtestStrategy("InverseVariance",@inverseVarianceFcn,...
    'RebalanceFrequency',20,...
    'TransactionCosts',[0.0025 0.005],...
    'InitialWeights',ivInitialWeights);

% Aggregate the strategies into an array
strategies = [ewStrategy ivStrategy];

Выполнить обратное тестирование

Создайте механизм тестирования и выполните тестирование в течение года данных запаса. Дополнительные сведения о создании механизмов обратного тестирования см. в разделе backtestEngine. Программное обеспечение инициализирует несколько свойств backtestEngine объект пуст. Эти свойства, доступные только для чтения, заполняются модулем после выполнения обратного теста.

% Create the backtesting engine using the default settings
backtester = backtestEngine(strategies)
backtester = 
  backtestEngine with properties:

               Strategies: [1x2 backtestStrategy]
             RiskFreeRate: 0
           CashBorrowRate: 0
          RatesConvention: "Annualized"
                    Basis: 0
    InitialPortfolioValue: 10000
                NumAssets: []
                  Returns: []
                Positions: []
                 Turnover: []
                  BuyCost: []
                 SellCost: []

Выполнить обратный тест с помощью runBacktest.

% Run the backtest
backtester = runBacktest(backtester,pricesTT(testRange,:));

Анализ итоговых результатов

summary функция использует результаты теста и возвращает таблицу высокоуровневых результатов теста.

s1 = summary(backtester)
s1=9×2 table
                       EqualWeighted    InverseVariance
                       _____________    _______________

    TotalReturn            0.17567           0.17155   
    SharpeRatio           0.097946           0.10213   
    Volatility           0.0074876         0.0069961   
    AverageTurnover      0.0007014         0.0024246   
    MaxTurnover           0.021107          0.097472   
    AverageReturn       0.00073178        0.00071296   
    MaxDrawdown           0.097647          0.096299   
    AverageBuyCost        0.018532          0.061913   
    AverageSellCost       0.037064           0.12383   

Каждая строка выходных данных таблицы представляет собой измерение эффективности стратегии. Каждая стратегия занимает столбец. summary сообщает о следующих метриках:

  • TotalReturn - неаннулированная общая отдача от стратегии, включая сборы, в течение всего периода обратного тестирования.

  • SharpeRatio - Неаннуализованное отношение Шарпа каждой стратегии к заднему тесту. Дополнительные сведения см. в разделе sharpe.

  • Volatility - Неаннуализованное среднеквадратическое отклонение стратегии на шаг по времени возвращается.

  • AverageTurnover - Средний оборот портфеля за шаг, выраженный в десятичном проценте.

  • MaxTurnover - Максимальный оборот портфеля в одном ребалансе, выраженный в десятичном проценте.

  • AverageReturn - среднее арифметическое для портфеля временных шагов.

  • MaxDrawdown - максимальное сокращение портфеля, выраженное в десятичном проценте. Дополнительные сведения см. в разделе maxdrawdown.

  • AverageBuyCost - Средние затраты на транзакцию за шаг по портфелю, понесенные при покупке активов.

  • AverageSellCost - Средние затраты на транзакцию за шаг по портфелю, понесенные при продаже активов.

Иногда полезно транспонировать summary при печати метрик различных стратегий.

s2 = rows2vars(s1);
s2.Properties.VariableNames{1} = 'StrategyName'
s2=2×10 table
       StrategyName        TotalReturn    SharpeRatio    Volatility    AverageTurnover    MaxTurnover    AverageReturn    MaxDrawdown    AverageBuyCost    AverageSellCost
    ___________________    ___________    ___________    __________    _______________    ___________    _____________    ___________    ______________    _______________

    {'EqualWeighted'  }      0.17567       0.097946      0.0074876        0.0007014        0.021107       0.00073178       0.097647         0.018532          0.037064    
    {'InverseVariance'}      0.17155        0.10213      0.0069961        0.0024246        0.097472       0.00071296       0.096299         0.061913           0.12383    

bar(s2.AverageTurnover)
title('Average Turnover')
ylabel('Average Turnover (%)')
set(gca,'xticklabel',s2.StrategyName)

Figure contains an axes. The axes with title Average Turnover contains an object of type bar.

Анализ подробных результатов

После того, как вы проведете обратный тест, backtestEngine объект обновляет поля, доступные только для чтения, с подробными результатами бэктеста. Returns, Positions, Turnover, BuyCost, и SellCost каждый из свойств содержит расписание результатов. Поскольку в этом примере используются данные о дневных ценах в фоновом тестировании, эти графики содержат ежедневные результаты.

backtester
backtester = 
  backtestEngine with properties:

               Strategies: [1x2 backtestStrategy]
             RiskFreeRate: 0
           CashBorrowRate: 0
          RatesConvention: "Annualized"
                    Basis: 0
    InitialPortfolioValue: 10000
                NumAssets: 7
                  Returns: [230x2 timetable]
                Positions: [1x1 struct]
                 Turnover: [230x2 timetable]
                  BuyCost: [230x2 timetable]
                 SellCost: [230x2 timetable]

Прибыль

Returns свойство содержит расписание стратегических (простых) возвратов для каждого временного шага. Эти возвраты включают все комиссии за транзакции.

head(backtester.Returns)
ans=8×2 timetable
       Time        EqualWeighted    InverseVariance
    ___________    _____________    _______________

    02-Feb-2006      -0.007553        -0.0070957   
    03-Feb-2006     -0.0037771         -0.003327   
    06-Feb-2006     -0.0010094        -0.0014312   
    07-Feb-2006      0.0053284         0.0020578   
    08-Feb-2006      0.0099755         0.0095781   
    09-Feb-2006     -0.0026871        -0.0014999   
    10-Feb-2006      0.0048374         0.0059589   
    13-Feb-2006     -0.0056868        -0.0051232   

binedges = -0.025:0.0025:0.025;
h1 = histogram(backtester.Returns.EqualWeighted,'BinEdges',binedges);
hold on
histogram(backtester.Returns.InverseVariance,'BinEdges',binedges);
hold off
title('Distribution of Daily Returns')
legend([strategies.Name]);

Figure contains an axes. The axes with title Distribution of Daily Returns contains 2 objects of type histogram. These objects represent EqualWeighted, InverseVariance.

Положения

Positions свойство содержит структуру расписаний, по одному на стратегию.

backtester.Positions
ans = struct with fields:
      EqualWeighted: [231x8 timetable]
    InverseVariance: [231x8 timetable]

Positions график каждой стратегии содержит позиции за шаг по каждому активу, а также Cash актив (который зарабатывает безрисковую ставку). Positions расписания содержат на одну строку больше, чем другие расписания результатов, потому что Positions графики включают первоначальные позиции стратегии в качестве их первого ряда. Начальные позиции можно рассматривать как Time = 0 портфельные позиции. В этом примере Positions расписание начинается с 1 февраля, а остальные начинаются 2 февраля.

head(backtester.Positions.InverseVariance)
ans=8×8 timetable
       Time           Cash          BA       CAT       DIS        GE       IBM       MCD       MSFT 
    ___________    ___________    ______    ______    ______    ______    ______    ______    ______

    01-Feb-2006              0    1401.2    682.17    795.14    2186.8    1900.1    1874.9    1159.8
    02-Feb-2006              0    1402.8    673.74    789.74    2170.8    1883.5    1863.6      1145
    03-Feb-2006     1.0987e-12    1386.5     671.2     787.2    2167.3    1854.3    1890.5      1139
    06-Feb-2006     2.1942e-12    1391.9    676.78    785.62    2161.1    1843.6    1899.1    1123.8
    07-Feb-2006     1.0994e-12      1400    661.66    840.23    2131.9    1851.6    1902.3    1114.5
    08-Feb-2006    -2.2198e-12    1409.8     677.9    846.58    2160.4    1878.2      1911    1113.2
    09-Feb-2006              0    1414.8    674.35    840.87    2172.2      1869    1908.3    1102.6
    10-Feb-2006     1.1148e-12    1425.1    677.29     839.6    2195.8    1890.6    1909.3    1103.9

% Plot the change of asset allocation over time
t = backtester.Positions.InverseVariance.Time;
positions = backtester.Positions.InverseVariance.Variables;
h = area(t,positions);
title('Inverse Variance Positions');
xlabel('Date');
ylabel('Asset Positions');
datetick('x','mm/dd','keepticks');
ylim([0 12000])
xlim([t(1) t(end)])
cm = parula(numel(h));
for i = 1:numel(h)
    set(h(i),'FaceColor',cm(i,:));
end

Figure contains an axes. The axes with title Inverse Variance Positions contains 8 objects of type area.

Товарооборот

Turnover график содержит оборот портфеля за шаг по времени.

head(backtester.Turnover)
ans=8×2 timetable
       Time        EqualWeighted    InverseVariance
    ___________    _____________    _______________

    02-Feb-2006          0                 0       
    03-Feb-2006          0                 0       
    06-Feb-2006          0                 0       
    07-Feb-2006          0                 0       
    08-Feb-2006          0                 0       
    09-Feb-2006          0                 0       
    10-Feb-2006          0                 0       
    13-Feb-2006          0                 0       

В зависимости от частоты перебалансировки, Turnover таблица может содержать в основном нули. Удаление этих нулей при визуализации оборота портфеля полезно.

nonZeroIdx = sum(backtester.Turnover.Variables,2) > 0;
to = backtester.Turnover(nonZeroIdx,:);
plot(to.Time,to.EqualWeighted,'-o',to.Time,to.InverseVariance,'-x',...
    'LineWidth',2,'MarkerSize',5);
legend([strategies.Name]);
title('Portfolio Turnover');
ylabel('Turnover (%)');

Figure contains an axes. The axes with title Portfolio Turnover contains 2 objects of type line. These objects represent EqualWeighted, InverseVariance.

Стоимость покупки и стоимость SellCost

BuyCost и SellCost расписания содержат пошаговые комиссии за транзакции для каждого типа транзакций, покупок и продаж.

totalCost = sum(backtester.BuyCost{:,:}) + sum(backtester.SellCost{:,:});
bar(totalCost);
title('Total Transaction Costs');
ylabel('$')
set(gca,'xticklabel',[strategies.Name])

Figure contains an axes. The axes with title Total Transaction Costs contains an object of type bar.

Создание кривой собственного капитала

Использовать equityCurve для построения кривой собственного капитала для стратегий равной взвешенной и обратной дисперсии.

equityCurve(backtester)

Figure contains an axes. The axes with title Equity Curve contains 2 objects of type line. These objects represent EqualWeighted, InverseVariance.

Функции ребалансировки

В этом разделе описывается реализация функций перебалансировки стратегии. Дополнительные сведения о создании стратегий и записи функций ребалансировки см. в разделе backtestStrategy.

function new_weights = equalWeightFcn(current_weights, pricesTT) %#ok<INUSL> 
% Equal weighted portfolio allocation

nAssets = size(pricesTT, 2);
new_weights = ones(1,nAssets);
new_weights = new_weights / sum(new_weights);

end
function new_weights = inverseVarianceFcn(current_weights, pricesTT) %#ok<INUSL> 
% Inverse-variance portfolio allocation

assetReturns = tick2ret(pricesTT);
assetCov = cov(assetReturns{:,:});
new_weights = 1 ./ diag(assetCov);
new_weights = new_weights / sum(new_weights);

end

Входные аргументы

свернуть все

Механизм обратного тестирования, указанный как backtestEngine объект. Использовать backtestEngine для создания механизма обратного тестирования и последующего использования runBacktest чтобы выполнить обратный тест.

Типы данных: object

Выходные аргументы

свернуть все

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

  • TotalReturn - Общая отдача стратегии за весь бэктест

  • SharpeRatio - Коэффициент Шарпа для каждой стратегии

  • Volatility - Волатильность каждой стратегии в фоновом режиме

  • AverageTurnover - Средний оборот за шаг времени в десятичном проценте

  • MaxTurnover - Максимальный оборот за один временной шаг

  • AverageReturn - Средняя доходность за шаг

  • MaxDrawdown - Максимальное сокращение портфеля в десятичном проценте

  • AverageBuyCost - Средние затраты на транзакцию за шаг для покупки основных средств

  • AverageSellCost - Средние затраты на транзакцию за шаг для продажи основных средств

Представлен в R2020b