Login  Register

Problem by pricing quanto asian basket options with MC simulation (multipath)

Posted by Giorgio Pazmandi on Feb 10, 2006; 10:30am
URL: http://quantlib.414.s1.nabble.com/Problem-by-pricing-quanto-asian-basket-options-with-MC-simulation-multipath-tp4466.html

Hi, we are having some problems by using the (multi)path simulation
capabilities of quantlib for the  pricing of quanto asian basket options
(these are asian basket options where the underlying are in  different
currencies but the payoff doesn't depend on any exchange rate). I hope that
this problem is not "out of topic" in this mailing list.

To simulate this options we let run a MC simulation with 3 stocastic
variables (the 2 underlying  prices and the exchange rate). We compared our
results with a commercial product wich prices this  kind of options. As long
as we put in the correlation matrix correlations beetwen the assets our
results match very well. When we add a correlation between the assets and
the exchange rate we get a  small effect on the price, while in the
commercial product we see a bigger effect.


test #1 (no correlation): Our simulation gives 8.65 +/- 0.09, reference
value is 8.64 +/- 0.08

test #2: (only correlation beetween the 2 asset): Our simulation gives 9.66
+/- 0.10, reference  value is 9.65 +/- 0.09

test #3: (only correlation between asset and ex.rate): Our simulation gives
8.66 +/- 0.09 (similar  to the simulation #1), reference value is 8.22 +/-
0.08

test #4: (all the correlations): Our simulation gives 9.67 +/- 0.10 (similar
simulation #2),  reference value is 9.24 +/- 0.09


Maybe somebody has some experience with such kind of options and can give us
a hint of what we are  doing wrong. Details on our test case and on our
aproach to price it follows below.

Thank in advance for any help

Giorgio






Here are the details of our test case: We consider a quanto asian basket
average rate option, which  has as underlying 2 equities quoted in
currencies AAA and BBB (the values are not "real word"  datas):

Underlying 1: current price = 75 AAA, dividend yield = 3.1%, volatility =
20%
Underlying 2: current price = 100 BBB, dividend yield = 2%, volatility = 15%

AAA risk free rate: 5.1%
BBB risk free rate: 3.5%
exchange rate AAA/BBB: 1.5
volatility of exchange rate AAA/BBB: 15%


The option is payed in currency AAA and has the payoff of a quanto asian
basket (note: in the payoff  there is no exchange rate):

basket1 = underlying1[samplingDate1] + underlying2[samplingDate1]
basket2 = underlying1[samplingDate2] + underlying2[samplingDate2]
average = (basket1 + basket2) / 2
payoff at expiry = max(0; average - strike)

strike: 175
sampling dates: 16.10.1998, 16.12.1998
expiry date: 16.12.1998

valuation date (today): 7.1.1998

correlation matrix:
                ex. rate        underlying1     underlying2
ex. rate        1               0               0.4
underlying1     0               1               0.3
underlying2     0.4             0.3             1




Here is what we do to simulate this option:


**********

void RunSimulation()
{
        // Ex. rate
        Handle<Quote> x0_1(boost::shared_ptr<Quote>(new SimpleQuote(1.5))); //
current value
        Handle<YieldTermStructure> r_1(flatRate(0.051, Actual360())); // "risk free
rate"
        Handle<YieldTermStructure> q_1(flatRate(0.035, Actual360())); // "dividend
yield rate"
        Handle<BlackVolTermStructure> sigma_1(flatVol(0.15, Actual360())); //
volatility

        // Underlying asset1
        Handle<Quote> x0_2(boost::shared_ptr<Quote>(new SimpleQuote(75.0))); //
current value
        Handle<YieldTermStructure> r_2(flatRate(0.051, Actual360())); // risk free
rate
        Handle<YieldTermStructure> q_2(flatRate(0.031, Actual360())); // dividend
yield rate
        Handle<BlackVolTermStructure> sigma_2(flatVol(0.20, Actual360())); //
volatility

        // Underlying asset2
        Handle<Quote> x0_3(boost::shared_ptr<Quote>(new SimpleQuote(100.0))); //
current value
        Handle<YieldTermStructure> r_3(flatRate(0.035, Actual360())); // risk free
rate
        Handle<YieldTermStructure> q_3(flatRate(0.02, Actual360())); // dividend
yield rate
        Handle<BlackVolTermStructure> sigma_3(flatVol(0.15, Actual360())); //
volatility

        Real strike = 175;

        // Creation of 3 stocastic processes (blackSholes)
        std::vector<boost::shared_ptr<StochasticProcess1D> > processes(3);
        processes[0] = boost::shared_ptr<StochasticProcess1D>(
                                       new
BlackScholesProcess(x0_1,q_1,r_1,sigma_1));
        processes[1] = boost::shared_ptr<StochasticProcess1D>(
                                       new
BlackScholesProcess(x0_2,q_2,r_2,sigma_2));
        processes[2] = boost::shared_ptr<StochasticProcess1D>(
                                       new
BlackScholesProcess(x0_3,q_3,r_3,sigma_3));

        // Correlation matrix

/* Test #1
        Matrix correlation(3,3);
        correlation[0][0] =  1.00; correlation[0][1] =  0.00; correlation[0][2] =
0.00;
        correlation[1][0] =  0.00; correlation[1][1] =  1.00; correlation[1][2] =
0.00;
        correlation[2][0] =  0.00; correlation[2][1] =  0.00; correlation[2][2] =
1.00;
*/

/* Test #2
        Matrix correlation(3,3);
        correlation[0][0] =  1.00; correlation[0][1] =  0.00; correlation[0][2] =
0.00;
        correlation[1][0] =  0.00; correlation[1][1] =  1.00; correlation[1][2] =
0.30;
        correlation[2][0] =  0.00; correlation[2][1] =  0.30; correlation[2][2] =
1.00;
*/

/* Test #3
        Matrix correlation(3,3);
        correlation[0][0] =  1.00; correlation[0][1] =  0.00; correlation[0][2] =
0.40;
        correlation[1][0] =  0.00; correlation[1][1] =  1.00; correlation[1][2] =
0.00;
        correlation[2][0] =  0.40; correlation[2][1] =  0.00; correlation[2][2] =
1.00;
*/

/* Test #4
        correlation[0][0] =  1.00; correlation[0][1] =  0.00; correlation[0][2] =
0.40;
        correlation[1][0] =  0.00; correlation[1][1] =  1.00; correlation[1][2] =
0.30;
        correlation[2][0] =  0.40; correlation[2][1] =  0.30; correlation[2][2] =
1.00;
*/

        Matrix correlation(3,3);
        correlation[0][0] =  1.00; correlation[0][1] =  0.00; correlation[0][2] =
0.40;
        correlation[1][0] =  0.00; correlation[1][1] =  1.00; correlation[1][2] =
0.30;
        correlation[2][0] =  0.40; correlation[2][1] =  0.30; correlation[2][2] =
1.00;

        // Creation of the stocastic process array
        boost::shared_ptr<StochasticProcess>
        process = boost::shared_ptr<StochasticProcess>(
                           new StochasticProcessArray(processes,
correlation));

        // Creation of time grid
        std::vector<Time> oTemp;
        oTemp.push_back((Time)282/365.0); // day diff between 16.10.1998 and
7.1.1998
        oTemp.push_back((Time)343/365.0); // day diff between 16.12.1998 and
7.1.1998
        TimeGrid timeGrid(oTemp.begin(), oTemp.end(), 1);

        std::cout << "Time grid" << std::endl;
        for (Size c = 0; c < timeGrid.size(); c++)
                std::cout << timeGrid[c] << std::endl;
        std::cout << std::endl;

#ifdef USE_SOBOL
        // LowDiscrepancy (sobol)
        typedef LowDiscrepancy::rsg_type rsg_type;
        BigNatural seed = 42;
        rsg_type randomSequenceGenerator =
LowDiscrepancy::make_sequence_generator((timeGrid.size()-1)*process->size(),
seed);
#else
        // (pseudo)random
        typedef PseudoRandom::rsg_type rsg_type;
        BigNatural seed = 42;
        rsg_type randomSequenceGenerator =
PseudoRandom::make_sequence_generator((timeGrid.size()-1)*process->size(),
seed);
#endif

        // Creation of the (multi)path generator
        bool brownianBridge = false;
        MultiPathGenerator<rsg_type> generator(process,
                                               timeGrid,
                                               randomSequenceGenerator,
                                               brownianBridge);

        // Setting some params
        Size numberOfSimulations = 10000;
        Size noUnderlyingAsset = 2;
        Size noSamplingDates = timeGrid.size()-1;

        // Running the simulation
        std::cout << "**********\nStarting simulation with " << numberOfSimulations
<< " simulation  paths" << std::endl;
        IncrementalStatistics payoffStat;
        Matrix prices(noUnderlyingAsset, noSamplingDates);
        for (Size i=1; i<=numberOfSimulations; i++)
        {
                // Simulate one path and calculates the payoff
                MultiPath path = generator.next().value;
                Real payoff = payoffFunctionAROBasket(prices, noUnderlyingAsset,
noSamplingDates,  strike);
                payoffStat.add(payoff);

                // Antithetic path
                MultiPath path_anti = generator.antithetic().value;
                Real payoff_anti = payoffFunctionAROBasket(prices, noUnderlyingAsset,
noSamplingDates, strike);
                payoffStat.add(payoff_anti);
        }

        Real timeToExpiry = timeGrid[timeGrid.size()-1];
        Real DF = 1.0 / exp(timeToExpiry * log(1.0 + 0.051));

        std::cout << "Option Fair Value:\t" << (payoffStat.mean() * DF) << "\t
Error estimate:\t" <<  (payoffStat.errorEstimate() * DF) << std::endl;
}


/* Not one of the best written functions, but it works ... :-) */
Real payoffFunctionAROBasket(const Matrix& prices, Size noAsset, Size
noSamplingDates, Real strike)
{
        Real* basket = new Real[noSamplingDates];
        for (Size i=0; i<noSamplingDates; i++)
        {
                basket[i] = 0.0;
                for (Size j=0; j<noAsset; j++)
                {
                        Real value = prices[j][i];
                        basket[i] += value;
                }
        }

        Real sum = 0.0;
        for (Size i=0; i<noSamplingDates; i++)
        {
                Real value = basket[i];
                sum += value;
        }

        Real average = sum / noSamplingDates;

        Real payoff = (average - strike) < 0.0 ? 0.0 : (average - strike);

        delete[] basket;
        return payoff;
}

**********