精选博文

C++ implementation of a simple order book

Please refer to my github for the code:  https://github.com/DongliangLarryYi.  1.      Data Structure 1.1   A basic or...

Wednesday, July 6, 2016

Quantitative Methods for Asian Option Pricing (in C+)


Question:


Below is the analysis report:

Quantitative Methods for Asian Option Pricing
By Dongliang “Larry” Yi

1.     Background

An Asian Option is a special kind of option, whose payoff is based on the difference be­tween the average asset price and the strike price. This is different from European Option whose payoff is only based on the execution day asset price and strike price.

This attribute makes it a little bit harder to price an Asian Option than a European one. Take the frequently used Monte Carlo Method as example, we generate one payoff for European Option by running one trial, and the expected European Option price can be quickly calculated as the trial number increases. However, since Asian Option need to use average price during a period to calculate the final payoff, so it requires us to generate as many as possible prices during the period to derive an accurate average price. So this is time consuming for Plain Monte Carlo Method.

In this report, we will compare efficiency of three different methods in pricing Asian Option, and then analyze the influence as the time of intervals increase.

2.     Quantitative Methods

During this part, we will price a 1-year Asian call option with strike price K = 100 and discrete monitoring (m = 50). The current asset price is S0 = 100. The risk free interest rate is r = 10%. The volatility of the asset is 20% per year.

2.1  Plain Monte Carlo Method

Monte Carlo Method is a frequently used quantitative method. In this case, we need to derive m = 50 Random Variables to get one payoff, and then we averaged all n payoffs, and we can get the expected price of this Asian Option. Below is the result based on different sample sizes.

Monte Carlo Plain
Sample size
Estimation
S.E.
Comp. Time(seconds)
Efficiency Measure
100000
7.18451
0.0275088
2.77716
0.002101572
400000
7.1769
0.0137552
11.0769
0.002095811
900000
7.17433
0.00916559
24.9306
0.002094371
1600000
7.17156
0.00686822
44.3177
0.002090574

2.2  Control Variate Method

Control Variate Method is an advanced variance reduction method which is used to let the final result have less volatility and more accuracy.

During this case, we use the geometric Asian Call as the control variate. The result shows that the correlation between geometric Asian Call and Asian Option is 0.99965 (close to 1), so this make the final result variance to be decreased with the net-off effect from adding geometric Asian Call part. Below is the result based on different sample sizes.

Control Variates
Sample size
Estimation
S.E.
Comp. Time(seconds)
Efficiency Measure
100000
7.16395
0.000802898
2.82134
1.81876E-06
400000
7.16463
0.000405716
11.1771
1.83981E-06
900000
7.16437
0.000270085
25.1649
1.83568E-06
1600000
7.16452
0.000202553
44.7103
1.83436E-06
b = 1.03801
𝞀 = 0.99965

2.3  Quasi Monte Carlo Method

Quasi Monte Carlo Method is aiming to make the generated Random Variables more evenly placed in the m dimensional space, and this can make the final result to converge more quickly. Below is the result based on different sample sizes.

Quasi Monte Carlo
Sample size
Estimation
S.E.
Comp. Time(seconds)
Efficiency Measure
100000
7.16149
0.00639813
2.76139
0.00011304
400000
7.16925
0.00314764
11.0941
0.000109916
900000
7.16723
0.001681
25.5573
7.22188E-05
1600000
7.16685
0.00102211
44.9236
4.69321E-05
L = 20

As the sample size increase, we can see the efficiency measure decrease. This may be caused by the more evenly distributed random variable in the m = 50 dimension because of increased sample size. We then calculated additional sample size to confirm this conclusion, and found the Efficiency Measure continues to be better.

Sample size
Estimation
S.E.
Comp. Time(seconds)
Efficiency Measure
2500000
7.16544
0.000786622
70.3995
4.35614E-05
3600000
7.16498
0.000572341
102.561
3.35963E-05




2.4  Comparison

According to Efficiency Measure, control variable with Geometric Asian Call has the best performance. The reason is the the Geometric Asian Call is almost linearly correlated with Asian Option, so the most of variance is netted off during computing. The Quasi Monte Carlo has the second best performance, because its almost evenly generated Random Variables. We also see that as the sample size increased, the Efficiency Measure became better. The Plain Monte Carlo method has the worst performance, the reason is that we need too many computing resource to generate each payoff, and the Pseudo Random Variables is not as evenly generated as Quasi Random Variables.




