backtestStrategy

Создание backtestStrategy объект для определения стратегии распределения портфеля

Описание

Создайте backtestStrategy объект, который определяет стратегию распределения портфеля.

Используйте этот рабочий процесс для разработки и запуска бэктеста:

  1. Определите логику стратегии с помощью backtestStrategy объект, чтобы определить, как стратегия восстанавливает баланс портфеля активов.

  2. Использование backtestEngine для создания backtestEngine объект, который задает параметры бэктеста.

  3. Использовать runBacktest для запуска бэктеста по данным о исторических ценах активов и, опционально, по данным о торговом сигнале.

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

  5. Использовать summary результирующие результаты в формате таблицы.

Для получения дополнительной информации об этом рабочем процессе смотрите Backtest Investment Strategies.

Создание

Описание

пример

strategy = backtestStrategy(name,rebalanceFcn) создает backtestStrategy объект.

пример

strategy = backtestStrategy(___,Name,Value) устанавливает свойства с помощью аргументов пары "имя-значение" и любого из аргументов в предыдущем синтаксисе. Можно задать несколько аргументы пары "имя-значение". Для примера, strat = backtestStrategy('MyStrategy',@myRebalFcn,'TransactionCost',0.005,'LookbackWindow',20).

Входные параметры

расширить все

Имя стратегии, заданное как строка.

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

Функция ребаланса, заданная как указатель на функцию. Указатель на функцию вычисляет новые веса портфеля во время бэктеста. Аргумент rebalanceFcn реализует основную логику торговой стратегии и должен иметь одну из следующих сигнатур:

  • new_weights = rebalanceFcn(weights,assetPrices)

  • new_weights = rebalanceFcn(weights,assetPrices,signalData)

Функция ребаланса вызывается backtestEngine объект каждый раз, когда стратегия должна быть восстановлена. The backtestEngine объект вызывает функцию ребаланса со следующими аргументами:

  • weights - Текущие веса портфеля перед перерасчетом, заданные как десятичные проценты.

  • assetPrices - A timetable содержащее скользящее окно скорректированных цен на основные средства.

  • signalData - A timetable содержит окно качения сигнальных данных. Если вы предоставляете данные сигнала в backtestEngine объект, затем объект engine передает его в функцию ребаланса стратегии с помощью синтаксиса трёх входных параметров. Если данные сигнала не предоставляются, backtestEngine объект, затем объект engine вызывает функцию ребаланса с двумя синтаксисами входных параметров.

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

    • Если на new_weights сумма по 1, затем портфель полностью инвестируется.

    • Если на new_weights сумма менее 1, тогда портфолио будет иметь остаток наличными, зарабатывая RiskFreeRate заданный в backtestEngine объект.

    • Если на new_weights сумма более 1, затем происходит отрицательная денежная позиция (маржа) и заимствованные денежные средства начисляют проценты по ставке заимствования денежных средств, указанной в CashBorrowRate свойство backtestEngine объект.

    Для получения дополнительной информации о разработке rebalanceFcn указатель на функцию, см. Backtest Investment Strategies.

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

Аргументы в виде пар имя-значение

Задайте необязательные разделенные разделенными запятой парами Name,Value аргументы. Name - имя аргумента и Value - соответствующее значение. Name должны находиться внутри кавычек. Можно задать несколько аргументов в виде пар имен и значений в любом порядке Name1,Value1,...,NameN,ValueN.

Пример: strat = backtestStrategy('MyStrategy',@myRebalFcn,'TransactionCost',0.005,'LookbackWindow',20)

Частота ребаланса во время обратного теста, заданная как разделенная разделенными запятой парами, состоящая из 'RebalanceFrequency' и скалярное целое число, duration объект, calendarDuration объект или вектор datetime объекты.

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

При использовании duration объект или calendarDurationСамый задний тест двигателя создает график ребаланса времени, начиная с самого заднего времени запуска, с временами ребаланса, происходящими после каждого шага заданной длительности.

Если используется вектор datetime объекты, RebalanceFrequency определяет явное расписание пересчета времени. Бэктест двигателя будет восстанавливать баланс в каждом datetime в указанном расписании.

Примечание

