MATH40082 (Computational Finance) Assignment No. 2

24
MATH40082 (Computational Finance) Assignment No. 2: Advanced Methods student ID: 10402042 Date: May 11, 2021

Transcript of MATH40082 (Computational Finance) Assignment No. 2

MATH40082 (Computational Finance)Assignment No. 2: Advanced Methods

student ID: 10402042

Date: May 11, 2021

Contents

1 European Options 11.1 Derivate the boundary condition . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1

1.2 Write code for Crank-Nicolson method . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1

1.3 Analyze the effect of β and σ on the results . . . . . . . . . . . . . . . . . . . . . . . . . . 5

1.4 Caculate S0 by using cubic interpolate . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7

2 American Options 92.1 Write code for Crank-Nicolson method with penalty . . . . . . . . . . . . . . . . . . . . . . 9

2.2 Plot out the value of bond contract related to S . . . . . . . . . . . . . . . . . . . . . . . . 9

2.3 Study how the r affects the results . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10

2.4 Provide the most accurate value possible . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11

Appendices 12

A C++ code 12A.1 European Options code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12

A.2 American Options code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17

1 European Options

1.1 Derivate the boundary condition

Put V (S, t) = SA(t) +B(t) into ∂V∂t + κ(X − S)∂V∂S − rV + Ce−αt = 0 ,we compute

SA′ +B′ +K (X − S)A− rSA− rB + Ce−αt

=(A′ − kA− rA

)S +B′ + kXA− rB + Ce−αt

=[A′ − (k + r)A

]S +B′ − rB + kXA+ Ce−αt

= 0,so we can get Differential equations

A′ − (k + r)A = 0

B′ − rB + kXA+ Ce−αt = 0.

The terminal condition is given by

V (S, T ) = SA (T ) +B (T ) = RS,

so we have two terminal conditions for each

A (T ) = R

B (T ) = 0.

The solutions of differential equations are shown

A (t) = Re−(k+r)(T−t)

B (t) = XR(

1− e−(k+r)(T−t))

+Ce−αt

α+ r

(1− e−α(T−t)

),

then we get the expression of V (s, t)

V (s, t) = SA (t) +B (t)

= SRe−(k+r)(T−t) +XR(

1− e−(k+r)(T−t))

+Ce−αt

α+ r

(1− e−α(T−t)

).

(1)

1.2 Write code for Crank-Nicolson method

Before coding, it is necessary to derive the finite-difference equations with a Crank-Nicolson scheme.

First of all, let

∂V

∂t+

1

2σ2S2β ∂

2V

∂S2+ κ(θ(t)− S)

∂V

∂S− rV + Ce−αt = 0 (2)

discreted. There two ways including forward difference and backward difference which are

introduced below.

1

We denoteµj,n = κ (θ (n∆t)− j∆x) , σ2

j,n = σ2 (j∆x)2β , fj,n = V (j∆x, n∆t)

xmin ≡ 0, x1, x2..., xJ−1, xJ ≡ Smax

tmin ≡ 0, t1, t2..., tn−1, tN ≡ T ,where

xj = x0 + j∆x, tj = t0 + j∆x

∆x = (xmax − xmin) /J = Smax/J

∆t = (tmax − tmin) /N = T/N .

∆x is the step length of S,∆t is the step length of t, x0 = 0 means that the initial price is zero, t0 = 0

means that the initial time is zero, Smax which we set equals 200,means that we think 200 as the supremum

of S, tmax is set by T = 3.

We have splitted the price S and time t into equal grids. which means the step lengths of S and T are

equal respectively.

When 0 < j < J , We can compute backward difference and forward difference

fj,n+1 − fj,n∆t

+ µj,n+1Dxfj,n+1 +1

2σ2j,n+1D

2xfj,n+1 − rfj,n+1 + Ce−α(n+1)∆t = 0

fj,n+1 − fj,n∆t

+ µj,nDxfj,n +1

2σ2j,nD

2xfj,n − rfj,n + Ce−αn∆t = 0,

which can be integrated into a Crank-Nicolson scheme

fj,n+1 − fj,n∆t

+1

2{µj,n+1Dxfj,n+1 + µj,nDxfj,n}

+1

2

{1

2σ2j,n+1D

2xfj,n+1 +

1

2σ2j,nD

2xfj,n

}− 1

2{rfj,n+1 + rfj,n}+

Ce−α(n+1)∆t + Ce−α(n∆t)

2= 0.

Above equation is just shorthand for

aj,nfj−1,n + bj,nfj,n + cj,nfj+1,n =

− aj,n+1fj−1,n+1 + b∗j,n+1fj,n+1 − cj,n+1fj+1,n+1 +Ce−α(n+1)∆t + Ce−α(n∆t)

2,

2

where the right hand of equation denoted by dj,n+1 , and

aj,n =1

4∆t

(σ2j,n

(∆x)2 −µj,n∆x

)=

1

4∆t

(σ2 (j∆x)2β

(∆x)2 − k (θ (n∆t)− j∆x)

∆x

)

bj,n = −1− 1

2∆t

(σ2j,n

(∆x)2 + r

)= −1− 1

2∆t

(σ2 (j∆x)2β

(∆x)2 + r

)

cj,n =1

4∆t

(σ2j,n

(∆x)2 +µj,n∆x

)=

1

4∆t

(σ2 (j∆x)2β

(∆x)2 +k (θ (n∆t)− j∆x)

∆x

)

b∗j,n = −1 +1

2∆t

(σ2j,n

(∆x)2 + r

)= −1 +

1

2∆t

(σ2 (j∆x)2β

(∆x)2 + r

).

(3)

For j = 0 or j = J , we complete

aJ,nfJ−1,n + bJ,nfJ,n = dJ,n+1

b0,nf0,n + c0,nf1,n = d0,n+1,

where

aJ,n = 0, bJ,n = 1, dJ,n+1 = fJ,n = SmaxA (n∆t) +B (n∆t) . (4)

The SmaxA(t) + B(t) is mentioned by equation 1,which derivated by boundary condition at S → ∞Recalling that we have not use boundary condition for S = 0, which we guess that b0,n,c0,n and d0,n+1 are

related to.Then this gives the derivation of b0,n, c0,n and d0,n+1.

For S = 0, original differential equation 2 can be reduced to

∂V

∂t+ κθ(t)

∂V

∂S− rV + Ce−αt = 0,

and let it discreted,we get

f0,n+1 − f0,n

∆t+ kθ (t)

f1,n − f0,n

∆x− rf0,n + Ce−α∆tn = 0,

or equivalently,

(1 +

kθ (t)∆t

∆x+ r∆t

)f0,n −

kθ (t)∆t

∆xf1,n = f0,n+1 + C∆te−αn∆t.

By comparing the forms of the equation above,we can see immediately that

b0,n = 1 +kθ (t)∆t

∆x+ r∆t

c0,n = −kθ (t)∆t

∆x

d0,n+1 = f0,n+1 + C∆te−αn∆t.

(5)

3

We end up with a matrix equation

b0,n c0,n 0 0 0 · · · 0

a1,n b1,n c1,n 0 0 · · ·0 a2,n b2,n c2,n 0 · · · 0... . . . . . . . . . ...... . . . . . . . . . ...

0 · · · 0 0 aJ−1,n bJ−1,n cJ−1,n

0 · · · 0 0 0 aJ,n bJ,n

f0,n

f1,n

f2,n

...

fJ,n

=

d0,n+1

d1,n+1

d2,n+1

...

...

dJ−1,n+1

dJ,n+1

.

To solve the Tridiagonal equation, LU Factorization is a good choose, which means we need to use

Gaussian elimination, forward replace and backward replace in turn to evaluate this equation.The details are

shown below:

1). Gaussian eliminationfor j = 0, 1, · · · , J − 1 :

aj+1,n := aj+1,n/bj,n

bj+1,n := bj+1,n − aj+1,ncj,n

2). forward replacefor j = 0,1,..., J − 1 :

dj+1,n+1 := dj+1,n+1 − aj+1,ndj,n+1

3). backward replacefJ,n := dJ,n+1/bJ,n