3.     The influence from time interval

In above case, we set m = 50, and we want to know what is the effect by change of m. Intuitively, I guess as the increased of m (or decrease of time interval), the Asian Option price will converge. So I used below data to analyze the effect from change of m. In the above, I have compared three methods with different trials, here I lock the sample size to be equal to 10000, and adjust the number of m to see the result.

3.1  Control Variate Method

As the dimension increases, the price converge to around 0.35.

Control Variate (Sample size = 10000)
Dimension (m)
Estimation
S.E.
Comp. Time(seconds)
Efficiency Measure
b
10
0.378035
0.000751855
0.059164
3.34446E-08
1.12431
50
0.355464
0.000650254
0.289591
1.22448E-07
1.14707
100
0.353466
0.000686634
0.579219
2.73082E-07
1.17496
200
0.351589
0.000698554
1.1534
5.62833E-07
1.1547
400
0.350083
0.000697202
2.3195
1.12749E-06
1.16532
600
0.351837
0.00080699
3.45002
2.24677E-06
1.17897
800
0.351336
0.00077872
4.58175
2.7784E-06
1.20046
1000
0.35086
0.000705947
5.71046
2.84587E-06
1.17944
10000
0.35146
0.000731521
57.1024
3.05568E-05
1.16261



3.2  Quasi Monte Carlo Method

As the dimension increases, the price converge to around 0.35. Since my sobol generator has maximum dimension to be 1024, so we do not compare the price under 10000 dimension.

Quasi Monte Carlo (Sample size = 10000)
Dimension (m)
Estimation
S.E.
Comp. Time(seconds)
Efficiency Measure
10
0.377003
0.00282379
0.055354
4.41381E-07
50
0.356068
0.00310931
0.267
2.5813E-06
100
0.351229
0.00321768
0.531172
5.49947E-06
200
0.357687
0.00356254
1.05542
1.33951E-05
400
0.356448
0.00403572
2.2403
3.64878E-05
600
0.360534
0.00387889
3.3541
5.04651E-05
800
0.35884
0.00454583
4.44688
9.18929E-05
1000
0.354494
0.00405514
5.29148
8.70139E-05
1024
0.352509
0.00496648
5.42279
0.000133758
L = 20



3.3  Conclusion

Both methods show that as the dimension increases, the Asian Option price converges. This result can be explained that as the time interval decreases (m increase), the average of discrete underlying asset prices tend to be the average of continuous ones. It is also obvious that as m increases the computer workload increases, so the efficiency measure increases. We can see that the efficiency measure is almost linearly related to the number of m in Control Variate Method, and so is Quasi Method. In this case, Control Variate is also better than Quasi Monte Carlo Method. This is just another prove to the result from the above comparison of three methods.




4.     Time Efficiency

From our tables it is obvious that Monte Carlo Method is time consuming. I can imagine if both number of trials and time intervals are big, we may need hours to calculate a result. So during this project, I tried to improve time efficiency by some small tricks.
a)    I used double type variable to store multiplied stock price after each time interval, this is enough for m = 50 situation, but not available when m is big. So I did exponentiation before multiplication, this can make sure the double type variable is enough to handle it.
b)    For some frequently multiplied number, I stored it in a variable. This can decrease the time to do the same multiplication.
c)     During computing the averages, I just add together and divide at last. This does not require additional memory resource and also decreased the time for divide computing.

5.     Conclusion

Asian Option is a kind of exotic option which does not has a closed form for its price. Although its price can be calculated from Monte Carlo Method, but it is very time consuming to get an accurate value with narrow confidence interval. Here we introduced two methods: Control Variate and Quasi Monte Carlo. Control Variate Method has a very good variance reduction, and Quasi Monte Carlo has a quicker convergence rate compared to Plain Monte Carlo. In this case, Control Variable Method is slightly better than Quasi Monte Carlo, since the chosen Geometric Call is almost perfectly correlated to Asian Call.



6.     Attachment
6.1  “Control Variate” Code