Как для синтаксиса длительности, так и для синтаксиса datetime, если время ребаланса не найдено в самом заднем наборе данных, механизм будет ребалансировать в ближайшее время до запланированного времени. Для примера, если график ребаланса содержит выходные, ребаланс произойдет в пятницу ранее.

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

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

  • rate - скалярный десятичный процент для покупок и продаж активов. Например, если вы задаете TransactionCosts на 0.001, тогда каждая транзакция (покупает и продает) заплатит 0,1% от комиссии за транзакцию.

  • [buyRate, sellRate] - A 1-by- 2 вектор десятичных процентных ставок, который определяет отдельные ставки для покупки и продажи активов.

  • computeTransactionCostsFcn - указатель на функцию для вычисления настраиваемых комиссий за транзакции. Если вы задаете указатель на функцию, backtestEngine объект вызывает TransactionCosts функция для вычисления сборов за каждый ребаланс. Определяемая пользователем указатель на функцию должна иметь следующую подпись:

    [buyCosts,sellCosts] = computeCostsFcn(deltaPositions)

    Пользовательский указатель на функцию принимает один входной параметр deltaPositions, который является вектором изменения позиций активов для всех активов (в валютных модулях) в результате ребаланса. Положительные элементы в deltaPositions вектор указывает на покупки, в то время как отрицательные значения представляют продажи. Определяемый пользователем указатель на функцию должен вернуть два выходных аргументов buyCosts и sellCosts, которые содержат общие затраты (в валюте) для всего ребаланса для каждого типа транзакции.

Типы данных: double | function_handle

Интерполяционное окно, заданное как разделенная разделенными запятой парами, состоящая из 'LookbackWindow' и a 1-by- 2 вектор целых чисел, a duration объект, или calendarDuration объект.

При использовании 1-by- 2 вектор с целыми числами, который определяет минимальный и максимальный размер скользящего окна данных (цены активов и сигнальные данные), которые вы предоставляете rebalanceFcn аргумент. Эти пределы задаются в терминах количества временных шагов. При задании в виде целых чисел окно поиска определяется в терминах строк данных из актива (pricesTT) и сигнал (signalTT) расписания, используемые в backtest. Интерполяционный минимум устанавливает минимальное количество строк данных цены актива, которые должны быть доступны для функции ребаланса перед возникновением ребаланса стратегии. Интерполяционный максимум устанавливает максимальный размер для скользящего окна ценовых данных, который передается в функцию ребаланса.

Для примера, если backtestEngine объект снабжается ежедневными ценовыми данными, затем LookbackWindow задает размерные границы окна качения в днях. Значение по умолчанию является [0 Inf], что означает, что все доступные прошлые данные даны функции ребаланса. Если вы задаете ненулевой минимум, то программное обеспечение не вызывает rebalanceFcn пока временные шаги процесс не достигнет минимального размера.

Если вы задаете LookbackWindow как одно скалярное значение, тогда значение является и минимальным, и максимальным LookbackWindow (то есть окно фиксированного размера).

При использовании duration объект или calendarDuration, минимальные и максимальные значения окна поиска заданы в терминах временных интервалов относительно времени при ребалансе. Для примера, если бы минимум поиска был установлен на пять дней (то есть days(5)), ребаланс произойдет только, если время начала бэктеста составляет не менее пяти дней до момента ребаланса. Точно так же, если бы искомый максимум был установлен на шесть месяцев (то есть calmonths(6)), окно поиска будет содержать только данные, которые произошли за шесть месяцев до момента ребаланса или позже.

Примечание

Кроме того, LookbackWindow может быть задано одно скалярное значение, указывающее, что скользящее окно должно быть точно таким же размером (либо в терминах строк, либо во временной длительности). Минимальный и максимальный размеры будут установлены на заданное значение.

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

Начальные веса портфеля, заданные как разделенная разделенными запятой парами, состоящая из 'InitialWeights' и вектор. The InitialWeights вектор устанавливает веса портфеля перед backtestEngine объект начинает бэктест. Размер вектора начальных весов должен совпадать с количеством активов, используемых в backtest.

Также можно задать InitialWeights Аргумент пары "имя-значение" в пустой ([ ]) указание стратегии начнется без инвестиций и в 100% денежной позиции. Значение по умолчанию для InitialWeights пуст ([ ]).

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

Свойства

расширить все

Имя стратегии, заданное как строка.

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

Функция ребаланса, заданная как указатель на функцию.

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

Частота ребаланса во время обратного теста, заданная в виде скалярного числа.

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

Транзакционные затраты, заданные как скалярное число, вектор или указатель на функцию.

Типы данных: double | function_handle

Интерполяционное окно, заданное в виде скалярного числа или вектора.

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

Начальные веса, заданные как вектор.

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

Примеры

свернуть все