for j = J − 1, J − 2, · · · , 1, 0 :

fj,n := [dj,n+1 − cj,nfj+1,n] /bj,n

The above algorithm can be written into a C++ program, which shown in the appendix. It is also

necessary for us to explain the values and meanings of the parameters used. These basic parameters are

given in the question. Alternatively, we also set the step length of S and t by ourselves, ,dx = 0.01, dt = 0.01

. According to the fact that the price of S is around 45, It gives Smax=200.For intuition, we organize it into

the following table.

4

Parameter meaning valuef the value of bond unsolvedT time 3F principal 190R - - 4κ response rates 0.8333µ - - 0.0191X - - 46.54C - - 1.87α - - 0.02β elastic coefficient 0.754σ volatility 0.812θ equilibrium price variabler risk-free rate 0.0197Pp price 200t0 American style deadline 1.0702

∆x price step length 0.01∆t time step length 0.01Smax max of S 200Jt S steps 20000Nt time steps 20000

Table 1: Parameter meaning table

1.3 Analyze the effect of β and σ on the results

We have plotted out the values of the option V (S, t) as a function of the underlying asset priceS(at t =

0) for β = 1, σ = 0.314 and β = 0.754, σ = 0.812 respectively,which are shown below.

5

Figure 1: the values of the option related to S for two cases respectively

The figures above show that price of bond is positively correlated with S, which is similar to the shape

of vanilla options. From this perspective, there is no obvious difference. Further, we merge the two plots

together and draw it with S value between 45− 53, as shown below.

Figure 2: the prices of both bond is related to S in the vicinity of S = 48

In the vicinity of S = 48, we find that the price of bond corresponding to the two cases are equal.

According to experience, both β and σ have a positive contribution to the price of bond, When S < 48, the

6

σ of case 2 is larger, while the corresponding price of bond is larger. When S > 48, the beta of case 1 is

larger, while the corresponding price of bond is larger,which shows that when S is very large, the effect of β

is greater, and when S is very small, contribution of σ is even greater.

1.4 Caculate S0 by using cubic interpolate

We use cubic interpolate method to interpolate the results of Crank-Nicolson Finite Difference to get the

estimate for the option value at S0. The larger the iMax and jMax, the smaller the corresponding ∆x and

∆t,the longer the calculation time,meaning that the lower the efficiency, but the more accurate. Moreover,

the larger Smax, the longer the calculation time and the more accurate the result.

Therefore, we must weigh between efficiency and accuracy. In the figure below, we show the value

of bond contract related to S near S0(46.54) of the different numerical parameters (∆t,∆x, Smax), which

related to (iMax, jMax, Smax).

Figure 3: the value of bond at S0 related to (∆t,∆x, Smax)

7

As can be seen from the above figure, Smax and ∆x have little effect on the result, while ∆t has a

significant effect. So when we set them , we can increase the number of time steps and appropriately reduce

the number of Smax and steps of underlying asset price S ,by which it can maintain accuracy and efficiency

. Alternatively, for a clearer comparison, we also record the data in the table below.

Smax = 100 dx=0.01 dx=0.05 dx=0.1dt=0.01 217.305 217.305 217.3045dt=0.05 217.403 217.4031 217.4033dt=0.1 217.594 217.594 217.5937

Smax = 150 dx=0.01 dx=0.05 dx=0.1dt=0.01 217.402 217.4022 217.4027dt=0.05 217.504 217.504 217.5039dt=0.1 217.697 217.6969 217.697

Smax = 200 dx=0.01 dx=0.05 dx=0.1dt=0.01 217.405 217.405 217.3045dt=0.05 217.506 217.5059 217.5069dt=0.1 217.7 217.6999 217.4049

Table 2: the value of bond at S0 related to (∆t,∆x, Smax)

Themost accurate estimate ofS is 217.405. In practice, we tend to use (∆t = 0.01,∆x = 0.05, Smax =

150) to caculate the result, which is near the most accurate estimate, while its efficient is higher. At this

time, the total number of calculations is T/∆t× Smax/∆x = 900, 000.

8

2 American Options

2.1 Write code for Crank-Nicolson method with penalty

