NonstandardSwap::NonstandardSwap(const VanillaSwap &fromVanilla) : Swap(2), type_((VanillaSwap::Type)fromVanilla.type()), fixedNominal_(std::vector<Real>(fromVanilla.fixedLeg().size(), fromVanilla.nominal())), floatingNominal_(std::vector<Real>(fromVanilla.floatingLeg().size(), fromVanilla.nominal())), fixedSchedule_(fromVanilla.fixedSchedule()), fixedRate_(std::vector<Real>(fromVanilla.fixedLeg().size(), fromVanilla.fixedRate())), fixedDayCount_(fromVanilla.fixedDayCount()), floatingSchedule_(fromVanilla.floatingSchedule()), iborIndex_(fromVanilla.iborIndex()), spread_(std::vector<Real>(fromVanilla.floatingLeg().size(), fromVanilla.spread())), gearing_(std::vector<Real>(fromVanilla.floatingLeg().size(), 1.0)), singleSpreadAndGearing_(true), floatingDayCount_(fromVanilla.floatingDayCount()), paymentConvention_(fromVanilla.paymentConvention()), intermediateCapitalExchange_(false), finalCapitalExchange_(false) { init(); }
void BlackStyleSwaptionEngine<Spec>::calculate() const { static const Spread 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; Rate strike = swap.fixedRate(); // using the discounting curve // swap.iborIndex() might be using a different forwarding curve swap.setPricingEngine(boost::shared_ptr<PricingEngine>(new DiscountingSwapEngine(discountCurve_, false))); Rate 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) { Spread correction = swap.spread() * std::fabs(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(boost::shared_ptr<PricingEngine>( new DiscountingSwapEngine(discountCurve_, false))); Real annuity; switch(arguments_.settlementType) { case Settlement::Physical: { annuity = std::fabs(swap.fixedLegBPS())/basisPoint; break; } case Settlement::Cash: { const Leg& fixedLeg = swap.fixedLeg(); boost::shared_ptr<FixedRateCoupon> firstCoupon = boost::dynamic_pointer_cast<FixedRateCoupon>(fixedLeg[0]); DayCounter dayCount = firstCoupon->dayCounter(); Real fixedLegCashBPS = CashFlows::bps(fixedLeg, InterestRate(atmForward, dayCount, Compounded, Annual), false, discountCurve_->referenceDate()) ; annuity = std::fabs(fixedLegCashBPS/basisPoint); break; } default: QL_FAIL("unknown settlement type"); } results_.additionalResults["annuity"] = annuity; // the swap length calculation might be improved using the value date // of the exercise date Time swapLength = vol_->swapLength(exerciseDate, arguments_.floatingPayDates.back()); results_.additionalResults["swapLength"] = swapLength; Real variance = vol_->blackVariance(exerciseDate, swapLength, strike); // once the deprecated methods allowing to override the displacement // are gone, we can avoid this and directly read the displacement // from the volatility structure Real displacement = displacement_ == Null<Real>() ? vol_->shift(exerciseDate, swapLength) : displacement_; Real stdDev = std::sqrt(variance); results_.additionalResults["stdDev"] = stdDev; Option::Type w = (arguments_.type==VanillaSwap::Payer) ? Option::Call : Option::Put; results_.value = Spec().value(w, strike, atmForward, stdDev, annuity, displacement); Time exerciseTime = vol_->timeFromReference(exerciseDate); results_.additionalResults["vega"] = Spec().vega( strike, atmForward, stdDev, exerciseTime, annuity, displacement); }