classdef blsOptionPricer < handle
% BLSOPTIONPRICER is a utility to explore the Black-Scholes-Merton option
% pricing model
%
% BLSOPTIONPRICER provides a graphical user interface to price vanilla call
% & put options as well as straddle and butterfly option combination
% contracts. It enables you to price these conracts as well as visualize
% the price & delta surface as a function of the spot price and time to
% expiration
% Copyright 2012 MathWorks, Inc.
properties % GUI Parameters
SpotPrice = 98
StrikePrice = 98
RiskFreeRate = .07
TimeExpiry = 2
Volatility = .2 % Expressed as a fraction .2 means 20% annual volatility
% Fraction of the spot price that spans the range of visualization.
% .1 means SpotPrice*.9 to SpotPrice*1.1
VisRange = .1
% Fraction of the strike price that spans the range of butterfly
% contracts. .1 implies a butterfly spread with two short options
% at StrikePrice and a short option at StrikePrice*.9 and a short
% option at StrikePrice*1.1
ButRange = .1
end
properties % Handles to graphics objects
hFig
hEditSpot
hEditStrike
hEditRate
hEditTime
hEditVolatility
hEditVisRange
hEditButRange
hRBGType
hRBCall
hRBPut
hRBStraddle
hRBButterfly
hEditPrice
hButPrice
hButVisualize
end
methods % Constructor & Initialization methods
function obj = blsOptionPricer
% Constructor - called when the object representing the GUI is
% created. The constructor's job is to create the UI components and
% set their callbacks.
% Create UI Components
obj.createUIComponents();
% Set callbacks
obj.setCallbacks();
end
function createUIComponents(obj)
% Create all of the UI components of the graphical interface
% and populate the properties of the object
obj.hFig = figure(...
'MenuBar','none',...
'Color',[0.941176470588235 0.941176470588235 0.941176470588235],...
'Name','Option Contract Pricing & Visualization Tool',...
'NumberTitle','off',...
'Position',[232 286 402 296],...
'ToolBar','none',...
'HandleVisibility','off',...
'Tag','figure1');
h2 = uipanel(...
'Parent',obj.hFig,...
'Title','Option Parameters',...
'Tag','uipanel1',...
'Position',[0.02 0.037 0.55 0.94]);
uicontrol(...
'Parent',h2,...
'Units','normalized',...
'FontSize',10,...
'FontWeight','bold',...
'Position',[0.0805084745762711 0.842496998799516 0.508474576271186 0.0937517864288573],...
'String','Spot Price',...
'Style','text',...
'Tag','text1');
obj.hEditSpot = uicontrol(...
'Parent',h2,...
'Units','normalized',...
'BackgroundColor',[1 1 1],...
'Position',[0.610169491525424 0.849997141713828 0.317796610169492 0.0937517864288573],...
'String','98',...
'Style','edit',...
'Tag','editSpot');
uicontrol(...
'Parent',h2,...
'Units','normalized',...
'CData',[],...
'FontSize',10,...
'FontWeight','bold',...
'Position',[0.0787037037037037 0.710317460317459 0.509259259259259 0.095238095238095],...
'String','Strike Price',...
'Style','text',...
'UserData',[],...
'Tag','text2');
obj.hEditStrike = uicontrol(...
'Parent',h2,...
'Units','normalized',...
'BackgroundColor',[1 1 1],...
'Position',[0.610169491525424 0.718744640713428 0.317796610169492 0.0937517864288573],...
'String','98',...
'Style','edit',...
'Tag','editStrike');
uicontrol(...
'Parent',h2,...
'Units','normalized',...
'CData',[],...
'FontSize',10,...
'FontWeight','bold',...
'Position',[0.0805084745762711 0.579991996798719 0.508474576271186 0.0937517864288573],...
'String','Risk Free Rate',...
'Style','text',...
'UserData',[],...
'Tag','text3');
obj.hEditRate = uicontrol(...
'Parent',h2,...
'Units','normalized',...
'BackgroundColor',[1 1 1],...
'Position',[0.610169491525424 0.587492139713028 0.317796610169492 0.0937517864288573],...
'String','0.07',...
'Style','edit',...
'Tag','editRate');
uicontrol(...
'Parent',h2,...
'Units','normalized',...
'CData',[],...
'FontSize',10,...
'FontWeight','bold',...
'Position',[0.0805084745762711 0.448739495798319 0.508474576271186 0.0937517864288573],...
'String','Months to Expiry',...
'Style','text',...
'UserData',[],...
'Tag','text4');
obj.hEditTime = uicontrol(...
'Parent',h2,...
'Units','normalized',...
'BackgroundColor',[1 1 1],...
'Position',[0.610169491525424 0.456239638712628 0.317796610169492 0.0937517864288573],...
'String','2',...
'Style','edit',...
'Tag','editTime');
uicontrol(...
'Parent',h2,...
'Units','normalized',...
'CData',[],...
'FontSize',10,...
'FontWeight','bold',...
'Position',[0.0805084745762711 0.317486994797919 0.508474576271186 0.0937517864288573],...
'String','Volatility',...
'Style','text',...
'UserData',[],...
'Tag','text5');
obj.hEditVolatility = uicontrol(...
'Parent',h2,...
'Units','normalized',...
'BackgroundColor',[1 1 1],...
'Position',[0.610169491525424 0.324987137712228 0.317796610169492 0.0937517864288573],...
'String','0.20',...
'Style','edit',...
'Tag','editVolatility');
uicontrol(...
'Parent',h2,...
'Units','normalized',...
'CData',[],...
'FontSize',10,...
'FontWeight','bold',...
'Position',[0.0805084745762711 0.163734065054593 0.508474576271186 0.1312525010004],...
'String','Visualization Range',...
'Style','text',...
'UserData',[],...
'Tag','text6');
obj.hEditVisRange = uicontrol(...
'Parent',h2,...
'Units','normalized',...
'BackgroundColor',[1 1 1],...
'Position',[0.610169491525424 0.193734636711827 0.317796610169492 0.0937517864288573],...
'String','0.10',...
'Style','edit',...
'Tag','editVisRange');
uicontrol(...
'Parent',h2,...
'Units','normalized',...
'CData',[],...
'FontSize',10,...
'FontWeight','bold',...
'Position',[0.0805084745762711 0.0212313496827303 0.508474576271186 0.1312525010004],...
'String','Butterfly Range',...
'Style','text',...
'UserData',[],...
'Tag','text7');
obj.hEditButRange = uicontrol(...
'Parent',h2,...
'Units','normalized',...
'BackgroundColor',[1 1 1],...
'Position',[0.610169491525424 0.0624821357114274 0.317796610169492 0.0937517864288573],...
'String','0.10',...
'Style','edit',...
'Tag','editButRange');
h17 = uipanel(...
'Parent',obj.hFig,...
'Title','Price',...
'Tag','uipanel4',...
'UserData',[],...
'Clipping','on',...
'Position',[0.597014925373134 0.189189189189189 0.378109452736318 0.290540540540541]);
uicontrol(...
'Parent',h17,...
'Units','normalized',...
'FontSize',10,...
'FontWeight','bold',...
'Position',[0.168918918918919 0.579710144927536 0.675675675675676 0.36231884057971],...
'String','Option Value',...
'Style','text',...
'Tag','text8');
obj.hEditPrice = uicontrol(...
'Parent',h17,...
'Units','normalized',...
'BackgroundColor',[1 1 1],...
'Position',[0.168918918918919 0.130434782608696 0.675675675675676 0.36231884057971],...
'Style','edit',...
'Tag','editPrice');
obj.hRBGType = uibuttongroup(...
'Parent',obj.hFig,...
'Title','Option Type',...
'Tag','uipanel5',...
'Position',[0.597014925373134 0.510135135135135 0.378109452736318 0.466216216216216]);
obj.hRBCall = uicontrol(...
'Parent',obj.hRBGType,...
'Units','normalized',...
'FontSize',10,...
'FontWeight','bold',...
'Position',[0.0810810810810811 0.745614035087719 0.810810810810811 0.219298245614035],...
'String','Call Option',...
'Style','radiobutton',...
'Value',1,...
'Tag','rbCall');
obj.hRBPut = uicontrol(...
'Parent',obj.hRBGType,...
'Units','normalized',...
'FontSize',10,...
'FontWeight','bold',...
'Position',[0.0810810810810811 0.526315789473684 0.810810810810811 0.219298245614035],...
'String','Put Option',...
'Style','radiobutton',...
'Tag','rbPut');
obj.hRBStraddle = uicontrol(...
'Parent',obj.hRBGType,...
'Units','normalized',...
'FontSize',10,...
'FontWeight','bold',...
'Position',[0.0810810810810811 0.307017543859649 0.810810810810811 0.219298245614035],...
'String','Straddle',...
'Style','radiobutton',...
'Tag','rbStraddle');
obj.hRBButterfly = uicontrol(...
'Parent',obj.hRBGType,...
'Units','normalized',...
'FontSize',10,...
'FontWeight','bold',...
'Position',[0.0810810810810811 0.087719298245614 0.810810810810811 0.219298245614035],...
'String','Butterfly',...
'Style','radiobutton',...
'Tag','rbButterfly');
obj.hButPrice = uicontrol(...
'Parent',obj.hFig,...
'Units','normalized',...
'FontSize',10,...
'FontWeight','bold',...
'Position',[0.597014925373134 0.0472972972972973 0.181592039800995 0.10472972972973],...
'String','Price',...
'Tag','butPrice');
obj.hButVisualize = uicontrol(...
'Parent',obj.hFig,...
'Units','normalized',...
'FontSize',10,...
'FontWeight','bold',...
'Position',[0.791044776119403 0.0472972972972973 0.181592039800995 0.10472972972973],...
'String','Visualize',...
'Tag','butVisualize');
end
function setCallbacks(obj)
% Assign the callback functions for the "Price" and "Visualize"
% buttons on the GUI
set(obj.hButPrice, 'Callback', @obj.onPrice);
set(obj.hButVisualize, 'Callback', @obj.onVisualize);
end
end
methods % Callbacks
function onPrice(obj, varargin)
% This method is called when the "Price" button is pushed. It
% collects the inputs from the GUI, prices the contract and
% displays the result in the GUI
[price, strike, rate, time, vol, visRange, butRange, optionType] = getGUIInputs(obj); %#ok<ASGLU>
optionPrice = priceContract(optionType, price, strike, rate, time, vol, butRange);
set(obj.hEditPrice, 'String', num2str(optionPrice));
end
function onVisualize(obj, varargin)
% This method is called when the "Visualize" button is pushed. It
% collects the inputs from the GUI, prices the contract for a
% range of values and creates a surface plot
[price, strike, rate, time, vol, visRange, butRange, optionType] = getGUIInputs(obj);
visualizeContract(optionType, price, strike, rate, time, vol, butRange, visRange);
end
end
methods % Helper functions
function [price, strike, rate, time, vol, visRange, butRange, optionType] = getGUIInputs(obj)
% getUIInputs collects all of the inputs from the GUI and
% converts them into the appropriate numeric type. This
% function is called by onPrice & onVisualize
price = str2double(get(obj.hEditSpot, 'String'));
strike = str2double(get(obj.hEditStrike, 'String'));
rate = str2double(get(obj.hEditRate, 'String'));
time = str2double(get(obj.hEditTime, 'String')) / 12;
vol = str2double(get(obj.hEditVolatility, 'String'));
visRange = str2double(get(obj.hEditVisRange, 'String'));
butRange = str2double(get(obj.hEditButRange, 'String'));
optionType = get(get(obj.hRBGType, 'SelectedObject'), 'String');
end
end
end
% Sub functions
function optionValue = priceContract(optionType, spotPrice, strikePrice, rfRate, timeExpiry, volatility, butterflyRange)
% PRICECONTRACT prices the option contract using the Black-Scholes-Model
% for scalar or matrix input values
%
% SYNTAX: optionValue = priceContract(optionType, spotPrice, strikePrice, rfRate, timeExpiry, volatility, butterflyRange)
% Price basic options
[call, put] = priceOption(spotPrice, strikePrice, rfRate, timeExpiry, volatility);
switch lower(optionType(1:3))
case 'cal'
optionValue = call;
case 'put'
optionValue = put;
case 'str'
optionValue = call + put;
case 'but'
lowCall = priceOption(spotPrice, strikePrice * (1 - butterflyRange), rfRate, timeExpiry, volatility);
highCall = priceOption(spotPrice, strikePrice * (1 + butterflyRange), rfRate, timeExpiry, volatility);
optionValue = lowCall + highCall - 2*call;
end
end
function visualizeContract(optionType, spotPrice, strikePrice, rfRate, timeExpiry, volatility, butterflyRange, vizRange)
% VISUALIZECONTRACT prices the option contract using the Black-Scholes-Model
% & then creates a surface plot of the option value (and gradient shown as
% color) for different values of the spot price and time to expiration
%
% SYNTAX: visualizeContract(optionType, spotPrice, strikePrice, rfRate, timeExpiry, volatility, butterflyRange, vizRange)
[spotMat, timeMat] = calcrange(spotPrice, timeExpiry, vizRange);
optionValue = priceContract(optionType, spotMat, strikePrice, rfRate, timeMat, volatility, butterflyRange);
hqr = surf(spotMat, timeMat, optionValue, gradient(optionValue, diff(spotMat(1,1:2)), diff(timeMat(1:2))));
xlabel('Spot Price');
ylabel('Time to Expiry');
zlabel('Option Value');
title(optionType);
set(hqr,'FaceAlpha',.6)
set(hqr,'EdgeAlpha',.2)
set(hqr,'FaceLighting','phong')
set(hqr,'FaceColor','interp')
end
function [SpotMat, TimeMat] = calcrange(SpotPrice, TimeExpiry, VizRange)
%CALCRANGE Compute spot price and time to expiry range based on visualization
%range
%Compute a step for the spot price range which scales based on the magnitude
%of the spot price and the visualization range
SpotStep = (SpotPrice - SpotPrice * (1 - VizRange / 2)) / 10;
%Compute the range of spot prices based on the visualization range
SpotRange = SpotPrice * (1 - VizRange / 2) : ...
SpotStep : SpotPrice * ((1 + VizRange / 2));
%Compute a step for the time to expiry range which scales based on the
%magnitude of the time to expiry and the visualization range
TimeStep = (TimeExpiry) / 30;
%Compute the range of times to expiry
TimeRange = 0 : TimeStep : TimeExpiry;
%Generate matrix spot prices and times to expiry based on the size of the
%spot price and time to expiry ranges
[SpotMat, TimeMat] = meshgrid(SpotRange, TimeRange);
end