Last active
April 3, 2020 18:26
-
-
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.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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