I would like to use method with penalty. We should solve the differential equation

for ∆tn < t0

∂V

∂t+

1

2σ2S2β ∂

2V

∂S2+ κ (θ (t)− S)

∂V

∂t− rV + Ce−αt + λmax {Pp − V, 0} = 0,

Where λ is a large number that penalizes deviations away from the condition

V > Pp, t 6 t0.

If it were the case that V < Pp, the penalty term would dominate the equation and

limλ→∞

V → Pp

We only need to change the backward replace of european bonds prcing program

fJ,n := max {dJ,n+1/bJ,n, PP }

for j =J − 1, J − 2, · · · , 1, 0 :

fj,n := max {[dj,n+1 − cj , nfj+1,n] /bj,n, PP } ,wherePpmeans value obtained from early exercise when t < t0, t0 is a time constant.Related parameters

can be understood by seeing Table 1. This program is essentially the same as the penalty method while it

looks more concise.

2.2 Plot out the value of bond contract related to S

We have plotted out the value of your American style bond contract as a function of asset price S, at

t = 0, and mark on the graph any optimal decision points. The red lines indicates optimal decision points of

which max value is 22.25. The figure can be seen below.

9

Figure 4: the value of bond contract related to S

2.3 Study how the r affects the results

weplot out three different lines for theAmerican style option valueV (S, t) as a function of the underlying

asset price S(at t = 0) on the same graph, using three different values of r ∈ {0.00985, 0.0197, 0.02955},with all other parameters as standard.

10

Figure 5: three different r as a function of S

From above figure, it is easy for us to spot that r is positively correlated with the price of bond regardless

of S. We can explain this finding from the perspective of economics. The risk-free interest rate measures

the opportunity cost of funds, the greater the value, the lower the relative value of derivative securities.

2.4 Provide the most accurate value possible

For grid,we use time step rotation strategy to accelerate Isometric grids are usually not the best choice

for numerical calculations. If the space-time grid points can be set between the density and the density

according to the local smoothness of the true solution, the overall calculation amount to meet the user’s

accuracy requirements using the same type of format will be significantly reduced. The CPU time will be

greatly reduced.

For interpolation,we use radial basis function quasi-interpolation to improve accuracy. it does not need

to solve the linear equations, and some quasi-interpolation also has polynomial reproducibility, monotonicity

preservation, convexity preservation and other shape-preserving properties. Among them, the more repre-

sentative one is Multiquadric (MQ) quasi-interpolation method. We use an MQ quasi-interpolation method,

and use this method to solve the numerical solutions of the above differential equations.

For computer,We use parallel computing. For each n,a and b can be calculated at the same time to save

time in gaussian eliminationate procedure.

11

A C++ code

A.1 European Options code

1

2 // European_option.cpp -- pricing program

3 // caculate Eurppean_option price

4

5 #include <iostream>

6 #include <vector>

7 #include <cmath>

8 using namespace std;

9 //define const

10 const double T = 3;

11 const double S_max = 200;

12 const double F = 190;

13 const double R = 4;

14 const double r = 0.0197;

15 const double k = 0.08333;

16 const double mu = 0.0191;

17 const double X = 46.54;

18 const double C = 1.87;

19 const double alpha = 0.02;

20 const double dx = 0.1;

21 const double dt = 0.01;

22 const int J = S_max / dx;

23 const int N = T / dt;

24 // declare function

25 double a_fun(int j, int n, double beta, double sigma);

26 double b_fun(int j, int n, double beta, double sigma);

27 double c_fun(int j, int n, double beta, double sigma);

28 double d_fun(int j, int n, vector<double> f, double beta, double sigma);

29 double terminal_condition(int j);

30 double boundary_condition_at_infinite(int n);

31 vector<double> Crank_Nicolson_method(double beta, double sigma);

32

12

33 int main()

34 {

35 double beta;

36 double sigma;

37 cout << "\nbeta\n";

38 cin >> beta;

39 cout << "\nsigma\n";

40 cin >> sigma;

41 cout << "please wait..." << endl;

42 vector<double> result = Crank_Nicolson_method(beta, sigma);

43 cout << "the results are:" << endl;

44 for (auto iter = result.begin(); iter != result.end(); iter++) {

45 cout << *iter << endl;

46 }

47 system("pause");

48 }

