Main Content

Price European Vanilla Call Options Using Black-Scholes Model and Different Equity Pricers

This example shows how to compare European Vanilla instrument call option prices using a BlackScholes model and different pricing methods. The pricing methods for this comparison are the Cox-Ross-Rubinstein, Leisen-Reimer, finite difference, and the Black-Scholes analytical formula.

Create ratecurve Object

Create a ratecurve object using ratecurve.

Settle = datetime(2019,01,01);
Maturity = datetime(2022,01,01);
Rate = 0.0111;
Compounding = -1;
ZeroCurve = ratecurve('zero',Settle,Maturity,Rate,'Compounding',Compounding);

Create BlackScholes Model Object

Use finmodel to create a BlackScholes model object.

Volatility = .35;
BSModel = finmodel("BlackScholes",'Volatility',Volatility);

Create Vanilla Instrument Object

Use fininstrument to create a Vanilla instrument object.

ExerciseDates = datetime(2019,09,01);
Strike = 30;
OptionType = 'call';

EuropeanCallOption = fininstrument("Vanilla",'ExerciseDate',ExerciseDates,'Strike',Strike,...
    'OptionType',OptionType,'Name',"vanilla_call_option");

Create Analytic, AssetTree, and FiniteDifference Pricer Objects

Create two scenarios for the Vanilla option. In the first scenario, the option is out of the money (OTM). In the second scenario the option is at the money (ATM).

% Define the number of levels of the tree for AssetTree pricer 
NumPeriods = 55;

Calculate Vanilla Option Price for OTM Option

Use finpricer to create an BlackScholes, AssetTree, and FiniteDifference pricer objects for the OTM option and use the ratecurve object for the 'DiscountCurve' name-value pair argument.

SpotPriceOTM = 25;

% Analytic Pricer
AnalyticPricerOTM = finpricer('Analytic', 'Model', BSModel, 'SpotPrice', SpotPriceOTM, 'DiscountCurve', ZeroCurve);
PriceBLSOTM = price(AnalyticPricerOTM, EuropeanCallOption);

% AssetTree Pricer
CRRPricerOTM = finpricer("AssetTree",'DiscountCurve',ZeroCurve,'Model',BSModel, 'SpotPrice',SpotPriceOTM, ...
                         'PricingMethod',"CoxRossRubinstein",'NumPeriods', NumPeriods, 'Maturity', ExerciseDates);
PriceCRROTM = price(CRRPricerOTM, EuropeanCallOption);


LRPricerOTM = finpricer("AssetTree",'DiscountCurve',ZeroCurve,'Model',BSModel, 'SpotPrice',SpotPriceOTM, ...
                        'PricingMethod',"LeisenReimer",'NumPeriods', NumPeriods, 'Maturity', ExerciseDates, 'Strike', Strike);
PriceLROTM = price(LRPricerOTM, EuropeanCallOption);

% FiniteDifference Pricer
FDPricerOTM = finpricer('FiniteDifference', 'Model', BSModel, 'SpotPrice', SpotPriceOTM, 'DiscountCurve', ZeroCurve);
PriceFDOTM = price(FDPricerOTM, EuropeanCallOption);

Calculate Vanilla Option Price for ATM Option

Use finpricer to create an BlackScholes, AssetTree, and FiniteDifference pricer objects for the ATM option and use the ratecurve object for the 'DiscountCurve' name-value pair argument.

SpotPriceATM = 30;

% Analytic Pricer
AnalyticPricerATM = finpricer('Analytic', 'Model', BSModel, 'SpotPrice', SpotPriceATM, 'DiscountCurve', ZeroCurve);
PriceBLSATM = price(AnalyticPricerATM, EuropeanCallOption);

% AsetTree Pricer
CRRPricerATM = finpricer("AssetTree",'DiscountCurve',ZeroCurve,'Model',BSModel, 'SpotPrice',SpotPriceATM, ...
                         'PricingMethod',"CoxRossRubinstein",'NumPeriods', NumPeriods, 'Maturity', ExerciseDates);
PriceCRRATM = price(CRRPricerATM, EuropeanCallOption);


LRPricerATM = finpricer("AssetTree",'DiscountCurve',ZeroCurve,'Model',BSModel, 'SpotPrice',SpotPriceATM, ...
                        'PricingMethod',"LeisenReimer",'NumPeriods', NumPeriods, 'Maturity', ExerciseDates, 'Strike', Strike);
PriceLRATM = price(LRPricerATM, EuropeanCallOption);

% FiniteDifference Pricer
FDPricerATM = finpricer('FiniteDifference', 'Model', BSModel, 'SpotPrice', SpotPriceATM, 'DiscountCurve', ZeroCurve);
PriceFDATM = price(FDPricerATM, EuropeanCallOption);

Vanilla Option Price Comparison When Option Is OTM

Use the displayPricesVanillaCallOption in Local Functions to compare the Vanilla call prices for OTM.

displayPricesVanillaCallOption("OTM", PriceBLSOTM, PriceCRROTM, PriceLROTM, PriceFDOTM)
Comparison of Vanilla Call Option Prices OTM:

Black-Scholes:        1.280591
Cox-Ross-Rubinstein:  1.278306
Leisen-Reimer:        1.280651
Finite-Difference:    1.280599

Vanilla Option Price Comparison When Option Is ATM

Use the displayPricesVanillaCallOption in Local Functions to compare the Vanilla call prices for ATM.

displayPricesVanillaCallOption("ATM", PriceBLSATM, PriceCRRATM, PriceLRATM, PriceFDATM)
Comparison of Vanilla Call Option Prices ATM:

Black-Scholes:        3.505323
Cox-Ross-Rubinstein:  3.520559
Leisen-Reimer:        3.505377
Finite-Difference:    3.505452

Analyze Effect of Number of Tree Levels on Price of Options When Using AssetTree Pricer

Create graphs to visualize how convergence changes as the number of steps in the binomial calculation increases for the Cox-Ross-Rubinstein and Leisen-Reimer tree models, as well as the impact on convergence to changes to the asset price.

% Define the number of time steps of the tree
NPoints = 240;

% Cox-Ross-Rubinstein
NumPeriodCRR  = 5 : 1 : NPoints;
NbStepCRR     = length(NumPeriodCRR);
PriceOTMCRR = nan(NbStepCRR, 1);
PriceATMCRR = PriceOTMCRR;

for i = 1 : NbStepCRR

    PricerCRROTM = finpricer("AssetTree",'DiscountCurve',ZeroCurve,'Model',BSModel, 'SpotPrice',SpotPriceOTM, ...
                   'PricingMethod',"CoxRossRubinstein",'NumPeriods', NumPeriodCRR(i), 'Maturity', ExerciseDates);
    PriceOTMCRR(i) = price(PricerCRROTM, EuropeanCallOption);

    PricerCRRATM = finpricer("AssetTree",'DiscountCurve',ZeroCurve,'Model',BSModel, 'SpotPrice',SpotPriceATM, ...
                   'PricingMethod',"CoxRossRubinstein",'NumPeriods', NumPeriodCRR(i), 'Maturity', ExerciseDates);
    PriceATMCRR(i) = price(PricerCRRATM, EuropeanCallOption);

end

% Leisen-Reimer
NumPeriodLR  = 5 : 2 : NPoints;
NbStepLR     = length(NumPeriodLR);
PriceOTMLR = nan(NbStepLR, 1);
PriceATMLR = PriceOTMLR;

for i = 1 : NbStepLR
    PricerLROTM = finpricer("AssetTree",'DiscountCurve',ZeroCurve,'Model',BSModel, 'SpotPrice',SpotPriceOTM, ...
                   'PricingMethod',"LeisenReimer",'NumPeriods', NumPeriodLR(i), 'Maturity', ExerciseDates, 'Strike', Strike);
    PriceOTMLR(i) = price(PricerLROTM, EuropeanCallOption);

    PricerLRATM = finpricer("AssetTree",'DiscountCurve',ZeroCurve,'Model',BSModel, 'SpotPrice',SpotPriceATM, ...
                   'PricingMethod',"LeisenReimer",'NumPeriods', NumPeriodLR(i), 'Maturity', ExerciseDates, 'Strike', Strike);
    PriceATMLR(i) = price(PricerLRATM, EuropeanCallOption);
