public void testCachedValue() { //"Testing swaption value against cached value..."); CommonVars vars = new CommonVars(); vars.today = new Date(13, 3, 2002); vars.settlement = new Date(15, 3, 2002); Settings.setEvaluationDate(vars.today); vars.termStructure.linkTo(Utilities.flatRate(vars.settlement, 0.05, new Actual365Fixed())); Date exerciseDate = vars.calendar.advance(vars.settlement, new Period(5, TimeUnit.Years)); Date startDate = vars.calendar.advance(exerciseDate, vars.settlementDays, TimeUnit.Days); VanillaSwap swap = new MakeVanillaSwap(new Period(10, TimeUnit.Years), vars.index, 0.06) .withEffectiveDate(startDate); Swaption swaption = vars.makeSwaption(swap, exerciseDate, 0.20); //#if QL_USE_INDEXED_COUPON double cachedNPV = 0.036418158579; //#else // double cachedNPV = 0.036421429684; //#endif // FLOATING_POINT_EXCEPTION if (Math.Abs(swaption.NPV() - cachedNPV) > 1.0e-12) { Assert.Fail("failed to reproduce cached swaption value:\n" + //QL_FIXED + std::setprecision(12) + "\ncalculated: " + swaption.NPV() + "\nexpected: " + cachedNPV); } }
public void testSwaptionPricing() { // Testing forward swap and swaption pricing 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, tmp.Count, 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) { QAssert.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 <IPath> path = (n % 2 != 0) ? generator.antithetic() : generator.next(); MultiPath value = path.value as MultiPath; Utils.QL_REQUIRE(value != null, () => "Invalid Path"); //Sample<MultiPath> path = generator.next(); List <double> rates_ = new InitializedList <double>(size); for (int k = 0; k < process.size(); ++k) { rates_[k] = 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) { QAssert.Fail("Failed to reproduce swaption npv" + "\n calculated: " + stat.mean() + "\n expected: " + swaption.NPV()); } } } } }
static void Main(string[] args) { DateTime startTime = DateTime.Now; Date todaysDate = new Date(15, Month.February, 2002); Calendar calendar = new TARGET(); Date settlementDate = new Date(19, Month.February, 2002); Settings.instance().setEvaluationDate(todaysDate); // flat yield term structure impling 1x5 swap at 5% Quote flatRate = new SimpleQuote(0.04875825); FlatForward myTermStructure = new FlatForward( settlementDate, new QuoteHandle(flatRate), new Actual365Fixed()); RelinkableYieldTermStructureHandle rhTermStructure = new RelinkableYieldTermStructureHandle(); rhTermStructure.linkTo(myTermStructure); // Define the ATM/OTM/ITM swaps Period fixedLegTenor = new Period(1, TimeUnit.Years); BusinessDayConvention fixedLegConvention = BusinessDayConvention.Unadjusted; BusinessDayConvention floatingLegConvention = BusinessDayConvention.ModifiedFollowing; DayCounter fixedLegDayCounter = new Thirty360(Thirty360.Convention.European); Period floatingLegTenor = new Period(6, TimeUnit.Months); double dummyFixedRate = 0.03; IborIndex indexSixMonths = new Euribor6M(rhTermStructure); Date startDate = calendar.advance(settlementDate, 1, TimeUnit.Years, floatingLegConvention); Date maturity = calendar.advance(startDate, 5, TimeUnit.Years, floatingLegConvention); Schedule fixedSchedule = new Schedule(startDate, maturity, fixedLegTenor, calendar, fixedLegConvention, fixedLegConvention, DateGeneration.Rule.Forward, false); Schedule floatSchedule = new Schedule(startDate, maturity, floatingLegTenor, calendar, floatingLegConvention, floatingLegConvention, DateGeneration.Rule.Forward, false); VanillaSwap swap = new VanillaSwap( VanillaSwap.Type.Payer, 1000.0, fixedSchedule, dummyFixedRate, fixedLegDayCounter, floatSchedule, indexSixMonths, 0.0, indexSixMonths.dayCounter()); DiscountingSwapEngine swapEngine = new DiscountingSwapEngine(rhTermStructure); swap.setPricingEngine(swapEngine); double fixedATMRate = swap.fairRate(); double fixedOTMRate = fixedATMRate * 1.2; double fixedITMRate = fixedATMRate * 0.8; VanillaSwap atmSwap = new VanillaSwap( VanillaSwap.Type.Payer, 1000.0, fixedSchedule, fixedATMRate, fixedLegDayCounter, floatSchedule, indexSixMonths, 0.0, indexSixMonths.dayCounter()); VanillaSwap otmSwap = new VanillaSwap( VanillaSwap.Type.Payer, 1000.0, fixedSchedule, fixedOTMRate, fixedLegDayCounter, floatSchedule, indexSixMonths, 0.0, indexSixMonths.dayCounter()); VanillaSwap itmSwap = new VanillaSwap( VanillaSwap.Type.Payer, 1000.0, fixedSchedule, fixedITMRate, fixedLegDayCounter, floatSchedule, indexSixMonths, 0.0, indexSixMonths.dayCounter()); atmSwap.setPricingEngine(swapEngine); otmSwap.setPricingEngine(swapEngine); itmSwap.setPricingEngine(swapEngine); // defining the swaptions to be used in model calibration PeriodVector swaptionMaturities = new PeriodVector(); swaptionMaturities.Add(new Period(1, TimeUnit.Years)); swaptionMaturities.Add(new Period(2, TimeUnit.Years)); swaptionMaturities.Add(new Period(3, TimeUnit.Years)); swaptionMaturities.Add(new Period(4, TimeUnit.Years)); swaptionMaturities.Add(new Period(5, TimeUnit.Years)); CalibrationHelperVector swaptions = new CalibrationHelperVector(); // List of times that have to be included in the timegrid DoubleVector times = new DoubleVector(); for (int i = 0; i < numRows; i++) { int j = numCols - i - 1; // 1x5, 2x4, 3x3, 4x2, 5x1 int k = i * numCols + j; Quote vol = new SimpleQuote(swaptionVols[k]); SwaptionHelper helper = new SwaptionHelper( swaptionMaturities[i], new Period(swapLengths[j], TimeUnit.Years), new QuoteHandle(vol), indexSixMonths, indexSixMonths.tenor(), indexSixMonths.dayCounter(), indexSixMonths.dayCounter(), rhTermStructure); swaptions.Add(helper); times.AddRange(helper.times()); } // Building time-grid TimeGrid grid = new TimeGrid(times, 30); // defining the models // G2 modelG2 = new G2(rhTermStructure)); HullWhite modelHW = new HullWhite(rhTermStructure); HullWhite modelHW2 = new HullWhite(rhTermStructure); BlackKarasinski modelBK = new BlackKarasinski(rhTermStructure); // model calibrations // Console.WriteLine( "G2 (analytic formulae) calibration" ); // for (int i=0; i<swaptions.Count; i++) // NQuantLibc.as_black_helper(swaptions[i]).setPricingEngine( // new G2SwaptionEngine( modelG2, 6.0, 16 ) ); // // calibrateModel( modelG2, swaptions, 0.05); // Console.WriteLine( "calibrated to:" ); // Console.WriteLine( "a = " + modelG2.parameters()[0] ); // Console.WriteLine( "sigma = " + modelG2.parameters()[1] ); // Console.WriteLine( "b = " + modelG2.parameters()[2] ); // Console.WriteLine( "eta = " + modelG2.parameters()[3] ); // Console.WriteLine( "rho = " + modelG2.parameters()[4] ); Console.WriteLine("Hull-White (analytic formulae) calibration"); for (int i = 0; i < swaptions.Count; i++) { NQuantLibc.as_black_helper(swaptions[i]).setPricingEngine( new JamshidianSwaptionEngine(modelHW)); } calibrateModel(modelHW, swaptions, 0.05); // Console.WriteLine( "calibrated to:" ); // Console.WriteLine( "a = " + modelHW.parameters()[0] ); // Console.WriteLine( "sigma = " + modelHW.parameters()[1] ); Console.WriteLine("Hull-White (numerical) calibration"); for (int i = 0; i < swaptions.Count; i++) { NQuantLibc.as_black_helper(swaptions[i]).setPricingEngine( new TreeSwaptionEngine(modelHW2, grid)); } calibrateModel(modelHW2, swaptions, 0.05); // std::cout << "calibrated to:\n" // << "a = " << modelHW2->params()[0] << ", " // << "sigma = " << modelHW2->params()[1] // << std::endl << std::endl; Console.WriteLine("Black-Karasinski (numerical) calibration"); for (int i = 0; i < swaptions.Count; i++) { NQuantLibc.as_black_helper(swaptions[i]).setPricingEngine( new TreeSwaptionEngine(modelBK, grid)); } calibrateModel(modelBK, swaptions, 0.05); // std::cout << "calibrated to:\n" // << "a = " << modelBK->params()[0] << ", " // << "sigma = " << modelBK->params()[1] // << std::endl << std::endl; // ATM Bermudan swaption pricing Console.WriteLine("Payer bermudan swaption struck at {0} (ATM)", fixedATMRate); DateVector bermudanDates = new DateVector(); Schedule schedule = new Schedule(startDate, maturity, new Period(3, TimeUnit.Months), calendar, BusinessDayConvention.Following, BusinessDayConvention.Following, DateGeneration.Rule.Forward, false); for (uint i = 0; i < schedule.size(); i++) { bermudanDates.Add(schedule.date(i)); } Exercise bermudaExercise = new BermudanExercise(bermudanDates); Swaption bermudanSwaption = new Swaption(atmSwap, bermudaExercise); bermudanSwaption.setPricingEngine( new TreeSwaptionEngine(modelHW, 50)); Console.WriteLine("HW: " + bermudanSwaption.NPV()); bermudanSwaption.setPricingEngine( new TreeSwaptionEngine(modelHW2, 50)); Console.WriteLine("HW (num): " + bermudanSwaption.NPV()); bermudanSwaption.setPricingEngine( new TreeSwaptionEngine(modelBK, 50)); Console.WriteLine("BK (num): " + bermudanSwaption.NPV()); DateTime endTime = DateTime.Now; TimeSpan delta = endTime - startTime; Console.WriteLine(); Console.WriteLine("Run completed in {0} s", delta.TotalSeconds); Console.WriteLine(); }
public void testCachedValues() { //("Testing Bermudan swaption against cached values..."); CommonVars vars = new CommonVars(); vars.today = new Date(15, Month.February, 2002); Settings.setEvaluationDate(vars.today); vars.settlement = new Date(19, Month.February, 2002); // flat yield term structure impling 1x5 swap at 5% vars.termStructure.linkTo(Utilities.flatRate(vars.settlement, 0.04875825, new Actual365Fixed())); double atmRate = vars.makeSwap(0.0).fairRate(); VanillaSwap itmSwap = vars.makeSwap(0.8 * atmRate); VanillaSwap atmSwap = vars.makeSwap(atmRate); VanillaSwap otmSwap = vars.makeSwap(1.2 * atmRate); double a = 0.048696, sigma = 0.0058904; ShortRateModel model = new HullWhite(vars.termStructure, a, sigma); List <Date> exerciseDates = new List <Date>(); List <CashFlow> leg = atmSwap.fixedLeg(); for (int i = 0; i < leg.Count; i++) { Coupon coupon = (Coupon)(leg[i]); exerciseDates.Add(coupon.accrualStartDate()); } Exercise exercise = new BermudanExercise(exerciseDates); IPricingEngine treeEngine = new TreeSwaptionEngine(model, 50); IPricingEngine fdmEngine = new FdHullWhiteSwaptionEngine(model as HullWhite); #if QL_USE_INDEXED_COUPON double itmValue = 42.2413, atmValue = 12.8789, otmValue = 2.4759; double itmValueFdm = 42.2111, atmValueFdm = 12.8879, otmValueFdm = 2.44443; #else double itmValue = 42.2470, atmValue = 12.8826, otmValue = 2.4769; double itmValueFdm = 42.2091, atmValueFdm = 12.8864, otmValueFdm = 2.4437; #endif double tolerance = 1.0e-4; Swaption swaption = new Swaption(itmSwap, exercise); swaption.setPricingEngine(treeEngine); if (Math.Abs(swaption.NPV() - itmValue) > tolerance) { QAssert.Fail("failed to reproduce cached in-the-money swaption value:\n" + "calculated: " + swaption.NPV() + "\n" + "expected: " + itmValue); } swaption.setPricingEngine(fdmEngine); if (Math.Abs(swaption.NPV() - itmValueFdm) > tolerance) { QAssert.Fail("failed to reproduce cached in-the-money swaption value:\n" + "calculated: " + swaption.NPV() + "\n" + "expected: " + itmValueFdm); } swaption = new Swaption(atmSwap, exercise); swaption.setPricingEngine(treeEngine); if (Math.Abs(swaption.NPV() - atmValue) > tolerance) { QAssert.Fail("failed to reproduce cached at-the-money swaption value:\n" + "calculated: " + swaption.NPV() + "\n" + "expected: " + atmValue); } swaption.setPricingEngine(fdmEngine); if (Math.Abs(swaption.NPV() - atmValueFdm) > tolerance) { QAssert.Fail("failed to reproduce cached at-the-money swaption value:\n" + "calculated: " + swaption.NPV() + "\n" + "expected: " + atmValueFdm); } swaption = new Swaption(otmSwap, exercise); swaption.setPricingEngine(treeEngine); if (Math.Abs(swaption.NPV() - otmValue) > tolerance) { QAssert.Fail("failed to reproduce cached out-of-the-money " + "swaption value:\n" + "calculated: " + swaption.NPV() + "\n" + "expected: " + otmValue); } swaption.setPricingEngine(fdmEngine); if (Math.Abs(swaption.NPV() - otmValueFdm) > tolerance) { QAssert.Fail("failed to reproduce cached out-of-the-money " + "swaption value:\n" + "calculated: " + swaption.NPV() + "\n" + "expected: " + otmValueFdm); } for (int j = 0; j < exerciseDates.Count; j++) { exerciseDates[j] = vars.calendar.adjust(exerciseDates[j] - 10); } exercise = new BermudanExercise(exerciseDates); #if QL_USE_INDEXED_COUPON itmValue = 42.1917; atmValue = 12.7788; otmValue = 2.4388; #else itmValue = 42.1974; atmValue = 12.7825; otmValue = 2.4399; #endif swaption = new Swaption(itmSwap, exercise); swaption.setPricingEngine(treeEngine); if (Math.Abs(swaption.NPV() - itmValue) > tolerance) { QAssert.Fail("failed to reproduce cached in-the-money swaption value:\n" + "calculated: " + swaption.NPV() + "\n" + "expected: " + itmValue); } swaption = new Swaption(atmSwap, exercise); swaption.setPricingEngine(treeEngine); if (Math.Abs(swaption.NPV() - atmValue) > tolerance) { QAssert.Fail("failed to reproduce cached at-the-money swaption value:\n" + "calculated: " + swaption.NPV() + "\n" + "expected: " + atmValue); } swaption = new Swaption(otmSwap, exercise); swaption.setPricingEngine(treeEngine); if (Math.Abs(swaption.NPV() - otmValue) > tolerance) { QAssert.Fail("failed to reproduce cached out-of-the-money " + "swaption value:\n" + "calculated: " + swaption.NPV() + "\n" + "expected: " + otmValue); } }
private static void Main() { DateTime startTime = DateTime.Now; var todaysDate = new DateTime(2002, 2, 15); Settings.instance().setEvaluationDate(todaysDate); Calendar calendar = new TARGET(); var settlementDate = new Date(19, Month.February, 2002); // flat yield term structure impling 1x5 swap at 5% Quote flatRate = new SimpleQuote(0.04875825); var myTermStructure = new FlatForward(settlementDate, new QuoteHandle(flatRate), new Actual365Fixed()); var rhTermStructure = new RelinkableYieldTermStructureHandle(); rhTermStructure.linkTo(myTermStructure); // Define the ATM/OTM/ITM swaps var fixedLegTenor = new Period(1, TimeUnit.Years); const BusinessDayConvention fixedLegConvention = BusinessDayConvention.Unadjusted; const BusinessDayConvention floatingLegConvention = BusinessDayConvention.ModifiedFollowing; DayCounter fixedLegDayCounter = new Thirty360(Thirty360.Convention.European); var floatingLegTenor = new Period(6, TimeUnit.Months); const double dummyFixedRate = 0.03; IborIndex indexSixMonths = new Euribor6M(rhTermStructure); Date startDate = calendar.advance(settlementDate, 1, TimeUnit.Years, floatingLegConvention); Date maturity = calendar.advance(startDate, 5, TimeUnit.Years, floatingLegConvention); var fixedSchedule = new Schedule(startDate, maturity, fixedLegTenor, calendar, fixedLegConvention, fixedLegConvention, DateGeneration.Rule.Forward, false); var floatSchedule = new Schedule(startDate, maturity, floatingLegTenor, calendar, floatingLegConvention, floatingLegConvention, DateGeneration.Rule.Forward, false); var swap = new VanillaSwap(VanillaSwap.Type.Payer, 1000.0, fixedSchedule, dummyFixedRate, fixedLegDayCounter, floatSchedule, indexSixMonths, 0.0, indexSixMonths.dayCounter()); var swapEngine = new DiscountingSwapEngine(rhTermStructure); swap.setPricingEngine(swapEngine); double fixedAtmRate = swap.fairRate(); double fixedOtmRate = fixedAtmRate * 1.2; double fixedItmRate = fixedAtmRate * 0.8; var atmSwap = new VanillaSwap(VanillaSwap.Type.Payer, 1000.0, fixedSchedule, fixedAtmRate, fixedLegDayCounter, floatSchedule, indexSixMonths, 0.0, indexSixMonths.dayCounter()); var otmSwap = new VanillaSwap(VanillaSwap.Type.Payer, 1000.0, fixedSchedule, fixedOtmRate, fixedLegDayCounter, floatSchedule, indexSixMonths, 0.0, indexSixMonths.dayCounter()); var itmSwap = new VanillaSwap(VanillaSwap.Type.Payer, 1000.0, fixedSchedule, fixedItmRate, fixedLegDayCounter, floatSchedule, indexSixMonths, 0.0, indexSixMonths.dayCounter()); atmSwap.setPricingEngine(swapEngine); otmSwap.setPricingEngine(swapEngine); itmSwap.setPricingEngine(swapEngine); // defining the swaptions to be used in model calibration var swaptionMaturities = new PeriodVector { new Period(1, TimeUnit.Years), new Period(2, TimeUnit.Years), new Period(3, TimeUnit.Years), new Period(4, TimeUnit.Years), new Period(5, TimeUnit.Years) }; var swaptions = new CalibrationHelperVector(); // List of times that have to be included in the timegrid var times = new DoubleVector(); for (int i = 0; i < NUM_ROWS; i++) { int j = NUM_COLS - i - 1; // 1x5, 2x4, 3x3, 4x2, 5x1 int k = i * NUM_COLS + j; Quote vol = new SimpleQuote(SWAPTION_VOLS[k]); var helper = new SwaptionHelper(swaptionMaturities[i], new Period(SWAP_LENGHTS[j], TimeUnit.Years), new QuoteHandle(vol), indexSixMonths, indexSixMonths.tenor(), indexSixMonths.dayCounter(), indexSixMonths.dayCounter(), rhTermStructure); swaptions.Add(helper); times.AddRange(helper.times()); } // Building time-grid var grid = new TimeGrid(times, 30); // defining the models // G2 modelG2 = new G2(rhTermStructure)); var modelHw = new HullWhite(rhTermStructure); var modelHw2 = new HullWhite(rhTermStructure); var modelBk = new BlackKarasinski(rhTermStructure); // model calibrations Console.WriteLine("Hull-White (analytic formulae) calibration"); foreach (CalibrationHelper calibrationHelper in swaptions) { NQuantLibc.as_black_helper(calibrationHelper).setPricingEngine(new JamshidianSwaptionEngine(modelHw)); } CalibrateModel(modelHw, swaptions, 0.05); Console.WriteLine("Hull-White (numerical) calibration"); foreach (CalibrationHelper calibrationHelper in swaptions) { NQuantLibc.as_black_helper(calibrationHelper).setPricingEngine(new TreeSwaptionEngine(modelHw2, grid)); } CalibrateModel(modelHw2, swaptions, 0.05); Console.WriteLine("Black-Karasinski (numerical) calibration"); foreach (CalibrationHelper calibrationHelper in swaptions) { NQuantLibc.as_black_helper(calibrationHelper).setPricingEngine(new TreeSwaptionEngine(modelBk, grid)); } CalibrateModel(modelBk, swaptions, 0.05); // ATM Bermudan swaption pricing Console.WriteLine("Payer bermudan swaption struck at {0} (ATM)", fixedAtmRate); var bermudanDates = new DateVector(); var schedule = new Schedule(startDate, maturity, new Period(3, TimeUnit.Months), calendar, BusinessDayConvention.Following, BusinessDayConvention.Following, DateGeneration.Rule.Forward, false); for (uint i = 0; i < schedule.size(); i++) { bermudanDates.Add(schedule.date(i)); } Exercise bermudaExercise = new BermudanExercise(bermudanDates); var bermudanSwaption = new Swaption(atmSwap, bermudaExercise); bermudanSwaption.setPricingEngine(new TreeSwaptionEngine(modelHw, 50)); Console.WriteLine("HW: " + bermudanSwaption.NPV()); bermudanSwaption.setPricingEngine(new TreeSwaptionEngine(modelHw2, 50)); Console.WriteLine("HW (num): " + bermudanSwaption.NPV()); bermudanSwaption.setPricingEngine(new TreeSwaptionEngine(modelBk, 50)); Console.WriteLine("BK (num): " + bermudanSwaption.NPV()); DateTime endTime = DateTime.Now; TimeSpan delta = endTime - startTime; Console.WriteLine(); Console.WriteLine("Run completed in {0} s", delta.TotalSeconds); Console.WriteLine(); }
public void testCachedValues() { //("Testing Bermudan swaption against cached values..."); CommonVars vars = new CommonVars(); vars.today = new Date(15, Month.February, 2002); Settings.setEvaluationDate(vars.today); vars.settlement = new Date(19, Month.February, 2002); // flat yield term structure impling 1x5 swap at 5% vars.termStructure.linkTo(Utilities.flatRate(vars.settlement, 0.04875825, new Actual365Fixed())); double atmRate = vars.makeSwap(0.0).fairRate(); VanillaSwap itmSwap = vars.makeSwap(0.8*atmRate); VanillaSwap atmSwap = vars.makeSwap(atmRate); VanillaSwap otmSwap = vars.makeSwap(1.2*atmRate); double a = 0.048696, sigma = 0.0058904; ShortRateModel model=new HullWhite(vars.termStructure,a, sigma); List<Date> exerciseDates= new List<Date>(); List<CashFlow> leg = atmSwap.fixedLeg(); for (int i=0; i<leg.Count; i++) { Coupon coupon = (Coupon)(leg[i]); exerciseDates.Add(coupon.accrualStartDate()); } Exercise exercise = new BermudanExercise(exerciseDates); IPricingEngine engine = new TreeSwaptionEngine(model, 50); #if QL_USE_INDEXED_COUPON Real itmValue = 42.2413, atmValue = 12.8789, otmValue = 2.4759; #else double itmValue = 42.2470, atmValue = 12.8826, otmValue = 2.4769; #endif double tolerance = 1.0e-4; Swaption swaption = new Swaption(itmSwap, exercise); swaption.setPricingEngine(engine); if (Math.Abs(swaption.NPV()-itmValue) > tolerance) Assert.Fail("failed to reproduce cached in-the-money swaption value:\n" + "calculated: " + swaption.NPV() + "\n" + "expected: " + itmValue); swaption = new Swaption(atmSwap, exercise); swaption.setPricingEngine(engine); if (Math.Abs(swaption.NPV()-atmValue) > tolerance) Assert.Fail("failed to reproduce cached at-the-money swaption value:\n" + "calculated: " + swaption.NPV() + "\n" + "expected: " + atmValue); swaption = new Swaption(otmSwap, exercise); swaption.setPricingEngine(engine); if (Math.Abs(swaption.NPV()-otmValue) > tolerance) Assert.Fail("failed to reproduce cached out-of-the-money " + "swaption value:\n" + "calculated: " + swaption.NPV() + "\n" + "expected: " + otmValue); for (int j=0; j<exerciseDates.Count; j++) exerciseDates[j] = vars.calendar.adjust(exerciseDates[j]-10); exercise = new BermudanExercise(exerciseDates); #if QL_USE_INDEXED_COUPON itmValue = 42.1917; atmValue = 12.7788; otmValue = 2.4388; #else itmValue = 42.1974; atmValue = 12.7825; otmValue = 2.4399; #endif swaption = new Swaption(itmSwap, exercise); swaption.setPricingEngine(engine); if (Math.Abs(swaption.NPV()-itmValue) > tolerance) Assert.Fail("failed to reproduce cached in-the-money swaption value:\n" + "calculated: " + swaption.NPV() + "\n" + "expected: " + itmValue); swaption = new Swaption(atmSwap, exercise); swaption.setPricingEngine(engine); if (Math.Abs(swaption.NPV()-atmValue) > tolerance) Assert.Fail("failed to reproduce cached at-the-money swaption value:\n" + "calculated: " + swaption.NPV() + "\n" + "expected: " + atmValue); swaption = new Swaption(otmSwap, exercise); swaption.setPricingEngine(engine); if (Math.Abs(swaption.NPV()-otmValue) > tolerance) Assert.Fail("failed to reproduce cached out-of-the-money " + "swaption value:\n" + "calculated: " + swaption.NPV() + "\n" + "expected: " + otmValue); }
static void Main(string[] args) { DateTime timer = DateTime.Now; Date todaysDate = new Date(15, 2, 2002); Calendar calendar = new TARGET(); Date settlementDate = new Date(19, 2, 2002); Settings.setEvaluationDate(todaysDate); // flat yield term structure impling 1x5 swap at 5% Quote flatRate = new SimpleQuote(0.04875825); Handle<YieldTermStructure> rhTermStructure = new Handle<YieldTermStructure>( new FlatForward(settlementDate, new Handle<Quote>(flatRate), new Actual365Fixed())); // Define the ATM/OTM/ITM swaps Frequency fixedLegFrequency = Frequency.Annual; BusinessDayConvention fixedLegConvention = BusinessDayConvention.Unadjusted; BusinessDayConvention floatingLegConvention = BusinessDayConvention.ModifiedFollowing; DayCounter fixedLegDayCounter = new Thirty360(Thirty360.Thirty360Convention.European); Frequency floatingLegFrequency = Frequency.Semiannual; VanillaSwap.Type type = VanillaSwap.Type.Payer; double dummyFixedRate = 0.03; IborIndex indexSixMonths = new Euribor6M(rhTermStructure); Date startDate = calendar.advance(settlementDate, 1, TimeUnit.Years, floatingLegConvention); Date maturity = calendar.advance(startDate, 5, TimeUnit.Years, floatingLegConvention); Schedule fixedSchedule = new Schedule(startDate, maturity, new Period(fixedLegFrequency), calendar, fixedLegConvention, fixedLegConvention, DateGeneration.Rule.Forward, false); Schedule floatSchedule = new Schedule(startDate, maturity, new Period(floatingLegFrequency), calendar, floatingLegConvention, floatingLegConvention, DateGeneration.Rule.Forward, false); VanillaSwap swap = new VanillaSwap( type, 1000.0, fixedSchedule, dummyFixedRate, fixedLegDayCounter, floatSchedule, indexSixMonths, 0.0, indexSixMonths.dayCounter()); swap.setPricingEngine(new DiscountingSwapEngine(rhTermStructure)); double fixedAtmRate = swap.fairRate(); double fixedOtmRate = fixedAtmRate * 1.2; double fixedItmRate = fixedAtmRate * 0.8; VanillaSwap atmSwap = new VanillaSwap( type, 1000.0, fixedSchedule, fixedAtmRate, fixedLegDayCounter, floatSchedule, indexSixMonths, 0.0, indexSixMonths.dayCounter()); VanillaSwap otmSwap = new VanillaSwap( type, 1000.0, fixedSchedule, fixedOtmRate, fixedLegDayCounter, floatSchedule, indexSixMonths, 0.0, indexSixMonths.dayCounter()); VanillaSwap itmSwap = new VanillaSwap( type, 1000.0, fixedSchedule, fixedItmRate, fixedLegDayCounter, floatSchedule, indexSixMonths, 0.0, indexSixMonths.dayCounter()); // defining the swaptions to be used in model calibration List<Period> swaptionMaturities = new List<Period>(5); swaptionMaturities.Add(new Period(1, TimeUnit.Years)); swaptionMaturities.Add(new Period(2, TimeUnit.Years)); swaptionMaturities.Add(new Period(3, TimeUnit.Years)); swaptionMaturities.Add(new Period(4, TimeUnit.Years)); swaptionMaturities.Add(new Period(5, TimeUnit.Years)); List<CalibrationHelper> swaptions = new List<CalibrationHelper>(); // List of times that have to be included in the timegrid List<double> times = new List<double>(); for (int i = 0; i < NumRows; i++) { int j = NumCols - i - 1; // 1x5, 2x4, 3x3, 4x2, 5x1 int k = i * NumCols + j; Quote vol = new SimpleQuote(SwaptionVols[k]); swaptions.Add(new SwaptionHelper(swaptionMaturities[i], new Period(SwapLenghts[j], TimeUnit.Years), new Handle<Quote>(vol), indexSixMonths, indexSixMonths.tenor(), indexSixMonths.dayCounter(), indexSixMonths.dayCounter(), rhTermStructure, false)); swaptions.Last().addTimesTo(times); } // Building time-grid TimeGrid grid = new TimeGrid(times, 30); // defining the models G2 modelG2 = new G2(rhTermStructure); HullWhite modelHw = new HullWhite(rhTermStructure); HullWhite modelHw2 = new HullWhite(rhTermStructure); BlackKarasinski modelBk = new BlackKarasinski(rhTermStructure); // model calibrations Console.WriteLine("G2 (analytic formulae) calibration"); for (int i = 0; i < swaptions.Count; i++) swaptions[i].setPricingEngine(new G2SwaptionEngine(modelG2, 6.0, 16)); CalibrateModel(modelG2, swaptions); Console.WriteLine("calibrated to:\n" + "a = {0:0.000000}, " + "sigma = {1:0.0000000}\n" + "b = {2:0.000000}, " + "eta = {3:0.0000000}\n" + "rho = {4:0.00000}\n", modelG2.parameters()[0], modelG2.parameters()[1], modelG2.parameters()[2], modelG2.parameters()[3], modelG2.parameters()[4]); Console.WriteLine("Hull-White (analytic formulae) calibration"); for (int i = 0; i < swaptions.Count; i++) swaptions[i].setPricingEngine(new JamshidianSwaptionEngine(modelHw)); CalibrateModel(modelHw, swaptions); Console.WriteLine("calibrated to:\n" + "a = {0:0.000000}, " + "sigma = {1:0.0000000}\n", modelHw.parameters()[0], modelHw.parameters()[1]); Console.WriteLine("Hull-White (numerical) calibration"); for (int i = 0; i < swaptions.Count(); i++) swaptions[i].setPricingEngine(new TreeSwaptionEngine(modelHw2, grid)); CalibrateModel(modelHw2, swaptions); Console.WriteLine("calibrated to:\n" + "a = {0:0.000000}, " + "sigma = {1:0.0000000}\n", modelHw2.parameters()[0], modelHw2.parameters()[1]); Console.WriteLine("Black-Karasinski (numerical) calibration"); for (int i = 0; i < swaptions.Count; i++) swaptions[i].setPricingEngine(new TreeSwaptionEngine(modelBk, grid)); CalibrateModel(modelBk, swaptions); Console.WriteLine("calibrated to:\n" + "a = {0:0.000000}, " + "sigma = {1:0.00000}\n", modelBk.parameters()[0], modelBk.parameters()[1]); // ATM Bermudan swaption pricing Console.WriteLine("Payer bermudan swaption " + "struck at {0:0.00000 %} (ATM)", fixedAtmRate); List<Date> bermudanDates = new List<Date>(); List<CashFlow> leg = swap.fixedLeg(); for (int i = 0; i < leg.Count; i++) { Coupon coupon = (Coupon)leg[i]; bermudanDates.Add(coupon.accrualStartDate()); } Exercise bermudanExercise = new BermudanExercise(bermudanDates); Swaption bermudanSwaption = new Swaption(atmSwap, bermudanExercise); // Do the pricing for each model // G2 price the European swaption here, it should switch to bermudan bermudanSwaption.setPricingEngine(new TreeSwaptionEngine(modelG2, 50)); Console.WriteLine("G2: {0:0.00}", bermudanSwaption.NPV()); bermudanSwaption.setPricingEngine(new TreeSwaptionEngine(modelHw, 50)); Console.WriteLine("HW: {0:0.000}", bermudanSwaption.NPV()); bermudanSwaption.setPricingEngine(new TreeSwaptionEngine(modelHw2, 50)); Console.WriteLine("HW (num): {0:0.000}", bermudanSwaption.NPV()); bermudanSwaption.setPricingEngine(new TreeSwaptionEngine(modelBk, 50)); Console.WriteLine("BK: {0:0.000}", bermudanSwaption.NPV()); // OTM Bermudan swaption pricing Console.WriteLine("Payer bermudan swaption " + "struck at {0:0.00000 %} (OTM)", fixedOtmRate); Swaption otmBermudanSwaption = new Swaption(otmSwap, bermudanExercise); // Do the pricing for each model otmBermudanSwaption.setPricingEngine(new TreeSwaptionEngine(modelG2, 50)); Console.WriteLine("G2: {0:0.0000}", otmBermudanSwaption.NPV()); otmBermudanSwaption.setPricingEngine(new TreeSwaptionEngine(modelHw, 50)); Console.WriteLine("HW: {0:0.0000}", otmBermudanSwaption.NPV()); otmBermudanSwaption.setPricingEngine(new TreeSwaptionEngine(modelHw2, 50)); Console.WriteLine("HW (num): {0:0.000}", otmBermudanSwaption.NPV()); otmBermudanSwaption.setPricingEngine(new TreeSwaptionEngine(modelBk, 50)); Console.WriteLine("BK: {0:0.0000}", otmBermudanSwaption.NPV()); // ITM Bermudan swaption pricing Console.WriteLine("Payer bermudan swaption " + "struck at {0:0.00000 %} (ITM)", fixedItmRate); Swaption itmBermudanSwaption = new Swaption(itmSwap, bermudanExercise); // Do the pricing for each model itmBermudanSwaption.setPricingEngine(new TreeSwaptionEngine(modelG2, 50)); Console.WriteLine("G2: {0:0.000}", itmBermudanSwaption.NPV()); itmBermudanSwaption.setPricingEngine(new TreeSwaptionEngine(modelHw, 50)); Console.WriteLine("HW: {0:0.000}", itmBermudanSwaption.NPV()); itmBermudanSwaption.setPricingEngine(new TreeSwaptionEngine(modelHw2, 50)); Console.WriteLine("HW (num): {0:0.000}", itmBermudanSwaption.NPV()); itmBermudanSwaption.setPricingEngine(new TreeSwaptionEngine(modelBk, 50)); Console.WriteLine("BK: {0:0.000}", itmBermudanSwaption.NPV()); Console.WriteLine(" \nRun completed in {0}", DateTime.Now - timer); Console.WriteLine(); Console.Write("Press any key to continue ..."); Console.ReadKey(); }
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()); } } } }
public void testImpliedVolatility() { //"Testing implied volatility for swaptions..."; CommonVars vars = new CommonVars(); int maxEvaluations = 100; double tolerance = 1.0e-08; Settlement.Type[] types = { Settlement.Type.Physical, Settlement.Type.Cash }; // test data double[] strikes = { 0.02, 0.03, 0.04, 0.05, 0.06, 0.07 }; double[] vols = { 0.01, 0.05, 0.10, 0.20, 0.30, 0.70, 0.90 }; for (int i = 0; i < exercises.Length; i++) { for (int j = 0; j < lengths.Length; j++) { Date exerciseDate = vars.calendar.advance(vars.today, exercises[i]); Date startDate = vars.calendar.advance(exerciseDate, vars.settlementDays, TimeUnit.Days); Date maturity = vars.calendar.advance(startDate, lengths[j], vars.floatingConvention); for (int t = 0; t < strikes.Length; t++) { for (int k = 0; k < type.Length; k++) { VanillaSwap swap = new MakeVanillaSwap(lengths[j], vars.index, strikes[t]) .withEffectiveDate(startDate) .withFloatingLegSpread(0.0) .withType(type[k]); for (int h = 0; h < types.Length; h++) { for (int u = 0; u < vols.Length; u++) { Swaption swaption = vars.makeSwaption(swap, exerciseDate, vols[u], types[h]); // Black price double value = swaption.NPV(); double implVol = 0.0; try { implVol = swaption.impliedVolatility(value, vars.termStructure, 0.10, tolerance, maxEvaluations); } catch (System.Exception e) { // couldn't bracket? swaption.setPricingEngine(vars.makeEngine(0.0)); double value2 = swaption.NPV(); if (Math.Abs(value - value2) < tolerance) { // ok, just skip: continue; } // otherwise, report error Assert.Fail("implied vol failure: " + exercises[i] + "x" + lengths[j] + " " + type[k] + "\nsettlement: " + types[h] + "\nstrike " + strikes[t] + "\natm level: " + swap.fairRate() + "\nvol: " + vols[u] + "\nprice: " + value + "\n" + e.Message.ToString()); } if (Math.Abs(implVol - vols[u]) > tolerance) { // the difference might not matter swaption.setPricingEngine(vars.makeEngine(implVol)); double value2 = swaption.NPV(); if (Math.Abs(value - value2) > tolerance) { Assert.Fail("implied vol failure: " + exercises[i] + "x" + lengths[j] + " " + type[k] + "\nsettlement: " + types[h] + "\nstrike " + strikes[t] + "\natm level: " + swap.fairRate() + "\nvol: " + vols[u] + "\nprice: " + value + "\nimplied vol: " + implVol + "\nimplied price: " + value2); } } } } } } } } }
public void testVega() { //"Testing swaption vega..."; CommonVars vars = new CommonVars(); Settlement.Type[] types = { Settlement.Type.Physical, Settlement.Type.Cash }; double[] strikes = { 0.03, 0.04, 0.05, 0.06, 0.07 }; double[] vols = { 0.01, 0.20, 0.30, 0.70, 0.90 }; double shift = 1e-8; for (int i = 0; i < exercises.Length; i++) { Date exerciseDate = vars.calendar.advance(vars.today, exercises[i]); // A VERIFIER§§§§ Date startDate = vars.calendar.advance(exerciseDate, vars.settlementDays, TimeUnit.Days); for (int j = 0; j < lengths.Length; j++) { for (int t = 0; t < strikes.Length; t++) { for (int h = 0; h < type.Length; h++) { VanillaSwap swap = new MakeVanillaSwap(lengths[j], vars.index, strikes[t]) .withEffectiveDate(startDate) .withFloatingLegSpread(0.0) .withType(type[h]); for (int u = 0; u < vols.Length; u++) { Swaption swaption = vars.makeSwaption(swap, exerciseDate, vols[u], types[h]); // FLOATING_POINT_EXCEPTION Swaption swaption1 = vars.makeSwaption(swap, exerciseDate, vols[u] - shift, types[h]); Swaption swaption2 = vars.makeSwaption(swap, exerciseDate, vols[u] + shift, types[h]); double swaptionNPV = swaption.NPV(); double numericalVegaPerPoint = (swaption2.NPV() - swaption1.NPV()) / (200.0 * shift); // check only relevant vega if (numericalVegaPerPoint / swaptionNPV > 1.0e-7) { double analyticalVegaPerPoint = (double)swaption.result("vega") / 100.0; double discrepancy = Math.Abs(analyticalVegaPerPoint - numericalVegaPerPoint); discrepancy /= numericalVegaPerPoint; double tolerance = 0.015; if (discrepancy > tolerance) { Assert.Fail("failed to compute swaption vega:" + "\n option tenor: " + exercises[i] + "\n volatility: " + vols[u] + "\n option type: " + swaption.type() + "\n swap tenor: " + lengths[j] + "\n strike: " + strikes[t] + "\n settlement: " + types[h] + "\n nominal: " + swaption.underlyingSwap().nominal + "\n npv: " + swaptionNPV + "\n calculated vega: " + analyticalVegaPerPoint + "\n expected vega: " + numericalVegaPerPoint + "\n discrepancy: " + discrepancy + "\n tolerance: " + tolerance); } } } } } } } }
public void testSpreadTreatment() { //"Testing swaption treatment of spread..."; CommonVars vars = new CommonVars(); double[] spreads = { -0.002, -0.001, 0.0, 0.001, 0.002 }; for (int i = 0; i < exercises.Length; i++) { for (int j = 0; j < lengths.Length; j++) { for (int k = 0; k < type.Length; k++) { Date exerciseDate = vars.calendar.advance(vars.today, exercises[i]); Date startDate = vars.calendar.advance(exerciseDate, vars.settlementDays, TimeUnit.Days); for (int l = 0; l < spreads.Length; l++) { VanillaSwap swap = new MakeVanillaSwap(lengths[j], vars.index, 0.06) .withEffectiveDate(startDate) .withFloatingLegSpread(spreads[l]) .withType(type[k]); // FLOATING_POINT_EXCEPTION double correction = spreads[l] * swap.floatingLegBPS() / swap.fixedLegBPS(); VanillaSwap equivalentSwap = new MakeVanillaSwap(lengths[j], vars.index, 0.06 + correction) .withEffectiveDate(startDate) .withFloatingLegSpread(0.0) .withType(type[k]); Swaption swaption1 = vars.makeSwaption(swap, exerciseDate, 0.20); Swaption swaption2 = vars.makeSwaption(equivalentSwap, exerciseDate, 0.20); Swaption swaption1_cash = vars.makeSwaption(swap, exerciseDate, 0.20, Settlement.Type.Cash); Swaption swaption2_cash = vars.makeSwaption(equivalentSwap, exerciseDate, 0.20, Settlement.Type.Cash); if (Math.Abs(swaption1.NPV() - swaption2.NPV()) > 1.0e-6) { Assert.Fail("wrong spread treatment:" + "\nexercise: " + exerciseDate + "\nlength: " + lengths[j] + "\ntype " + type[k] + "\nspread: " + spreads[l] + "\noriginal swaption value: " + swaption1.NPV() + "\nequivalent swaption value: " + swaption2.NPV()); } if (Math.Abs(swaption1_cash.NPV() - swaption2_cash.NPV()) > 1.0e-6) { Assert.Fail("wrong spread treatment:" + "\nexercise date: " + exerciseDate + "\nlength: " + lengths[j] + //"\npay " + (type[k] ? "fixed" : "floating") + "\nspread: " + spreads[l] + "\nvalue of original swaption: " + swaption1_cash.NPV() + "\nvalue of equivalent swaption: " + swaption2_cash.NPV()); } } } } } }
public void testSpreadDependency() { //"Testing swaption dependency on spread..."; CommonVars vars = new CommonVars(); double[] spreads = { -0.002, -0.001, 0.0, 0.001, 0.002 }; for (int i = 0; i < exercises.Length; i++) { for (int j = 0; j < lengths.Length; j++) { for (int k = 0; k < type.Length; k++) { Date exerciseDate = vars.calendar.advance(vars.today, exercises[i]); Date startDate = vars.calendar.advance(exerciseDate, vars.settlementDays, TimeUnit.Days); // store the results for different rates... List <double> values = new InitializedList <double>(spreads.Length); List <double> values_cash = new InitializedList <double>(spreads.Length); for (int l = 0; l < spreads.Length; l++) { VanillaSwap swap = new MakeVanillaSwap(lengths[j], vars.index, 0.06) .withEffectiveDate(startDate) .withFloatingLegSpread(spreads[l]) .withType(type[k]); Swaption swaption = vars.makeSwaption(swap, exerciseDate, 0.20); // FLOATING_POINT_EXCEPTION values[l] = swaption.NPV(); Swaption swaption_cash = vars.makeSwaption(swap, exerciseDate, 0.20, Settlement.Type.Cash); values_cash[l] = swaption_cash.NPV(); } // and check that they go the right way if (type[k] == VanillaSwap.Type.Payer) { for (int n = 0; n < spreads.Length - 1; n++) { if (values[n] > values[n + 1]) { Assert.Fail("NPV is decreasing with the spread " + "in a payer swaption (physical delivered):" + "\nexercise date: " + exerciseDate + "\nlength: " + lengths[j] + "\nvalue: " + values[n] + " for spread: " + spreads[n] + "\nvalue: " + values[n + 1] + " for spread: " + spreads[n + 1]); } if (values_cash[n] > values_cash[n + 1]) { Assert.Fail("NPV is decreasing with the spread " + "in a payer swaption (cash delivered):" + "\nexercise date: " + exerciseDate + "\nlength: " + lengths[j] + "\nvalue: " + values_cash[n] + " for spread: " + spreads[n] + "\nvalue: " + values_cash[n + 1] + " for spread: " + spreads[n + 1]); } } } else { for (int n = 0; n < spreads.Length - 1; n++) { if (values[n] < values[n + 1]) { Assert.Fail("NPV is increasing with the spread " + "in a receiver swaption (physical delivered):" + "\nexercise date: " + exerciseDate + "\nlength: " + lengths[j] + "\nvalue: " + values[n] + " for spread: " + spreads[n] + "\nvalue: " + values[n + 1] + " for spread: " + spreads[n + 1]); } if (values_cash[n] < values_cash[n + 1]) { Assert.Fail("NPV is increasing with the spread " + "in a receiver swaption (cash delivered):" + "\nexercise date: " + exerciseDate + "\nlength: " + lengths[j] + "\nvalue: " + values_cash[n] + " for spread: " + spreads[n] + "\nvalue: " + values_cash[n + 1] + " for spread: " + spreads[n + 1]); } } } } } } }
public void testStrikeDependency() { //("Testing swaption dependency on strike......"); CommonVars vars = new CommonVars(); double[] strikes = new double[] { 0.03, 0.04, 0.05, 0.06, 0.07 }; for (int i = 0; i < exercises.Length; i++) { for (int j = 0; j < lengths.Length; j++) { for (int k = 0; k < type.Length; k++) { Date exerciseDate = vars.calendar.advance(vars.today, exercises[i]); Date startDate = vars.calendar.advance(exerciseDate, vars.settlementDays, TimeUnit.Days); // store the results for different rates... List <double> values = new InitializedList <double>(strikes.Length); List <double> values_cash = new InitializedList <double>(strikes.Length); double vol = 0.20; for (int l = 0; l < strikes.Length; l++) { VanillaSwap swap = new MakeVanillaSwap(lengths[j], vars.index, strikes[l]) .withEffectiveDate(startDate) .withFloatingLegSpread(0.0) .withType(type[k]); Swaption swaption = vars.makeSwaption(swap, exerciseDate, vol); // FLOATING_POINT_EXCEPTION values[l] = swaption.NPV(); Swaption swaption_cash = vars.makeSwaption(swap, exerciseDate, vol, Settlement.Type.Cash); values_cash[l] = swaption_cash.NPV(); } // and check that they go the right way if (type[k] == VanillaSwap.Type.Payer) { for (int z = 0; z < values.Count - 1; z++) { if (values[z] < values[z + 1]) { Assert.Fail("NPV of Payer swaption with delivery settlement" + "is increasing with the strike:" + "\noption tenor: " + exercises[i] + "\noption date: " + exerciseDate + "\nvolatility: " + vol + "\nswap tenor: " + lengths[j] + "\nvalue: " + values[z] + " at strike: " + strikes[z] + "\nvalue: " + values[z + 1] + " at strike: " + strikes[z + 1]); } } for (int z = 0; z < values_cash.Count - 1; z++) { if (values_cash[z] < values_cash[z + 1]) { Assert.Fail("NPV of Payer swaption with cash settlement" + "is increasing with the strike:" + "\noption tenor: " + exercises[i] + "\noption date: " + exerciseDate + "\nvolatility: " + vol + "\nswap tenor: " + lengths[j] + "\nvalue: " + values_cash[z] + " at strike: " + strikes[z] + "\nvalue: " + values_cash[z + 1] + " at strike: " + strikes[z + 1]); } } } else { for (int z = 0; z < values.Count - 1; z++) { if (values[z] > values[z + 1]) { Assert.Fail("NPV of Receiver swaption with delivery settlement" + "is increasing with the strike:" + "\noption tenor: " + exercises[i] + "\noption date: " + exerciseDate + "\nvolatility: " + vol + "\nswap tenor: " + lengths[j] + "\nvalue: " + values[z] + " at strike: " + strikes[z] + "\nvalue: " + values[z + 1] + " at strike: " + strikes[z + 1]); } } for (int z = 0; z < values_cash.Count - 1; z++) { if (values[z] > values[z + 1]) { Assert.Fail("NPV of Receiver swaption with cash settlement" + "is increasing with the strike:" + "\noption tenor: " + exercises[i] + "\noption date: " + exerciseDate + "\nvolatility: " + vol + "\nswap tenor: " + lengths[j] + "\nvalue: " + values_cash[z] + " at strike: " + strikes[z] + "\nvalue: " + values_cash[z + 1] + " at strike: " + strikes[z + 1]); } } } } } } }
static void Main(string[] args) { DateTime timer = DateTime.Now; Date todaysDate = new Date(15, 2, 2002); Calendar calendar = new TARGET(); Date settlementDate = new Date(19, 2, 2002); Settings.setEvaluationDate(todaysDate); // flat yield term structure impling 1x5 swap at 5% Quote flatRate = new SimpleQuote(0.04875825); Handle <YieldTermStructure> rhTermStructure = new Handle <YieldTermStructure>( new FlatForward(settlementDate, new Handle <Quote>(flatRate), new Actual365Fixed())); // Define the ATM/OTM/ITM swaps Frequency fixedLegFrequency = Frequency.Annual; BusinessDayConvention fixedLegConvention = BusinessDayConvention.Unadjusted; BusinessDayConvention floatingLegConvention = BusinessDayConvention.ModifiedFollowing; DayCounter fixedLegDayCounter = new Thirty360(Thirty360.Thirty360Convention.European); Frequency floatingLegFrequency = Frequency.Semiannual; VanillaSwap.Type type = VanillaSwap.Type.Payer; double dummyFixedRate = 0.03; IborIndex indexSixMonths = new Euribor6M(rhTermStructure); Date startDate = calendar.advance(settlementDate, 1, TimeUnit.Years, floatingLegConvention); Date maturity = calendar.advance(startDate, 5, TimeUnit.Years, floatingLegConvention); Schedule fixedSchedule = new Schedule(startDate, maturity, new Period(fixedLegFrequency), calendar, fixedLegConvention, fixedLegConvention, DateGeneration.Rule.Forward, false); Schedule floatSchedule = new Schedule(startDate, maturity, new Period(floatingLegFrequency), calendar, floatingLegConvention, floatingLegConvention, DateGeneration.Rule.Forward, false); VanillaSwap swap = new VanillaSwap( type, 1000.0, fixedSchedule, dummyFixedRate, fixedLegDayCounter, floatSchedule, indexSixMonths, 0.0, indexSixMonths.dayCounter()); swap.setPricingEngine(new DiscountingSwapEngine(rhTermStructure)); double fixedAtmRate = swap.fairRate(); double fixedOtmRate = fixedAtmRate * 1.2; double fixedItmRate = fixedAtmRate * 0.8; VanillaSwap atmSwap = new VanillaSwap( type, 1000.0, fixedSchedule, fixedAtmRate, fixedLegDayCounter, floatSchedule, indexSixMonths, 0.0, indexSixMonths.dayCounter()); VanillaSwap otmSwap = new VanillaSwap( type, 1000.0, fixedSchedule, fixedOtmRate, fixedLegDayCounter, floatSchedule, indexSixMonths, 0.0, indexSixMonths.dayCounter()); VanillaSwap itmSwap = new VanillaSwap( type, 1000.0, fixedSchedule, fixedItmRate, fixedLegDayCounter, floatSchedule, indexSixMonths, 0.0, indexSixMonths.dayCounter()); // defining the swaptions to be used in model calibration List <Period> swaptionMaturities = new List <Period>(5); swaptionMaturities.Add(new Period(1, TimeUnit.Years)); swaptionMaturities.Add(new Period(2, TimeUnit.Years)); swaptionMaturities.Add(new Period(3, TimeUnit.Years)); swaptionMaturities.Add(new Period(4, TimeUnit.Years)); swaptionMaturities.Add(new Period(5, TimeUnit.Years)); List <CalibrationHelper> swaptions = new List <CalibrationHelper>(); // List of times that have to be included in the timegrid List <double> times = new List <double>(); for (int i = 0; i < NumRows; i++) { int j = NumCols - i - 1; // 1x5, 2x4, 3x3, 4x2, 5x1 int k = i * NumCols + j; Quote vol = new SimpleQuote(SwaptionVols[k]); swaptions.Add(new SwaptionHelper(swaptionMaturities[i], new Period(SwapLenghts[j], TimeUnit.Years), new Handle <Quote>(vol), indexSixMonths, indexSixMonths.tenor(), indexSixMonths.dayCounter(), indexSixMonths.dayCounter(), rhTermStructure, false)); swaptions.Last().addTimesTo(times); } // Building time-grid TimeGrid grid = new TimeGrid(times, 30); // defining the models G2 modelG2 = new G2(rhTermStructure); HullWhite modelHw = new HullWhite(rhTermStructure); HullWhite modelHw2 = new HullWhite(rhTermStructure); BlackKarasinski modelBk = new BlackKarasinski(rhTermStructure); // model calibrations Console.WriteLine("G2 (analytic formulae) calibration"); for (int i = 0; i < swaptions.Count; i++) { swaptions[i].setPricingEngine(new G2SwaptionEngine(modelG2, 6.0, 16)); } CalibrateModel(modelG2, swaptions); Console.WriteLine("calibrated to:\n" + "a = {0:0.000000}, " + "sigma = {1:0.0000000}\n" + "b = {2:0.000000}, " + "eta = {3:0.0000000}\n" + "rho = {4:0.00000}\n", modelG2.parameters()[0], modelG2.parameters()[1], modelG2.parameters()[2], modelG2.parameters()[3], modelG2.parameters()[4]); Console.WriteLine("Hull-White (analytic formulae) calibration"); for (int i = 0; i < swaptions.Count; i++) { swaptions[i].setPricingEngine(new JamshidianSwaptionEngine(modelHw)); } CalibrateModel(modelHw, swaptions); Console.WriteLine("calibrated to:\n" + "a = {0:0.000000}, " + "sigma = {1:0.0000000}\n", modelHw.parameters()[0], modelHw.parameters()[1]); Console.WriteLine("Hull-White (numerical) calibration"); for (int i = 0; i < swaptions.Count(); i++) { swaptions[i].setPricingEngine(new TreeSwaptionEngine(modelHw2, grid)); } CalibrateModel(modelHw2, swaptions); Console.WriteLine("calibrated to:\n" + "a = {0:0.000000}, " + "sigma = {1:0.0000000}\n", modelHw2.parameters()[0], modelHw2.parameters()[1]); Console.WriteLine("Black-Karasinski (numerical) calibration"); for (int i = 0; i < swaptions.Count; i++) { swaptions[i].setPricingEngine(new TreeSwaptionEngine(modelBk, grid)); } CalibrateModel(modelBk, swaptions); Console.WriteLine("calibrated to:\n" + "a = {0:0.000000}, " + "sigma = {1:0.00000}\n", modelBk.parameters()[0], modelBk.parameters()[1]); // ATM Bermudan swaption pricing Console.WriteLine("Payer bermudan swaption " + "struck at {0:0.00000 %} (ATM)", fixedAtmRate); List <Date> bermudanDates = new List <Date>(); List <CashFlow> leg = swap.fixedLeg(); for (int i = 0; i < leg.Count; i++) { Coupon coupon = (Coupon)leg[i]; bermudanDates.Add(coupon.accrualStartDate()); } Exercise bermudanExercise = new BermudanExercise(bermudanDates); Swaption bermudanSwaption = new Swaption(atmSwap, bermudanExercise); // Do the pricing for each model // G2 price the European swaption here, it should switch to bermudan bermudanSwaption.setPricingEngine(new TreeSwaptionEngine(modelG2, 50)); Console.WriteLine("G2: {0:0.00}", bermudanSwaption.NPV()); bermudanSwaption.setPricingEngine(new TreeSwaptionEngine(modelHw, 50)); Console.WriteLine("HW: {0:0.000}", bermudanSwaption.NPV()); bermudanSwaption.setPricingEngine(new TreeSwaptionEngine(modelHw2, 50)); Console.WriteLine("HW (num): {0:0.000}", bermudanSwaption.NPV()); bermudanSwaption.setPricingEngine(new TreeSwaptionEngine(modelBk, 50)); Console.WriteLine("BK: {0:0.000}", bermudanSwaption.NPV()); // OTM Bermudan swaption pricing Console.WriteLine("Payer bermudan swaption " + "struck at {0:0.00000 %} (OTM)", fixedOtmRate); Swaption otmBermudanSwaption = new Swaption(otmSwap, bermudanExercise); // Do the pricing for each model otmBermudanSwaption.setPricingEngine(new TreeSwaptionEngine(modelG2, 50)); Console.WriteLine("G2: {0:0.0000}", otmBermudanSwaption.NPV()); otmBermudanSwaption.setPricingEngine(new TreeSwaptionEngine(modelHw, 50)); Console.WriteLine("HW: {0:0.0000}", otmBermudanSwaption.NPV()); otmBermudanSwaption.setPricingEngine(new TreeSwaptionEngine(modelHw2, 50)); Console.WriteLine("HW (num): {0:0.000}", otmBermudanSwaption.NPV()); otmBermudanSwaption.setPricingEngine(new TreeSwaptionEngine(modelBk, 50)); Console.WriteLine("BK: {0:0.0000}", otmBermudanSwaption.NPV()); // ITM Bermudan swaption pricing Console.WriteLine("Payer bermudan swaption " + "struck at {0:0.00000 %} (ITM)", fixedItmRate); Swaption itmBermudanSwaption = new Swaption(itmSwap, bermudanExercise); // Do the pricing for each model itmBermudanSwaption.setPricingEngine(new TreeSwaptionEngine(modelG2, 50)); Console.WriteLine("G2: {0:0.000}", itmBermudanSwaption.NPV()); itmBermudanSwaption.setPricingEngine(new TreeSwaptionEngine(modelHw, 50)); Console.WriteLine("HW: {0:0.000}", itmBermudanSwaption.NPV()); itmBermudanSwaption.setPricingEngine(new TreeSwaptionEngine(modelHw2, 50)); Console.WriteLine("HW (num): {0:0.000}", itmBermudanSwaption.NPV()); itmBermudanSwaption.setPricingEngine(new TreeSwaptionEngine(modelBk, 50)); Console.WriteLine("BK: {0:0.000}", itmBermudanSwaption.NPV()); Console.WriteLine(" \nRun completed in {0}", DateTime.Now - timer); Console.WriteLine(); Console.Write("Press any key to continue ..."); Console.ReadKey(); }