Запустите backtest на одной или нескольких стратегиях
запускает backtest по расписанию настроенных данных цен активов.backtester
= runBacktest(backtester
,pricesTT
)
runBacktest
инициализирует каждую стратегию ранее заданное использование backtestStrategy
к InitialPortfolioValue
и затем начинает обрабатывать расписание ценовых данных (pricesTT
) можно следующим образом:
На каждом временном шаге, runBacktest
функция применяется, актив возвращается к положениям портфеля стратегии.
runBacktest
функция определяет который стратегии изменять баланс на основе RebalanceFrequency
свойство backtestStrategy
объекты.
Для стратегий, для которых нужно изменение баланса, runBacktest
вызовы функции их восстановление равновесия функционируют с прокручивающимся окном данных цен активов на основе LookbackWindow
свойство каждого backtestStrategy
.
Операционные издержки вычислены и заряжены на основе изменений в положениях актива и TransactionCosts
свойство каждого backtestStrategy
объект.
После того, как backtest завершен, результаты хранятся в нескольких свойствах backtestEngine
объект.
запустите backtest использование настроенных данных цен активов и данных сигнала. Когда вы задаете расписание данных сигнала (backtester
= runBacktest(backtester
,pricesTT
,signalTT
)signalTT
), затем runBacktest
функционируйте запускает backtest и дополнительно передает прокручивающееся окно данных сигнала к функции восстановления равновесия каждой стратегии во время шага восстановления равновесия.
задает опции с помощью одного или нескольких дополнительных аргументов пары "имя-значение" в дополнение к входным параметрам в предыдущем синтаксисе. Например, backtester
= runBacktest(___,Name,Value
)backtester = runBacktest(backtester,assetPrices,'Start',50,'End',100)
.
MATLAB® backtesting механизм запускает backtests стратегий портфельных инвестиций по timeseries данных цен активов. После создания набора backtest стратегий с помощью backtestStrategy
и backtest механизм с помощью backtestEngine
, runBacktest
функция выполняет backtest. Этот пример иллюстрирует, как использовать runBacktest
функционируйте, чтобы протестировать инвестиционные стратегии.
Загрузка данных
Загрузите один год данных о курсе акций. Для удобочитаемости этот пример только использует подмножество запасов DJIA.
% Read table of daily adjusted close prices for 2006 DJIA stocks T = readtable('dowPortfolio.xlsx'); % Prune the table on only hold 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
Создайте стратегию
В этом вводном примере протестируйте равную взвешенную инвестиционную стратегию. Эта стратегия инвестирует равный фрагмент ликвидного капитала в каждый актив. Этот пример действительно описывает детали о том, как создают backtest стратегии. Для получения дополнительной информации о создании backtest стратегии, смотрите backtestStrategy
.
Установите RebalanceFrequency
восстанавливать равновесие портфеля каждые 60 дней. Этот пример не использует lookback окно, чтобы изменять баланс.
% Create the strategy numAssets = size(pricesTT,2); equalWeightsVector = ones(1,numAssets) / numAssets; equalWeightsRebalanceFcn = @(~,~) equalWeightsVector; ewStrategy = backtestStrategy("EqualWeighted",equalWeightsRebalanceFcn,... 'RebalanceFrequency',60,... 'LookbackWindow',0,... 'TransactionCosts',0.005,... 'InitialWeights',equalWeightsVector)
ewStrategy = backtestStrategy with properties: Name: "EqualWeighted" RebalanceFcn: @(~,~)equalWeightsVector RebalanceFrequency: 60 TransactionCosts: 0.0050 LookbackWindow: 0 InitialWeights: [0.1429 0.1429 0.1429 0.1429 0.1429 0.1429 0.1429]
Запустите Backtest
Создайте backtesting механизм и запустите backtest более чем год данных о запасе. Для получения дополнительной информации о создании backtest механизмы, смотрите backtestEngine
.
% Create the backtest engine. The backtest engine properties that hold the % results are initialized to empty. backtester = backtestEngine(ewStrategy)
backtester = backtestEngine with properties: Strategies: [1x1 backtestStrategy] RiskFreeRate: 0 CashBorrowRate: 0 RatesConvention: "Annualized" Basis: 0 InitialPortfolioValue: 10000 NumAssets: [] Returns: [] Positions: [] Turnover: [] BuyCost: [] SellCost: []
% Run the backtest. The empty properties are now populated with % timetables of detailed backtest results. backtester = runBacktest(backtester,pricesTT)
backtester = backtestEngine with properties: Strategies: [1x1 backtestStrategy] RiskFreeRate: 0 CashBorrowRate: 0 RatesConvention: "Annualized" Basis: 0 InitialPortfolioValue: 10000 NumAssets: 7 Returns: [250x1 timetable] Positions: [1x1 struct] Turnover: [250x1 timetable] BuyCost: [250x1 timetable] SellCost: [250x1 timetable]
Сводные данные Backtest
Используйте summary
функция, чтобы сгенерировать сводную таблицу результатов backtest.
% Examing results. The summary table shows several performance metrics.
summary(backtester)
ans=9×1 table
EqualWeighted
_____________
TotalReturn 0.22943
SharpeRatio 0.11415
Volatility 0.0075013
AverageTurnover 0.00054232
MaxTurnover 0.038694
AverageReturn 0.00085456
MaxDrawdown 0.098905
AverageBuyCost 0.030193
AverageSellCost 0.030193
При выполнении backtest в MATLAB® необходимо изучить то, что - начальные условия, когда backtest начинается. Начальные веса для каждой стратегии, размера стратегии lookback окно и любое потенциальное разделение набора данных в разделы обучения и тестирования влияют на результаты backtest. В этом примере показано, как использовать runBacktest
функция с 'Start'
и 'End'
аргументы пары "имя-значение", которые взаимодействуют с 'LookbackWindow'
и 'RebalanceFrequency'
свойства backtestStrategy
возразите против "горячего запуска" backtest.
Загрузка данных
Загрузите один год данных о курсе акций. Для удобочитаемости этот пример использует только подмножество запасов 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
Создайте стратегию
Этот пример backtests "обратное отклонение" стратегия. Обратная функция восстановления равновесия отклонения реализована в разделе Local Functions. Для получения дополнительной информации о создании backtest стратегии, смотрите backtestStrategy
. Обратное использование стратегии отклонения ковариация актива возвращается, чтобы принять решения относительно распределения активов. LookbackWindow
поскольку эта стратегия должна содержать по крайней мере 30 дней запаздывающих данных (приблизительно 6 недель), и самое большее, 60 дней (приблизительно 12 недель).
Установите RebalanceFrequency
для backtestStrategy
восстанавливать равновесие портфеля каждые 25 дней.
% Create the strategy minLookback = 30; maxLookback = 60; ivStrategy = backtestStrategy("InverseVariance",@inverseVarianceFcn,... 'RebalanceFrequency',25,... 'LookbackWindow',[minLookback maxLookback],... 'TransactionCosts',[0.0025 0.005])
ivStrategy = backtestStrategy with properties: Name: "InverseVariance" RebalanceFcn: @inverseVarianceFcn RebalanceFrequency: 25 TransactionCosts: [0.0025 0.0050] LookbackWindow: [30 60] InitialWeights: [1x0 double]
Запустите Backtest и исследуйте результаты
Создайте backtesting механизм и запустите backtest более чем год данных о запасе. Для получения дополнительной информации о создании backtest механизмы, смотрите backtestEngine
.
% Create the backtest engine. backtester = backtestEngine(ivStrategy); % Run the backtest. backtester = runBacktest(backtester,pricesTT);
Используйте assetAreaPlot
функция помощника, заданная в разделе Local Functions этого примера, чтобы отобразить изменение в распределении активов в течение backtest.
assetAreaPlot(backtester,"InverseVariance")
Заметьте, что обратная стратегия отклонения начинает все наличными и остается в том состоянии в течение приблизительно 2,5 месяцев. Это вызвано тем, что backtestStrategy
объект не имеет заданного набора начальных весов, которые вы задаете использование InitialPortfolioValue
аргумент пары "имя-значение". Обратная стратегия отклонения требует 30 дней запаздывающей истории цен активов перед изменением баланса. Можно использовать printRebalanceTable
функция помощника, заданная в разделе Local Functions, чтобы отобразить расписание восстановления равновесия.
printRebalanceTable(ivStrategy,pricesTT,minLookback);
First Day of Data Backtest Start Date Minimum Days to Rebalance _________________ ___________________ _________________________ 03-Jan-2006 03-Jan-2006 30 Rebalance Dates Days of Available Price History Enough Data to Rebalance _______________ _______________________________ ________________________ 08-Feb-2006 26 "No" 16-Mar-2006 51 "Yes" 21-Apr-2006 76 "Yes" 26-May-2006 101 "Yes" 03-Jul-2006 126 "Yes" 08-Aug-2006 151 "Yes" 13-Sep-2006 176 "Yes" 18-Oct-2006 201 "Yes" 22-Nov-2006 226 "Yes" 29-Dec-2006 251 "Yes"
Первая дата восстановления равновесия происходит 8 февраля, но стратегия не имеет достаточного количества ценовой истории, чтобы заполнить допустимое lookback окно (минимум составляет 30 дней), таким образом, никакое восстановление равновесия не происходит. Следующая дата восстановления равновесия 16 марта, полные 50 дни в backtest.
Эта ситуация не идеальна, когда эти 50 дней, находясь во все-денежной позиции представляют приблизительно 20% общего количества backtest. Следовательно, когда backtesting отчеты механизма относительно эффективности стратегии (то есть, совокупный доход, отношение Шарпа, энергозависимость, и так далее), результаты не отражают "истинную" эффективность стратегии, потому что стратегия только начала принимать решения распределения активов только приблизительно 20% в backtest.
Горячий запуск Backtest
Это возможно к "горячему запуску" backtest. Горячий запуск означает, что результаты backtest отражают эффективность стратегии в состоянии рынка, отраженном в ценовом расписании. Чтобы запуститься, установите начальные веса стратегии постараться не запускать все наличными.
Обратная стратегия отклонения требует, чтобы 30 дней ценовой истории заполнили допустимое lookback окно, таким образом, можно разделить ценовой набор данных в два раздела, набор "прогрева" и "тестовый" набор.
warmupRange = 1:30; % The 30th row is included in both ranges since the day 30 price is used % to compute the day 31 returns. testRange = 30:height(pricesTT);
Используйте раздел прогрева, чтобы установить начальные веса обратной стратегии отклонения. Путем выполнения так, можно начать backtest со стратегии, уже "запускающейся", и избежать начальных недель, проведенных в денежной позиции.
% Use the rebalance function to set the initial weights. This might % or might not be possible for other strategies depending on the details of % the strategy logic. initWeights = inverseVarianceFcn([],pricesTT(warmupRange,:));
Обновите стратегию и повторно выполните backtest. Поскольку область значений прогрева используется, чтобы инициализировать обратную стратегию отклонения, необходимо не использовать эти данные из backtest, чтобы избежать предварительного смещения, или "наблюдения будущего", и к backtest только в "тестовой области значений".
% Set the initial weights on the strategy in the backtester. You can do this when you % create the strategy as well, using the 'InitialWeights' parameter. backtester.Strategies(1).InitialWeights = initWeights; % Rerun the backtest over the "test" range. backtester = runBacktest(backtester,pricesTT(testRange,:));
Когда вы генерируете график области, вы видите, что проблемы, где стратегия находится наличными для первого фрагмента backtest, избегают.
assetAreaPlot(backtester,"InverseVariance")
Однако, если вы смотрите на таблицу восстановления равновесия, вы видите, что стратегия все еще "пропустила" первую дату восстановления равновесия. Когда вы запускаете backtest в тестовой области значений набора данных, первая дата восстановления равновесия 22 марта. Это вызвано тем, что область значений прогрева не использована из ценовой истории, и стратегия имела только 26 дней в наличии истории в ту дату (меньше, чем минимальные 30 дней, требуемых для lookback окна). Поэтому восстановление равновесия 22 марта пропущено.
Чтобы избежать backtesting в области значений прогрева, область значений была удалена это из набора данных. Это означает новую backtest дату начала, и все последующие даты восстановления равновесия 30 дней спустя. Ценовые данные об истории, содержавшиеся в области значений прогрева, были полностью удалены, поэтому когда backtest механизм совершил нападки, первое восстановление равновесия датируются, ценовая история была недостаточна, чтобы изменять баланс.
printRebalanceTable(ivStrategy,pricesTT(testRange,:),minLookback);
First Day of Data Backtest Start Date Minimum Days to Rebalance _________________ ___________________ _________________________ 14-Feb-2006 14-Feb-2006 30 Rebalance Dates Days of Available Price History Enough Data to Rebalance _______________ _______________________________ ________________________ 22-Mar-2006 26 "No" 27-Apr-2006 51 "Yes" 02-Jun-2006 76 "Yes" 10-Jul-2006 101 "Yes" 14-Aug-2006 126 "Yes" 19-Sep-2006 151 "Yes" 24-Oct-2006 176 "Yes" 29-Nov-2006 201 "Yes"
Этот сценарий также не правилен, поскольку исходное ценовое расписание (прогрев и тестовые разделы вместе) действительно имеет достаточно ценовой истории к 22 марта, чтобы заполнить допустимое lookback окно. Однако более ранние данные не доступны для backtest механизма, потому что backtest был запущен с помощью только тестовый раздел.
Используйте Start
и End
Параметры для runBacktest
Идеальный рабочий процесс в этой ситуации должен оба не использовать диапазон данных прогрева от backtest, чтобы избежать предварительного смещения, но включать данные прогрева в ценовую историю, чтобы смочь заполнить lookback окно стратегии со всеми доступными ценовыми данными об истории. Можно сделать так при помощи 'Start'
параметр для runBacktest
функция.
'Start'
и 'End'
аргументы пары "имя-значение" для runBacktest
включите вам к началу и концу backtest в определенные даты. Можно задать 'Start'
и 'End'
как строки ценового расписания или как значения datetime (см. документацию для runBacktest
функция для деталей). 'Start'
аргумент позволяет backtest начаться в конкретную дату при предоставлении backtest доступа к механизму к полному набору данных.
Повторно выполните backtest использование 'Start'
аргумент пары "имя-значение", а не только работа раздела исходного набора данных.
% Rerun the backtest starting on the last day of the warmup range. startRow = warmupRange(end); backtester = runBacktest(backtester,pricesTT,'Start',startRow);
Постройте новый график области актива.
assetAreaPlot(backtester,"InverseVariance")
Просмотрите новую таблицу восстановления равновесия с новым 'Start'
параметр.
printRebalanceTable(ivStrategy,pricesTT,minLookback,startRow);
First Day of Data Backtest Start Date Minimum Days to Rebalance _________________ ___________________ _________________________ 03-Jan-2006 14-Feb-2006 30 Rebalance Dates Days of Available Price History Enough Data to Rebalance _______________ _______________________________ ________________________ 22-Mar-2006 55 "Yes" 27-Apr-2006 80 "Yes" 02-Jun-2006 105 "Yes" 10-Jul-2006 130 "Yes" 14-Aug-2006 155 "Yes" 19-Sep-2006 180 "Yes" 24-Oct-2006 205 "Yes" 29-Nov-2006 230 "Yes"
Обратная стратегия отклонения теперь имеет достаточно данных, чтобы изменять баланс в первую дату восстановления равновесия (22 марта), и backtest является "теплым, запустился". При помощи исходного набора данных первый день данных остается 3 января, и 'Start'
параметр позволяет вам перемещать backtest дату начала вперед, чтобы избежать области значений прогрева.
Даже при том, что результаты не существенно отличаются, этот пример иллюстрирует взаимодействие между LookbackWindow
and
RebalanceFrequency
аргументы пары "имя-значение" для backtestStrategy
возразите и область значений данных, используемых в runBacktest
когда вы оцениваете эффективность стратегии в backtest.
Локальные функции
Функция восстановления равновесия стратегии реализована можно следующим образом. Для получения дополнительной информации о создании стратегий и записи функций восстановления равновесия, смотрите backtestStrategy
.
function new_weights = inverseVarianceFcn(current_weights, pricesTT) % Inverse-variance portfolio allocation. assetReturns = tick2ret(pricesTT); assetCov = cov(assetReturns{:,:}); new_weights = 1 ./ diag(assetCov); new_weights = new_weights / sum(new_weights); end
Этот помощник графики функций распределение активов как график области.
function assetAreaPlot(backtester,strategyName) t = backtester.Positions.(strategyName).Time; positions = backtester.Positions.(strategyName).Variables; h = area(t,positions); title(sprintf('%s Positions',strategyName)); xlabel('Date'); ylabel('Asset Positions'); datetick('x','mm/dd','keepticks'); xlim([t(1) t(end)]) oldylim = ylim; ylim([0 oldylim(2)]); cm = parula(numel(h)); for i = 1:numel(h) set(h(i),'FaceColor',cm(i,:)); end legend(backtester.Positions.(strategyName).Properties.VariableNames) end
Эта функция помощника генерирует таблицу дат восстановления равновесия наряду с доступной ценовой историей в каждую дату.
function printRebalanceTable(strategy,pricesTT,minLookback,startRow) if nargin < 4 startRow = 1; end allDates = pricesTT.(pricesTT.Properties.DimensionNames{1}); rebalanceDates = allDates(startRow:strategy.RebalanceFrequency:end); [~,rebalanceIndices] = ismember(rebalanceDates,pricesTT.Dates); disp(table(allDates(1),rebalanceDates(1),minLookback,'VariableNames',{'First Day of Data','Backtest Start Date','Minimum Days to Rebalance'})); fprintf('\n\n'); numHistory = rebalanceIndices(2:end); sufficient = repmat("No",size(numHistory)); sufficient(numHistory > minLookback) = "Yes"; disp(table(rebalanceDates(2:end),rebalanceIndices(2:end),sufficient,'VariableNames',{'Rebalance Dates','Days of Available Price History','Enough Data to Rebalance'})); end
backtester
— Механизм BacktestingbacktestEngine
объектМеханизм Backtesting в виде backtestEngine
объект. Используйте backtestEngine
создать backtester
объект.
Типы данных: object
pricesTT
— Цены активовЦены активов в виде расписания цен активов, что backtestEngine
использование к backtest стратегии. Каждый столбец ценового расписания должен содержать timeseries цен на актив. Исторические цены активов должны быть настроены для разделений и дивидендов.
Типы данных: timetable
signalTT
— Данные сигнала(Необязательно) Данные сигнала в виде расписания торговых сигналов, что использование стратегий, чтобы принять торговые решения. signalTT
является дополнительным. Если обеспечено, backtestEngine
вызывает функции восстановления равновесия стратегии и с данными цен активов и с данными сигнала. signalTT
расписание должно иметь то же измерение времени как pricesTT
расписание.
Типы данных: timetable
Задайте дополнительные разделенные запятой пары Name,Value
аргументы. Name
имя аргумента и Value
соответствующее значение. Name
должен появиться в кавычках. Вы можете задать несколько аргументов в виде пар имен и значений в любом порядке, например: Name1, Value1, ..., NameN, ValueN
.
backtester = runBacktest(backtester,assetPrices,'Start',50,'End',100)
'Start'
— Временной шаг, чтобы запустить backtest
(значение по умолчанию) | целое число | datetimeВременной шаг, чтобы запустить backtest в виде разделенной запятой пары, состоящей из 'Start'
и скалярное целое число или datetime.
Если целое число, Start
время относится к строке в pricesTT
расписание, где backtest начинается.
Если datetime
объект, backtest начнется в первый раз в ценовом расписании, которое происходит на или после 'Start'
параметр. backtest закончится на прошлом разе в ценовом расписании, которое происходит на или перед 'End'
параметр. 'Start'
и 'End'
параметры устанавливают контур данных, которые включены в backtest.
Типы данных: double |
datetime
'End'
— Временной шаг, чтобы закончить backtestpricesTT
расписание (значение по умолчанию) | целое число | datetimebacktester
— Механизм BacktestingbacktestEngine
объектМеханизм Backtesting, возвращенный как обновленный backtestEngine
объект. После того, как backtesting завершен, runBacktest
заполняет несколько свойств в backtestEngine
объект результатами backtest. Можно обобщить результаты при помощи summary
функция.
У вас есть модифицированная версия этого примера. Вы хотите открыть этот пример со своими редактированиями?
1. Если смысл перевода понятен, то лучше оставьте как есть и не придирайтесь к словам, синонимам и тому подобному. О вкусах не спорим.
2. Не дополняйте перевод комментариями “от себя”. В исправлении не должно появляться дополнительных смыслов и комментариев, отсутствующих в оригинале. Такие правки не получится интегрировать в алгоритме автоматического перевода.
3. Сохраняйте структуру оригинального текста - например, не разбивайте одно предложение на два.
4. Не имеет смысла однотипное исправление перевода какого-то термина во всех предложениях. Исправляйте только в одном месте. Когда Вашу правку одобрят, это исправление будет алгоритмически распространено и на другие части документации.
5. По иным вопросам, например если надо исправить заблокированное для перевода слово, обратитесь к редакторам через форму технической поддержки.