public GFunctionExactYield(CmsCoupon coupon) { SwapIndex swapIndex = coupon.swapIndex(); VanillaSwap swap = swapIndex.underlyingSwap(coupon.fixingDate()); Schedule schedule = swap.fixedSchedule(); Handle <YieldTermStructure> rateCurve = swapIndex.forwardingTermStructure(); DayCounter dc = swapIndex.dayCounter(); double swapStartTime = dc.yearFraction(rateCurve.link.referenceDate(), schedule.startDate()); double swapFirstPaymentTime = dc.yearFraction(rateCurve.link.referenceDate(), schedule.date(1)); double paymentTime = dc.yearFraction(rateCurve.link.referenceDate(), coupon.date()); delta_ = (paymentTime - swapStartTime) / (swapFirstPaymentTime - swapStartTime); List <CashFlow> fixedLeg = new List <CashFlow>(swap.fixedLeg()); int n = fixedLeg.Count; accruals_ = new List <double>(); for (int i = 0; i < n; ++i) { Coupon coupon1 = fixedLeg[i] as Coupon; accruals_.Add(coupon1.accrualPeriod()); } }
//===========================================================================// // GFunctionWithShifts // //===========================================================================// public GFunctionWithShifts(CmsCoupon coupon, Handle <Quote> meanReversion) { meanReversion_ = meanReversion; calibratedShift_ = 0.03; tmpRs_ = 10000000.0; accuracy_ = 1.0e-14; SwapIndex swapIndex = coupon.swapIndex(); VanillaSwap swap = swapIndex.underlyingSwap(coupon.fixingDate()); swapRateValue_ = swap.fairRate(); objectiveFunction_ = new ObjectiveFunction(this, swapRateValue_); Schedule schedule = swap.fixedSchedule(); Handle <YieldTermStructure> rateCurve = swapIndex.forwardingTermStructure(); DayCounter dc = swapIndex.dayCounter(); swapStartTime_ = dc.yearFraction(rateCurve.link.referenceDate(), schedule.startDate()); discountAtStart_ = rateCurve.link.discount(schedule.startDate()); double paymentTime = dc.yearFraction(rateCurve.link.referenceDate(), coupon.date()); shapedPaymentTime_ = shapeOfShift(paymentTime); List <CashFlow> fixedLeg = new List <CashFlow>(swap.fixedLeg()); int n = fixedLeg.Count; shapedSwapPaymentTimes_ = new List <double>(); swapPaymentDiscounts_ = new List <double>(); accruals_ = new List <double>(); for (int i = 0; i < n; ++i) { Coupon coupon1 = fixedLeg[i] as Coupon; accruals_.Add(coupon1.accrualPeriod()); Date paymentDate = new Date(coupon1.date().serialNumber()); double swapPaymentTime = dc.yearFraction(rateCurve.link.referenceDate(), paymentDate); shapedSwapPaymentTimes_.Add(shapeOfShift(swapPaymentTime)); swapPaymentDiscounts_.Add(rateCurve.link.discount(paymentDate)); } discountRatio_ = swapPaymentDiscounts_.Last() / discountAtStart_; }
public override void calculate() { double basisPoint = 1.0e-4; Date exerciseDate = arguments_.exercise.date(0); // the part of the swap preceding exerciseDate should be truncated // to avoid taking into account unwanted cashflows // for the moment we add a check avoiding this situation VanillaSwap swap = arguments_.swap; double strike = swap.fixedRate; List <CashFlow> fixedLeg = swap.fixedLeg(); FixedRateCoupon firstCoupon = fixedLeg[0] as FixedRateCoupon; Utils.QL_REQUIRE(firstCoupon != null, () => "wrong coupon type"); Utils.QL_REQUIRE(firstCoupon.accrualStartDate() >= exerciseDate, () => "swap start (" + firstCoupon.accrualStartDate() + ") before exercise date (" + exerciseDate + ") not supported in Black swaption engine"); // using the forecasting curve swap.setPricingEngine(new DiscountingSwapEngine(swap.iborIndex().forwardingTermStructure())); double atmForward = swap.fairRate(); // Volatilities are quoted for zero-spreaded swaps. // Therefore, any spread on the floating leg must be removed // with a corresponding correction on the fixed leg. if (swap.spread.IsNotEqual(0.0)) { double correction = swap.spread * Math.Abs(swap.floatingLegBPS() / swap.fixedLegBPS()); strike -= correction; atmForward -= correction; results_.additionalResults["spreadCorrection"] = correction; } else { results_.additionalResults["spreadCorrection"] = 0.0; } results_.additionalResults["strike"] = strike; results_.additionalResults["atmForward"] = atmForward; // using the discounting curve swap.setPricingEngine(new DiscountingSwapEngine(discountCurve_, false)); double annuity = 0; switch (arguments_.settlementType) { case Settlement.Type.Physical: { annuity = Math.Abs(swap.fixedLegBPS()) / basisPoint; break; } case Settlement.Type.Cash: { DayCounter dayCount = firstCoupon.dayCounter(); // we assume that the cash settlement date is equal // to the swap start date Date discountDate = model_ == CashAnnuityModel.DiscountCurve ? firstCoupon.accrualStartDate() : discountCurve_.link.referenceDate(); double fixedLegCashBPS = CashFlows.bps(fixedLeg, new InterestRate(atmForward, dayCount, Compounding.Compounded, Frequency.Annual), false, discountDate); annuity = Math.Abs(fixedLegCashBPS / basisPoint) * discountCurve_.link.discount(discountDate); break; } default: Utils.QL_FAIL("unknown settlement type"); break; } results_.additionalResults["annuity"] = annuity; double swapLength = vol_.link.swapLength(swap.floatingSchedule().dates().First(), swap.floatingSchedule().dates().Last()); results_.additionalResults["swapLength"] = swapLength; double variance = vol_.link.blackVariance(exerciseDate, swapLength, strike); double displacement = displacement_ == null ? vol_.link.shift(exerciseDate, swapLength) : Convert.ToDouble(displacement_); double stdDev = Math.Sqrt(variance); results_.additionalResults["stdDev"] = stdDev; Option.Type w = (arguments_.type == VanillaSwap.Type.Payer) ? Option.Type.Call : Option.Type.Put; results_.value = new Spec().value(w, strike, atmForward, stdDev, annuity, displacement); double exerciseTime = vol_.link.timeFromReference(exerciseDate); results_.additionalResults["vega"] = new Spec().vega(strike, atmForward, stdDev, exerciseTime, annuity, displacement); }
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 override void calculate() { double basisPoint = 1.0e-4; Date exerciseDate = arguments_.exercise.date(0); // the part of the swap preceding exerciseDate should be truncated // to avoid taking into account unwanted cashflows VanillaSwap swap = arguments_.swap; double strike = swap.fixedRate; // using the forecasting curve swap.setPricingEngine(new DiscountingSwapEngine(swap.iborIndex().forwardingTermStructure())); double atmForward = swap.fairRate(); // Volatilities are quoted for zero-spreaded swaps. // Therefore, any spread on the floating leg must be removed // with a corresponding correction on the fixed leg. if (swap.spread != 0.0) { double correction = swap.spread * Math.Abs(swap.floatingLegBPS() / swap.fixedLegBPS()); strike -= correction; atmForward -= correction; results_.additionalResults["spreadCorrection"] = correction; } else { results_.additionalResults["spreadCorrection"] = 0.0; } results_.additionalResults["strike"] = strike; results_.additionalResults["atmForward"] = atmForward; // using the discounting curve swap.setPricingEngine(new DiscountingSwapEngine(termStructure_)); double annuity; switch (arguments_.settlementType) { case Settlement.Type.Physical: { annuity = Math.Abs(swap.fixedLegBPS()) / basisPoint; break; } case Settlement.Type.Cash: { List <CashFlow> fixedLeg = swap.fixedLeg(); FixedRateCoupon firstCoupon = (FixedRateCoupon)fixedLeg[0]; DayCounter dayCount = firstCoupon.dayCounter(); double fixedLegCashBPS = CashFlows.bps(fixedLeg, new InterestRate(atmForward, dayCount, QLNet.Compounding.Compounded, Frequency.Annual), false, termStructure_.link.referenceDate()); annuity = Math.Abs(fixedLegCashBPS / basisPoint); break; } default: throw new ApplicationException("unknown settlement type"); } results_.additionalResults["annuity"] = annuity; // the swap length calculation might be improved using the value date // of the exercise date double swapLength = volatility_.link.swapLength(exerciseDate, arguments_.floatingPayDates.Last()); results_.additionalResults["swapLength"] = swapLength; double variance = volatility_.link.blackVariance(exerciseDate, swapLength, strike); double stdDev = Math.Sqrt(variance); results_.additionalResults["stdDev"] = stdDev; Option.Type w = (arguments_.type == VanillaSwap.Type.Payer) ? Option.Type.Call : Option.Type.Put; results_.value = Utils.blackFormula(w, strike, atmForward, stdDev, annuity); double exerciseTime = volatility_.link.timeFromReference(exerciseDate); results_.additionalResults["vega"] = Math.Sqrt(exerciseTime) * Utils.blackFormulaStdDevDerivative(strike, atmForward, stdDev, annuity); }