function varargout = supersharesensbybls(RateSpec, StockSpec, Settle, Maturity, StrikeLow, StrikeHigh, varargin)
% SUPERSENSBYBLS Calculate supershare digital option prices and 
%                sensitivities using the Black-Scholes option pricing model.
%
% PriceSens = supersharesensbybls(RateSpec, StockSpec, Settle, Maturity, StrikeLow,...
%                            StrikeHigh)
%
% PriceSens = supersharesensbybls(RateSpec, StockSpec, Settle, Maturity, StrikeLow,...
%                            StrikeHigh, 'Name1', Value1)
%
% Inputs:
%   RateSpec        - The annualized continuously compounded rate term 
%                     structure. Type "help intenvset" for information
%                     on the interest rate specification.
%   StockSpec       - Stock specification. Type "help stockspec" for 
%                     information on the stock specification. 
%   Settle          - NINST x 1 Settlement date. 
%   Maturity        - NINST x 1 Maturity date.
%   StrikeLow       - NINST x 1 vector of low strike price values.
%   StrikeHigh      - NINST x 1 vector of high strike price values.
%
%
% Optional Inputs:
%   All optional inputs are specified as matching parameter name/value pairs.
%   The parameter name is specified as a character string, followed by the 
%   corresponding parameter value. Parameter name/value pairs may be specified
%   in any order; names are case-insensitive and partial string matches are 
%   allowed provided no ambiguities exist. Valid parameter names are as follows:
%
%   OutSpec         - NOUT x 1 or 1 x NOUT cell array of strings indicating  
%                     the nature and order of the outputs for the function.
%                     Possible values are 'Price', 'Delta', 'Gamma', 'Vega',
%                     'Lambda', 'Rho', 'Theta' and 'All'.
%
%                     For example: OutSpec = {'Price'; 'Lambda'; 'Rho'} 
%                     specifies that the output should be Price, Lambda and 
%                     Rho, in that order. 
%
%                     Function invocation would be:
%                     [Price, Lambda, Rho] = supersharesensbybls(...,
%                                     'OutSpec', {'Price', 'Lambda', 'Rho'})
%
%                     Default is OutSpec = {'Price'}.
%
%                     OutSpec = {'All'} specifies that the output should be
%                     Delta, Gamma, Vega, Lambda, Rho, Theta and Price, in 
%                     that order. This is the same as specifying OutSpec as 
%                     follows: 
%                     
%                     OutSpec = {'delta', 'gamma', 'vega', 'lambda', 'rho',...
%                                'theta', 'price'};
%
% Outputs:
%   PriceSens     - NINST x 1 expected prices or sensitivities values.
%
% Note: The model used to price the supershare digital option is a 
%       variation of the Black-Scholes model. 
%
% See also INTENVSET, STOCKSPEC, SUPERSHAREBYBLS.

%   Copyright 1998-2008 The MathWorks, Inc.

%---------------------------------------------------
% Input argument checking & default assignment
%---------------------------------------------------

if nargin < 6
    error(message('fininst:supersharesensbybls:InsufficientInputs'))
end

if(any(~isnumeric(StrikeLow(:)))) 
     error(message('fininst:supersharesensbybls:InvalidStrikeLow')); 
end

if(any(~isnumeric(StrikeHigh(:)))) 
     error(message('fininst:supersharesensbybls:InvalidStrikeHigh')); 
end

if(~isafin(RateSpec, 'RateSpec'))
    error(message('fininst:supersharesensbybls:InvalidRateSpec'));
end

if(~isafin(StockSpec, 'StockSpec'))
    error(message('fininst:supersharesensbybls:InvalidStockSpec'));
end

Settle  = datenum(Settle);
Maturity = datenum(Maturity);


% Get OutSpec from NVPs
OutSpec = parsepvpairs({'OutSpec'}, {{'Price'}}, varargin{:});

if(~ischar(OutSpec) && ~iscell(OutSpec))
    error(message('fininst:supersharesensbybls:InvalidOutSpec'));  
end

if(ischar(OutSpec))
    OutSpec = cellstr(OutSpec);
end
    
% Verify that the cell array is only strings
if(~all(cellfun(@ischar, OutSpec)))
     error(message('fininst:supersharesensbybls:InvalidOutSpec'));  
end

OutSpec = lower(OutSpec);

% Verify that there are either no dividends, or only continuous dividends
% are specified:
DivType = StockSpec.DividendType;
if(~isempty(DivType))
    divMask = ~cellfun(@isempty, DivType);
    if(any(~strcmpi(DivType(divMask), 'continuous')))
        error(message('fininst:supersharesensbybls:InvalidDivType'));
    end
end

% Extract div amounts
Div = zeros(size(StockSpec.AssetPrice));
if(~isempty(DivType))
    Div(divMask) = StockSpec.DividendAmounts(divMask);
end

% Do dimension expansion to make sure all sizes are appropriate:
Vol   = StockSpec.Sigma;
So    = StockSpec.AssetPrice;

% Inputs should have consistent sizes
Settle = Settle(:);
So = So(:);
Div = Div(:);
Vol = Vol(:);
Maturity = Maturity(:);
StrikeLow = StrikeLow(:);
StrikeHigh = StrikeHigh(:);

try
    [Settle, Maturity, So, Div, Vol, StrikeLow, StrikeHigh] = ...
        finargsz(1, Settle, Maturity, So, Div, Vol, StrikeLow, StrikeHigh);
catch ME   
        error(message('fininst:supersharesensbybls:InconsistentSizes'));
end


if (any(StrikeLow < 0 | StrikeHigh < 0))
    error(message('fininst:supersharesensbybls:NegativeStrikes'));
end

if(any(StrikeLow>StrikeHigh))
    error(message('fininst:supersharesensbybls:InvalidInputs'));
end

if(any(Settle >= Maturity))
    error(message('fininst:supersharesensbybls:InvalidDates'));
end

% Get the risk-free rate between settle and mat - make sure it's continuously compounded:
RS  = intenvset(RateSpec, 'Compounding', -1);
RS2 = intenvset(RS, 'ValuationDate', min(Settle), 'StartDates', Settle, 'EndDates', Maturity);
MaturityTime = intenvget(RS2, 'EndTimes') - intenvget(RS2, 'StartTimes');
RiskFreeRates   = intenvget(RS2, 'Rates');

varargout = binoptpriceeng(OutSpec, @getsuperprice, RiskFreeRates, So, Div, Vol, MaturityTime, StrikeLow, StrikeHigh);



%==========================================================================
%    Supershare Options
%==========================================================================
function [Price, So] = getsuperprice(RiskFreeRates, So, Div, Vol, MaturityTime, StrikeLow, StrikeHigh )


% calculate intermediate params:
b = RiskFreeRates - Div;
VolT = Vol .* sqrt(MaturityTime);
VolB = (b + (Vol .^ 2) ./ 2) .* MaturityTime;
d1 = (log(So ./ StrikeLow) + VolB) ./ VolT;
d2 = (log(So ./ StrikeHigh) + VolB) ./ VolT;

Price = (So .* exp((b-RiskFreeRates) .* MaturityTime) ./ StrikeLow) .* ...
    (normcdf(d1) - normcdf(d2));






