Skip to content

Instantly share code, notes, and snippets.

@nairbv
Last active April 3, 2020 18:26
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save nairbv/8726970 to your computer and use it in GitHub Desktop.
Save nairbv/8726970 to your computer and use it in GitHub Desktop.
Scala script to price a call option using a binomial model. Work backwards from market price (using a solver) to find implied vol.
import scala.math
import scala.util.Random
/**
* Pricing a call option using a binomial option pricing model.
* Formulas from: http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.119.9442&rep=rep1&type=pdf
*/
val r = new Random
// the up move in the binomial model
def up(sigma:Double, rf:Double, t:Double)=
math.exp(sigma * math.sqrt(t))
// probability of an up move
def probabilityUp(rf:Double, u:Double,d:Double,t :Double) =
(math.exp( t * rf) - d)/(u-d)
// time a function and output duration
def time( f: => Unit ) {
val start = System.currentTimeMillis;
f
println("time: " + (System.currentTimeMillis - start) )
}
def call(undly:Double,
strike:Double,
toExpiry:Double,
n:Int,
sigma:Double,
rf:Double) = {
val t = toExpiry / n
val u = up(sigma,rf,t)
val d = 1/u
val p = probabilityUp(rf, u, d, t)
val cache = Array.fill[Double](n+1,n+1)(-10)
def f(i:Int,j:Int):Double = {
val result = if( cache(i)(j) != -10 ) {
cache(i)(j)
} else if( i == n )
math.max( undly * math.pow(u,j) * math.pow(d,n-j) - strike, 0d)
else {
math.max( undly * math.pow(u,j) * math.pow(d,i-j) - strike,
math.exp(-rf*t) * p * f(i+1,j+1) + (1-p)*f(i+1,j))
}
cache(i)(j)=result
result
}
f(0,0)
}
// today is jan 30 2013
// looking at Dec 20, 2014 $130 calls
// current price of spy is 179.23
// https://www.google.com/finance?q=NYSEARCA:SPY
val price = 179.23
// the 130 calls
val strike = 130
// jan 30 2013 -> dec 20 2014 is approximately 11 months to expiry
val toExpiry = 11/12.0
// 1 year treasury is .10 as of jan 30 2013.
// http://www.treasury.gov/resource-center/data-chart-center/interest-rates/Pages/TextView.aspx?data=yield
// subtracting a dividend yield of 1.87% from google finance.
val rf = 0.001 - 0.0187
// Using VIX as implied vol since this is SPY. Can use a solver to search for implied vol in:
// call(u,s,ex,n,impliedVol,rf)-marketPrice==0
// VIX = 17.29: http://finance.yahoo.com/q?s=%5EVIX
val sigma = .1729
// increase for better accuracy, decrease for performance.
val n = 100
time { println( call( price, strike, toExpiry, n, sigma, rf) ) }
// actual output:
// 49.22999999999999
// time: 19
// price of SPY 130 dec 20 2014 calls on google finance are:
// 48.15/48.81/49.25 for the last_trade/bid/ask.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment