Solves the generalized Feynman-Kac PDE on a rectangular grid using a finite element Galerkin method. Initial and boundary conditions are provided. The solution is represented by a series of C2 Hermite quintic splines.
Required Arguments
XGRID — Rank-1 array containing the set of breakpoints that define the end points for the Hermite quintic splines. (Input) Let m = size(XGRID). The points in XGRID must be in strictly increasing order, and m≥ 2.
TGRID — Rank-1 array containing the set of time points (in time-remaining units) at which an approximate solution is computed. (Input) Let n = size(TGRID). The points in TGRID must be strictly positive and in strictly increasing order and n≥ 1.
NLBC — The number of left boundary conditions. (Input) 1 ≤NLBC≤ 3.
NRBC — The number of right boundary conditions. (Input) 1 ≤NRBC≤ 3.
FKCOEF — User-supplied FUNCTION to evaluate the coefficients σ, σ′, μ and κ of the Feynman-Kac PDE. The usage is FKCOEF (X, TX, IFLAG[, …]), where
Function Return Value
FKCOEF — Value of the coefficient function. Which value is computed depends on the input value for IFLAG, see description of IFLAG.
Required Arguments
X — Point in the x-space at which the coefficient is to be evaluated. (Input)
TX — Time point at which the coefficient is to be evaluated. (Input)
IFLAG — Flag related to the coefficient that has to be computed (Input/Output). On entry, IFLAG indicates which coefficient is to be computed. The following table shows which value has to be returned by FKCOEF for all possible values of IFLAG:
IFLAG
Computed coefficient
1
2
σ
3
μ
4
κ
One indicates when a coefficient does not depend on t by setting IFLAG = 0 after the coefficient is defined. If there is time dependence, the value of IFLAG should not be changed. This action will usually yield a more efficient algorithm because some finite element matrices do not have to be reassembled for each t value.
Optional Arguments
FCN_DATA — A derived type, s_fcn_data, which may be used to pass additional integer or floating point information to or from the user-supplied function. For a detailed description of this argument see FCN_DATA below. (Input/Output)
FKCOEF must be declared EXTERNAL in the calling program.
FKINITCOND — User-supplied FUNCTION to evaluate the initial condition function p(x) in the Feynman-Kac PDE. The usage is FKINITCOND (X[, …]), where
Function Return Value
FKINITCOND — Value of the initial condition function p(x).
Required Arguments
X — Point in the x-space at which the initial condition is to be evaluated. (Input)
Optional Arguments
FCN_DATA — A derived type, s_fcn_data, which may be used to pass additional integer or floating point information to or from the user-supplied function. For a detailed description of this argument see FCN_DATA below. (Input/Output)
FKINITCOND must be declared EXTERNAL in the calling program.
FKBC — User-supplied subroutine to evaluate the coefficients for the left and right boundary conditions the Feynman-Kac PDE must satisfy. There are NLBC conditions specified at the left end, xmin, and NRBC conditions at the right end, xmax. The boundary conditions can be vectors of dimension 1, 2 or 3 and are defined by
The usage is FKBC (TX, IFLAG, BCCOEFS[, …]) where
Required Arguments
TX — Time point at which the coefficients are to be evaluated. (Input)
IFLAG — Flag related to the boundary conditions that have to be computed (Input/Output). On input, IFLAG indicates whether the coefficients for the left or right boundary conditions have to be computed:
IFLAG
Computed boundary conditions
1
Left end, x = xmin
2
Right end, x = xmax
If there is no time dependence for one of the boundaries then set IFLAG = 0 after the array BCCOEFS is defined for either end point. This can avoid unneeded continued computation of the finite element matrices.
BCCOEFS — Array of size 3 × 4 containing the coefficients of the left or right boundary conditions in its first NLBC or NRBC rows, respectively. (Output) The coefficients for xmin are stored row-wise according to the following matrix-scheme:
The coefficients for xmax are stored similarly.
Optional Arguments
FCN_DATA — A derived type, s_fcn_data, which may be used to pass additional integer or floating point information to or from the user-supplied subroutine. For a detailed description of this argument see FCN_DATA below. (Input/Output)
FKBC must be declared EXTERNAL in the calling program.
Y — Array of size (3*m) by (n+1) containing the coefficients of the Hermite representation of the approximate solution for the Feynman-Kac PDE at time points (in time-remaining units) 0, TGRID(1), …, TGRID(n). (Output) For t = TGRID(j), j = 1, …, n, the coefficients are stored in columns 1, …, n of array Y and the approximate solution is given by
The coefficients of the representation for the initial data are given in column 0 of array Y and are defined by
The starting coefficients Y(i,0), i = 1, …, m are estimated using least-squares.
After the integrations, use Y(:,0) and Y(:,j) as input argument COEFFS to function HQSVAL to obtain an array of values for f(x, t) or its partials at time points t = 0 and t = TGRID(j), j=1, …, n, respectively.
YPRIME — Array of size (3*m) by (n + 1) containing the first derivatives of the coefficients of the Hermite representation of the approximate solution for the Feynman-Kac PDE at time points (in time-remaining units) 0, TGRID(1), …, TGRID(n). (Output) For t = 0 and t = TGRID(j), j=1, …, n , the derivatives of the coefficients are stored in column 0 and columns 1 to n of array YPRIME, respectively. The columns in YPRIME represent
and
After the integrations, use YPRIME(:,j) as input argument COEFFS to function HQSVAL to obtain an array of values for the partials at time points t=TGRID(j), j = 1, …, n, and YPRIME(:,0) for the partials at t = 0.
Optional Arguments
FKINIT — User-supplied subroutine that allows for adjustment of initial data or as an opportunity for output during the integration steps.
The usage is CALLFKINIT (XGRID, TGRID, TX, YPRIME, Y, ATOL, RTOL, [, …]) where
Required Arguments
XGRID — Array of size m containing the set of breakpoints that define the end points for the Hermite quintic splines. (Input)
TGRID — Array of size n containing the set of time points (in time-remaining units) at which an approximate solution is computed. (Input)
TX — Time point for the evaluation. (Input) Possible values are 0 (the initial or “terminal” time point) and all values in array TGRID.
YPRIME — Array of length 3*m containing the derivatives of the Hermite quintic spline coefficients at time point TX. (Input)
Y — Array of length 3*m containing the Hermite quintic spline coefficients at time point TX. (Input/Output) For the initial time point TX = 0 this array can be used to reset the Hermite quintic spline coefficients to user defined values. For all other values of TX array Y is an input array.
ATOL — Array of length 3*m containing absolute error tolerances used in the integration routine that determines the Hermite quintic spline coefficients and its derivatives. (Input/Output)
RTOL — Array of length 3*m containing relative error tolerances used in the integration routine that determines the Hermite quintic spline coefficients and its derivatives. (Input/Output)
Optional Arguments
FCN_DATA — A derived type, s_fcn_data, which may be used to pass additional integer or floating point information to or from the user-supplied function. For a detailed description of this argument see FCN_DATA below. (Input/Output)
FKINIT must be declared EXTERNAL in the calling program.
FKFORCE — User-supplied subroutine that computes local contributions
The usage is CALLFKFORCE (I, T, WIDTH, Y, XLOCAL, QW, U, PHI, DPHI[, …]) where
Required Arguments
I — Index related to the integration interval (XGRID(I), XGRID(I+1)). (Input)
T — Time point at which the local contributions are computed. (Input)
WIDTH — Width of the integration interval I, WIDTH=XGRID(I+1)-XGRID(I). (Input)
Y — Array of length 3*m containing the coefficients of the Hermite quintic spline representing the solution of the Feynman-Kac PDE at time point T. (Input) For each
the approximate solution is locally defined by
Here, the functions are basis polynomials of order 5 and
The values
are stored as successive triplets in array Y.
XLOCAL — Array containing the Gauss-Legendre points translated and normalized to the interval [XGRID(I),XGRID(I+1)]. (Input) The size of the array is equal to the degree of the Gauss-Legendre polynomials used for constructing the finite element matrices.
QW — Array containing the Gauss-Legendre weights. (Input) The size of the array is equal to the degree of the Gauss-Legendre polynomials used for constructing the finite element matrices.
U — Array of size size (XLOCAL) × 12 containing the basis function values that define at the Gauss-Legendre points XLOCAL. (Input) Let
Using the local approximation in the I-th interval, defined by
and setting
vector is defined as
PHI — Array of size 6 containing a Gauss-Legendre approximation for the local contribution , where t = T and . (Output)
Setting NDEG:=SIZE(XLOCAL) and xj = XLOCAL(j), array PHI contains elements
for i = 1, …, 6.
DPHI — Array of size 6 × 6, a Gauss-Legendre approximation for the Jacobian of the local contribution at time point t = T, (Output)
The approximation to this symmetric matrix is stored row-wise, i.e.
DPHI(i,j) = WIDTH
for i, j = 1, …, 6.
Optional Arguments
FCN_DATA — A derived type, s_fcn_data, which may be used to pass additional integer or floating point information to or from the user-supplied subroutine. For a detailed description of this argument see FCN_DATA below. (Input/Output)
FKFORCE must be declared EXTERNAL in the calling program.
If subroutine FKFORCE is not used as an optional argument then it is assumed that the forcing term in the Feynman-Kac equation is identically zero.
ATOL — Array of non-negative values containing absolute error tolerances used in the computation of each column of solution array Y via integration routine DASPH. (Input) The size of array ATOL can be 1 or 3 ×m. In the first case, ATOL(1:1) is applied to all solution components, in the latter each component of ATOL is assigned to the corresponding solution component allowing for individual control of the error tolerances. At least one entry in arrays ATOL or RTOL must be greater than 0. Default: ATOL(1:1) = 1.0e-3 for single and 1.0d-5 for double precision.
RTOL — Array of non-negative values containing relative error tolerances used in the computation of each column of solution array Y via integration routine DASPH. (Input) The size of array RTOL can be 1 or 3 ×m. In the first case, RTOL(1:1) is applied to all solution components, in the latter each component of RTOL is assigned to the corresponding solution component allowing for individual control of the error tolerances. At least one entry in arrays ATOL or RTOL must be greater than 0. Default: RTOL(1:1) = 1.0e-3 for single and 1.0d-5 for double precision.
NDEG — Degree of the Gauss-Legendre formulas used for constructing the finite element matrices. (Input) NDEG≥ 6. Default: NDEG = 6.
RINITSTEPSIZE — Starting step size for the integration. (Input) RINITSTEPSIZE must be strictly negative since the integration is internally done from T = 0 to T = TGRID(n) in a negative direction. Default: Program defined initial stepsize.
MAXBDFORDER — Maximum order of the backward differentiation formulas (BDF) used in the integrator DASPH. (Input) 1 ≤MAXBDFORDER≤ 5. Default: MAXBDFORDER = 5.
RMAXSTEPSIZE — Maximum step size the integrator may take. (Input) RMAXSTEPSIZE must be strictly positive. Default: RMAXSTEPSIZE=AMACH(2), the largest possible machine number.
MAXIT — Maximum number of internal integration steps between two consecutive time points in TGRID. (Input) MAXIT must be strictly positive. Default: MAXIT = 500000.
IMETHSTEPCTRL — Indicates which step control algorithm is used in the integration. (Input) If IMETHSTEPCTRL = 0, then the step control method of Söderlind is used. If IMETHSTEPCTRL = 1, then the method used by the original Petzold code SASSL is used.
IMETHSTEPCTRL
Method used
0
Method of Söderlind..
1
Method from Petzold code SASSL.
Default: IMETHSTEPCTRL = 0.
TBARRIER — Time barrier past which the integration routine DASPH will not go during integration. (Input) TBARRIER≥TGRID(n). Default: TBARRIER = TGRID(n).
ISTATE — Array of size 5 whose entries flag the state of computation for the matrices and vectors required in the integration. (Output) For each entry, a zero indicates that no computation has been done or that there is a time dependence. A one indicates that the entry has been computed and there is no time dependence.The ISTATE entries are as follows:
I
ISTATE(I)
1
State of computation of Mass matrix, M.
2
State of computation of Stiffness matrix, N.
3
State of computation of Bending matrix, R.
4
State of computation of Weighted mass matrix, K.
5
State of computation of initial data.
NVAL — Array of size 3 summarizing the number of evaluations required during the integration. (Output)
I
NVAL(I)
1
Number of residual function evaluationsof the DAE used in the model.
2
Number of factorizations of the differential matrix associated with solving the DAE.
3
Number of linear system solve steps using the differential matrix.
ITDEPEND — Logical array of size 7 indicating time dependence of the coefficients, boundary conditions and forcing term φ in the Feynman-Kac equation. (Output) If ITDEPEND(I)=.FALSE. then argument I is not time dependent. If ITDEPEND(I)=.TRUE. then argument I is time dependent.
I
ITDEPEND(I)
1
Time dependence of σ′.
2
Time dependence of σ.
3
Time dependence of μ.
4
Time dependence of κ.
5
Time dependence of left boundary conditions.
6
Time dependence of right boundary conditions.
7
Time dependence of φ.
FCN_DATA — A derived type, s_fcn_data, which may be used to pass additional information to/from the user-supplied function. (Input/Output) The derived type, s_fcn_data, is defined as:
type s_fcn_data
real(kind(1e0)), pointer, dimension(:) :: rdata
integer, pointer, dimension(:) :: idata
end type
in module mp_types. The double precision counterpart to s_fcn_data is named d_fcn_data. The user must include a use mp_types statement in the calling program to define this derived type.
Note that if user-supplied data are required in one of the user-defined functions or subroutines available for routine FEYNMAN_KAC then these data must be defined via FCN_DATA.
Specific: The specific interface names are S_FEYNMAN_KAC and D_FEYNMAN_KAC.
Description
The generalized Feynman-Kac differential equation has the form
where the initial data satisfies
The derivatives are etc.
FEYNMAN_KAC uses a finite element Galerkin method over the rectangle
in to compute the approximate solution. The interval is decomposed with a grid
On each subinterval the solution is represented by
The values are time-dependent coefficients associated with each interval. The basis functions are given for ,
by
The Galerkin principle is then applied. Using the provided initial and boundary conditions leads to an index 1 differential-algebraic equation (DAE) for the time-dependent coefficients
This system is integrated using the variable order, variable step algorithm DASPH. Solution values and their time derivatives are returned at a grid preceding time T, expressed in units of time remaining.
In Beckers (1980) there is a model for a Stochastic Differential Equation of option pricing. The idea is a “constant elasticity of variance diffusion (or CEV) class”
The Black-Scholes model is the limiting case α→ 2. A numerical solution of this diffusion model yields the price of a call option. Various values of the strike price K, time values σ, and power coefficient α are used to evaluate the option price at values of the underlying price. The sets of parameters in the computation are:
1. power α = {2.0,1.0,0.0}
2. strike price K = {15.0,20.0,25.0}
3. volatility σ = {0.2,0.3,0.4}
4. times until expiration = {1/12,4/12,7/12}
5. underlying prices = {19.0,20.0,21.0}
6. interest rate r = 0.05
7. xmin = 0, xmax = 60
8. nx = 121, n = 3 ×nx = 363
With this model the Feynman-Kac differential equation is defined by identifying:
The payoff function is the “vanilla option”, .
(Example feynman_kac_ex1.f90)
! Compute Constant Elasticity of Variance Model for Vanilla Call
Constant Elasticity of Variance Model for Vanilla Call
Interest Rate 0.050 Continuous Dividend 0.000
Minimum and Maximum Prices of Underlying 0.00 60.00
Number of equally spaced spline knots 120
Number of unknowns 363
Time in Years Prior to Expiration 0.0833 0.3333 0.5833
Option valued at Underlying Prices 19.00 20.00 21.00
Strike=15.00 Sigma= 0.20 Alpha= 2.00
Call Option Values 4.0624 4.2575 4.4730
Call Option Values 5.0624 5.2506 5.4490
Call Option Values 6.0624 6.2486 6.4385
Strike=20.00 Sigma= 0.20 Alpha= 2.00
Call Option Values 0.1310 0.5955 0.9699
Call Option Values 0.5018 1.0887 1.5101
Call Option Values 1.1977 1.7483 2.1752
Strike=25.00 Sigma= 0.20 Alpha= 2.00
Call Option Values 0.0000 0.0112 0.0745
Call Option Values 0.0000 0.0372 0.1621
Call Option Values 0.0007 0.1027 0.3141
Strike=15.00 Sigma= 0.30 Alpha= 2.00
Call Option Values 4.0637 4.3398 4.6622
Call Option Values 5.0626 5.2944 5.5786
Call Option Values 6.0624 6.2708 6.5240
Strike=20.00 Sigma= 0.30 Alpha= 2.00
Call Option Values 0.3109 1.0276 1.5494
Call Option Values 0.7326 1.5424 2.1017
Call Option Values 1.3765 2.1690 2.7379
Strike=25.00 Sigma= 0.30 Alpha= 2.00
Call Option Values 0.0006 0.1112 0.3543
Call Option Values 0.0038 0.2169 0.5548
Call Option Values 0.0184 0.3857 0.8222
Strike=15.00 Sigma= 0.40 Alpha= 2.00
Call Option Values 4.0755 4.5138 4.9675
Call Option Values 5.0662 5.4201 5.8326
Call Option Values 6.0634 6.3579 6.7301
Strike=20.00 Sigma= 0.40 Alpha= 2.00
Call Option Values 0.5115 1.4640 2.1273
Call Option Values 0.9621 1.9951 2.6929
Call Option Values 1.5814 2.6105 3.3216
Strike=25.00 Sigma= 0.40 Alpha= 2.00
Call Option Values 0.0083 0.3286 0.7790
Call Option Values 0.0285 0.5167 1.0657
Call Option Values 0.0813 0.7687 1.4103
Strike=15.00 Sigma= 0.20 Alpha= 1.00
Call Option Values 4.0624 4.2479 4.4311
Call Option Values 5.0624 5.2479 5.4311
Call Option Values 6.0624 6.2479 6.4311
Strike=20.00 Sigma= 0.20 Alpha= 1.00
Call Option Values 0.0000 0.0218 0.1045
Call Option Values 0.1498 0.4109 0.6485
Call Option Values 1.0832 1.3314 1.5773
Strike=25.00 Sigma= 0.20 Alpha= 1.00
Call Option Values 0.0000 0.0000 0.0000
Call Option Values 0.0000 0.0000 0.0000
Call Option Values 0.0000 0.0000 0.0000
Strike=15.00 Sigma= 0.30 Alpha= 1.00
Call Option Values 4.0624 4.2477 4.4309
Call Option Values 5.0624 5.2477 5.4309
Call Option Values 6.0624 6.2477 6.4309
Strike=20.00 Sigma= 0.30 Alpha= 1.00
Call Option Values 0.0011 0.0781 0.2201
Call Option Values 0.1994 0.5000 0.7543
Call Option Values 1.0835 1.3443 1.6023
Strike=25.00 Sigma= 0.30 Alpha= 1.00
Call Option Values 0.0000 0.0000 0.0000
Call Option Values 0.0000 0.0000 0.0000
Call Option Values 0.0000 0.0000 0.0005
Strike=15.00 Sigma= 0.40 Alpha= 1.00
Call Option Values 4.0624 4.2479 4.4312
Call Option Values 5.0624 5.2479 5.4312
Call Option Values 6.0624 6.2479 6.4312
Strike=20.00 Sigma= 0.40 Alpha= 1.00
Call Option Values 0.0076 0.1563 0.3452
Call Option Values 0.2495 0.5907 0.8706
Call Option Values 1.0868 1.3779 1.6571
Strike=25.00 Sigma= 0.40 Alpha= 1.00
Call Option Values 0.0000 0.0000 0.0001
Call Option Values 0.0000 0.0000 0.0008
Call Option Values 0.0000 0.0003 0.0063
Strike=15.00 Sigma= 0.20 Alpha= 0.00
Call Option Values 4.0626 4.2479 4.4311
Call Option Values 5.0623 5.2480 5.4311
Call Option Values 6.0624 6.2480 6.4312
Strike=20.00 Sigma= 0.20 Alpha= 0.00
Call Option Values 0.0001 0.0001 0.0002
Call Option Values 0.0816 0.3316 0.5748
Call Option Values 1.0818 1.3308 1.5748
Strike=25.00 Sigma= 0.20 Alpha= 0.00
Call Option Values 0.0000 0.0000 0.0000
Call Option Values 0.0000 0.0000 0.0000
Call Option Values 0.0000 0.0000 0.0000
Strike=15.00 Sigma= 0.30 Alpha= 0.00
Call Option Values 4.0625 4.2479 4.4312
Call Option Values 5.0623 5.2479 5.4312
Call Option Values 6.0624 6.2479 6.4312
Strike=20.00 Sigma= 0.30 Alpha= 0.00
Call Option Values 0.0000 0.0000 0.0029
Call Option Values 0.0894 0.3326 0.5753
Call Option Values 1.0826 1.3306 1.5749
Strike=25.00 Sigma= 0.30 Alpha= 0.00
Call Option Values 0.0000 0.0000 0.0000
Call Option Values 0.0000 0.0000 0.0000
Call Option Values 0.0000 0.0000 0.0000
Strike=15.00 Sigma= 0.40 Alpha= 0.00
Call Option Values 4.0624 4.2479 4.4312
Call Option Values 5.0623 5.2479 5.4312
Call Option Values 6.0624 6.2479 6.4312
Strike=20.00 Sigma= 0.40 Alpha= 0.00
Call Option Values 0.0000 0.0002 0.0113
Call Option Values 0.0985 0.3383 0.5781
Call Option Values 1.0830 1.3306 1.5749
Strike=25.00 Sigma= 0.40 Alpha= 0.00
Call Option Values 0.0000 0.0000 0.0000
Call Option Values 0.0000 0.0000 0.0000
Call Option Values 0.0000 0.0000 0.0000
Example 2 – American Option vs. European Option On a Vanilla Put
The value of the American Option on a Vanilla Put can be no smaller than its European counterpart. That is due to the American Option providing the opportunity to exercise at any time prior to expiration. This example compares this difference – or premium value of the American Option – at two time values using the Black-Scholes model. The example is based on Wilmott et al. (1996, p. 176), and uses the non-linear forcing or weighting term described in Hanson, R. (2008), “Integrating Feynman-Kac Equations Using Hermite Quintic Finite Elements”, for evaluating the price of the American Option. A call to the subroutine fkinit_put sets the initial conditions. One breakpoint is set exactly at the strike price.
The sets of parameters in the computation are:
1. Strike price K = {10.0}
2. Volatility σ = {0.4}
3. Times until expiration = {1/4,1/2}
4. Interest rate r = 0.1
5. xmin = 0.0, xmax = 30.0
6. nx = 121, n = 3 ×nx = 363
The payoff function is the “vanilla option”, .
(Example feynman_kac_ex2.f90)
! Compute American Option Premium for Vanilla Put
use feynman_kac_int
use hqsval_int
use mp_types
use umach_int
implicit none
! The strike price
real(kind(1e0)) :: ks = 10.0e0
! The sigma value
real(kind(1e0)) :: sigma = 0.4e0
! Time values for the options
integer, parameter :: nt = 2
real(kind(1e0)) :: time(nt)=(/0.25e0, 0.5e0/)
! Values of the underlying where evaluations are made
! Set initial data precisely. The strike price is a breakpoint.
! Average the derivative limit values from either side.
do i=1,size(xgrid)
if (xgrid(i) < fcn_data % rdata(1)) then
y(3*i-2) = fcn_data % rdata(1) - xgrid(i)
y(3*i-1) = -1.0e0
y(3*i)= 0.0e0
else if (xgrid(i) == fcn_data % rdata(1)) then
y(3*i-2) = 0.0e0
y(3*i-1) = -0.5e0
y(3*i) = 0.0e0
else
y(3*i-2) = 0.0e0
y(3*i-1) = 0.0e0
y(3*i) = 0.0e0
end if
end do
end if
end subroutine fkinit_put
Output
American Option Premium for Vanilla Put, 3 and 6 Months Prior to
Expiry
Number of equally spaced spline knots 121
Number of unknowns 363
Strike= 10.00, Sigma= 0.40, Interest Rate= 0.10
Underlying European American
0.0000 9.7536 9.5137 10.0000 10.0000
2.0000 7.7536 7.5138 8.0000 8.0000
4.0000 5.7537 5.5156 6.0000 6.0000
6.0000 3.7614 3.5680 4.0000 4.0000
8.0000 1.9064 1.9162 2.0214 2.0909
10.0000 0.6516 0.8540 0.6767 0.9034
12.0000 0.1625 0.3365 0.1675 0.3515
14.0000 0.0369 0.1266 0.0374 0.1322
16.0000 0.0088 0.0481 0.0086 0.0504
Example 3 – European Option With Two Payoff Strategies
This example evaluates the price of a European Option using two payoff strategies: Cash-or-Nothing and Vertical Spread. In the first case the payoff function is
The value B is regarded as the bet on the asset price, see Wilmott et al. (1995, p. 39-40). The second case has the payoff function
Both problems use the same boundary conditions. Each case requires a separate integration of the Black-Scholes differential equation, but only the payoff function evaluation differs in each case. The sets of parameters in the computation are:
1. Strike and bet prices K1={10.0}, K2 = {15.0}, and B = {2.0}
2. Volatility σ = {0.4}.
3. Times until expiration = {1/4, 1/2}.
4. Interest rate r = 0.1.
5. xmin = 0, xmax = 30.
6. nx =121, n = 3 ×nx = 363.
(Example feynman_kac_ex3.f90)
! Compute European Option Premium for a Cash-or-Nothing
! and a Vertical Spread Call.
use feynman_kac_int
use hqsval_int
use mp_types
use umach_int
implicit none
! The strike price
real(kind(1e0)) :: ks1 = 10.0e0
! The spread value
real(kind(1e0)) :: ks2 = 15.0e0
! The Bet for the Cash-or-Nothing Call
real(kind(1e0)) :: bet = 2.0e0
! The sigma value
real(kind(1e0)) :: sigma = 0.4e0
! Time values for the options
integer, parameter :: nt = 2
real(kind(1e0)) :: time(nt)=(/0.25e0, 0.5e0/)
! Values of the underlying where evaluation are made
! Use flag passed to decide on boundary condition -
select case (fcn_data % idata(1))
case(1)
bccoefs(1,1:4) = (/1.0e0, 0.0e0, 0.0e0, bet*df/)
case(2)
bccoefs(1,1:4) = (/1.0e0, 0.0e0, 0.0e0,&
(spread-strike_price)*df/)
end select
bccoefs(2,1:4) = (/0.0e0, 1.0e0, 0.0e0, 0.0e0/)
bccoefs(3,1:4) = (/0.0e0, 0.0e0, 1.0e0, 0.0e0/)
return
end select
! Note no time dependence in case (1) for iflag
iflag = 0
end subroutine fkbc_call
Output
European Option Value for A Bet
and a Vertical Spread, 3 and 6 Months Prior to Expiry
Number of equally spaced spline knots 61
Number of unknowns 183
Strike= 10.00, Sigma= 0.40, Interest Rate= 0.10
Bet = 2.00, Spread Value = 15.00
Underlying A Bet Vertical Spread
2.0000 0.0000 0.0000 0.0000 0.0000
4.0000 0.0000 0.0014 0.0000 0.0006
6.0000 0.0110 0.0723 0.0039 0.0447
8.0000 0.2691 0.4302 0.1478 0.3832
10.0000 0.9948 0.9781 0.8909 1.1926
12.0000 1.6094 1.4290 2.1911 2.2273
14.0000 1.8655 1.6922 3.4254 3.1553
16.0000 1.9338 1.8175 4.2263 3.8264
18.0000 1.9476 1.8700 4.6264 4.2492
20.0000 1.9501 1.8904 4.7911 4.4921
22.0000 1.9505 1.8979 4.8497 4.6231
24.0000 1.9506 1.9007 4.8685 4.6909
Example 4– Convertible Bonds
This example evaluates the price of a convertible bond. Here, convertibility means that the bond may, at any time of the holder’s choosing, be converted to a multiple of the specified asset. Thus a convertible bond with price x returns an amount K at time Tunless the owner has converted the bond to νx, ν≥ 1, units of the asset at some time prior to T. This definition, the differential equation and boundary conditions are given in Chapter 18 of Wilmott et al. (1996). Using a constant interest rate and volatility factor, the parameters and boundary conditions are:
1. Bond face value K = {1}, conversion factor ν = 1.125
2. Volatility σ = {0.25}
3. Times until expiration = {1/2,1}
4. Interest rate r = 0.1, dividend D = 0.02
5. xmin = 0, xmax = 4
6. nx = 61, n = 3 ×nx = 183
7. Boundary conditions
8. Terminal data
9. Constraint for bond holder
Note that the error tolerance is set to a pure absolute error of value 10-3. The free boundary constraint f(x,t) = νx is achieved by use of a non-linear forcing term in the subroutine fkforce_cbond. The terminal conditions are provided with the user subroutine fkinit_cbond.
(Example feynman_kac_ex4.f90)
! Compute value of a Convertible Bond
use feynman_kac_int
use hqsval_int
use mp_types
use umach_int
implicit none
! The face value
real(kind(1e0)) :: ks = 1.0e0
! The sigma or volatility value
real(kind(1e0)) :: sigma = 0.25e0
! Time values for the options
integer, parameter :: nt = 2
real(kind(1e0)) :: time(nt)=(/0.5e0, 1.0e0/)
! Values of the underlying where evaluation are made
This example illustrates a method for evaluating a certain “Bermudan Style” or non-standard American option. These options are American Style options restricted to certain dates where the option may be exercised. Since this agreement gives the holder more opportunity than a European option, it is worth more. But since the holder can only exercise at certain times it is worth no more than the American style option value that can be exercised at any time. Our solution method uses the same model and data as in Example 2, but allows exercise at weekly intervals. Thus we integrate, for half a year, over each weekly interval using a European style Black-Scholes model, but with initial data at each new week taken from the corresponding values of the American style option.
(Example feynman_kac_ex5.f90)
! Compute Bermudan-Style Option Premium for Vanilla Put
use feynman_kac_int
use hqsval_int
use mp_types
use umach_int
implicit none
integer :: nout
! The strike price
real(kind(1e0)) :: ks = 10.0e0
! The sigma value
real(kind(1e0)) :: sigma = 0.4e0
! Program working stores
real(kind(1e0)) :: week
! Time values for the options
integer, parameter :: nt = 26
integer, parameter :: ndeg = 6
real(kind(1e0)) :: time(nt), time_end = 0.5e0
! Values of the underlying where evaluation are made
! Set initial data for each week at the previously computed
! American Option values. These coefficients are passed
! in the derived type fcn_data_berm.
do i=1,size(xgrid)
y(3*i-2) = fcn_data_berm % rdata(3+3*i)
y(3*i-1) = fcn_data_berm % rdata(4+3*i)
y(3*i ) = fcn_data_berm % rdata(5+3*i)
end do
end if
end subroutine fkinit_berm_put
Output
American Option Premium for Vanilla Put, 6 Months Prior to Expiry
Exercise Opportunities At Weekly Intervals
Number of equally spaced spline knots 61
Number of unknowns 183
Strike= 10.00, Sigma= 0.40, Interest Rate= 0.10
Underlying Bermudan Style American
0.0000 9.9808 10.0000
2.0000 7.9808 8.0000
4.0000 5.9808 6.0000
6.0000 3.9808 4.0000
8.0000 2.0924 2.0926
10.0000 0.9139 0.9138
12.0000 0.3570 0.3569
14.0000 0.1309 0.1309
16.0000 0.0468 0.0469
Example 6 – Oxygen Diffusion Problem
Our previous examples are from the field of financial engineering. A final example is a physical model. The Oxygen Diffusion Problem is summarized in Crank [4], p. 10-20, 261-262. We present the numerical treatment of the transformed one-dimensional system
A slight difference from the Crank development is that we have reflected the time variable t→-t to match our form of the Feynman-Kac equation. We have a free boundary problem because the interface s(t) is implicit. This interface is implicitly defined by solving the variational relation (ft + fxx‑1)f = 0, f≥ 0. The first factor is zero for 0 ≤x < s(t) and the second factor is zero for s(t) ≤x≤ 1. We list the Feynman-Kac equation coefficients, forcing term and boundary conditions, followed by comments.
The φ forcing term has the property of being almost the value 1 when the solution is larger than the factor ɛ. As the solution, the forcing term φ is almost the value zero. These properties combine to approximately achieve the variational relation that defines the free boundary. Note that the arc of the free boundary is not explicitly available with this numerical method. We have used ɛ = ATOL, the requested absolute error tolerance for the numerical integration.
The boundary condition fx(t,0) = 0, t < 0 is discontinuous as , since the initial data yields fx(0,0) = 1. For the numerical integration we have chosen a boundary value function that starts with the value 1 at t = 0 and rapidly blends to the value zero as the integration proceeds in the negative direction. It is necessary to give the integrator the opportunity to severely limit the step size near t = 0 to achieve continuity during the blending.
In the example code, values of f(0,t) are checked against published values for certain values of t. Also checked are values of f(0,s(t)) = 0 at published values of the free boundary, for the same values of t.
(Example feynman_kac_ex6.f90)
! Integrate Oxygen Diffusion Model found in the book
! Crank, John. Free and Moving Boundary Problems,
! Oxford Univ. Press, (1984), p. 19-20 and p. 261-262.
real(kind(1e0)) :: value, zero = 0.0e0, one = 1.0e0, rt
yl = y(3*interval-2:3*interval+3)
phi = zero
value = fk_ox2 % rdata(1)
ndeg = fk_ox2 % idata(1)
mu = 2
do j=1,local
do l=1,ndeg
bf(1:3) = u(l,1:3)
bf(4:6) = u(l,7:9)
rt = dot_product(yl,bf)
rt = one - (value/(rt + value))**mu
phi(j) = phi(j) + qw(l) * bf(j) * RT
end do
end do
phi = phi * hx
! This is the local derivative matrix for the forcing term -
dphi = zero
do j=1,local
do i = 1,local
do l=1,ndeg
bf(1:3) = u(l,1:3)
bf(4:6) = u(l,7:9)
rt = dot_product(yl,bf)
rt = one/(rt + value)
dphi(i,j) = dphi(i,j) + qw(l) * bf(i) * bf(j) *&
rt**(mu+1)
end do
end do
end do
dphi = mu * dphi * hx * value**mu
return
end subroutine fkforce_ox2
Output
Oxygen Depletion Model, from Crank's Book, p. 261-262,
'Free and Moving Boundary Value Problems'
FEYNMAN_KAC Example 6 - Fixed Sealed Surface Values are correct
FEYNMAN_KAC Example 6 - Free Boundary Position Values are correct
Example 7 – Calculating the Greeks
In this example, routine FEYNMAN_KAC is used to solve for the Greeks, i.e. various derivatives of Feynman-Kac (FK) solutions applicable to the pricing of options and related financial derivatives. In order to illustrate and verify these calculations, the Greeks are calculated by two methods. The first method involves the FK solution to the diffusion model for call options given in Example 1 for the Black-Scholes (BS) case, i.e. . The second method calculates the Greeks using the closed-form BS evaluations which can be found at http://en.wikipedia.org/wiki/The_Greeks.
This example calculates FK and BS solutions V(S,t) to the BS problem and the following Greeks:
Delta =
is the first derivative of the Value, V(S,t), of a portfolio of derivative security derived from underlying instrument with respect to the underlying instrument’s price S.
Gamma =
Theta = is the negative first derivative of V with respect to time t
Charm =
Color =
Rho = is the first derivative of V with respect to the risk-free rate r
Vega = measures sensivity to volatility parameter α of the underlying S
Volga =
Vanna =
Speed =
Intrinsic Greeks include derivatives involving only S and t, the intrinsic FK arguments. In the above list, Value, Delta, Gamma, Theta, Charm, Color and Speed are all intrinsic Greeks. As is discussed in Hanson, R. (2008) “Integrating Feynman-Kac Equations Using Hermite Quintic Finite Elements”, the expansion of the FK solution function V(S,t) in terms of quintic polynomial functions defined on S-grid subintervals and subject to continuity constraints in derivatives 0, 1 and 2 across the boundaries of these subintervals allows Value, Delta, Gamma, Theta, Charm and Color to be calculated directly by routines FEYNMAN_KAC and HQSVAL.
Non-intrinsic Greeks are derivatives of V involving FK parameters other than the intrinsic arguments S and t, such as r and α. Non-intrinsic Greeks in the above list include Rho, Vega, Volga and Vanna. In order to calculate non-intrinsic Greek (parameter) derivatives or intrinsic Greek S-derivatives beyond the second (such as Speed) or t-derivatives beyond the first, the entire FK solution must be calculated 3 times (for a parabolic fit) or five times (for a quartic fit), at the point where the derivative is to be evaluated and at nearby points located symmetrically on either side.
Using a Taylor series expansion of f(σ + ɛ) truncated to m + 1 terms (to allow an m-degree polynomial fit of m+1 data points),
we are able to derive the following parabolic (3 point) estimation of first and second derivatives f (1)(σ) and f (2)(σ) in terms of the three values f(σ‑ɛ ), f(σ) and f(σ + ɛ), where ɛ = ɛfracσ and 0 < ɛfrac << 1:
Similarly, the quartic (5 point) estimation of f (1)(σ) and f (2)(σ) in terms of f(σ‑ 2ɛ), f(σ‑ɛ ), f(σ), f(σ + ɛ), and f(σ + 2ɛ) is:
For our example, the quartic estimate does not appear to be significantly better than the parabolic estimate, so we have produced only parabolic estimates by setting variable iquart to 0. The user may try the example with the quartic estimate simply by setting iquart to 1.
As is pointed out in “Integrating Feynman-Kac Equations Using Hermite Quintic Finite Elements”, the quintic polynomial expansion function used by FEYNMAN_KAC only allows for continuous derivatives through the second derivative. While up to fifth derivatives can be calculated from the quintic expansion (indeed function HQSVAL will allow the third derivative to be calculated by setting optional argument IDERIV to 3, as is done in this example), the accuracy is compromised by the inherent lack of continuity across grid points (i.e. subinterval boundaries).
The accurate second derivatives in S returned by function HQSVAL can be leveraged into a third derivative estimate by calculating three FK second derivative solutions, the first solution for grid and evaluation point set {S, f (2)(S)} and the second and third solutions for solution grid and evaluation point sets {S + ɛ, f (2)(S + ɛ)} and {S + ɛ,f (2)(S‑ɛ)} , where the solution grid and evaluation point sets are shifted up and down by ɛ. In this example, ɛ is set to , where is the average value of S over the range of grid values and 0 < ɛfrac << 1. The third derivative solution can then be obtained using the parabolic estimate
This procedure is implemented in the current example to calculate the Greek Speed. (For comparison purposes, Speed is also calculated directly by setting the optional argument IDERIV to 3 in the call to function HQSVAL. The output from this direct calculation is called “Speed2”.)
To reach better accuracy results, all computations are done in double precision.
The average and maximum relative errors (defined as the absolute value of the difference between the BS and FK values divided by the BS value) for each of the Greeks is given at the end of the output. (These relative error statistics are given for nine combinations of Strike Price and volatility, but only one of the nine combinations is actually printed in the output.) Both intrinsic and non-intrinsic Greeks have good accuracy (average relative error is in the range 0.01 – 0.00001) except for Volga, which has an average relative error of about 0.05. This is probably a result of the fact that Volga involves differences of differences, which will more quickly erode accuracy than calculations using only one difference to approximate a derivative. Possible ways to improve upon the 2 to 4 significant digits of accuracy achieved in this example include increasing FK integration accuracy by reducing the initial stepsize (via optional argument RINITSTEPSIZE), by choosing more closely spaced S and t grid points (by adjusting FEYNMAN_KAC’s input arrays XGRID and TGRID) and by adjusting ɛfrac so that the central differences used to calculate the derivatives are not too small to compromise accuracy.