Published on June 15 , 2016

The Binomial Options Pricing Model (BOPM) is a generalized numerical method used to value options in the quantitative financial services industry. Specifically, it is a lattice-based approach that uses a discrete-time model of the varying price over time of the underlying financial instrument. For historical reasons, it’s also known as a tree model because it has a root and leaf-nodes. In this paper, we continue to follow tree-analogy convention knowing that it is more truly a lattice approach.

Binomial option pricing is a simple but powerful technique that can be used to solve many complex option-pricing problems. The binomial model was first proposed by Cox, Ross, and Rubenstein in 1979^{1}. The name was derived from the construction of a binomial tree that models different possible paths that might be followed by the underlying asset price over the time span of the option.

This article presents the Binomial Option Pricing Code to provide a representative way of pricing derivatives using lattice methods.

Binomial Option Pricing Code is maintained by Shuo Li and is available under the BSD 3-Clause Licensing Agreement. The code supports the asynchronous offload of the Intel® Xeon® processor (referred to as “host” in this document) with the Intel® Xeon Phi™ processor in a single node environment.

To get access to the code and test workloads, download the Binomial.tar file.

Here are the steps you need to follow in order to rebuild the program:

- Install Intel® Parallel Studio XE 2015 SP3 in your system
- Source the environment variable script file compilervars.sh under /pkg_bin
- Untar the binomial.tar and type
`make`

to build the executables files

You should expect to see binomial.knl and binomial.bdw - Make sure the host machine is powered by Intel Xeon Phi processors
`[sli@ortce-knl7 ~]$ lscpu Architecture: x86_64 CPU op-mode(s): 32-bit, 64-bit Byte Order: Little Endian CPU(s): 272 On-line CPU(s) list: 0-271 Thread(s) per core: 4 Core(s) per socket: 68 Socket(s): 1 NUMA node(s): 8 Vendor ID: GenuineIntel CPU family: 6 Model: 87 Model name: Intel(R) Xeon Phi(TM) CPU 7250 @ 1.40GHz Stepping: 1 CPU MHz: 1400.273 BogoMIPS: 2793.61 Virtualization: VT-x L1d cache: 32K L1i cache: 32K L2 cache: 1024K NUMA node0 CPU(s): 5,6,11,12,17,18,23-25,73-86,135-148,197-210,259-271 NUMA node1 CPU(s): 1,2,7,8,13,14,19,20,43-58,105-120,167-182,229-244 NUMA node2 CPU(s): 3,4,9,10,15,16,21,22,59-72,121-134,183-196,245-258 NUMA node3 CPU(s): 0,26-42,87-104,149-166,211-228For Double Precision processing: BlackScholesDP.kn`

- Run binomial.knl

At the prompt, enter:

`./binomial.knl [verbose] [precision]`

Values:

`verbose`

`0: turn off workload feedback and result validation (default)`

`1: turn on workload feedback and result validation`

`precision`

`0: single precision (default)`

`1: double precision`

```
[command prompt]$ ./binomial
[sli@ortce-knl8 clean]$ ./binomial.knl
Binomial Single Precision.
Compiler Version = 16
Release Update = 3
Build Time = May 27 2016 16:08:12
Input Dataset = 557056
Binomial Option Pricing in single precision:
Pricing 557056 Option with time step of 2048.
```

```
Binomial Option Pricing using Pragma SIMD Vectorization.
Completed in 2.39326 seconds. Options per second: 232760.03965
[sli@ortce-knl8 clean]$ ./binomial.knl 0 1
Binomial Single Precision.
Compiler Version = 16
Release Update = 3
Build Time = May 27 2016 16:08:12
Input Dataset = 557056
Binomial Option Pricing in double precision:
Pricing 557056 Option with time step of 2048.
```

```
Binomial Option Pricing using Pragma SIMD Vectorization.
Completed in 6.84975 seconds. Options per second: 81325.03577
TEST PASSED
```

The program created and priced 36,600,000 sets of option data. The program was vectorized and parallelized to run on both the Intel Xeon processors and Intel Xeon Phi processor. The products involved are Intel E2697V2 at 2.7 Ghz and Intel Xeon Phi processor 7120P. Intel® Parallel Studio XE 2013 SP1 is used to build the final executable program.

This program calculates the European call option price for each input data set. This benchmark runs on single node with or without an Intel Xeon Phi processor. It can also be modified to run in a cluster environment. The program reports a latency measure in seconds spent in pricing activities and also a throughput measure using 36.6 million options. Verbose mode provides additional information and also validates the results using a Black-Scholes-Merton^{2} formula.

Binomial option pricing is a simple but powerful technique used to solve complex option-pricing problems. Unlike the Black-Scholes-Merton and other complex option pricing models, it does not require solutions to stochastic differential equations; the binomial option-pricing model is mathematically trivial. Anyone with a good understanding of the time value of money and risk-neutral valuation should be able to understand the binomial model.

Figure 1.

Consider a stock with the initial value of **S _{0}** and an option

Let’s suppose that when the stock price moves to **S _{0}u**, the payoff from option is

**S _{0}u Δ -f_{u} = S_{0}d Δ –f_{d}**

Therefore:

The risk-neutral argument also dictates that all portfolios shall earn the risk-free interest rate. Since we know the risk-free interest * r*, the current value of the portfolio when the stock goes up can be written as follows:

*S _{0}u* –

This must equal the cost of setting up the portfolio:

*S _{0}Δ - f = (S_{0}u –f_{u})e^{-rT}*

Thus:

*f = S _{0}Δ - (S_{0}u –f_{u})e-^{rT}*

Since we know **Δ**, we can further reduce this equation as follows:

*f = e ^{-rT }[pf_{u} + (1-p)f_{d} ]*

where

With the last two equations, we can naturally interpret the variable * p* as the probability of an upward movement in the underlying stock price. Thus,

The last challenge in creating a binomial option-pricing algorithm is to integrate the stock price movement process into the binomial tree parameters * u* and

These values not only match the volatility with the up and down movement of stock price but also make the binomial tree recombinant in the sense that the nodes that represent a stock moving up then down and the stock price moving down then up, will be merged or recombined as a single node. This property also spares us from the elaborated process to propagate the internal node values to the leaf nodes; instead it gives a closed-end formula for each leaf node.

Now we can easily extend the one-step binomial tree into a two-step binomial tree, three-step binomial tree, and N-step binomial tree. The previous picture shows a perfectly balanced N-step binomial tree, where each initial node has exactly two child nodes representing an upward movement and a downward movement of the stock price, respectively.

The probability of an upward movement is * p* and the probability of downward movement is

Binomial option pricing can be conceptually described as a three-step process:

- Binomial tree representation and generation
- Calculation of option values at the leaf nodes
- Backward inductive calculation of option value at internal nodes; the value at the root node is the current price of the option

The next step is to determine a data structure that can represent all the tree nodes. Since the binomial tree model involves calculations on adjacent levels, the minimum data structure required is the one that holds all the node values in one level, including the leaf nodes level, which has the number of nodes equal to the number of time steps **+1**. Depending on the application precision requirement, we can choose a one-dimensional, single-precision, floating-point array to accomplish this purpose.

`static float Call[NUM_STEPS+1];`

The following code gives the implementation of Binomial Tree European Option Pricing in C/C++.

```
#include <mathimf.h>
#include <omp.h>
#include <stdio.h>
#define NUM_STEPS 2048
#define OPT_N 18300000
const float RISKFREE = 0.06f;
const float VOLATILITY = 0.10f;
__forceinline
float Exp( float x)
{
return expf( x);
}
__forceinline
double Exp( double x)
{
return exp( x);
}
__forceinline
float Sqrt( float x)
{
return sqrtf( x);
}
__forceinline
double Sqrt( double x)
{
return sqrt( x);
}
template <class Basetype>
void BinomialTemplate(
Basetype *CallResult,
Basetype *S,
Basetype *X,
Basetype *T)
{
#pragma omp parallel for
for(int opt = 0; opt < OPT_N; opt++)
{
__attribute__((align(4096)))Basetype Call[NUM_STEPS + 1];
const Basetype Sx = S[opt];
const Basetype Xx = X[opt];
const Basetype Tx = T[opt];
const Basetype dt = Tx / static_cast<Basetype>(NUM_STEPS);
const Basetype vDt = VOLATILITY * Sqrt(dt);
const Basetype rDt = RISKFREE * dt;
const Basetype If = Exp(rDt);
const Basetype Df = Exp(-rDt);
const Basetype u = Exp(vDt);
const Basetype d = Exp(-vDt);
const Basetype pu = (If - d) / (u - d);
const Basetype pd = 1.0f - pu;
const Basetype puByDf = pu * Df;
const Basetype pdByDf = pd * Df;
#pragma simd
for(int i = 0; i <= NUM_STEPS; i++)
{
Basetype d = Sx * Exp(vDt * (2.0 * i - NUM_STEPS)) - Xx;
Call[i] = (d > 0) ? d : 0;
}
for(int i = NUM_STEPS; i > 0; i--)
#pragma simd
#pragma unroll(4)
for(int j = 0; j <= i - 1; j++)
Call[j] = puByDf * Call[j + 1] + pdByDf * Call[j];
CallResult[opt] = (Basetype)Call[0];
}
}
```

Shuo Li works at Software and Services Group at Intel Corporation. His main interest is parallel programming, and application software performance. In his role as a software performance engineer covering financial service industry, Shuo works closely with software developers and modelers and help them achieve best possible performance with their software solutions.

Shuo holds a Master's degree in Computer Science from the University of Oregon and an MBA degree from Duke University.

1 Cox, John C., Ross, Stephen A., and Rubenstein, Mark. *Option Pricing: A Simplified Approach* (1979).

2 Black, Fischer, and Scholes, Myron. *The Pricing of Options and Corporate Liabilities* (May-Jun 1973).

3 Hull, John C, *Options, Futures, and other Derivatives,10 ^{th} Edition* Prentice-Hull, 2014

4 Intel Xeon processor: http://www.intel.com/content/www/us/en/processors/xeon/xeon-processor-e7-family.html

Intel's compilers may or may not optimize to the same degree for non-Intel microprocessors for optimizations that are not unique to Intel microprocessors. These optimizations include SSE2, SSE3, and SSSE3 instruction sets and other optimizations. Intel does not guarantee the availability, functionality, or effectiveness of any optimization on microprocessors not manufactured by Intel. Microprocessor-dependent optimizations in this product are intended for use with Intel microprocessors. Certain optimizations not specific to Intel microarchitecture are reserverd for Intel microprocessors. Please refer to the applicable product User and Reference Guides for more information regarding the specific instruction sets covered by this notice.

Notice revision #20110804