int monte_carlo_initial()
{
    double Price[_m];
    double RV = get_gaussian_inverse();
    Price[0]=_S0*exp((_r-_q-pow(_sigma,2)*0.5)*_deltaT*(1)+_sigma*sqrt(_deltaT*(1))*RV);
    for (int M = 1; M<_m; M++) {
        RV = get_gaussian_inverse();
        Price[M] = Price[M-1]*exp((_r-_q-pow(_sigma,2)*0.5)*_deltaT*(1)+_sigma*sqrt(_deltaT*(1))*RV);
    }
   
    double Inter_Price = pow(Price[0], inv_m);
    for (int M = 1; M<_m; M++) {
        Inter_Price = Inter_Price * pow(Price[M], inv_m);
    }
    Inter_Price = max(Inter_Price-_K, 0);
    control[0]=Inter_Price;

   double x = 0;
    for (int j = 0; j<_m; j++) {
        x += Price[j];    }
    x = x/_m;
    x = max(x-_K,0);
   value[0]=x;
  
for (int i=1; i<1000; i++) {
       
        RV = get_gaussian_inverse();
        Price[0]=_S0*exp((_r-_q-pow(_sigma,2)*0.5)*_deltaT*(1)+_sigma*sqrt(_deltaT*(1))*RV);
        for (int M = 1; M<_m; M++) {
            RV = get_gaussian_inverse();
            Price[M] = Price[M-1]*exp((_r-_q-pow(_sigma,2)*0.5)*_deltaT*(1)+_sigma*sqrt(_deltaT*(1))*RV);
        }
        double Inter_Price = pow(Price[0],inv_m);
        for (int M = 1; M<_m; M++) {
            Inter_Price = Inter_Price * pow(Price[M],inv_m);
        }
        Inter_Price = max(Inter_Price - _K, 0);
        control[i]=Inter_Price;

        long double x = 0;
        for (int j = 0; j<_m; j++) {
            x += Price[j];    }
        x = x/_m;
        x = max(x-_K,0);
        value[i]=x;
    }
    return 1;
}

int b_Cal()
{
    long double X = 0;
    long double Y = 0;
    for (int i=0; i<1000; i++) {
        X+=control[i];
        Y+=value[i];
    }
    X=X/1000;
    Y=Y/1000;
    long double xx=0.0;
    long double xy=0.0;
    long double yy=0.0;
for (int i=0; i<1000; i++) {
        long double temp=control[i]-X;
        long double temp2=value[i]-Y;
        xx+=pow(temp,2);
        xy+=temp2*temp;
        yy+=pow(temp2,2);
 }
    _b=xy/xx;
    _pho=xy/sqrt(xx*yy);
    return 1;
}
double option_price_call_black_scholes(const double& S,       // spot (underlying) price
                                       const double& K,       // strike (exercise) price,
                                       const double& r,       // interest rate
                                       const double& sigma,   // volatility
                                       const double& time,   // time to maturity
                                       const double& q)
{
    double time_sqrt = sqrt(time);
    double d1 = (log(S/K)+(r-q)*time)/(sigma*time_sqrt)+0.5*sigma*time_sqrt;
    double d2 = d1-(sigma*time_sqrt);
    return S*exp(-q*time)*get_cdf(d1) - K*exp(-r*time)*get_cdf(d2);
};

int Expectation_Geometric_Call_cal()
{
    double _r_ = _r;
    double _q_ = _q + 0.5*_sigma*_sigma-0.5*(2*_m+1)*_sigma*_sigma/(3*_m);
    double _sigma_ = sqrt((2*_m+1)*_sigma*_sigma/(3*_m));
    double _K_ = _K;
    double _T_ = 0.5*(_T+ _deltaT);
    double _S0_ =_S0;
    Expectation_Geometric_Call = exp(_r_*_T_)*option_price_call_black_scholes( _S0_, _K_, _r_, _sigma_, _T_, _q_);
  return 1; 
}

