%% Backtest Strategy Using backtestEngine
% Use a backtesting engine in MATLAB® to run a backtest on an investment strategy over a time series of market data. You can define a backtesting engine by using backtestEngine object. A backtestEngine object sets properties of the backtesting environment, such as the risk-free rate, and holds the results of the backtest. In this example, you can create a backtesting engine to run a simple backtest and examine the results.
%
%% Create Strategy
% Define an investment strategy by using the backtestStrategy function. This example builds a simple equal-weighted investment strategy that invests equally across all assets. For more information on creating backtest strategies, see backtestStrategy.

% The rebalance function is simple enough that you can use an anonymous function
equalWeightRebalanceFcn = @(current_weights,~) ones(size(current_weights)) / numel(current_weights);

% Create the strategy
strategy = backtestStrategy("EqualWeighted",equalWeightRebalanceFcn,...
    'RebalanceFrequency',20,...
    'TransactionCosts',[0.0025 0.005],...
    'LookbackWindow',0)

%
%% Set Backtesting Engine Properties
% The backtesting engine has several properties that you set by using parameters to the backtestEngine function.
%% Risk-Free Rate
% The RiskFreeRate property holds the interest rate earned for uninvested capital (that is, cash). When the sum of portfolio weights is below 1, the remaining capital is invested in cash and earns the risk-free rate. The risk-free rate is defined as the "per-time-step" rate, meaning that it is the interest rate that cash earns for each step of the backtest, not the annualized rate. For this example, you run the backtest using daily data and the risk-free interest rate is 2% annualized, so set the RiskFreeRate property to 0.02 / 252 to approximate the daily interest rate.

% Approximate a 2% annualized risk-free rate for daily backtest data
riskFreeRate = 0.02 / 252;

%% Cash Borrow Rate
% The CashBorrowRate property sets the interest accrual rate applied to negative cash balances. If at any time the portfolio weights sum to a value greater than 1, then the cash position is negative by the amount in excess of 1. This behavior of portfolio weights is analogous to borrowing capital on margin to invest with leverage. Like the RiskFreeRate property, the CashBorrowRate property is defined as the per-time-step rate, you must provide the annualized rate divided by the number of time steps per year.

% Approximate a 6% annualized margin interest rate for daily backtest data
cashBorrowRate = 0.06 / 252;

%% Initial Portfolio Value
% The InitialPortfolioValue property sets the value of the portfolio at the start of the backtest for all strategies. The default is $10,000.

% Start backtest with $1M
initPortfolioValue = 1000000;

%
%% Create Backtest Engine
% Using the prepared properties, create the backtesting engine using the backtestEngine function.

% The backtesting engine takes an array of backtestStrategy objects as the first argument
backtester = backtestEngine(strategy,...
    'RiskFreeRate',riskFreeRate,...
    'CashBorrowRate',cashBorrowRate,...
    'InitialPortfolioValue',initPortfolioValue)

% Several additional properties of the backtesting engine are initialized to empty. The backtesting engine populates these properties, which contain the results of the backtest, upon completion of the backtest.
%
%% Load Data and Run Backtest
% Run the backtest over daily price data from the 30 component stocks of the DJIA.

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

% Remove the DJI index column and convert to timetable
pricesTT = table2timetable(T(:,[1 3:end]),'RowTimes','Dates');

% Run the backtest using the runBacktest function.

backtester = runBacktest(backtester,pricesTT)

%
%% Examine Results
% The backtesting engine populates the read-only properties of the backtestEngine object with the backtest results. Daily values for portfolio returns, asset positions, turnover, and transaction costs are available to examine.

% Generate a histogram of daily portfolio returns
histogram(backtester.Returns{:,1})
title('Daily Portfolio Returns')

% Copyright 2020 The MathWorks, Inc.