Black-Scholes Formula

MATLAB has a built-in function erf that evaluates the error function:

\textnormal{erf}(z) = \frac{2}{\sqrt{\pi}} \int_{0}^{z} e^{-s^{2}} \, ds.

A simple calculation shows that

N(x) = \frac{1}{2}\left(1+\textnormal{erf}(x/\sqrt{2})\right),

where N(\cdot) is the cumulative distribution function for the standard normal variable.

The matlab function below calculates the Black-Scholes European call price:

c(S,K,T) = SN(d_{+})-Ke^{-rT}N(d_{-})

where S is the current underlying (non-dividend paying) stock price, K is the strike price, T is the time to maturity, and

d_{\pm} = \frac{1}{\sigma \sqrt{T}} \left(\ln(S/K)+(r\pm \sigma^{2}/2)T\right).

EuCall_BS.m

function price=EuCall_BS(S, K, T, r, sigma)
% EuCall_BS(S,K,T,r,sigma) 
% calculates Black-Scholes call price (no dividends)
% S0=spot asset price
% K=strike price
% T=time to maturity
% r=risk-free rate
% sigma=volativity

d1=(log(S./K)+(r+0.5*sigma^2).*T)./(sigma*sqrt(T));
d2=d1-sigma*sqrt(T);
N1=0.5*(1+erf(d1/sqrt(2)));
N2=0.5*(1+erf(d2/sqrt(2)));

price=S.*N1-K*exp(-r.*T).*N2;

Posted in Matlab | Leave a comment

CRR American put price

The MATLAB function below calculates the American put price under CRR binomial model.

AmPut_CRR.m

function price = AmPut_CRR(S0, K, T, r, sigma, n)
% AmPut_CRR(S0, K, T, r, sigma, n)
% S0=spot price
% K = strike price
% T = time to maturity
% r = risk-free rate (per annum continuously compunded)
% sigma = volatility
% n = number of time-steps in the CRR binomial model

dt = T/n;
u = exp(sigma*sqrt(dt));
d=1/u;
p = (exp(r*dt)-d)/(u-d);
q = 1-p;
D=exp(-r*dt);
% Initialization
V = zeros(n+1,1);

% Stock price dynamics at maturity
S=S0*d.^([n:-1:0]').*u.^([0:n]');

% Option values at time T
V = max(K-S,0);

% Backward induction
for i = n:-1:1 % time index
for j = 1:i
S(j)=S(j)*u; 
V(j) = max((p*V(j+1) + q*V(j))*D, K-S(j)) ;
end
end

price = V(1);

Posted in Matlab | Leave a comment

CRR European put price

The MATLAB function below calculates the European put price under CRR binomial model. To see how the prices converge as the number of time steps increase, you can plot the graph by executing the following in the command window:

>> S0=100;K=100;T=1;r=0.1;sigma=0.3;
>> for n=1:1:100
prices(n)=EuPut_CRR(S0,K,T,r,sigma,n);
end
>> plot(prices)

EuPut_CRR.m

function price = EuPut_CRR(S0, K, T, r, sigma, n)
% EuPut_CRR(S0, K, T, r, sigma, n)
% S0=spot price
% K = strike price
% T = time to maturity
% r = risk-free rate (per annum continuously compounded)
% sigma = volatility
% n = number of time-steps in the CRR binomial model

dt = T/n;
u = exp(sigma*sqrt(dt));
d=1/u;
p = (exp(r*dt)-d)/(u-d);
q = 1-p;

% Initialization
V = zeros(n+1,1);
S(1) = S0;

% Option values at time T
V = max(K-S0*d.^([n:-1:0]').*u.^([0:n]'),0);

%Backward induction
for i = n:-1:1
for j = 1:i
V(j) = p*V(j+1) + q*V(j);
end
end
V(1) = exp(-r*T)*V(1);

price = V(1);

Posted in Matlab | Leave a comment

Forward price, delivery price and value of forward contract

Suppose time today is 0, and I enter into a contract to buy the underlying asset for K at maturity date T (I am in the long position of the contract). Recall that the payoff at maturity to my long position is S_{T}-K. Here, K is called the delivery price of the contract and must be fixed at the initiation of the contract.

  1. How should K be chosen?
  2. What is the value of my long position in the contract?
  3. What is the difference between the current forward price F_{0,T} and the delivery price K?

The answers to the above questions are related.

  • If K=F_{0,T}, then the value of my (long) position in the contract is 0. This is true by definition of the forward price; it is the delivery price such that it costs nothing (for both the buyer and the seller) to enter into the contract.
  • If K>F_{0,T}, then my payoff would be less than that in the 1st case since S_{T}-K < S_{T}-F_{0,T}. The positive difference is exactly K-F_{0,T}. Discounting it back to the present, this amount is exactly (K-F_{0,T})e^{-rT}. I should be compensated by this amount today for the lesser amount at maturity (compared to the 1st case). So I should receive (K-F_{0,T})e^{-rT} (positive cashflows) when entering into the position, so the value of this position is the negative of this amount, which is (F_{0,T}-K)e^{-rT}. This agrees with the formula in the lecture for the value of long forward contract.
  • If K<F_{0,T}, then my payoff would be more than that in the 1st case since S_{T}-K > S_{T}-F_{0,T}. The positive difference is exactly F_{0,T}-K. Discounting it back to the present, this amount is exactly (F_{0,T}-K)e^{-rT}. I should pay this amount to the seller today for the extra amount at maturity (compared to the 1st case). So I should pay (F_{0,T}-K)e^{-rT} (negative cashflows) when entering into the position, so the value of this position is the positive of this amount, which is (F_{0,T}-K)e^{-rT}. Again, this agrees with the formula in the lecture for the value of long forward contract.
