public void testSwaptionPricing()
{
//"Testing forward swap and swaption pricing...");
//SavedSettings backup;
const int size = 10;
const int steps = 8*size;
#if QL_USE_INDEXED_COUPON
const double tolerance = 1e-6;
#else
const double tolerance = 1e-12;
#endif
List<Date> dates = new List<Date>();
List<double> rates = new List<double>();
dates.Add(new Date(4,9,2005));
dates.Add(new Date(4,9,2011));
rates.Add(0.04);
rates.Add(0.08);
IborIndex index = makeIndex(dates, rates);
LiborForwardModelProcess process = new LiborForwardModelProcess(size, index);
LmCorrelationModel corrModel = new LmExponentialCorrelationModel(size, 0.5);
LmVolatilityModel volaModel = new LmLinearExponentialVolatilityModel(process.fixingTimes(),
0.291, 1.483, 0.116, 0.00001);
// set-up pricing engine
process.setCovarParam((LfmCovarianceParameterization)
new LfmCovarianceProxy(volaModel, corrModel));
// set-up a small Monte-Carlo simulation to price swations
List<double> tmp = process.fixingTimes();
TimeGrid grid=new TimeGrid(tmp ,steps);
List<int> location=new List<int>();
for (int i=0; i < tmp.Count; ++i) {
location.Add(grid.index(tmp[i])) ;
}
ulong seed=42;
const int nrTrails = 5000;
LowDiscrepancy.icInstance = new InverseCumulativeNormal();
IRNG rsg = (InverseCumulativeRsg<RandomSequenceGenerator<MersenneTwisterUniformRng>
,InverseCumulativeNormal>)
new PseudoRandom().make_sequence_generator(process.factors()*(grid.size()-1),seed);
MultiPathGenerator<IRNG> generator=new MultiPathGenerator<IRNG>(process,
grid,
rsg, false);
LiborForwardModel liborModel = new LiborForwardModel(process, volaModel, corrModel);
Calendar calendar = index.fixingCalendar();
DayCounter dayCounter = index.forwardingTermStructure().link.dayCounter();
BusinessDayConvention convention = index.businessDayConvention();
Date settlement = index.forwardingTermStructure().link.referenceDate();
SwaptionVolatilityMatrix m = liborModel.getSwaptionVolatilityMatrix();
for (int i=1; i < size; ++i) {
for (int j=1; j <= size-i; ++j) {
Date fwdStart = settlement + new Period(6*i, TimeUnit.Months);
Date fwdMaturity = fwdStart + new Period(6*j, TimeUnit.Months);
Schedule schedule =new Schedule(fwdStart, fwdMaturity, index.tenor(), calendar,
convention, convention, DateGeneration.Rule.Forward, false);
double swapRate = 0.0404;
VanillaSwap forwardSwap = new VanillaSwap(VanillaSwap.Type.Receiver, 1.0,
schedule, swapRate, dayCounter,
schedule, index, 0.0, index.dayCounter());
forwardSwap.setPricingEngine(new DiscountingSwapEngine(index.forwardingTermStructure()));
// check forward pricing first
double expected = forwardSwap.fairRate();
double calculated = liborModel.S_0(i-1,i+j-1);
if (Math.Abs(expected - calculated) > tolerance)
Assert.Fail("Failed to reproduce fair forward swap rate"
+ "\n calculated: " + calculated
+ "\n expected: " + expected);
swapRate = forwardSwap.fairRate();
forwardSwap =
new VanillaSwap(VanillaSwap.Type.Receiver, 1.0,
schedule, swapRate, dayCounter,
schedule, index, 0.0, index.dayCounter());
forwardSwap.setPricingEngine(new DiscountingSwapEngine(index.forwardingTermStructure()));
if (i == j && i<=size/2) {
IPricingEngine engine =
new LfmSwaptionEngine(liborModel, index.forwardingTermStructure());
Exercise exercise =
new EuropeanExercise(process.fixingDates()[i]);
Swaption swaption =
new Swaption(forwardSwap, exercise);
swaption.setPricingEngine(engine);
GeneralStatistics stat = new GeneralStatistics();
for (int n=0; n<nrTrails; ++n) {
Sample<MultiPath> path = (n%2!=0) ? generator.antithetic()
: generator.next();
//Sample<MultiPath> path = generator.next();
List<double> rates_ = new InitializedList<double>(size);
for (int k=0; k<process.size(); ++k) {
rates_[k] = path.value[k][location[i]];
}
List<double> dis = process.discountBond(rates_);
double npv=0.0;
for (int k=i; k < i+j; ++k) {
npv += (swapRate - rates_[k])
* ( process.accrualEndTimes()[k]
- process.accrualStartTimes()[k])*dis[k];
}
stat.add(Math.Max(npv, 0.0));
}
if (Math.Abs(swaption.NPV() - stat.mean())
> stat.errorEstimate()*2.35)
Assert.Fail("Failed to reproduce swaption npv"
+ "\n calculated: " + stat.mean()
+ "\n expected: " + swaption.NPV());
}
}
}
}