This function solves the generalized Feynman-Kac PDE on a rectangular grid using a finite element Galerkin method. Initial and boundary conditions are satisfied. The solution is represented by a series of C2 Hermite quintic splines.
intnxgrid (Input) Number of grid lines in the x-direction. nxgrid must be at least 2.
intntgrid (Input) Number of time points where an approximate solution is returned. The value ntgrid must be at least 1.
intnlbcd (Input) Number of left boundary conditions. It is required that 1 ≤nlbcd≤ 3.
int nrbcd (Input) Number of right boundary conditions. It is required that 1 ≤nrbcd ≤ 3.
floatxgrid[] (Input) Array of length nxgrid containing the breakpoints for the Hermite quintic splines used in the x discretization. The points in xgrid must be strictly increasing. The values xgrid[0] and xgrid[nxgrid-1] are the endpoints of the interval.
floattgrid[] (Input) Array of length ntgrid containing the set of time points (in time-remaining units) where an approximate solution is returned. The points in tgrid must be positive and strictly increasing.
voidfcn_fkcfiv (floatx, floatt, int*iflag,float*value) User-supplied function to compute the values of the coefficients for the Feynman-Kac PDE and the initial data function .
floatx (Input) Space variable.
floatt (Input) Time variable.
int*iflag (Input/Output) On entry, iflag indicates which coefficient or data function is to be computed. The following table shows which value has to be returned by fcn_fkcfiv for all possible values of iflag:
iflag
Computed coefficient
-1
0
1
2
3
For non-zero input values of iflag, note when a coefficient does not depend on t. This is done 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.
float*value (Output) Value of the coefficient or initial data function. Which value is computed depends on the input value for iflag, see description of iflag.
voidfcn_fkbcp(intnbc, floatt,int*iflag,floatvalues[]) User-supplied function to define boundary values that the solution of the differential equation must satisfy. There are nlbcd conditions specified at the left end, , and nrbcd conditions at the right end, . The boundary conditions are
intnbc (Input) Number of boundary conditions. At xmin, nbc=nlbcd, at xmax, nbc = nrbcd.
floatt (Input) Time point of the boundary conditions.
int*iflag (Input/Output) On entry, iflag indicates whether the coefficients for the left or right boundary conditions are to be computed:
iflag
Computed boundary conditions
1
Left end, x = xmin
0
Right end, x = xmax
If there is no time dependence for one of the boundaries then set iflag = 0 after the array values is defined for either end point. This flag can avoid unneeded continued computation of the finite element matrices.
floatvalues[] (Output) Array of length 4 * max (nlbcd, nrbcd) containing the values of the boundary condition coefficients in its first 4*nbc locations. The coefficients for xminare stored row-wise according to the following scheme:
The coefficients for xmax are stored similarly.
floaty[] (Output) An array of size (ntgrid+1) by (3 ×nxgrid) containing the coefficients of the Hermite representation of the approximate solution for the Feynman-Kac PDE at time points 0, tgrid[0], …, tgrid[ntgrid-1]. The approximate solution is given by
for
The representation for the initial data at t = 0 is
The (ntgrid + 1) by (3 * nxgrid) matrix
is stored row-wise in array y.
After the integration, use row i of array y as input argument coef in function imsl_f_feynman_kac_evaluate to obtain an array of values for f(x, t) or its partials at time point t=0,tgrid[i-1], i=1,…,ntgrid.
floaty_prime[] (Output) An array of size (ntgrid + 1) by (3 ×nxgrid) containing the first derivatives of y at time points 0, tgrid[0],…,tgrid[ntgrid - 1], i.e.
for
and
The (ntgrid+ 1) by (3 *nxgrid) matrix
is stored row-wise in array y_prime.
After the integration, use row i of array y_prime as input argument coef in function imsl_f_feynman_kac_evaluate to obtain an array of values for the partials at time point t=tgrid[i-1], i=1,…,ntgrid, and row 0 for the partials at t=0.
IMSL_FCN_FKCFIV_W_DATA, voidfcn_fkcfiv(floatx, floatt,int*iflag, float*value, void *data), void*data(Input) User-supplied function to compute the values of the coefficients for the Feynman-Kac PDE and the initial data function . This function also accepts a pointer to the object data supplied by the user.
IMSL_FCN_FKBCP_W_DATA, voidfcn_fkbcp(intnbc, floatt,int*iflag,floatvalues[], void*data),void*data(Input) User-supplied function to define boundary values that the solution of the differential equation must satisfy. This function also accepts a pointer to data supplied by the user.
IMSL_FCN_INIT, voidfcn_fkinit(int nxgrid, int ntgrid, floatxgrid[], floattgrid[], floattime, floatyprime[], floaty[], floatatol[], floatrtol[]) (Input) User-supplied function for adjustment of initial data or as an opportunity for output during the integration steps. The solution values of the model parameters are presented in the arrays y and yprime at the integration points time = 0, tgrid[j], j=0,…,ntgrid-1. At the initial point, integral least-squares estimates are made for representing the initial data . If this is not satisfactory, fcn_fkinit can change the contents of y[] to match data for any reason.
int nxgrid (Input) Number of grid lines in the x-direction.
int ntgrid (Input) Number of time points where an approximate solution is returned.
floatxgrid[](Input) Vector of length nxgrid containing the breakpoints for the Hermite quintic splines used in the x discretization.
floattgrid[](Input) Vector of length ntgrid containing the set of time points (in time-remaining units) where an approximate solution is returned.
floattime (Input) Time variable.
floatyprime[] (Input) Vector of length 3*nxgrid containing the derivative of the coefficients of the Hermite quintic spline at time point time.
floaty[] (Input/Output) Vector of length 3 ×nxgrid containing the coefficients of the Hermite quintic spline at time point time.
floatatol[] (Input/Output) Array of length 3 ×nxgridcontaining absolute error tolerances.
IMSL_FCN_INIT_W_DATA, void fcn_fkinit(int nxgrid, int ntgrid, floatxgrid[], floattgrid[], floattime, floatyprime[], floaty[], floatatol[], floatrtol[], void *data),void*data (Input) User-supplied function for adjustment of initial data or as an opportunity for output during the integration steps which also accepts a pointer to data supplied by the user. For an explanation of the other arguments of function fcn_fkinit, see optional argument IMSL_FCN_INIT.
Function fcn_fkforce is used in case there is a non-zero term in the Feynman-Kac differential equation. If function fcn_fkforce is not used, it is assumed that is identically zero.
intinterval (Input) Index indicating the bounds xgrid[interval-1] and xgrid[interval] of the integration interval, 1≤interval≤nxgrid-1.
intndeg (Input) The degree used for the Gauss-Legendre formulas.
int nxgrid (Input) Number of grid lines in the x-direction.
floaty[] (Input) Vector of length 3*nxgrid containing the coefficients of the Hermite quintic spline representing the solution of the Feynman-Kac equation at time point time.
float time (Input) Time variable.
floatwidth (Input) The interval width, width =xgrid[interval]-xgrid[interval-1].
floatxlocal[] (Input) Array of length ndeg containing the Gauss-Legendre points translated and normalized to the interval [xgrid[interval-1],xgrid[interval]].
float qw[](Input) Vector of length ndeg containing the Gauss-Legendre weights.
floatu[] (Input) Array of dimension 12 by ndeg containing the basis function values that define at the Gauss-Legendre points xlocal. Setting u[i+k*ndeg] and xlocal[i], is defined as
floatphi[] (Output) Vector of length 6 containing Gauss-Legendre approximations for the local contributions
where time and
Vector phi contains elements
for i=0,…,5.
floatdphi[] (Output) Array of dimension 6 by 6 containing a Gauss-Legendre approximation for the Jacobian of the local contributions at time,
The approximation to this symmetric matrix is stored row-wise, i.e.
for i, j = 0, …, 5.
IMSL_FCN_FORCE_W_DATA, voidfcn_fkforce(intinterval, intndeg, intnxgrid, float y[], floattime, floatwidth, float xlocal[], floatqw[], floatu[], floatphi[], float dphi[], void*data),void*data (Input) Function fcn_fkforce is used in case there is a non-zero term in the Feynman-Kac differential equation. This function also accepts a data pointer to data supplied by the user. For an explanation of the other arguments of function fcn_fkforce, see optional argument IMSL_FCN_FORCE.
IMSL_ATOL_RTOL_SCALARS, floatatol, float rtol (Input) Scalar values that apply to the error estimates of all components of the solution y in the differential equation solver SDASLX. See optional argument IMSL_ATOL_RTOL_ARRAYS if separate tolerances are to be applied to each component of y.
Default: atol and rtol are set to 10-3 in single precision and 10-5 in double precision.
IMSL_ATOL_RTOL_ARRAYS, floatatol[], floatrtol[], (Input) Componentwise tolerances are used for the computation of solution y in the differential equation solver SDASLX. Arguments atol and rtol are pointers to arrays of length 3 ×nxgrid to be used for the absolute and relative tolerance and to be applied to each component of the solution, y. See optional argument IMSL_ATOL_RTOL_SCALARS if scalar values of absolute and relative tolerances are to be applied to all components.
Default: All elements of atol and rtol are set to 10-3 in single precision and 10-5 in double precision.
IMSL_NDEGREE,intndeg (Input) The degree used for the Gauss-Legendre formulas for constructing the finite element matrices. It is required that ndeg ≥ 6.
Default: ndeg = 6.
IMSL_TDEPEND, inttdepend[] (Output) Vector of length 7 indicating time dependence of the coefficients, boundary conditions and function φ in the Feynman-Kac equation. If tdepend[i]= 0 then argument i is not time dependent, if tdepend[i]=1 then argument i is time dependent.
i
Computed coefficient
0
1
2
3
4
Left boundary conditions
5
Right boundary conditions
6
φ
IMSL_MAX_STEP, floatmax_stepsize (Input) This is the maximum step size the integrator may take.
Default: max_stepsize = imsl_f_machine(2), the largest possible machine number.
IMSL_INITIAL_STEPSIZE, floatinit_stepsize (Input) The starting step size for the integration. Must be less than zero since the integration is internally done from t=0 to t=tgrid[ntgrid-1] in a negative direction.
Default: init_stepsize = -Ɛ, where Ɛ is the machine precision.
IMSL_MAX_NUMBER_STEPS, int max_steps (Input) The maximum number of steps between each output point of the integration.
Default: maxsteps = 500000.
IMSL_STEP_CONTROL, intstep_control (Input) Indicates which step control algorithm is used for the integration. If step_control = 0, then the step control method of Söderlind is used. If step_control = 1, then the method used by the original Petzold code SASSL is used.
Default: step_control = 0.
IMSL_MAX_BDF_ORDER, intmax_bdf_order (Input) Maximum order of the backward differentiation formulas used in the integrator. It is required that 1≤max_bdf_order ≤ 5.
Default: max_bdf_order = 5.
IMSL_T_BARRIER, floatt_barrier (Input) This optional argument controls whether the code should integrate past a special point, t_barrier, and then interpolate to get and at the points in tgrid[]. If this optional argument is present, the integrator assumes the equations either change on the alternate sides of t_barrier or they are undefined there. In this case, the code creeps up to t_barrier in the direction of integration. It is required that t_barrier≥tgrid[ntgrid-1].
Default: t_barrier = tgrid[ntgrid-1].
IMSL_ISTATE, int istate[] (Output) An array of length 7 whose entries flag the state of computation for the matrices and vectors required in the integration. For each entry, a zero indicates that no computation has been done or 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
Entry in istate
0
Mass Matrix, M
1
Stiffness matrix, N
2
Bending matrix, R
3
Weighted mass, K
4
Left boundary conditions
5
Right- boundary conditions
6
Forcing term
Default: istate[i] = 0 for I = 0,…,6.
IMSL_EVALS, intnval[] (Output) Array of length 3 summarizing the number of evaluations required during the integration.
i
nval[i]
0
Number of residual function evaluations of the DAE used in the model.
1
Number of factorizations of the differential matrix associated with solving the DAE.
2
Number of linear system solve steps using the differential matrix.
Description
The generalized Feynman-Kac differential equation has the form
where the initial data satisfies . The derivatives are
The function imsl_f_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 for the time-dependent coefficients
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. The coefficients, payoff, boundary conditions and forcing term for American and European options are defined by the user functions fkcfiv_put, fkbcp_put and fkforce_put, respectively. One breakpoint is set exactly at the strike price.
American Option Premium for Vanilla Put, 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
Underlying European American
0.0000 9.7534 9.5136 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.7615 3.5683 4.0000 4.0000
8.0000 1.9070 1.9168 2.0170 2.0865
10.0000 0.6529 0.8548 0.6771 0.9030
12.0000 0.1632 0.3371 0.1680 0.3519
14.0000 0.0372 0.1270 0.0373 0.1321
16.0000 0.0088 0.0483 0.0084 0.0501
Example 2
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 . A numerical solution of this diffusion model yields the price of a call option. Various values of the strike price , 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. strike price .
3. volatility .
4. times until expiration .
5. underlying prices .
6. interest rate .
7. .
8. .
With this model the Feynman-Kac differential equation is defined by identifying:
The payoff function is the “vanilla option”, .
#include <imsl.h>
#include <stdio.h>
#include <math.h>
#define max(A,B) ((A) >= (B) ? (A) : (B))
#define NXGRID 121
#define NTGRID 3
#define NV 3
void fcn_fkcfiv(float, float, int *, float *, void *);
void fcn_fkbcp(int, float, int *, float[], void *);
int main()
{
/* Compute Constant Elasticity of Variance Model for Vanilla Call */
/* The set of strike prices */
float KS[] = { 15.0, 20.0, 25.0};
/* The set of sigma values */
float sigma[] = { 0.2, 0.3, 0.4};
/* The set of model diffusion powers */
float alpha[] = { 2.0, 1.0, 0.0};
/* Time values for the options */
int nt = 3;
float time[] = { 1.0/12.0, 4.0/12.0, 7.0/12.0 };
/* Values of the underlying where evaluations are made */
float xs[] = { 19.0, 20.0, 21.0};
/* Value of the interest rate and continuous dividend */
float r=0.05, dividend=0.0;
/* Values of the min and max underlying values modeled */
float x_min=0.0, x_max=60.0;
/* Define parameters for the integration step. */
int nint = NXGRID-1, n=3*NXGRID;
float xgrid[NXGRID], y[(NTGRID+1)*3*NXGRID];
float yprime[(NTGRID+1)*3*NXGRID], f[NTGRID*NV];
float dx;
/* Number of left/right boundary conditions */
int nlbcd = 3, nrbcd = 3;
float usr_data[6];
int i,i1,i2,i3,j;
/* Define equally-spaced grid of points for the underlying price */
dx = (x_max-x_min)/((float) nint);
xgrid[0] = x_min;
xgrid[NXGRID-1] = x_max;
for (i=2; i<=NXGRID-1; i++)
xgrid[i-1] = xgrid[i-2]+dx;
printf("%2sConstant Elasticity of Variance Model for Vanilla Call\n",
void fcn_fkbcp(int nbc, float tx, int *iflag, float val[],
void *data_ptr)
{
float x_max, df, interest_rate, strike_price;
float *data = NULL;
data = (float *)data_ptr;
strike_price = data[0];
x_max = data[1];
interest_rate = data[4];
switch (*iflag)
{
case 1:
val[0] = 1.0; val[1] = 0.0; val[2] = 0.0;
val[3] = 0.0; val[4] = 0.0; val[5] = 1.0;
val[6] = 0.0; val[7] = 0.0; val[8] = 0.0;
val[9] = 0.0; val[10] = 1.0; val[11] = 0.0;
/* Note no time dependence at left end */
*iflag = 0;
break;
case 2:
df = exp(interest_rate*tx);
val[0] = 1.0; val[1] = 0.0; val[2] = 0.0;
val[3] = x_max - df*strike_price; val[4] = 0.0;
val[5] = 1.0; val[6] = 0.0; val[7] = 1.0;
val[8] = 0.0; val[9] = 0.0; val[10] = 1.0;
val[11] = 0.0;
break;
}
data = NULL;
return;
}
Output
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.2577 4.4730
Call Option Values 5.0624 5.2507 5.4491
Call Option Values 6.0624 6.2487 6.4386
Strike=20.00, Sigma= 0.20, Alpha= 2.00
Call Option Values 0.1310 0.5956 0.9699
Call Option Values 0.5028 1.0889 1.5100
Call Option Values 1.1979 1.7485 2.1751
Strike=25.00, Sigma= 0.20, Alpha= 2.00
Call Option Values 0.0000 0.0113 0.0742
Call Option Values 0.0000 0.0372 0.1614
Call Option Values 0.0007 0.1025 0.3132
Strike=15.00, Sigma= 0.30, Alpha= 2.00
Call Option Values 4.0637 4.3399 4.6623
Call Option Values 5.0626 5.2945 5.5788
Call Option Values 6.0624 6.2709 6.5241
Strike=20.00, Sigma= 0.30, Alpha= 2.00
Call Option Values 0.3103 1.0274 1.5500
Call Option Values 0.7315 1.5422 2.1024
Call Option Values 1.3758 2.1689 2.7385
Strike=25.00, Sigma= 0.30, Alpha= 2.00
Call Option Values 0.0006 0.1112 0.3547
Call Option Values 0.0038 0.2170 0.5552
Call Option Values 0.0184 0.3857 0.8225
Strike=15.00, Sigma= 0.40, Alpha= 2.00
Call Option Values 4.0759 4.5136 4.9673
Call Option Values 5.0664 5.4199 5.8321
Call Option Values 6.0635 6.3577 6.7294
Strike=20.00, Sigma= 0.40, Alpha= 2.00
Call Option Values 0.5116 1.4645 2.1286
Call Option Values 0.9623 1.9957 2.6944
Call Option Values 1.5815 2.6110 3.3230
Strike=25.00, Sigma= 0.40, Alpha= 2.00
Call Option Values 0.0083 0.3288 0.7790
Call Option Values 0.0285 0.5169 1.0657
Call Option Values 0.0813 0.7688 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.0241 0.1061
Call Option Values 0.1498 0.4102 0.6483
Call Option Values 1.0832 1.3313 1.5772
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.4310
Call Option Values 5.0624 5.2477 5.4310
Call Option Values 6.0624 6.2477 6.4310
Strike=20.00, Sigma= 0.30, Alpha= 1.00
Call Option Values 0.0016 0.0812 0.2214
Call Option Values 0.1981 0.4981 0.7535
Call Option Values 1.0836 1.3441 1.6018
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.0072 0.1556 0.3445
Call Option Values 0.2501 0.5919 0.8720
Call Option Values 1.0867 1.3783 1.6577
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.0007
Call Option Values 0.0000 0.0002 0.0059
Strike=15.00, Sigma= 0.20, Alpha= 0.00
Call Option Values 4.0625 4.2479 4.4311
Call Option Values 5.0625 5.2479 5.4312
Call Option Values 6.0623 6.2479 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.0624 4.2479 4.4311
Call Option Values 5.0625 5.2479 5.4311
Call Option Values 6.0623 6.2479 6.4311
Strike=20.00, Sigma= 0.30, Alpha= 0.00
Call Option Values 0.0000 -0.0000 0.0029
Call Option Values 0.0895 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.0624 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.0001 0.0111
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 3
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 =61, n = 3 ×nx = 183.
#include <imsl.h>
#include <stdio.h>
#include <math.h>
#define max(A,B) ((A) >= (B) ? (A) : (B))
#define NXGRID 61
#define NTGRID 2
#define NV 12
void fkcfiv_call(float, float, int *, float *, void *);
void fkbcp_call(int, float, int *, float[], void *);
int main()
{
int i;
/* The strike price */
float KS1 = 10.0;
/* The spread value */
float KS2 = 15.0;
/* The Bet for the Cash-or-Nothing Call */
float bet = 2.0;
/* The sigma value */
float sigma = 0.4;
/* Time values for the options */
int nt = 2;
float time[] = {0.25, 0.5};
/* Values of the underlying where evaluations are made */
float xs[NV];
/* Value of the interest rate and continuous dividend */
float r = 0.1, dividend=0.0;
/* Values of the min and max underlying values modeled */
void fkbcp_call(int nbc, float tx, int *iflag, float val[],
void *data_ptr)
{
float strike_price, spread, bet, interest_rate, df;
int *data_int = NULL;
float *data_real = NULL;
struct struct_data {
int idope[1];
float rdope[7];
};
struct struct_data *data = NULL;
data = data_ptr;
data_int = data->idope;
data_real = data->rdope;
strike_price = data_real[0];
bet = data_real[1];
spread = data_real[2];
interest_rate = data_real[5];
switch (*iflag)
{
case 1:
val[0] = 1.0; val[1] = 0.0; val[2] = 0.0;
val[3] = 0.0; val[4] = 0.0; val[5] = 1.0;
val[6] = 0.0; val[7] = 0.0; val[8] = 0.0;
val[9] = 0.0; val[10] = 1.0; val[11] = 0.0;
/* Note no time dependence in case (1) for IFLAG */
*iflag = 0;
break;
case 2:
/* This is the discount factor using the risk-free
interest rate */
df = exp(interest_rate*tx);
/* Use flag passed to decide on boundary condition */
switch (data_int[0])
{
case 1:
val[0] = 1.0; val[1] = 0.0; val[2] = 0.0;
val[3] = bet*df;
break;
case 2:
val[0] = 1.0; val[1] = 0.0; val[2] = 0.0;
val[3] = (spread-strike_price)*df;
break;
}
val[4] = 0.0; val[5] = 1.0; val[6] = 0.0;
val[7] = 0.0; val[8] = 0.0; val[9] = 0.0;
val[10] = 1.0; val[11] = 0.0;
break;
}
data_real = NULL;
data_int = NULL;
data = NULL;
return;
}
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.0722 0.0039 0.0446
8.0000 0.2690 0.4304 0.1479 0.3831
10.0000 0.9948 0.9781 0.8909 1.1927
12.0000 1.6095 1.4287 2.1911 2.2274
14.0000 1.8654 1.6924 3.4255 3.1551
16.0000 1.9337 1.8177 4.2264 3.8263
18.0000 1.9476 1.8700 4.6264 4.2492
20.0000 1.9501 1.8903 4.7911 4.4922
22.0000 1.9505 1.8979 4.8497 4.6232
24.0000 1.9506 1.9007 4.8685 4.6909
Example 4
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 returns an amount at time unless the owner has converted the bond to units of the asset at some time prior to . 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 , conversion factor
2. Volatility
3. Times until expiration
4. Interest rate , dividend
5.
6.
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 . The free boundary constraint is achieved by use of a non-linear forcing term in the function fkforce_cbond. The terminal conditions are provided with the user function fkinit_cbond.
#include <imsl.h>
#include <stdio.h>
#include <math.h>
#define max(A,B) ((A) >= (B) ? (A) : (B))
#define NXGRID 61
#define NTGRID 2
#define NV 13
void fkcfiv_cbond(float, float, int *, float *, void *);
void fkbcp_cbond(int, float, int *, float[], void *);