Определите стратегию бэктеста при помощи backtestStrategy объект. backtestStrategy объекты содержат свойства, характерные для торговой стратегии, такие как частота ребаланса, транзакционные затраты и функция ребаланса. Функция ребаланса реализует основную логику стратегии и используется механизмом обратного тестирования во время бэктеста, чтобы позволить стратегии изменить распределение активов и совершить сделки. В этом примере, чтобы проиллюстрировать, как создать и использовать стратегии backtest в MATLAB ®, вы готовите две простые стратегии для обратного тестирования :

  1. Равная взвешенная стратегия

  2. Стратегия, которая пытается «преследовать возвраты»

Логика стратегии для этих двух стратегий определяется функциями ребаланса.

Задание свойств стратегии

A backtestStrategy объект имеет несколько свойств, которые вы задаете используя параметры для backtestStrategy функция.

Начальные веса

The InitialWeights свойство содержит веса распределения активов в начале бэктеста. Значение по умолчанию для InitialWeights пуст ([]), что указывает на то, что стратегия начинает самые непосвященные, что означает, что 100% капитала находится в наличности, зарабатывая безрисковую ставку.

Установите InitialWeights к определенному распределению основных средств. Размер вектора начальных весов должен совпадать с количеством активов в бэктесте.

% Initialize the strategies with 30 weights, since the backtest
% data comes from a year of the 30 DJIA stocks.
numAssets = 30;

% Give the initial weights for both strategies equal weighting. Weights
% must sum to 1 to be fully invested.
initialWeights = ones(1,numAssets);
initialWeights = initialWeights / sum(initialWeights);

Транзакционные издержки

The TransactionCosts свойство позволяет вам установить комиссии, которые стратегия платит за торговые активы. Транзакционные затраты оплачиваются в процентах от общего изменения позиции для каждого актива. Задайте затраты в десятичных процентах. Для примера, если TransactionCosts устанавливается равным 1% (0.01) и стратегия покупает акции на 100 долларов, тогда понесенные транзакционные издержки составляют 1 доллар.

Транзакционные затраты устанавливаются с помощью 1-by- 2 вектор, который устанавливает отдельные ставки комиссии для покупок и продаж активов. В этом примере обе стратегии оплачивают одни и те же транзакционные затраты - 25 базисных пунктов для покупок основных средств и 50 базисных точек для продаж.

% Define the Transaction costs as [buyCosts sellCost] and specify the costs
% as decimal percentages.
tradingCosts = [0.0025 0.005];

Можно также задать свойство TransactionCost в качестве указателя на функцию, если необходимо реализовать произвольно сложные структуры затрат на транзакции. Для получения дополнительной информации о создании функций транзакционных затрат см. backtestStrategy.

Частота ребаланса

The RebalanceFrequency свойство определяет, как часто механизм обратного тестирования ребалансировает и перераспределяет портфель стратегии, используя функцию ребаланса. Установите RebalanceFrequency с точки зрения временных шагов в backtest. Например, если механизм обратного тестирования тестирует стратегию с набором ежедневных данных о ценах, задайте функцию ребаланса в днях. По существу, RebalanceFrequency представляет количество строк ценовых данных для обработки между каждым вызовом функции ребаланса стратегии.

% Both strategies rebalance every 4 weeks (20 days).
rebalFreq = 20;

Интерполяционное окно

Каждый раз, когда механизм обратного тестирования вызывает функцию ребаланса стратегии, окно данных о цене актива (и, возможно, данных о сигнале) передается в функцию ребаланса. Функция ребаланса может затем принимать решения о торговле и распределении на основе скользящего окна рыночных данных. The LookbackWindow свойство задает размер этих окон качения. Установите окно в терминах временных шагов. Окно определяет количество строк данных из расписания цен основных средств, которые передаются в функцию ребаланса.

The LookbackWindow свойство может быть задано двумя способами. Для скользящего окна данных фиксированного размера (для примера, «50 дней истории цен»), LookbackWindow свойство устанавливается в одно скалярное значение (N = 50). Затем программное обеспечение вызывает функцию ребаланса с расписанием цен, содержащим точно N строки данных скользящих цен.

Также можно задать свойство LookbackWindow при помощи 1-by- 2 векторная [min max] это задает минимальный и максимальный размер для расширяющегося окна данных. Таким образом можно задать гибкие размеры окон. Для примера:

  • [10 Inf] - Не менее 10 строк данных

  • [0 50] - Не более 50 строк данных

  • [0 Inf] - все доступные данные (то есть не минимум, не максимум); это значение по умолчанию

  • [20 20] - Ровно 20 строк данных; это эквивалентно установке LookbackWindow к скалярному значению 20

Программа не вызывает функцию ребаланса, если данных недостаточно для создания допустимого окна качения, независимо от значения RebalanceFrequency свойство.

