Created
April 26, 2015 15:50
-
-
Save kireal/7aade9c9cf8ad808b70a to your computer and use it in GitHub Desktop.
Compute maxdrawdown statistics on equity, Matlab Financial Toolbox (c)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function [MaxDD, MaxDDIndex] = maxdrawdown(Data, Format) | |
%MAXDRAWDOWN Calculate maximum drawdown for one or more price series. | |
% Given a T x N matrix of Data with T observations of N total return price series (also known as | |
% total equity), compute maximum drawdown for each series in an N vector MaxDD and identify start | |
% and end indexes of maximum drawdown period for each series in a 2 x N matrix MaxDDIndex. | |
% | |
% MaxDD = maxdrawdown(Data); | |
% MaxDD = maxdrawdown(Data, Format); | |
% [MaxDD, MaxDDIndex] = maxdrawdown(Data, Format); | |
% | |
% Inputs: | |
% Data - T x N matrix with T samples of N total equity time series with earliest data in row | |
% T(1,:) and most recent data in row T(end,:). | |
% | |
% Optional Inputs: | |
% Format - String to indicate format of data. Options are: | |
% 'return' (default) - Compute maximum drawdown as a maximum percentage drop from a peak. | |
% 'arithmetic' - Compute maximum drawdown of a Brownian motion with drift (differences of | |
% data from peak to trough). | |
% 'geometric' - Compute maximum drawdown of a geometric Brownian motion with drift | |
% (differences of log of data from peak to trough). | |
% | |
% Outputs: | |
% MaxDD - 1 x N vector with maximum drawdown for each of N time series. | |
% MaxDDIndex - 2 x N vector of latest start and earliest end indexes for each maximum drawdown | |
% period for each total equity time series, where the first row contains the start indexes | |
% and the second row contains the end indexes of each maximum drawdown period. | |
% | |
% Notes: | |
% Drawdown is the drop in total returns from the start to the end of a period. If the total | |
% equity time series is increasing over an entire period, drawdown is zero. Otherwise, it is a | |
% positive number. Maximum drawdown is an ex-ante proxy for "downside risk" that computes the | |
% largest drawdown over all intervals of time that can be formed within a specified interval | |
% of time. | |
% | |
% Maximum drawdown is sensitive to quantization error, i.e., daily and monthly data over | |
% identical time periods will usually have different values for maximum drawdown. | |
% | |
% If raw data are in return form, convert to a price series in the function call with: | |
% MaxDD = maxdrawdown(ret2tick(Data), Format); | |
% | |
% If a series never has a drawdown, the value MaxDD is 0 and MaxDDIndex has NaNs for index | |
% values. | |
% | |
% Maximum drawdown requires positive input data unless the format is 'arithmetic'. | |
% | |
% If two or more periods exist with the same maximum drawdown, the indexes | |
% for the earliest period are returned. | |
% | |
% See also emaxdrawdown | |
% Copyright 1995-2010 The MathWorks, Inc. | |
% Step 1 - check arguments | |
if nargin < 1 || isempty(Data) | |
error(message('finance:maxdrawdown:MissingInputArg')); | |
end | |
if ~isscalar(Data) && isvector(Data) && isa(Data,'double') | |
Data = Data(:); | |
[T, N] = size(Data); | |
elseif ndims(Data) == 2 && min(size(Data)) > 1 && isa(Data,'double') | |
[T, N] = size(Data); | |
else | |
error(message('finance:maxdrawdown:InvalidInputArg')); | |
end | |
if nargin < 2 || isempty(Format) | |
Format = 'return'; | |
end | |
if ~ischar(Format) || size(Format,1) ~= 1 | |
error(message('finance:maxdrawdown:InvalidFormatType')); | |
end | |
choice = find(strncmpi(Format,{'return','arithmetic','geometric'},length(Format))); | |
if isempty(choice) | |
error(message('finance:maxdrawdown:InvalidFormatValue')); | |
end | |
% Step 2 - compute maximum drawdown | |
MaxDD = zeros(1,N); | |
MaxDDIndex = ones(2,N); | |
if choice == 1 || choice == 3 | |
if any(any(Data <= 0)) | |
error(message('finance:maxdrawdown:InvalidData')); | |
end | |
end | |
if choice == 1 % 'return' format | |
MaxData = Data(1,:); | |
MaxIndex = ones(1,N); | |
for i = 1:T | |
MaxData = max(MaxData, Data(i,:)); | |
q = MaxData == Data(i,:); | |
MaxIndex(1,q) = i; | |
DD = (MaxData - Data(i,:)) ./ MaxData; | |
if any(DD > MaxDD) | |
p = DD > MaxDD; | |
MaxDD(p) = DD(p); | |
MaxDDIndex(1,p) = MaxIndex(p); | |
MaxDDIndex(2,p) = i; | |
end | |
end | |
else % 'arithmetic' or 'geometric' formats | |
if choice == 3 | |
Data = log(Data); | |
end | |
MaxData = Data(1,:); | |
MaxIndex = ones(1,N); | |
for i = 1:T | |
MaxData = max(MaxData, Data(i,:)); | |
q = MaxData == Data(i,:); | |
MaxIndex(1,q) = i; | |
DD = MaxData - Data(i,:); | |
if any(DD > MaxDD) | |
p = DD > MaxDD; | |
MaxDD(p) = DD(p); | |
MaxDDIndex(1,p) = MaxIndex(p); | |
MaxDDIndex(2,p) = i; | |
end | |
end | |
end | |
k = MaxDDIndex(1,:) == MaxDDIndex(2,:); | |
MaxDDIndex(:,k) = NaN; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment