# NAG CL Interfaced03ncc (dim1_​blackscholes_​fd)

Settings help

CL Name Style:

## 1Purpose

d03ncc solves the Black–Scholes equation for financial option pricing using a finite difference scheme.

## 2Specification

 #include
 void d03ncc (Nag_OptionType kopt, double x, Nag_MeshType mesh, Integer ns, double s[], Integer nt, double t[], const Nag_Boolean tdpar[], const double r[], const double q[], const double sigma[], double alpha, Integer ntkeep, double f[], double theta[], double delta[], double gamma[], double lambda[], double rho[], NagError *fail)
The function may be called by the names: d03ncc, nag_pde_dim1_blackscholes_fd or nag_pde_bs_1d.

## 3Description

d03ncc solves the Black–Scholes equation (see Hull (1989) and Wilmott et al. (1995))
 $∂f ∂t +(r-q)S ∂f ∂S +σ2S22 ∂2f ∂S2 =rf$ (1)
 $Smin (2)
for the value $f$ of a European or American, put or call stock option, with exercise price $X$. In equation (1) $t$ is time, $S$ is the stock price, $r$ is the risk free interest rate, $q$ is the continuous dividend, and $\sigma$ is the stock volatility. According to the values in the array tdpar, the arguments $r$, $q$ and $\sigma$ may each be either constant or functions of time. The function also returns values of various Greeks.
d03ncc uses a finite difference method with a choice of time-stepping schemes. The method is explicit for ${\mathbf{alpha}}=0.0$ and implicit for nonzero values of alpha. Second order time accuracy can be obtained by setting ${\mathbf{alpha}}=0.5$. According to the value of the argument mesh the finite difference mesh may be either uniform, or user-defined in both $S$ and $t$ directions.
Hull J (1989) Options, Futures and Other Derivative Securities Prentice–Hall
Wilmott P, Howison S and Dewynne J (1995) The Mathematics of Financial Derivatives Cambridge University Press

## 5Arguments

1: $\mathbf{kopt}$Nag_OptionType Input
On entry: specifies the kind of option to be valued.
${\mathbf{kopt}}=\mathrm{Nag_EuropeanCall}$
A European call option.
${\mathbf{kopt}}=\mathrm{Nag_AmericanCall}$
An American call option.
${\mathbf{kopt}}=\mathrm{Nag_EuropeanPut}$
A European put option.
${\mathbf{kopt}}=\mathrm{Nag_AmericanPut}$
An American put option.
Constraint: ${\mathbf{kopt}}=\mathrm{Nag_EuropeanCall}$, $\mathrm{Nag_AmericanCall}$, $\mathrm{Nag_EuropeanPut}$ or $\mathrm{Nag_AmericanPut}$.
2: $\mathbf{x}$double Input
On entry: the exercise price $X$.
3: $\mathbf{mesh}$Nag_MeshType Input
On entry: indicates the type of finite difference mesh to be used:
${\mathbf{mesh}}=\mathrm{Nag_UniformMesh}$
Uniform mesh.
${\mathbf{mesh}}=\mathrm{Nag_CustomMesh}$
Custom mesh supplied by you.
Constraint: ${\mathbf{mesh}}=\mathrm{Nag_UniformMesh}$ or $\mathrm{Nag_CustomMesh}$.
4: $\mathbf{ns}$Integer Input
On entry: the number of stock prices to be used in the finite difference mesh.
Constraint: ${\mathbf{ns}}\ge 2$.
5: $\mathbf{s}\left[{\mathbf{ns}}\right]$double Input/Output
On entry: if ${\mathbf{mesh}}=\mathrm{Nag_CustomMesh}$, ${\mathbf{s}}\left[\mathit{i}-1\right]$ must contain the $\mathit{i}$th stock price in the mesh, for $\mathit{i}=1,2,\dots ,{\mathbf{ns}}$. These values should be in increasing order, with ${\mathbf{s}}\left[0\right]={S}_{\mathrm{min}}$ and ${\mathbf{s}}\left[{\mathbf{ns}}-1\right]={S}_{\mathrm{max}}$.
If ${\mathbf{mesh}}=\mathrm{Nag_UniformMesh}$, ${\mathbf{s}}\left[0\right]$ must be set to ${S}_{\mathrm{min}}$ and ${\mathbf{s}}\left[{\mathbf{ns}}-1\right]$ to ${S}_{\mathrm{max}}$, but ${\mathbf{s}}\left[1\right],{\mathbf{s}}\left[2\right],\dots ,{\mathbf{s}}\left[{\mathbf{ns}}-2\right]$ need not be initialized, as they will be set internally by the function in order to define a uniform mesh.
On exit: if ${\mathbf{mesh}}=\mathrm{Nag_UniformMesh}$, the elements of s define a uniform mesh over $\left[{S}_{\mathrm{min}},{S}_{\mathrm{max}}\right]$.
If ${\mathbf{mesh}}=\mathrm{Nag_CustomMesh}$, the elements of s are unchanged.
Constraints:
• if ${\mathbf{mesh}}=\mathrm{Nag_CustomMesh}$, ${\mathbf{s}}\left[0\right]\ge 0.0$ and ${\mathbf{s}}\left[\mathit{i}-1\right]<{\mathbf{s}}\left[\mathit{i}\right]$, for $\mathit{i}=1,2,\dots ,{\mathbf{ns}}-1$;
• if ${\mathbf{mesh}}=\mathrm{Nag_UniformMesh}$, $0.0\le {\mathbf{s}}\left[0\right]<{\mathbf{s}}\left[{\mathbf{ns}}-1\right]$.
6: $\mathbf{nt}$Integer Input
On entry: the number of time-steps to be used in the finite difference method.
Constraint: ${\mathbf{nt}}\ge 2$.
7: $\mathbf{t}\left[{\mathbf{nt}}\right]$double Input/Output
On entry: if ${\mathbf{mesh}}=\mathrm{Nag_CustomMesh}$ then ${\mathbf{t}}\left[\mathit{j}-1\right]$ must contain the $\mathit{j}$th time in the mesh, for $\mathit{j}=1,2,\dots ,{\mathbf{nt}}$. These values should be in increasing order, with ${\mathbf{t}}\left[0\right]={t}_{\mathrm{min}}$ and ${\mathbf{t}}\left[{\mathbf{nt}}-1\right]={t}_{\mathrm{max}}$.
If ${\mathbf{mesh}}=\mathrm{Nag_UniformMesh}$ then ${\mathbf{t}}\left[0\right]$ must be set to ${t}_{\mathrm{min}}$ and ${\mathbf{t}}\left[{\mathbf{nt}}-1\right]$ to ${t}_{\mathrm{max}}$, but ${\mathbf{t}}\left[1\right],{\mathbf{t}}\left[2\right],\dots ,{\mathbf{t}}\left[{\mathbf{nt}}-2\right]$ need not be initialized, as they will be set internally by the function in order to define a uniform mesh.
On exit: if ${\mathbf{mesh}}=\mathrm{Nag_UniformMesh}$, the elements of t define a uniform mesh over $\left[{t}_{\mathrm{min}},{t}_{\mathrm{max}}\right]$.
If ${\mathbf{mesh}}=\mathrm{Nag_CustomMesh}$, the elements of t are unchanged.
Constraints:
• if ${\mathbf{mesh}}=\mathrm{Nag_CustomMesh}$, ${\mathbf{t}}\left[0\right]\ge 0.0$ and ${\mathbf{t}}\left[\mathit{j}-1\right]<{\mathbf{t}}\left[\mathit{j}\right]$, for $\mathit{j}=1,2,\dots ,{\mathbf{nt}}-1$;
• if ${\mathbf{mesh}}=\mathrm{Nag_UniformMesh}$, $0.0\le {\mathbf{t}}\left[0\right]<{\mathbf{t}}\left[{\mathbf{nt}}-1\right]$.
8: $\mathbf{tdpar}\left[3\right]$const Nag_Boolean Input
On entry: specifies whether or not various arguments are time-dependent. More precisely, $r$ is time-dependent if ${\mathbf{tdpar}}\left[0\right]=\mathrm{Nag_TRUE}$ and constant otherwise. Similarly, ${\mathbf{tdpar}}\left[1\right]$ specifies whether $q$ is time-dependent and ${\mathbf{tdpar}}\left[2\right]$ specifies whether $\sigma$ is time-dependent.
9: $\mathbf{r}\left[\mathit{dim}\right]$const double Input
Note: the dimension, dim, of the array r must be at least
• ${\mathbf{nt}}$ when ${\mathbf{tdpar}}\left[0\right]=\mathrm{Nag_TRUE}$;
• $1$ otherwise.
On entry: if ${\mathbf{tdpar}}\left[0\right]=\mathrm{Nag_TRUE}$ then ${\mathbf{r}}\left[\mathit{j}-1\right]$ must contain the value of the risk-free interest rate $r\left(t\right)$ at the $\mathit{j}$th time in the mesh, for $\mathit{j}=1,2,\dots ,{\mathbf{nt}}$.
If ${\mathbf{tdpar}}\left[0\right]=\mathrm{Nag_FALSE}$ then ${\mathbf{r}}\left[0\right]$ must contain the constant value of the risk-free interest rate $r$. The remaining elements need not be set.
10: $\mathbf{q}\left[\mathit{dim}\right]$const double Input
Note: the dimension, dim, of the array q must be at least
• ${\mathbf{nt}}$ when ${\mathbf{tdpar}}\left[1\right]=\mathrm{Nag_TRUE}$;
• $1$ otherwise.
On entry: if ${\mathbf{tdpar}}\left[1\right]=\mathrm{Nag_TRUE}$ then ${\mathbf{q}}\left[\mathit{j}-1\right]$ must contain the value of the continuous dividend $q\left(t\right)$ at the $\mathit{j}$th time in the mesh, for $\mathit{j}=1,2,\dots ,{\mathbf{nt}}$.
If ${\mathbf{tdpar}}\left[1\right]=\mathrm{Nag_FALSE}$ then ${\mathbf{q}}\left[0\right]$ must contain the constant value of the continuous dividend $q$. The remaining elements need not be set.
11: $\mathbf{sigma}\left[\mathit{dim}\right]$const double Input
Note: the dimension, dim, of the array sigma must be at least
• ${\mathbf{nt}}$ when ${\mathbf{tdpar}}\left[2\right]=\mathrm{Nag_TRUE}$;
• $1$ otherwise.
On entry: if ${\mathbf{tdpar}}\left[2\right]=\mathrm{Nag_TRUE}$ then ${\mathbf{sigma}}\left[\mathit{j}-1\right]$ must contain the value of the volatility $\sigma \left(t\right)$ at the $\mathit{j}$th time in the mesh, for $\mathit{j}=1,2,\dots ,{\mathbf{nt}}$.
If ${\mathbf{tdpar}}\left[2\right]=\mathrm{Nag_FALSE}$ then ${\mathbf{sigma}}\left[0\right]$ must contain the constant value of the volatility $\sigma$. The remaining elements need not be set.
12: $\mathbf{alpha}$double Input
On entry: the value of $\lambda$ to be used in the time-stepping scheme. Typical values include:
${\mathbf{alpha}}=0.0$
Explicit forward Euler scheme.
${\mathbf{alpha}}=0.5$
Implicit Crank–Nicolson scheme.
${\mathbf{alpha}}=1.0$
Implicit backward Euler scheme.
The value $0.5$ gives second-order accuracy in time. Values greater than $0.5$ give unconditional stability. Since $0.5$ is at the limit of unconditional stability this value does not damp oscillations.
Suggested value: ${\mathbf{alpha}}=0.55$.
Constraint: $0.0\le {\mathbf{alpha}}\le 1.0$.
13: $\mathbf{ntkeep}$Integer Input
On entry: the number of solutions to be stored in the time direction. The function calculates the solution backwards from ${\mathbf{t}}\left[{\mathbf{nt}}-1\right]$ to ${\mathbf{t}}\left[0\right]$ at all times in the mesh. These time solutions and the corresponding Greeks will be stored at times ${\mathbf{t}}\left[\mathit{i}-1\right]$, for $\mathit{i}=1,2,\dots ,{\mathbf{ntkeep}}$, in the arrays f, theta, delta, gamma, lambda and rho. Other time solutions will be discarded. To store all time solutions set ${\mathbf{ntkeep}}={\mathbf{nt}}$.
Constraint: $1\le {\mathbf{ntkeep}}\le {\mathbf{nt}}$.
14: $\mathbf{f}\left[{\mathbf{ns}}×{\mathbf{ntkeep}}\right]$double Output
On exit: ${\mathbf{f}}\left[{\mathbf{ns}}×\left(\mathit{j}-1\right)+\mathit{i}-1\right]$, for $\mathit{i}=1,2,\dots ,{\mathbf{ns}}$ and $\mathit{j}=1,2,\dots ,{\mathbf{ntkeep}}$, contains the value $f$ of the option at the $\mathit{i}$th mesh point ${\mathbf{s}}\left[\mathit{i}-1\right]$ at time ${\mathbf{t}}\left[\mathit{j}-1\right]$.
15: $\mathbf{theta}\left[{\mathbf{ns}}×{\mathbf{ntkeep}}\right]$double Output
16: $\mathbf{delta}\left[{\mathbf{ns}}×{\mathbf{ntkeep}}\right]$double Output
17: $\mathbf{gamma}\left[{\mathbf{ns}}×{\mathbf{ntkeep}}\right]$double Output
18: $\mathbf{lambda}\left[{\mathbf{ns}}×{\mathbf{ntkeep}}\right]$double Output
19: $\mathbf{rho}\left[{\mathbf{ns}}×{\mathbf{ntkeep}}\right]$double Output
On exit: the values of various Greeks at the $i$th mesh point ${\mathbf{s}}\left[i-1\right]$ at time ${\mathbf{t}}\left[j-1\right]$, as follows:
 $theta[ns×(j-1)+i-1]= ∂f ∂t , delta[ns×(j-1)+i-1]= ∂f ∂S , gamma[ns×(j-1)+i-1]= ∂2f ∂S2 , lambda[ns×(j-1)+i-1]= ∂f ∂σ , rho[ns×(j-1)+i-1]= ∂f ∂r .$
20: $\mathbf{fail}$NagError * Input/Output
The NAG error argument (see Section 7 in the Introduction to the NAG Library CL Interface).

## 6Error Indicators and Warnings

NE_ALLOC_FAIL
Dynamic memory allocation failed.
See Section 3.1.2 in the Introduction to the NAG Library CL Interface for further information.
On entry, argument $⟨\mathit{\text{value}}⟩$ had an illegal value.
NE_INT
On entry, ${\mathbf{ns}}=⟨\mathit{\text{value}}⟩$.
Constraint: ${\mathbf{ns}}\ge 2$.
On entry, ${\mathbf{nt}}=⟨\mathit{\text{value}}⟩$.
Constraint: ${\mathbf{nt}}\ge 2$.
On entry, ${\mathbf{ntkeep}}=⟨\mathit{\text{value}}⟩$.
Constraint: ${\mathbf{ntkeep}}\ge 1$.
NE_INT_2
On entry, ${\mathbf{ntkeep}}=⟨\mathit{\text{value}}⟩$ and ${\mathbf{nt}}=⟨\mathit{\text{value}}⟩$.
Constraint: ${\mathbf{ntkeep}}\le {\mathbf{nt}}$.
NE_INTERNAL_ERROR
An internal error has occurred in this function. Check the function call and any array sizes. If the call is correct then please contact NAG for assistance.
See Section 7.5 in the Introduction to the NAG Library CL Interface for further information.
NE_NO_LICENCE
Your licence key may have expired or may not have been installed correctly.
See Section 8 in the Introduction to the NAG Library CL Interface for further information.
NE_NOT_STRICTLY_INCREASING
On entry, ${\mathbf{s}}\left[⟨\mathit{\text{value}}⟩+1\right]\le {\mathbf{s}}\left[⟨\mathit{\text{value}}⟩\right]$.
Constraint: when ${\mathbf{mesh}}=\mathrm{Nag_CustomMesh}$, ${\mathbf{s}}\left[\mathit{i}-1\right]<{\mathbf{s}}\left[\mathit{i}\right]$, for $\mathit{i}=1,2,\dots ,{\mathbf{ns}}-1$.
On entry, ${\mathbf{t}}\left[⟨\mathit{\text{value}}⟩+1\right]\le {\mathbf{t}}\left[⟨\mathit{\text{value}}⟩\right]$.
Constraint: when ${\mathbf{mesh}}=\mathrm{Nag_CustomMesh}$, ${\mathbf{t}}\left[\mathit{i}-1\right]<{\mathbf{t}}\left[\mathit{i}\right]$, for $\mathit{i}=1,2,\dots ,{\mathbf{nt}}-1$.
NE_REAL
On entry, ${\mathbf{alpha}}=⟨\mathit{\text{value}}⟩$.
Constraint: ${\mathbf{alpha}}\le 1.0$.
On entry, ${\mathbf{alpha}}=⟨\mathit{\text{value}}⟩$.
Constraint: ${\mathbf{alpha}}\ge 0.0$.
On entry, ${\mathbf{s}}\left[0\right]=⟨\mathit{\text{value}}⟩$.
Constraint: ${\mathbf{s}}\left[0\right]\ge 0.0$.
On entry, ${\mathbf{t}}\left[0\right]=⟨\mathit{\text{value}}⟩$.
Constraint: ${\mathbf{t}}\left[0\right]\ge 0.0$.
NE_REAL_2
On entry, ${\mathbf{s}}\left[{\mathbf{ns}}-1\right]=⟨\mathit{\text{value}}⟩$ and ${\mathbf{s}}\left[0\right]=⟨\mathit{\text{value}}⟩$.
Constraint: ${\mathbf{s}}\left[{\mathbf{ns}}-1\right]>{\mathbf{s}}\left[0\right]$.
On entry, ${\mathbf{t}}\left[{\mathbf{nt}}-1\right]=⟨\mathit{\text{value}}⟩$ and ${\mathbf{t}}\left[0\right]=⟨\mathit{\text{value}}⟩$.
Constraint: ${\mathbf{t}}\left[{\mathbf{nt}}-1\right]>{\mathbf{t}}\left[0\right]$.

