Skip to content

Instantly share code, notes, and snippets.

@kireal
Created April 26, 2015 15:50
Show Gist options
  • Save kireal/7aade9c9cf8ad808b70a to your computer and use it in GitHub Desktop.
Save kireal/7aade9c9cf8ad808b70a to your computer and use it in GitHub Desktop.
Compute maxdrawdown statistics on equity, Matlab Financial Toolbox (c)
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