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;
}
**********