## 7Accuracy

The accuracy of the solution $f$ and the various derivatives returned by the function is dependent on the values of ns and nt supplied, the distribution of the mesh points, and the value of alpha chosen. For most choices of alpha the solution has a truncation error which is second-order accurate in $S$ and first order accurate in $t$. For ${\mathbf{alpha}}=0.5$ the truncation error is also second-order accurate in $t$.
The simplest approach to improving the accuracy is to increase the values of both ns and nt.

## 8Parallelism and Performance

d03ncc is threaded by NAG for parallel execution in multithreaded implementations of the NAG Library.
d03ncc makes calls to BLAS and/or LAPACK routines, which may be threaded within the vendor library used by this implementation. Consult the documentation for the vendor library for further information.
Please consult the X06 Chapter Introduction for information on how to control and interrogate the OpenMP environment used within this function. Please also consult the Users' Note for your implementation for any additional implementation-specific information.

### 9.1Timing

Each time-step requires the construction and solution of a tridiagonal system of linear equations. To calculate each of the derivatives lambda and rho requires a repetition of the entire solution process. The time taken for a call to the function is, therefore, proportional to ${\mathbf{ns}}×{\mathbf{nt}}$.

### 9.2Algorithmic Details

d03ncc solves equation (1) using a finite difference method. The solution is computed backwards in time from ${t}_{\mathrm{max}}$ to ${t}_{\mathrm{min}}$ using a $\lambda$ scheme, which is implicit for all nonzero values of $\lambda$, and is unconditionally stable for values of $\lambda >0.5$. For each time-step a tridiagonal system is constructed and solved to obtain the solution at the earlier time. For the explicit scheme ($\lambda =0$) this tridiagonal system degenerates to a diagonal matrix and is solved trivially. For American options the solution at each time-step is inspected to check whether early exercise is beneficial, and amended accordingly.
To compute the arrays lambda and rho, which are derivatives of the stock value $f$ with respect to the problem arguments $\sigma$ and $r$ respectively, the entire solution process is repeated with perturbed values of these arguments.

## 10Example

This example, taken from Hull (1989), solves the one-dimensional Black–Scholes equation for valuation of a $5$-month American put option on a non-dividend-paying stock with an exercise price of \$$50$. The risk-free interest rate is 10% per annum, and the stock volatility is 40% per annum.
A fully implicit backward Euler scheme is used, with a mesh of $20$ stock price intervals and $10$ time intervals.

### 10.1Program Text

Program Text (d03ncce.c)

### 10.2Program Data

Program Data (d03ncce.d)

### 10.3Program Results

Program Results (d03ncce.r)