function index = rsindex(varargin)
%RSINDEX Relative Strength Index (RSI).
%
% Syntax: 
%
%   index = rsindex(Data)
%   index = rsindex(Data,WindowSize)
%
% Description:
%
%   RSINDEX calculates the Relative Strength Index (RSI) from the series of
%   closing stock prices. By default, RSI values are based on a 14-period window.
%
% Input Argument:
%
%   Data    - A vector, table, or timetable. For matrix input, Data is an 
%             M-by-1 vector of closing prices. Timetables and tables with M 
%             rows contain variables named 'Close' (case insensitive).
%
% Optional Input Argument:
%
%   WindowSize          - Positive integer scalar indicating the moving window
%                         size for relative strength index. The default is 14.
%
% Output Argument:
%
%   index   - Relative StrengthIndex with the same number of rows (M) and 
%             type as the input data.
%
% Note: 
%   The RS factor is calculated by dividing the average of the gains by the
%   average of the losses within a specified period.
%
%         RS = (average gains) / (average losses)
%
%   Also, the first value of RSI, RSI(1), is a NaN in order to preserve the
%   dimensions of CLOSEP.
%
% Example:   
%              load SimulatedStock.mat
%              index = rsindex(TMW)
%              index = rsindex(TMW,14)
%
%   See also NEGVOLIDX, POSVOLIDX.
%
%   Reference: Murphy, John J., Technical Analysis of the Futures Market,
%              New York Institute of Finance, 1986, pp. 295-302

%   Copyright 1995-2018 The MathWorks, Inc.

%--------------------- Parse/Validation ----------------------------------%
windowSizeValidate = @(x) validateattributes(x,{'numeric'},{'scalar','integer','positive'},'','%K Periods');
optionalValidate = {windowSizeValidate};

try
    narginchk(1,Inf);
    output = internal.finance.ftseriesInputParser(varargin,1,{'close'},{},{}, ...
        {'WindowSize'},{14},optionalValidate,0);
catch ME
    throwAsCaller(ME)
end

[data,optional,dates,datatypeFlag] = output{:};
closep   = data;
windowSize = optional.WindowSize;

% Check for data sufficiency.
numObs = length(closep);
validateattributes(windowSize,{'numeric'},{'<=',numObs,'scalar'},'','Number of periods');

%--------------------- Calculation ---------------------------------------%
% Calculate the Relative Strength index (RSI).

% Take a diff of the closing prices
priceChange = diff(closep);

% Create '+' Delta vectors and '-' Delta vectors
advances = priceChange;
declines = priceChange;

advances(priceChange < 0) = 0;
declines(priceChange >= 0) = 0;
declines = -declines;

% Calculate the RSI of the closing prices. 
% Gains/losses
totalGain = movsum(advances,[windowSize-1,0],'Endpoints','discard');
totalLoss = movsum(declines,[windowSize-1,0],'Endpoints','discard');

% Calculate RSI
rs = totalGain ./ totalLoss;
index = 100 - (100 ./ (1+rs));
index = [nan(windowSize,1);index]; % Fill up missing values.

%--------------------- Output Preparation --------------------------------%
switch datatypeFlag
    case 0 % double
        % PASS
    case 1 % table
        index = array2table(index,'VariableNames',{'RelativeStrengthIndex'});
        index.Properties.Description = ...
            ['RelativeStrengthIndex: ',varargin{1}.Properties.Description];
    case 2 % timetable
        index = array2timetable(index,'RowTimes',dates,'VariableNames',{'RelativeStrengthIndex'});
        index.Properties.Description = ...
            ['RelativeStrengthIndex: ',varargin{1}.Properties.Description];
end

end
