F# for Quantitative Finance — Save 50%
An introductory guide to utilizing F# for quantitative finance leveraging the .NET platform with this booka and ebook
In this article by Johan Astborg, author of the book F# for Quantitative Finance, you will learn about option pricing.
(for more resources related to this topic, see here.)
Introduction to options
Options come in two variants, puts and calls. The call option gives the owner of the option the right, but not the obligation, to buy the underlying asset at the strike price. The put gives the holder of the contract, the right but not the obligation to sell the underlying asset. The BlackScholes formula describes the European option, which can only be exercised on the maturity date, in contrast to for example American options. The buyer of the option pays a premium for this, to cover the risk taken from the counterpart side. Options have become very popular and they are traded on the major exchanges throughout the world, covering most assetclasses.
The theory behind options can become complex pretty quick. In this article we'll look at the basics of options and how to explore them using code written in F#.
Looking into contract specifications
Options comes in a wide number of variations, some of them will be covered briefly below. The contract specifications for options will also depend on its type. Generally there are some properties that are more or less general to all of them. The general specifications are as follows:
 Side
 Quantity
 Strike price
 Expiration date
 Settlement terms
The contract specifications, or know variables, are used then we valuate options.
European options
European options are the basic form of options that the other variants derive, American options and exotic options are some examples. We'll stick to European options in this article.
American options
American options are options that may be exercised on any trading day on or before expiry.
Exotic options
Exotic options are any of the broad category of options that may include complex financial structures and may be combinations of other instruments as well.
Learning about Wiener processes
Wiener processes are closely related to stochastic differential equations and volatility. Wiener processes or geometric Brownian motion, is defined as this:
The formula describes the change in the stock price, or underlying, with a drift, μ, and a volatility, σ, and the Wiener process, Wt. This process is used to model the prices in BlackScholes.
We'll simulate market data using a Brownian motion, or Wiener process implemented in F# as a sequence. Sequences can be infinite and only the values used are evaluated, which suites or needs. We'll implement a generator function, to generate the Wiener process as a sequence as follows:
// A normally distributed random generator let normd = new Normal(0.0, 1.0) let T = 1.0 let N = 500.0 let dt:float = T / N /// Sequences represent infinite number of elements // p > probability mean // s > scaling factor let W s = let rec loop x = seq { yield x; yield! loop (x + sqrt(dt)
*normd.Sample()*s)} loop s;;
Here we use the random function in normd.Sample(). Let's explain the parameters and the theory behind Brownian motion before looking at the implementation. The parameter T is the time used to create a discrete time increment dt. Notice that dt will assume there is 500 N:s, 500 items in the sequence, this is of course not always the case but will do fine in here. Next, we use recursion to create the sequence, where we add an increment to the previous value (x+...), where x c] xt1.
We can easily generate an arbitrary length of the sequence:
> Seq.take 50 (W 55.00);; val it : seq<float> = seq [55.0; 56.72907873; 56.96071054;
58.72850048; ...]
Here we create a sequence of length 50. Let's plot the sequence to get a better understanding about the process.
A Wiener process generated from the sequence generator above.
Next we'll look at the code to generate the graph in the figure above.
open System open System.Net open System.Windows.Forms open System.Windows.Forms.DataVisualization.Charting open Microsoft.FSharp.Control.WebExtensions open MathNet.Numerics.Distributions; // A normally distributed random generator let normd = new Normal(0.0, 1.0) // Create chart and form let chart = new Chart(Dock = DockStyle.Fill) let area = new ChartArea("Main") chart.ChartAreas.Add(area) let mainForm = new Form(Visible = true, TopMost = true, Width = 700, Height = 500) do mainForm.Text < "Wiener process in F#" mainForm.Controls.Add(chart) // Create series for stock price let wienerProcess = new Series("process") do wienerProcess.ChartType < SeriesChartType.Line do wienerProcess.BorderWidth < 2 do wienerProcess.Color < Drawing.Color.Red chart.Series.Add(wienerProcess) let random = new System.Random() let rnd() = random.NextDouble() let T = 1.0 let N = 500.0 let dt:float = T / N /// Sequences represent infinite number of elements let W s = let rec loop x = seq { yield x; yield! loop (x +/
sqrt(dt)*normd.Sample()*s)} loop s;; do (Seq.take 100 (W 55.00)) > Seq.iter (wienerProcess.Points.Add
>> ignore)
Most of the code will be familiar to you at this stage, but the interesting part is the last line, where we can simply feed a chosen number of elements from the sequence into the Seq.iter which will plot the values, elegant and efficient.
Learning the BlackScholes formula
The BlackScholes formula was developed by Fischer Black and Myron Scholes in the 1970s. The BlackScholes formula is a stochastic partial differential equation, which estimates the price an the option. The main idea behind the formula is the delta neutral portfolio. They created the theoretical delta neutral portfolio, to reduce the uncertainty involved.
This was a necessary step to be able to come to the analytical formula which we’ll cover in this section. Below is the assumptions made under BlackScholes:
 No arbitrage
 Possible to borrow money at a constant riskfree interest rate (throughout the holding of the option)
 Possible to buy, sell and short fractional amounts of underlying asset
 No transaction costs
 Price of underlying follows a Brownian Motion, constant drift and volatility
 No dividends paid from underlying security