Posted in MA3245 Concepts | Leave a comment

A QuantNet Guide to Financial Engineering

Nowadays, many quant jobs require at least a Master in Financial Engineering (MFE).  The following guide provides some useful information about preparing for a quant career in the financial industry.

Screen shot 2013-02-23 at AM 11.24.20

Posted in Career | Leave a comment

Stock Data — from Yahoo to Matlab

1. Save the following Matlab code as stock_data.m, say in C:\Desktop.

2. Open Matlab and change the current directory to C:\Desktop.

3. At the Matlab Command >> type

>>[hist_date, hist_high, hist_low, hist_open, hist_close, hist_vol] = stock_data(‘GOOG’);

Here, GOOG is the stock symbol for Google Inc.

4. Among others, the above will return hist_close as a (column) vector of daily closing stock prices starting from the 1st trading day of 2005 to the present day. Depending on your needs, you may wish to change the start year on Line 06 below. We can later use hist_close to analyse the continuously compounnded returns of the stock.

stock_data.m


% Script to Retrieve Historical Stock Data from Yahoo! Finance
% modified from LuminousLogic.com
function [hist_date, hist_high, hist_low, hist_open, hist_close, hist_vol] = stock_data(stock_symbol)

% Define starting year (the further back in time, the longer it takes to download)
start_year = '2005';

% Get current date
[this_year, this_month, this_day, dummy, dummy, dummy] = datevec(date);

% Build URL string
url_string = 'http://ichart.finance.yahoo.com/table.csv?';
url_string = strcat(url_string, 's=', upper(stock_symbol));
url_string = strcat(url_string, '&d=', num2str(this_month-1));
url_string = strcat(url_string, '&e=', num2str(this_day));
url_string = strcat(url_string, '&f=', num2str(this_year));
url_string = strcat(url_string, '&g=d&a=0&b=1&c=', start_year);
url_string = strcat(url_string, '&ignore.csv');

% Open a connection to the URL and retrieve data into a buffer
buffer = java.io.BufferedReader(...
         java.io.InputStreamReader(...
         openStream(...
         java.net.URL(url_string))));

% Read the first line (a header) and discard
dummy   = readLine(buffer);

% Read all remaining lines in buffer
ptr = 1;
while 1

% Read line
buff_line = char(readLine(buffer));

% Break if this is the end
if length(buff_line)<3, break; end

% Find comma delimiter locations
commas    = find(buff_line== ',');

% Extract high, low, open, close, etc. from string
DATEvar   = buff_line(1:commas(1)-1);
OPENvar   = str2num( buff_line(commas(1)+1:commas(2)-1));
HIGHvar   = str2num( buff_line(commas(2)+1:commas(3)-1));
LOWvar    = str2num( buff_line(commas(3)+1:commas(4)-1));
CLOSEvar  = str2num( buff_line(commas(4)+1:commas(5)-1));
VOLvar    = str2num( buff_line(commas(5)+1:commas(6)-1));
adj_close = str2num( buff_line(commas(6)+1:end));

% Adjust for dividends, splits, etc.
DATEtemp{ptr,1} = DATEvar;
OPENtemp(ptr,1) = OPENvar  * adj_close / CLOSEvar;
HIGHtemp(ptr,1) = HIGHvar  * adj_close / CLOSEvar;
LOWtemp (ptr,1) = LOWvar   * adj_close / CLOSEvar;
CLOSEtemp(ptr,1)= CLOSEvar * adj_close / CLOSEvar;
VOLtemp(ptr,1)  = VOLvar;

ptr = ptr + 1;
end

% Reverse to normal chronological order, so 1st entry is oldest data point
hist_date  = flipud(DATEtemp);
hist_open  = flipud(OPENtemp);
hist_high  = flipud(HIGHtemp);
hist_low   = flipud(LOWtemp);
hist_close = flipud(CLOSEtemp);
hist_vol   = flipud(VOLtemp);
Posted in Matlab | Leave a comment

Early Exercise of American Call

The time now is 0. An American call option is written on a stock which pays a known dividend D at time t_{D}, where 0< t_{D} < T, and T is the maturity date of the option.

Explain why it is not optimal to exercise the American option EXCEPT POSSIBLY at maturity date T or immediately before t_{D}.

On a side: Let t_{D}^{-} and t_{D}^{+} denote the time immediately before and after t_{D}. The interval between t_{D}^{-} and t_{D}^{+} is so small such that we can assume t_{D}-t_{D}^{-}=0 and t_{D}^{+}-t_{D}=0. Also, we will not talk about S_{t_{D}}; instead, we speak of S_{t_{D}^{-}} and S_{t_{D}^{+}}. If the dividend paid at t_{D} is D, then S_{t_{D}^{+}}=S_{t_{D}^{-}}-D.

Posted in MA3245 Extra Practice Questions | 3 Comments