49

50

51

52 //define function

53 double terminal_condition(int j) {

54 double S = j * dx;

55 return F > R * S ? F : R * S;

56 }

57

58 double boundary_condition_at_infinite(int n) {

59 double t = n * dt;

60 double At = R * exp(-(k + r) * (T - t));

61 double Bt = (X * R - C / (alpha + r) * exp(-alpha * T)) * exp(-r * (T - t)) \

62 + C / (alpha + r) * exp(-alpha * t) - X * R * exp(-(k + r) * (T - t));

63 return S_max * At + Bt;

64 }

65

66 double a_fun(int j, int n, double beta, double sigma) {

67 double S = j * dx;

13

68 double t = n * dt;

69 double theta = (1 + mu) * X * exp(mu * t);

70 if (j == J)return 0;

71 // 1=<j<J

72 else {

73 double sigma2_j_n = sigma * sigma * pow(S, 2 * beta);

74 double mu_j_n = k * (theta - S);

75 return 0.25 * dt * (sigma2_j_n / (dx * dx) - mu_j_n / dx);

76 }

77 }

78

79 double b_fun(int j, int n, double beta, double sigma) {

80 // 1=<j<J

81 double S = j * dx;

82 double t = n * dt;

83 double theta = (1 + mu) * X * exp(mu * t);

84 if (j == 0) {

85 return 1 + (k * theta/dx + r) * dt;

86 }

87 if (j == J)return 1;

88 else {

89 double sigma2_j_n = sigma * sigma * pow(S, 2 * beta);

90 double mu_j_n = k * (theta - S);

91 return -1 - 0.5 * dt * (sigma2_j_n / (dx * dx) + r);

92 }

93 }

94

95 double c_fun(int j, int n, double beta, double sigma) {

96 double S = j * dx;

97 double t = n * dt;

98 double theta = (1 + mu) * X * exp(mu * t);

99 if (j == 0) {

100 return -k * theta * dt / dx;

101 }

102 else {

14

103 // 1=<j<J

104 double sigma2_j_n = sigma * sigma * pow(S, 2 * beta);

105 double mu_j_n = k * (theta- S);

106 return 0.25 * dt * (sigma2_j_n / (dx * dx) + mu_j_n / dx);

107 }

108 }

109

110 double b_star_fun(int j, int n, double beta, double sigma) {

111 // 1=<j<J

112 double S = j * dx;

113 double t = n * dt;

114 double theta = (1 + mu) * X * exp(mu * t);

115 double sigma2_j_n = sigma * sigma * pow(S, 2 * beta);

116 double mu_j_n = k * (theta - S);

117 return -1 + 0.5 * dt * (sigma2_j_n / (dx * dx) + r);

118 }

119

120 double d_fun(int j, int n, vector<double> f, double beta, double sigma) {

121 double t = n * dt;

122 if (j == 0) {

123 return f[0] + C * exp(-alpha * t) * dt;

124 }

125 else if (j == J)return boundary_condition_at_infinite(n - 1);

126 // 1=<j<J

127 else {

128 return -a_fun(j, n, beta, sigma) * f[j - 1] + b_star_fun(j, n, beta, sigma)

* f[j] \

129 - c_fun(j, n, beta, sigma) * f[j + 1] \

130 - (C * exp(-alpha * t) + C * exp(-alpha * t + dt)) * dt / 2;

131 }

132 }

133

