public override void calculate() { Utils.QL_REQUIRE(arguments_.settlementMethod != Settlement.Method.ParYieldCurve, () => "cash-settled (ParYieldCurve) swaptions not priced with Lfm engine"); VanillaSwap swap = arguments_.swap; IPricingEngine pe = new DiscountingSwapEngine(discountCurve_); swap.setPricingEngine(pe); double correction = swap.spread * Math.Abs(swap.floatingLegBPS() / swap.fixedLegBPS()); double fixedRate = swap.fixedRate - correction; double fairRate = swap.fairRate() - correction; SwaptionVolatilityMatrix volatility = model_.link.getSwaptionVolatilityMatrix(); Date referenceDate = volatility.referenceDate(); DayCounter dayCounter = volatility.dayCounter(); double exercise = dayCounter.yearFraction(referenceDate, arguments_.exercise.date(0)); double swapLength = dayCounter.yearFraction(referenceDate, arguments_.fixedPayDates.Last()) - dayCounter.yearFraction(referenceDate, arguments_.fixedResetDates[0]); Option.Type w = arguments_.type == VanillaSwap.Type.Payer ? Option.Type.Call : Option.Type.Put; double vol = volatility.volatility(exercise, swapLength, fairRate, true); results_.value = (swap.fixedLegBPS() / Const.BASIS_POINT) * Utils.blackFormula(w, fixedRate, fairRate, vol * Math.Sqrt(exercise)); }
public override void calculate() { Utils.QL_REQUIRE(arguments_.settlementType == Settlement.Type.Physical, () => "cash-settled swaptions not priced with G2 engine"); // adjust the fixed rate of the swap for the spread on the // floating leg (which is not taken into account by the // model) VanillaSwap swap = arguments_.swap; swap.setPricingEngine(new DiscountingSwapEngine(model_.link.termStructure())); double correction = swap.spread * Math.Abs(swap.floatingLegBPS() / swap.fixedLegBPS()); double fixedRate = swap.fixedRate - correction; results_.value = model_.link.swaption(arguments_, fixedRate, range_, intervals_); }
public override void calculate() { 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; if (arguments_.settlementType == Settlement.Type.Physical || (arguments_.settlementType == Settlement.Type.Cash && arguments_.settlementMethod == Settlement.Method.CollateralizedCashPrice)) { annuity = Math.Abs(swap.fixedLegBPS()) / Const.BASIS_POINT; } else if (arguments_.settlementType == Settlement.Type.Cash && arguments_.settlementMethod == Settlement.Method.ParYieldCurve) { 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 / Const.BASIS_POINT) * discountCurve_.link.discount(discountDate); } else { Utils.QL_FAIL("unknown settlement type"); } 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); }
public override void initialize(FloatingRateCoupon coupon) { coupon_ = coupon as CmsCoupon; Utils.QL_REQUIRE(coupon_ != null, () => "CMS coupon needed"); gearing_ = coupon_.gearing(); spread_ = coupon_.spread(); fixingDate_ = coupon_.fixingDate(); paymentDate_ = coupon_.date(); SwapIndex swapIndex = coupon_.swapIndex(); rateCurve_ = swapIndex.forwardingTermStructure().link; Date today = Settings.Instance.evaluationDate(); if (paymentDate_ > today) { discount_ = rateCurve_.discount(paymentDate_); } else { discount_ = 1.0; } spreadLegValue_ = spread_ * coupon_.accrualPeriod() * discount_; if (fixingDate_ > today) { swapTenor_ = swapIndex.tenor(); VanillaSwap swap = swapIndex.underlyingSwap(fixingDate_); swapRateValue_ = swap.fairRate(); annuity_ = Math.Abs(swap.fixedLegBPS() / Const.BASIS_POINT); int q = (int)swapIndex.fixedLegTenor().frequency(); Schedule schedule = swap.fixedSchedule(); DayCounter dc = swapIndex.dayCounter(); double startTime = dc.yearFraction(rateCurve_.referenceDate(), swap.startDate()); double swapFirstPaymentTime = dc.yearFraction(rateCurve_.referenceDate(), schedule.date(1)); double paymentTime = dc.yearFraction(rateCurve_.referenceDate(), paymentDate_); double delta = (paymentTime - startTime) / (swapFirstPaymentTime - startTime); switch (modelOfYieldCurve_) { case GFunctionFactory.YieldCurveModel.Standard: gFunction_ = GFunctionFactory.newGFunctionStandard(q, delta, swapTenor_.length()); break; case GFunctionFactory.YieldCurveModel.ExactYield: gFunction_ = GFunctionFactory.newGFunctionExactYield(coupon_); break; case GFunctionFactory.YieldCurveModel.ParallelShifts: { Handle <Quote> nullMeanReversionQuote = new Handle <Quote>(new SimpleQuote(0.0)); gFunction_ = GFunctionFactory.newGFunctionWithShifts(coupon_, nullMeanReversionQuote); } break; case GFunctionFactory.YieldCurveModel.NonParallelShifts: gFunction_ = GFunctionFactory.newGFunctionWithShifts(coupon_, meanReversion_); break; default: Utils.QL_FAIL("unknown/illegal gFunction type"); break; } vanillaOptionPricer_ = new BlackVanillaOptionPricer(swapRateValue_, fixingDate_, swapTenor_, swaptionVolatility().link); } }