Friday 15 March 2013

Pricing Vanilla option using Monte Carlo

Monte Carlo simulation
Monte Carlo method can be simply explained as algorithm uses random sampling for an expected result. For more about Monte Carlo simulation, please refer to Monte Carlo method.

Risk neutral valuation
In risk neutral valuation, we can always make sample paths to obtain a future price, discounted back using the risk neutral interest rate will give you an estimation of the option price.
$$V_0 = e^{-r*T}E(V_T|f_0)$$ One more assumption needed that the stock price should follow a geometric brownian motion.
$$\frac{dS_t}{S_t} = r * d_t + \sigma*dB_t$$
The stock price at maturity can be easily solved as:
$$ d(lnS) = \frac{1}{S}dS - \frac{1}{2}\frac{1}{S^2}(dS)^2 = (r - \frac{1}{2}\sigma^2)dt + \sigma dB_t$$ $$ S_t = S_0 * exp((r - \frac{1}{2}\sigma^2)t + \sigma B_t) = S_0 * exp((r - \frac{1}{2}\sigma^2)t + \sigma \sqrt{t}\phi) $$ where $\phi$ follows a standard Normal distribution.

Simulate the stock price
From above equation, we can now simulate the stock price:

Next is a simple example of pricing vanilla option using Monte Carlo, the "Random1.h" is a normal random number generator, for more information, please check normal random variable  :

/* Copyright(c)Eric jie, Tue Jul  3 17:42:08 SGT 2012
 * Simple Monte-Carlo simulation
 * keywords: monte-carlo
 */

double simpleMonteCarlo1(int option, double expiry, double strike, double spot, double vol, double r, unsigned long numberofPaths);

int main(int argc, char *argv[]){
    double expiry = 1;
    double strike = 100;
    double spot = 100;
    double vol = 0.03;
    double r = 0.02;
    unsigned long numberofPaths = 10000;
    int option;
    cout << "Enter option form: 1.European call 2.European put 3.Digital call 4.Digital put\n";
    cin >> option;
    double result = simpleMonteCarlo1(option, expiry, strike, spot, vol, r, numberofPaths);
    cout << "the option price given above info: " << result << endl;  
    return 0;
}

double simpleMonteCarlo1(int option, double expiry, double strike, double spot, double vol, double r, unsigned long numberofPaths){
    double driftSpot = spot * exp((r - 0.5 * vol * vol) * expiry);
    double runningSum = 0.0;
    double payoff;
    double optionPrice;
    double adjVol;    
    vectorspotExpiry;

    // simulate stock price at expiry
    for(int i = 0; i < numberofPaths; i++){
        adjVol = vol * sqrt(expiry) * getOneGaussianByBoxMuller();
        spotExpiry.push_back(driftSpot * exp(adjVol));
    }   

    switch(option){
    case 1: // for european call option
        for(int i = 0; i < numberofPaths; i++){
            payoff = (spotExpiry[i] > strike) ? (spotExpiry[i] - strike) : 0;
            runningSum += payoff;
        }break;
    case 2: // for european put option
        for(int i = 0; i < numberofPaths; i++){
            payoff = (strike > spotExpiry[i]) ? (strike - spotExpiry[i]) : 0;
            runningSum += payoff;
        }break;
    case 3: // for digital call option
        for(int i = 0; i < numberofPaths; i++){
            payoff = (spotExpiry[i] > strike) ? 1 : 0;
            runningSum += payoff;
        }break;
    case 4: // for digital put option
        for(int i = 0; i < numberofPaths; i++){
            payoff = (strike > spotExpiry[i]) ? 1 : 0;
            runningSum += payoff;
        }break;
    default:break;
    }

    optionPrice = exp(-r * expiry) *runningSum / static_cast(numberofPaths);
    return optionPrice;
}

outcome:
Enter option form: 1.European call 2.European put 3.Digital call 4.Digital put
1
the call option price given above info: 2.38314

No comments:

Post a Comment