The simplest of the two variants is the one for call options. First the stock price is scaled using the cumulative distribution function with d1 as a parameter. Then the stock price is reduced by the discounted strike price scaled by the cumulative distribution function of d2. In other words, it’s the difference between the stock price and the strike using probability scaling of each and discounting the strike price.
The formula for the put is a little more involved, but follows the same principles.
The BlackScholes formula are often separated into parts, where d1, d2 are the probability factors, describing the probability of the stock price being related to the strike price.
The parameters used in the formula above can be summarized as follows:
 N – The cumulative distribution function
 T  Time to maturity, expressed in years
 S – The stock price, or other underlying
 K – The strike price
 r – The risk free interest rate
 σ – The volatility of the underlying
Implementing BlackScholes in F#
Now that we've looked at the basics behind the BlackScholes formula, and the parameters involved, we can implement it ourselves. The cumulative distribution function is implemented here to avoid dependencies and to illustrate that it's quite simple to implement it yourself too. Below is the BlackScholes implemented in F#. It takes six arguments; the first is a callputflag that determines if it's a call or put option. The constants a1 to a5 are the Taylor series coefficients used in the approximation for the numerical implementation.
let pow x n = exp(n * log(x)) type PutCallFlag = Put  Call /// Cumulative distribution function let cnd x = let a1 = 0.31938153 let a2 = 0.356563782 let a3 = 1.781477937 let a4 = 1.821255978 let a5 = 1.330274429 let pi = 3.141592654 let l = abs(x) let k = 1.0 / (1.0 + 0.2316419 * l) let w = (1.01.0/sqrt(2.0*pi)*exp(l*l/2.0)*(a1*k+a2*k*k+a3*
(pow k 3.0)+a4*(pow k 4.0)+a5*(pow k 5.0))) if x < 0.0 then 1.0  w else w /// BlackScholes // call_put_flag: Put  Call // s: stock price // x: strike price of option // t: time to expiration in years // r: risk free interest rate // v: volatility let black_scholes call_put_flag s x t r v = let d1=(log(s / x) + (r+v*v*0.5)*t)/(v*sqrt(t)) let d2=d1v*sqrt(t) //let res = ref 0.0 match call_put_flag with  Put > x*exp(r*t)*cnd(d2)s*cnd(d1)  Call > s*cnd(d1)x*exp(r*t)*cnd(d2)
Let's use the black_scholes function using some various numbers for call and put options. Suppose we want to know the price of an option, where the underlying is a stock traded at $58.60 with an annual volatility of 30%. The risk free interest rate is, let's say, 1%. Then we can use our formula, we defined previously to get the theoretical price according the BlackScholes formula of a call option with 6 month to maturity (0.5 years):
> black_scholes Call 58.60 60.0 0.5 0.01 0.3;; val it : float = 4.465202269
And the value for the put option, just by changing the flag to the function:
> black_scholes Put 58.60 60.0 0.5 0.01 0.3;; val it : float = 5.565951021
Sometimes it's more convenient to express the time to maturity in number of days, instead of years. Let's introduce a helper function for that purpose.
/// Convert the nr of days to years let days_to_years d = (float d) / 365.25
Note the number 365.25 which includes the factor for leap years. This is not necessary in our examples, but used for correctness. We can now use this function instead, when we know the time in days.
> days_to_years 30;; val it : float = 0.08213552361
Let's use the same example above, but now with 20 days to maturity.
> black_scholes Call 58.60 60.0 (days_to_years 20) 0.01 0.3;; val it : float = 1.065115482 > black_scholes Put 58.60 60.0 (days_to_years 20) 0.01 0.3;; val it : float = 2.432270266
Using BlackScholes together with Charts
Sometimes it's useful to be able to plot the price of an option until expiration. We can use our previously defined functions and vary the time left and plot the values coming out. In this example we'll make a program that outputs the graph seen below.
Chart showing prices for call and put option as function of time
/// Plot price of option as function of time left to maturity #r "System.Windows.Forms.DataVisualization.dll" open System open System.Net open System.Windows.Forms open System.Windows.Forms.DataVisualization.Charting open Microsoft.FSharp.Control.WebExtensions /// Create chart and form let chart = new Chart(Dock = DockStyle.Fill) let area = new ChartArea("Main") chart.ChartAreas.Add(area) chart.Legends.Add(new Legend()) let mainForm = new Form(Visible = true, TopMost = true, Width = 700, Height = 500) do mainForm.Text < "Option price as a function of time" mainForm.Controls.Add(chart) /// Create series for call option price let optionPriceCall = new Series("Call option price") do optionPriceCall.ChartType < SeriesChartType.Line do optionPriceCall.BorderWidth < 2 do optionPriceCall.Color < Drawing.Color.Red chart.Series.Add(optionPriceCall) /// Create series for put option price let optionPricePut = new Series("Put option price") do optionPricePut.ChartType < SeriesChartType.Line do optionPricePut.BorderWidth < 2 do optionPricePut.Color < Drawing.Color.Blue chart.Series.Add(optionPricePut) /// Calculate and plot call option prices let opc = [for x in [(days_to_years 20)..((days_to_years 1))..0.0]
do yield black_scholes Call 58.60 60.0 x 0.01 0.3] do opc > Seq.iter (optionPriceCall.Points.Add >> ignore) /// Calculate and plot put option prices let opp = [for x in [(days_to_years 20)..((days_to_years 1))..0.0]
do yield black_scholes Put 58.60 60.0 x 0.01 0.3] do opp > Seq.iter (optionPricePut.Points.Add >> ignore)
The code is just a modified version of the code seen in the previous article, with the options parts added. We have two series in this chart, one for call options and one for put options. We also add a legend for each of the series. The last part is the calculation of the prices and the actual plotting. List comprehensions are used for compact code, and the BlackScholes formula is called for everyday until expiration, where the days are counted down by one day at each step.
It's up to you as a reader to modify the code to plot various aspects of the option, such as the option price as a function of an increase in the underlying stock price etc.
Introducing the greeks
The greeks are partial derivatives of the BlackScholes formula, with respect to a particular parameter such as time, rate, volatility or stock price. The greeks can be divided into two or more categories, with respect to the order of the derivatives. Below we'll look at the first and second order greeks.
First order greeks
In this section we'll present the first order greeks using the table below.
Name 
Symbol 
Description 
Delta 
Δ 
Rate of change of option value with respect to change in the price of the underlying asset. 
Vega 
ν 
Rate of change of option value with respect to change in the volatility of the underlying asset. Referred to as the volatility sensitivity. 
Theta 
Θ 
Rate of change of option value with respect to time. The sensitivity with respect to time will decay as time elapses, phenomenon referred to as the "time decay." 
Rho 
ρ 
Rate of change of option value with respect to the interest rate. 
Second order greeks
In this section we'll present the second order greeks using the table below.
Name 
Symbol 
Description 
Gamma 
Γ 
Rate of change of delta with respect to change in the price of the underlying asset. 
Veta 
 