Если стратегия не требует никакой цены или истории данных сигнала, то можно указать, что функция ребаланса не требует никаких данных путем установки LookbackWindow свойство к 0.

% The equal weight strategy does not require any price history data.
ewLookback = 0;

% The "chase returns" strategy bases its decisions on the trailing
% 10-day asset returns. The lookback window is set to 11 since computing 10 days 
% of returns requires the close price from day 0.
chaseLookback = 11;

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

Функция ребаланса (rebalanceFcn) - авторская функция, содержащая логику стратегии. Механизм обратного тестирования вызывает функцию ребаланса стратегии с фиксированным набором параметров и ожидает, что она вернет вектор весов активов, представляющий новое, желаемое распределение портфеля после ребаланса. Для получения дополнительной информации см. функции ребаланса.

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

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

% Create the equal weighted strategy. The rebalance function @equalWeights
% is defined in the Rebalance Functions section at the end of this example.
equalWeightStrategy = backtestStrategy("EqualWeight",@equalWeight,...
    'RebalanceFrequency',rebalFreq,...
    'TransactionCosts',tradingCosts,...
    'LookbackWindow',ewLookback,...
    'InitialWeights',initialWeights)
equalWeightStrategy = 
  backtestStrategy with properties:

                  Name: "EqualWeight"
          RebalanceFcn: @equalWeight
    RebalanceFrequency: 20
      TransactionCosts: [0.0025 0.0050]
        LookbackWindow: 0
        InitialWeights: [1x30 double]

% Create the "chase returns" strategy.  The rebalance function
% @chaseReturns is defined in the Rebalance Functions section at the end of this example.
chaseReturnsStrategy = backtestStrategy("ChaseReturns",@chaseReturns,...
    'RebalanceFrequency',rebalFreq,...
    'TransactionCosts',tradingCosts,...
    'LookbackWindow',chaseLookback,...
    'InitialWeights',initialWeights)
chaseReturnsStrategy = 
  backtestStrategy with properties:

                  Name: "ChaseReturns"
          RebalanceFcn: @chaseReturns
    RebalanceFrequency: 20
      TransactionCosts: [0.0025 0.0050]
        LookbackWindow: 11
        InitialWeights: [1x30 double]

Настройка Backtesting Engine

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

% Create an array of strategies for the backtestEngine.
strategies = [equalWeightStrategy chaseReturnsStrategy];

% Create backtesting engine to test both strategies.
backtester = backtestEngine(strategies);

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

Функции ребалансировки стратегии, определенные с помощью rebalanceFcn аргумент для backtestStrategy необходимо придерживаться фиксированного API, который подсистема backtest ожидает при взаимодействии с каждой стратегией. Функции ребаланса должны реализовать один из следующих двух синтаксисов:

function new_weights = exampleRebalanceFcn(current_weights,assetPriceTimeTable)

function new_weights = exampleRebalanceFcn(current_weights,assetPriceTimeTable,signalDataTimeTable)

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

Второй и третий аргументы синтаксиса функции ребаланса являются скользящими окнами цен на активы и необязательными сигнальными данными. Две таблицы содержат конечные N строки расписаний активов и сигналов, которые передаются в runBacktest function, где N устанавливается с помощью LookbackWindow свойство каждой стратегии.

Если необязательные данные сигнала передаются в runBacktest функция, затем двигатель backtest передает окно качения данных сигнала каждой стратегии, которая поддерживает его.

The equalWeight стратегия просто одинаково инвестирует во все активы.

function new_weights = equalWeight(current_weights,assetPrices) %#ok<INUSD> 

% Invest equally across all assets.
num_assets = numel(current_weights);
new_weights = ones(1,num_assets) / num_assets;

end

The chaseReturns стратегия инвестирует только в верхние акции X на основе их скользящих возвратов в интерполяционном окне. Эта наивная стратегия используется просто как иллюстративный пример.

function new_weights = chaseReturns(current_weights,assetPrices) 

% Set number of stocks to invest in.
numStocks = 15;

% Compute rolling returns from lookback window.
rollingReturns = assetPrices{end,:} ./ assetPrices{1,:};

% Select the X best performing stocks over the lookback window
[~,idx] = sort(rollingReturns,'descend');
bestStocksIndex = idx(1:numStocks);

% Initialize new weights to all zeros.
new_weights = zeros(size(current_weights));

% Invest equally across the top performing stocks.
new_weights(bestStocksIndex) = 1;
new_weights = new_weights / sum(new_weights);

end
Введенный в R2020b