end

First Scenario: OTM Vanilla Call Option

Plot the convergence of CRR and LR models to a Black-Scholes solution for an OTM option.

% Cox-Ross-Rubinstein
plot(NumPeriodCRR, PriceOTMCRR);
hold on;
plot(NumPeriodCRR, PriceBLSOTM*ones(NbStepCRR,1),'Color',[0 0.9 0], 'linewidth', 1.5);

% Leisen-Reimer
plot(NumPeriodLR, PriceOTMLR, 'Color',[0.9 0 0], 'linewidth', 1.5);

% Concentrate the area of interest by clipping on the Y axis at five times the
% LR price:
YLimDelta = 5*abs(PriceOTMLR(1) - PriceBLSOTM);
ax = gca;
ax.YLim = [PriceBLSOTM - YLimDelta PriceBLSOTM + YLimDelta];
ax.XLim = [5 NPoints];

% Annotate plot
titleString = sprintf('\nConvergence of CRR and LR Models to a BLS Solution (OTM)\nStrike = %d,  Asset Price = %d', Strike , SpotPriceOTM);
title(titleString)
ylabel('Option Price')
xlabel('Number of Steps')
legend('CRR', 'BLS', 'LR', 'Location', 'NorthEast')

Figure contains an axes object. The axes object with title Convergence of CRR and LR Models to a BLS Solution (OTM) Strike = 30, Asset Price = 25 contains 3 objects of type line. These objects represent CRR, BLS, LR.

Observe that the Leisen-Reimer model removes the oscillation and produces estimates close to the Black-Scholes model using only a small number of steps.

Second Scenario: ATM Vanilla Call Option

Plot the convergence of CRR and LR models to a Black-Scholes solution for an ATM option.

% Cox-Ross-Rubinstein
figure;
plot(NumPeriodCRR, PriceATMCRR);
hold on;
plot(NumPeriodCRR, PriceBLSATM*ones(NbStepCRR,1),'Color',[0 0.9 0], 'linewidth', 1.5);

% Leisen-Reimer
plot(NumPeriodLR, PriceATMLR, 'Color',[0.9 0 0], 'linewidth', 1.5);

% Concentrate the area of interest by clipping on the Y axis at five times the
% LR price:
YLimDelta = 5*abs(PriceATMLR(1) - PriceBLSATM);
ax = gca;
ax.YLim = [PriceBLSATM - YLimDelta PriceBLSATM + YLimDelta];
ax.XLim = [5 NPoints];
% Annotate plot
titleString = sprintf('\nConvergence of CRR and LR Models to a BLS Solution (ATM)\nStrike = %d,  Asset Price = %d', Strike , SpotPriceATM);
title(titleString)
ylabel('Option Price')
xlabel('Number of Steps')
legend('CRR', 'BLS', 'LR', 'Location', 'NorthEast')

Figure contains an axes object. The axes object with title Convergence of CRR and LR Models to a BLS Solution (ATM) Strike = 30, Asset Price = 30 contains 3 objects of type line. These objects represent CRR, BLS, LR.

While the CRR binomial model and the Black-Scholes model converge as the number of time steps increases, this convergence, except for the at-the-money options, is anything but smooth or uniform.

Local Functions

function displayPricesVanillaCallOption(type, PriceBLS, PriceCRR, PriceLR, PriceFD)
fprintf('Comparison of Vanilla Call Option Prices %s:\n', type);
fprintf('\n');
fprintf('Black-Scholes:        %f\n', PriceBLS);
fprintf('Cox-Ross-Rubinstein:  %f\n', PriceCRR);
fprintf('Leisen-Reimer:        %f\n', PriceLR);
fprintf('Finite-Difference:    %f\n', PriceFD);
fprintf('\n');
end

See Also

| | |

Related Examples

More About

External Websites