Rate of change in Vega with respect to time. 
Vera 
 
Rate of change in Rho with respect to volatility. 
Some of the second order greeks are omitted for clarity, we'll not cover these in this book.
Implementing the greeks in F#
Let's implement the greeks; Delta, Gamma, Vega, Theta and Rho. First we look at the formulas for each greek. In some of the cases they vary for calls and puts respectively.
We need the derivative of the cumulative distribution function, which in fact is the normal distribution with zero mean and standard deviation of one:
/// Normal distribution open MathNet.Numerics.Distributions; let normd = new Normal(0.0, 1.0)
Delta
Delta is the rate of change of option price with respect to change in the price of the underlying asset.
/// BlackScholes Delta // call_put_flag: Put  Call // s: stock price // x: strike price of option // t: time to expiration in years // r: risk free interest rate // v: volatility let black_scholes_delta call_put_flag s x t r v = let d1=(log(s / x) + (r+v*v*0.5)*t)/(v*sqrt(t)) match call_put_flag with  Put > cnd(d1)  1.0  Call > cnd(d1)
Gamma
Gamma is the rate of change of delta with respect to change in the price of the underlying asset. This is the 2^{nd} derivative, with respect to price of the underlying asset. It measures the acceleration of the price of the option with respect to the underlying price.
/// BlackScholes Gamma // s: stock price // x: strike price of option // t: time to expiration in years // r: risk free interest rate // v: volatility let black_scholes_gamma s x t r v = let d1=(log(s / x) + (r+v*v*0.5)*t)/(v*sqrt(t)) normd.Density(d1) / (s*v*sqrt(t)
Vega
Vega is the rate of change of option value with respect to change in the volatility of the underlying asset. It is referred to as the volatility sensitivity.
/// BlackScholes Vega // s: stock price // x: strike price of option // t: time to expiration in years // r: risk free interest rate // v: volatility let black_scholes_vega s x t r v = let d1=(log(s / x) + (r+v*v*0.5)*t)/(v*sqrt(t)) s*normd.Density(d1)*sqrt(t)
Theta
Theta is the rate of change of option value with respect to time. The sensitivity with respect to time will decay as time elapses, phenomenon referred to as the “time decay.”
/// BlackScholes Theta // call_put_flag: Put  Call // s: stock price // x: strike price of option // t: time to expiration in years // r: risk free interest rate // v: volatility let black_scholes_theta call_put_flag s x t r v = let d1=(log(s / x) + (r+v*v*0.5)*t)/(v*sqrt(t)) let d2=d1v*sqrt(t) let res = ref 0.0 match call_put_flag with  Put > (s*normd.Density(d1)*v)/(2.0*sqrt(t))+r*x*exp(r*t)*cnd(d2)  Call > (s*normd.Density(d1)*v)/(2.0*sqrt(t))r*x*exp(r*t)*cnd(d2)
Rho
Rho is rate of change of option value with respect to the interest rate.
/// BlackScholes Rho // call_put_flag: Put  Call // s: stock price // x: strike price of option // t: time to expiration in years // r: risk free interest rate // v: volatility let black_scholes_rho call_put_flag s x t r v = let d1=(log(s / x) + (r+v*v*0.5)*t)/(v*sqrt(t)) let d2=d1v*sqrt(t) let res = ref 0.0 match call_put_flag with  Put > x*t*exp(r*t)*cnd(d2)  Call > x*t*exp(r*t)*cnd(d2)
Investigating the sensitivity of the of the greeks
Now that we have all the greeks implemented we'll investigate the sensitivity of some of them and see how they vary when the underlying stock price changes.
The figure below is a surface plot with four of the greeks where time and underlying price is changing. The figure below is generated in MATLAB, and will not be generated in F#. We’ll use a 2D version of the graph to study the greeks below.
Surface plot of Delta, Gamma, Theta and Rho of a call option.
In this section we'll start by plotting the value of Delta for a call option where we vary the price of the underlying. This will result in the following 2D plot:
A plot of call option delta versus price of underlying
The result in the plot seen in figure above will be generated by the code presented next. We'll reuse most of the code from the example where we looked at the option prices for calls and puts. A slightly modified version is presented here, where the price of the underlying varies from $10.0 to $70.0.
/// Plot delta of call option as function of underlying price #r "System.Windows.Forms.DataVisualization.dll" open System open System.Net open System.Windows.Forms open System.Windows.Forms.DataVisualization.Charting open Microsoft.FSharp.Control.WebExtensions /// Create chart and form let chart = new Chart(Dock = DockStyle.Fill) let area = new ChartArea("Main") chart.ChartAreas.Add(area) chart.Legends.Add(new Legend()) let mainForm = new Form(Visible = true, TopMost = true, Width = 700, Height = 500) do mainForm.Text < "Option delta as a function of underlying price" mainForm.Controls.Add(chart) /// Create series for call option delta let optionDeltaCall = new Series("Call option delta") do optionDeltaCall.ChartType < SeriesChartType.Line do optionDeltaCall.BorderWidth < 2 do optionDeltaCall.Color < Drawing.Color.Red chart.Series.Add(optionDeltaCall) /// Calculate and plot call delta let opc = [for x in [10.0..1.0..70.0] do yield black_scholes_delta Call
x 60.0 0.5 0.01 0.3] do opc > Seq.iter (optionDeltaCall.Points.Add >> ignore)
We can extend the code to plot all four greeks, as in the figure with the surface plots, but here in 2D. The result will be a graph like seen in the figure below.
Graph showing the for Greeks for a call option with respect to price change (xaxis).
Code listing for visualizing the four greeks
Below is the code listing for the entire program used to create the graph above.
#r "System.Windows.Forms.DataVisualization.dll" open System open System.Net open System.Windows.Forms open System.Windows.Forms.DataVisualization.Charting open Microsoft.FSharp.Control.WebExtensions /// Create chart and form let chart = new Chart(Dock = DockStyle.Fill) let area = new ChartArea("Main") chart.ChartAreas.Add(area) chart.Legends.Add(new Legend()) let mainForm = new Form(Visible = true, TopMost = true, Width = 700, Height = 500) do mainForm.Text < "Option delta as a function of underlying price" mainForm.Controls.Add(chart)
We’ll create one series for each greek:
/// Create series for call option delta let optionDeltaCall = new Series("Call option delta") do optionDeltaCall.ChartType < SeriesChartType.Line do optionDeltaCall.BorderWidth < 2 do optionDeltaCall.Color < Drawing.Color.Red chart.Series.Add(optionDeltaCall) /// Create series for call option gamma let optionGammaCall = new Series("Call option gamma") do optionGammaCall.ChartType < SeriesChartType.Line do optionGammaCall.BorderWidth < 2 do optionGammaCall.Color < Drawing.Color.Blue chart.Series.Add(optionGammaCall) /// Create series for call option theta let optionThetaCall = new Series("Call option theta") do optionThetaCall.ChartType < SeriesChartType.Line do optionThetaCall.BorderWidth < 2 do optionThetaCall.Color < Drawing.Color.Green chart.Series.Add(optionThetaCall) /// Create series for call option vega let optionVegaCall = new Series("Call option vega") do optionVegaCall.ChartType < SeriesChartType.Line do optionVegaCall.BorderWidth < 2 do optionVegaCall.Color < Drawing.Color.Purple chart.Series.Add(optionVegaCall)
Next, we’ll calculate the values to plot for each greek:
/// Calculate and plot call delta let opd = [for x in [10.0..1.0..70.0] do yield black_scholes_delta
Call x 60.0 0.5 0.01 0.3] do opd > Seq.iter (optionDeltaCall.Points.Add >> ignore) /// Calculate and plot call gamma let opg = [for x in [10.0..1.0..70.0] do yield black_scholes_gamma
x 60.0 0.5 0.01 0.3] do opg > Seq.iter (optionGammaCall.Points.Add >> ignore) /// Calculate and plot call theta let opt = [for x in [10.0..1.0..70.0] do yield black_scholes_theta
Call x 60.0 0.5 0.01 0.3] do opt > Seq.iter (optionThetaCall.Points.Add >> ignore) /// Calculate and plot call vega let opv = [for x in [10.0..1.0..70.0] do yield black_scholes_vega
x 60.0 0.1 0.01 0.3] do opv > Seq.iter (optionVegaCall.Points.Add >> ignore)
Summary
In this article, we looked into using F# for investigating different aspects of volatility. Volatility is an interesting dimension of finance where you quickly dive into complex theories and models. Here it's very much helpful to have a powerful tool such as F# and F# Interactive. We've just scratched the surface of options and volatility in this article. There is a lot more to cover, but that's outside the scope of this book. Most of the content here will be used in the trading system.
resources for article:
further resources on this subject:
 Working with Windows Phone Controls [article]
 Simplifying Parallelism Complexity in C# [article]
 Watching Multiple Threads in C# [article]
An introductory guide to utilizing F# for quantitative finance leveraging the .NET platform with this booka and ebook 
About the Author :
Johan Astborg
Johan Astborg is the developer and architect of various kinds of software systems and applications, financial software systems, trading systems, as well as mobile and web applications. He is interested in computer science, mathematics, and quantitative finance, with a special focus on functional programming. Johan is passionate about languages such as F#, Clojure, and Haskell, and operating systems such as Linux, Mac OS X, and Windows for his work. Most of Johan's quantitative background comes from Lund University, where he studied courses in computer science, mathematics, and physics. Currently Johan is studying pure mathematics at Lund University, Sweden, and is aiming for a PhD in the future, combining mathematics and functional programming. Professionally, Johan has worked as a parttime developer for Sony Ericsson and various smaller firms in Sweden. He also works as a parttime consultant focusing on web technologies and cloud solutions. You can easily contact him by sending an email to joastbg@gmail.com or visit his GitHub page at https://github.com/joastbg.
Books From Packt