134 vector<double> Crank_Nicolson_method(double beta, double sigma) {

135 vector <double> f;

136 for (int n = N; n >= 0; n--) {

15

137 vector <double> a_vector;

138 vector <double> b_vector;

139 vector <double> c_vector;

140 vector <double> d_vector;

141 if (n == N) {

142 for (int j = 0; j <= J; j++) {

143 f.push_back(terminal_condition(j));

144 }

145 }

146 else {

147 // set coefficent

148 for (int j = 0; j <= J; j++) {

149 a_vector.push_back(a_fun(j, n, beta, sigma));

150 b_vector.push_back(b_fun(j, n, beta, sigma));

151 c_vector.push_back(c_fun(j, n, beta, sigma));

152 d_vector.push_back(d_fun(j, n + 1, f, beta, sigma));

153 }

154 // gauss

155 for (int j = 0; j < J; j++) {

156 a_vector[j + 1] = a_vector[j + 1] / b_vector[j];

157 b_vector[j + 1] = b_vector[j + 1] \

158 - a_vector[j + 1] * c_vector[j];

159 }

160 //progress

161 for (int j = 0; j < J; j++) {

162 d_vector[j + 1] = d_vector[j + 1] - a_vector[j + 1] * d_vector[j];

163 }

164 //backward

165 f[J] = d_vector[J] / b_vector[J];

166 for (int j = J - 1; j >= 0; j--) {

167 f[j] = (d_vector[j] - c_vector[j] * f[j + 1]) / b_vector[j];

168 }

169 }

170 }

171 return f;

16

172 }

A.2 American Options code

1 // America_option.cpp -- pricing program

2 // caculate America_option price

3

4 #include <iostream>

5 #include <vector>

6 #include <cmath>

7 using namespace std;

8 //define const

9 const double T = 3;

10 const double t_American_style = 1.0702;

11 const double Pp = 200;

12 const double S_max = 200;

13 const double F = 190;

14 const double R = 4;

15 const double r = 0.0197;

16 const double k = 0.08333;

17 const double mu = 0.0191;

18 const double X = 46.54;

19 const double C = 1.87;

20 const double alpha = 0.02;

21 const double dx = 0.05;

22 const double dt = 0.01;

23 const int J = S_max / dx;

24 const int N = T / dt;

25 // declare function

26 double a_fun(int j, int n, double beta, double sigma);

27 double b_fun(int j, int n, double beta, double sigma);

28 double c_fun(int j, int n, double beta, double sigma);

29 double d_fun(int j, int n, vector<double> f, double beta, double sigma);

30 double terminal_condition(int j);

31 double boundary_condition_at_infinite(int n);

17

32 vector<double> Crank_Nicolson_method(double beta, double sigma);

33

34 int main()

35 {

36 double beta;

37 double sigma;

38 cout << "\nbeta\n";

39 cin >> beta;

40 cout << "\nsigma\n";

41 cin >> sigma;

42 cout << "please wait..." << endl;

43 vector<double> result = Crank_Nicolson_method(beta, sigma);

44 cout << "the results are:" << endl;

45 for (auto iter = result.begin(); iter != result.end(); iter++) {

46 cout << *iter << endl;

47 }

48 system("pause");

49 }

50

51

52

53 //define function

54 double terminal_condition(int j) {

55 double S = j * dx;

56 return F > R * S ? F : R * S;

57 }

58

59 double boundary_condition_at_infinite(int n) {

60 double t = n * dt;

61 double At = R * exp(-(k + r) * (T - t));

62 double Bt = (X * R - C / (alpha + r) * exp(-alpha * T)) * exp(-r * (T - t)) \

63 + C / (alpha + r) * exp(-alpha * t) - X * R * exp(-(k + r) * (T - t));

64 return S_max * At + Bt;

65 }

66

18

67 double a_fun(int j, int n, double beta, double sigma) {

68 double S = j * dx;

69 double t = n * dt;

70 double theta = (1 + mu) * X * exp(mu * t);

71 if (j == J)return 0;

72 // 1=<j<J

73 else {

74 double sigma2_j_n = sigma * sigma * pow(S, 2 * beta);

75 double mu_j_n = k * (theta - S);

76 return 0.25 * dt * (sigma2_j_n / (dx * dx) - mu_j_n / dx);

77 }

78 }

79

80 double b_fun(int j, int n, double beta, double sigma) {

81 // 1=<j<J

82 double S = j * dx;

83 double t = n * dt;

84 double theta = (1 + mu) * X * exp(mu * t);

85 if (j == 0) {

86 return 1 + (k * theta / dx + r) * dt;

87 }

88 if (j == J)return 1;

89 else {

90 double sigma2_j_n = sigma * sigma * pow(S, 2 * beta);

91 double mu_j_n = k * (theta - S);

92 return -1 - 0.5 * dt * (sigma2_j_n / (dx * dx) + r);

93 }

94 }

