NAG CL Interface
s30acc (opt_​imp_​vol)

Settings help

CL Name Style:


1 Purpose

s30acc computes the implied volatility of a European option contract based on the Black–Scholes–Merton formula.

2 Specification

#include <nag.h>
void  s30acc (Nag_CallPut option, Integer n, const double p[], const double k[], const double s0[], const double t[], const double r[], double sigma[], Integer mode, Integer ivalid[], NagError *fail)
The function may be called by the names: s30acc or nag_specfun_opt_imp_vol.

3 Description

The Black–Scholes formula for the price of a European option is
Pcall = S0 Φ ( ln( S0 K ) + [r+ σ2 2 ] T σT ) - K e -rT Φ ( ln( S0 K ) + [r- σ2 2 ] T σ T ) ,  
for a call option, and
Pput = K e-rT Φ ( - ln( S0 K ) - [r- σ2 2 ] T σ T ) - S0 Φ ( - ln( S0 K ) - [r+ σ2 2 ] T σ T ) ,  
for a put option, where Φ is the cumulative Normal distribution function, T is the time to maturity, S0 is the spot price of the underlying asset, K is the strike price, r is the interest rate and σ is the volatility.
Given arrays of values Pi, Ki, S0i, Ti and ri, for i=1,2,n, s30acc computes the implied volatilities σi.
s30acc offers the choice of two algorithms. The algorithm of Glau et al. (2018) uses Chebyshev interpolation to compute the implied volatilities, and performs best for long arrays of input data. The algorithm of Jäckel (2015) uses a third order Householder iteration and performs better for short arrays of input data.

4 References

Glau K, Herold P, Madan D B and Pötz C (2018) The Chebyshev method for the implied volatility Accepted for publication in the Journal of Computational Finance
Jäckel P (2015) Let's be Rational Wilmott Magazine 2015(75) 40–53

5 Arguments

1: option Nag_CallPut Input
On entry: determines whether the option is a call or a put.
option=Nag_Call
A call; the holder has a right to buy.
option=Nag_Put
A put; the holder has a right to sell.
Constraint: option=Nag_Call or Nag_Put.
2: n Integer Input
On entry: n, the number of implied volatilities to be computed.
Constraint: n0.
3: p[n] const double Input
On entry: p[i-1] must contain Pi, the ith option price, for i=1,2,,n.
Constraint: p[i-1]0.0, for i=1,2,,n.
4: k[n] const double Input
On entry: k[i-1] must contain Ki, the ith strike price, for i=1,2,,n.
Constraint: k[i-1]>0.0, for i=1,2,,n.
5: s0[n] const double Input
On entry: s0[i-1] must contain S0i, the ith spot price, for i=1,2,,n.
Constraint: s0[i-1]>0.0, for i=1,2,,n.
6: t[n] const double Input
On entry: t[i-1] must contain Ti, the ith time, in years, to maturity, for i=1,2,,n.
Constraint: t[i-1]>0.0, for i=1,2,,n.
7: r[n] const double Input
On entry: r[i-1] must contain ri, the ith interest rate, for i=1,2,,n. Note that a rate of 5% should be entered as 0.05.
8: sigma[n] double Output
On exit: sigma[i-1] contains σi, the ith implied volatility, for i=1,2,,n.
9: mode Integer Input
On entry: specifies which algorithm will be used to compute the implied volatilities. See Sections 7 and 8 for further guidance on the choice of mode.
mode=0
The Glau et al. (2018) algorithm will be used. The nodes used in the Chebyshev interpolation will be chosen to achieve relative accuracy to approximately seven decimal places;
mode=1
The Glau et al. (2018) algorithm will be used. The nodes used in the Chebyshev interpolation will be chosen to achieve relative accuracy to approximately 15 decimal places, but limited by the machine precision;
mode=2
The Jäckel (2015) algorithm will be used, aiming for accuracy to approximately 1516 decimal places, but limited by machine precision.
Constraint: mode=0, 1 or 2.
10: ivalid[n] Integer Output
On exit: ivalid[i-1] indicates any errors with the input arguments that prevented σi from being computed. If ivalid[i-1]0, sigma[i-1] contains 0.0.
ivalid[i-1]=0
No error.
ivalid[i-1]=1
Pi<0.0.
ivalid[i-1]=2
Ki0.0.
ivalid[i-1]=3
S0i0.0.
ivalid[i-1]=4
Ti0.0.
ivalid[i-1]=5
The combination of Pi, Ki, S0i, Ti and ri is out of the domain in which σi can be computed. See Section 9 for further details.
11: fail NagError * Input/Output
The NAG error argument (see Section 7 in the Introduction to the NAG Library CL Interface).

6 Error 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.
NE_BAD_PARAM
On entry, argument value had an illegal value.
NE_INT
On entry, mode=value.
Constraint: mode=0, 1 or 2.
On entry, n=value.
Constraint: n0.
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.
NW_IVALID
On entry at least one input argument was invalid.
Check ivalid for more information.

7 Accuracy

If mode=0 or 1 then s30acc uses Chebyshev interpolation. For mode=0 it aims for relative accuracy to roughly single precision (approximately seven decimal places). For mode=1 it aims for relative accuracy to roughly double precision (approximately sixteen decimal places).
If mode=2, a Householder iteration is used to achieve relative accuracy to roughly double precision (approximately sixteen decimal places). In practice there is very little difference in accuracy between mode=1 and 2, though for more extreme input values, mode=2 is likely to be more accurate.

8 Parallelism and Performance

Background information to multithreading can be found in the Multithreading documentation.
s30acc is threaded by NAG for parallel execution in multithreaded implementations of the NAG Library.
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.
When mode=0 or 1, s30acc uses an algorithm optimized for performance on large vectors of input data (n1000) by exploiting vector instructions when available.
When mode=2, s30acc uses an algorithm optimized for performance on smaller vectors of input data.
Numerical experiments suggest that for n1000, the best performance is always achieved by choosing mode=2, whereas for n1000, mode=0 or 1 should be used, according to the desired accuracy.

9 Further Comments

The domain of inputs, Pi, Ki, S0i, Ti and ri, for which s30acc is able to accurately compute σi is very large and should cover all practical applications of this function. Thus, encountering arguments for which ivalid[i-1]=5 is returned is highly unlikely. Note that it is not possible to give a closed-form expression for the allowed range of arguments because this range is based on a transformation to the normalized call price.
Note that some formulations of the Black–Scholes equation also include the annual yield rate, q. If you wish to incorporate q here, then you must first compute the quantities S~0=S0e-qT, K~=Ke-qT and r~=r-q. s30acc should then be called with S~0, K~ and r~ in place of S0, K and r respectively.
s30acc can also be used with Black's model for European futures options. In this case, the forward price, F, and the discount factor, D, are used, which are related to S0 via F=S0/D. In addition, the option price is scaled by a factor e-rT.
Approximately 7×n of real allocatable memory and 3×n of integer allocatable memory is required by the function.

10 Example

This example reads in values of Pi, Ki, S0i, Ti and r from a file, evaluates the implied volatilities, σi, and prints the results.

10.1 Program Text

Program Text (s30acce.c)

10.2 Program Data

Program Data (s30acce.d)

10.3 Program Results

Program Results (s30acce.r)