function oscillator = adosc(varargin)
%ADOSC  Accumulation/Distribution (A/D) Oscillator.
%
% Syntax:
%
%   oscillator = adosc(Data)
%
% Description:
%
%   ADOSC calculates the Accumulation/Distribution Oscillator from a set of
%   opening, high, low, and closing prices of a security.
%
% Input Argument:
%
%   Data    - A matrix, table, or timetable. For matrix input, Data is an
%             M-by-4 matrix of opening, high, low, and closing prices.
%             Timetables and tables with M rows contain variables named
%             'Open', 'High', 'Low', and 'Close' (case insensitive).
%
% Output Argument:
%
%   oscillator - Accumulation/Distribution oscillator with the same number of
%                rows (M) and type as the input data.
%
% Example:  
%           load SimulatedStock.mat
%           oscillator = adosc(TMW);
%
%   Reference: Kaufman, P. J., The New Commodity Trading Systems and Methods, 
%              New York: John Wiley & Sons, 1987
%   See also ADLINE, WILLAD.

%   Copyright 1995-2020 The MathWorks, Inc.

%--------------------- Parse/Validation ----------------------------------%
try
    output = internal.finance.ftseriesInputParser(varargin,4, ...
        {'open','high','low','close'},{},{},{},{},{},0);
catch ME
    throwAsCaller(ME)
end

[data, ~, dates, datatypeFlag] = output{:};
openp = data(:,1);
highp = data(:,2);
lowp = data(:,3);
closep = data(:,4);

%--------------------- Calculation ---------------------------------------%

% Calculate the Accumulation/Distribution Oscillator.
oscillator = 100 * ((highp-openp) + (closep-lowp)) ./ ...
    (2*(highp-lowp));

% Handle denominator == 0 issue
oscillator(isinf(oscillator)) = NaN;

%--------------------- Output Preparation --------------------------------%
switch datatypeFlag
    case 0 % double
        if ~isempty(dates)
            oscillator = [dates,oscillator];
        end
    case 1 % table
        oscillator = table(oscillator,'VariableNames',{'ADOscillator'});
        oscillator.Properties.Description = ...
            ['ADOscillator: ',varargin{1}.Properties.Description];
    case 2 % timetable
        oscillator = timetable(dates,oscillator,'VariableNames',{'ADOscillator'});
        oscillator.Properties.Description = ...
            ['ADOscillator: ',varargin{1}.Properties.Description];
end

end