95

96 double c_fun(int j, int n, double beta, double sigma) {

97 double S = j * dx;

98 double t = n * dt;

99 double theta = (1 + mu) * X * exp(mu * t);

100 if (j == 0) {

101 return -k * theta * dt / dx;

19

102 }

103 else {

104 // 1=<j<J

105 double sigma2_j_n = sigma * sigma * pow(S, 2 * beta);

106 double mu_j_n = k * (theta - S);

107 return 0.25 * dt * (sigma2_j_n / (dx * dx) + mu_j_n / dx);

108 }

109 }

110

111 double b_star_fun(int j, int n, double beta, double sigma) {

112 // 1=<j<J

113 double S = j * dx;

114 double t = n * dt;

115 double theta = (1 + mu) * X * exp(mu * t);

116 double sigma2_j_n = sigma * sigma * pow(S, 2 * beta);

117 double mu_j_n = k * (theta - S);

118 return -1 + 0.5 * dt * (sigma2_j_n / (dx * dx) + r);

119 }

120

121 double d_fun(int j, int n, vector<double> f, double beta, double sigma) {

122 double t = n * dt;

123 if (j == 0) {

124 return f[0] + C * exp(-alpha * t) * dt;

125 }

126 else if (j == J)return boundary_condition_at_infinite(n - 1);

127 // 1=<j<J

128 else {

129 return -a_fun(j, n, beta, sigma) * f[j - 1] + b_star_fun(j, n, beta, sigma)

* f[j] \

130 - c_fun(j, n, beta, sigma) * f[j + 1] \

131 - (C * exp(-alpha * t) + C * exp(-alpha * t + dt)) * dt / 2;

132 }

133 }

134

135 vector<double> Crank_Nicolson_method(double beta, double sigma) {

20

136 vector <double> f;

137 for (int n = N; n >= 0; n--) {

138 vector <double> a_vector;

139 vector <double> b_vector;

140 vector <double> c_vector;

141 vector <double> d_vector;

142 double t = n * dt;

143 if (n == N) {

144 for (int j = 0; j <= J; j++) {

145 f.push_back(terminal_condition(j));

146 }

147 }

148 else {

149 // set coefficent

150 for (int j = 0; j <= J; j++) {

151 a_vector.push_back(a_fun(j, n, beta, sigma));

152 b_vector.push_back(b_fun(j, n, beta, sigma));

153 c_vector.push_back(c_fun(j, n, beta, sigma));

154 d_vector.push_back(d_fun(j, n + 1, f, beta, sigma));

155 }

156 // gauss

157 for (int j = 0; j < J; j++) {

158 a_vector[j + 1] = a_vector[j + 1] / b_vector[j];

159 b_vector[j + 1] = b_vector[j + 1] \

160 - a_vector[j + 1] * c_vector[j];

161 }

162 //progress

163 for (int j = 0; j < J; j++) {

164 d_vector[j + 1] = d_vector[j + 1] - a_vector[j + 1] * d_vector[j];

165 }

166

167 //backward

168 if (t < t_American_style) {

169 f[J] = d_vector[J] / b_vector[J];

170 if (f[J] < Pp) {

21

171 f[J] = Pp;

172 if (n == 0)cout << S_max << endl;

173 }

174 for (int j = J - 1; j >= 0; j--) {

175 double S = j * dx;

176 f[j] = (d_vector[j] - c_vector[j] * f[j + 1]) / b_vector[j];

177 if (f[j] < Pp) {

178 f[j] = Pp;

179 if (n == 0)cout << S << endl;

180 }

181 }

182 }

183 else {

184 f[J] = d_vector[J] / b_vector[J];

185 for (int j = J - 1; j >= 0; j--) {

186 f[j] = (d_vector[j] - c_vector[j] * f[j + 1]) / b_vector[j];

187 }

188

189 }

190 }

191 }

192 return f;

193 }

22