int monte_carlo_inverse(int no_of_trials)
{
    double x,x2;
    double Price[_m];
    double RV = get_gaussian_inverse();
    Price[0]=_S0*exp((_r-_q-pow(_sigma,2)*0.5)*_deltaT*(1)+_sigma*sqrt(_deltaT*(1))*RV);
    for (int M = 1; M<_m; M++) {
        RV = get_gaussian_inverse();
        Price[M] = Price[M-1]*exp((_r-_q-pow(_sigma,2)*0.5)*_deltaT*(1)+_sigma*sqrt(_deltaT*(1))*RV);
    }

    double Inter_Price = pow(Price[0],inv_m);
    for (int M = 1; M<_m; M++) {
        Inter_Price = Inter_Price * pow(Price[M],inv_m);
    }
    Inter_Price = max(Inter_Price - _K, 0);
   
   
    x = 0;
    for (int j = 0; j<_m; j++) {
        x += Price[j];
        //cout << "Price " << j+1 << " : " << Price[j]<<endl;
    }
    x = x/_m;
    x = max(x-_K,0) + _b*(Expectation_Geometric_Call-Inter_Price);
   
    x2 = pow(x, 2);
   
for (int i=1; i<no_of_trials; i++) {
        RV = get_gaussian_inverse();
        Price[0]=_S0*exp((_r-_q-pow(_sigma,2)*0.5)*_deltaT*(1)+_sigma*sqrt(_deltaT*(1))*RV);
        for (int M = 1; M<_m; M++) {
            double RV = get_gaussian_inverse();
            Price[M] = Price[M-1]*exp((_r-_q-pow(_sigma,2)*0.5)*_deltaT*(1)+_sigma*sqrt(_deltaT*(1))*RV);
        }
       
        double Inter_Price = pow(Price[0],inv_m);
        for (int M = 1; M<_m; M++) {
            Inter_Price = Inter_Price * pow(Price[M],inv_m);
        }
        Inter_Price = max(Inter_Price - _K, 0);
      
 long double Temp_x = 0;
        for (int j = 0; j<_m; j++) {
            Temp_x += Price[j];
        }
        Temp_x = Temp_x/_m;
        Temp_x = max(Temp_x-_K, 0) + _b*(Expectation_Geometric_Call-Inter_Price);
        double Temp_x2 = pow(Temp_x, 2);
        x += Temp_x;
        x2 += Temp_x2;
    }
    expectation=x/no_of_trials;
    se=sqrt(((x2/no_of_trials)-pow(expectation, 2))/(no_of_trials-1));
    return 1;
}

6.2  “Quasi Monte Carlo” Code

double Quasi_Monte_Carlo_Sobol(int number, int batch)
{
    double y, y2;
    y=0;
    y2=0;
    srand((int)time(0));
    for (int j = 0 ; j<batch; j++) {
    
   double x;
        x =0;
      double U[_m];
     for (int i =0 ; i<_m; i++) {
            srand(((int)time(0)*10000*(j+1))*batch);
            U[i]=Uniform01();
        }
for (unsigned long long i = 0; i < number; ++i)
        {
            // Print a few dimensions of each point.
            double Price[_m];
            const double s = sobol::sample(i+1, 0);
            double inter = s+U[0] - floor(s+U[0]);
            const double RV = get_gaussian_determin(inter);
            Price[0]=_S0*exp((_r-_q-pow(_sigma,2)*0.5)*_deltaT*(1)+_sigma*sqrt(_deltaT*(1))*RV);
           
           
           
for (unsigned d = 1; d < _m; ++d)
            {
                const double s = sobol::sample(i+1, d);
                double inter = s+U[d] - floor(s+U[d]);
                const double RV = get_gaussian_determin(inter);
                Price[d]=Price[d-1]*exp((_r-_q-pow(_sigma,2)*0.5)*_deltaT*(1)+_sigma*sqrt(_deltaT*(1))*RV);
}
            double Temp_x = 0;
            for (int j = 0; j<_m; j++) {
                Temp_x += Price[j];
            }
            Temp_x = Temp_x/_m;
            Temp_x = max(Temp_x-_K, 0);
           
            //cout <<Temp_x<<endl;
            x += Temp_x;
 }
        x = x/number;
 double x2= pow(x, 2);
        y += x;
        y2 +=x2;
    }
expectation = y/batch;
    se = sqrt(((y2/batch)-pow(expectation, 2))/(batch-1));
 return expectation;
}


No comments:

Post a Comment