Post on 17-Mar-2023
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