public override void calculate() { if (!(arguments_.settlementType == Settlement.Type.Physical)) { throw new ApplicationException("cash-settled swaptions not priced with Lfm engine"); } double basisPoint = 1.0e-4; 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_.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() / basisPoint) * Utils.blackFormula(w, fixedRate, fairRate, vol * Math.Sqrt(exercise)); }
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_); }
//////////////////////////////////////////////////// //! RateHelper interface public override double impliedQuote() { if (termStructure_ == null) { throw new ArgumentException("term structure not set"); } // we didn't register as observers - force calculation swap_.recalculate(); // it is from lazy objects // weak implementation... to be improved const double basisPoint = 1.0e-4; double floatingLegNPV = swap_.floatingLegNPV(); double spread = this.spread(); double spreadNPV = swap_.floatingLegBPS() / basisPoint * spread; double totNPV = -(floatingLegNPV + spreadNPV); double result = totNPV / (swap_.fixedLegBPS() / basisPoint); return(result); }
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); }
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); }
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.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(); double bp = 1.0e-4; annuity_ = Math.Abs(swap.fixedLegBPS() / bp); int q = (int)swapIndex.fixedLegTenor().frequency(); Schedule schedule = swap.fixedSchedule(); DayCounter dc = swapIndex.dayCounter(); //DayCounter dc = coupon.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: throw new Exception("unknown/illegal gFunction type"); } vanillaOptionPricer_ = new BlackVanillaOptionPricer(swapRateValue_, fixingDate_, swapTenor_, swaptionVolatility().link); } }