Simple Black-Scholes model in Python and R

The stock price \(S_t\) follows a geometrical brownian motion:

\[\frac{d S_t}{S_t} = r dt + \sigma dW_t\]

The price of european call and put options with maturity \(T\) and strike \(K\) are then given by:

\[\text{Call} = S_0 \mathcal{N}(d_1) - e^{-rT} K \mathcal{N}(d_2)\]

\[\text{Put} = -S_0 \mathcal{N}(-d_1) + e^{-rT} K \mathcal{N}(-d_2)\]

where:

Python

In [49]:
from scipy.stats import norm

def BlackScholes(CallPutFlag,S,X,T,r,v):

    d1 = (log(S/X)+(r+v*v/2.)*T)/(v*sqrt(T))

    d2 = d1-v*sqrt(T)
    if CallPutFlag=='c':
        P = S*norm.cdf(d1) - X*exp(-r*T)*norm.cdf(d2)

    else:
        P = -S*norm.cdf(-d1) + X*exp(-r*T)*norm.cdf(-d2)
    return P

def ExpiryValue(CallPutFlag,S,X):
    op_type = 1 if CallPutFlag is 'c' else -1
    return max(op_type*(S-X), 0)
In [50]:
S_range = range(30, 200, 2)
P = [BlackScholes('c', float(S), 100, 1, .1, .3) for S in S_range]
Ex = [ExpiryValue('c', float(S), 100) for S in S_range]
plot(S_range, P, lw=2)
plot(S_range, Ex, 'r-', lw=2)
xlabel('Spot')
ylabel('Call Price')
title('Call Price, Strike = 100')
Out[50]:
<matplotlib.text.Text at 0xba4ab30>

R

In [51]:
%load_ext rmagic
The rmagic extension is already loaded. To reload it, use:
  %reload_ext rmagic

In [52]:
%%R
BSOption <- function(CallPutFlag, S, X, Time, r, sigma) {

    d1 <- (log(S/X)+(r+sigma^2/2)*Time)/sigma*sqrt(Time)
    d2 <- d1 - sigma * sqrt(Time)

    if(CallPutFlag == 'c') {
        P <- S*pnorm(d1) - X*exp(-r*Time)*pnorm(d2)
    } else {
        P <- -S*pnorm(-d1) + X*exp(-r*Time)*pnorm(-d2)
    }
    P
    }
ExpiryValue <- function(CallPutFlag,S,X) {
    op_type = ifelse(CallPutFlag == 'c', 1, -1)
    max(op_type*(S-X), 0)
    }
In [53]:
%%R
S_range = seq(30, 200, 2)
P = sapply(S_range, function(S) BSOption('c', S, 100, 1, .1, .3))
Ex = sapply(S_range, function(S) ExpiryValue('c', S, 100))
plot(S_range, P, type='l', col='blue', lwd=2, xlab='Spot', ylab='Call Price')
lines(S_range, Ex, col='red', lwd=2)