shared_ptr<VanillaSwap> SwapIndex::underlyingSwap(const Date& fixingDate) const { QL_REQUIRE(fixingDate!=Date(), "null fixing date"); // caching mechanism if (lastFixingDate_!=fixingDate) { Rate fixedRate = 0.0; if (exogenousDiscount_) lastSwap_ = MakeVanillaSwap(tenor_, iborIndex_, fixedRate) .withEffectiveDate(valueDate(fixingDate)) .withFixedLegCalendar(fixingCalendar()) .withFixedLegDayCount(dayCounter_) .withFixedLegTenor(fixedLegTenor_) .withFixedLegConvention(fixedLegConvention_) .withFixedLegTerminationDateConvention(fixedLegConvention_) .withDiscountingTermStructure(discount_); else lastSwap_ = MakeVanillaSwap(tenor_, iborIndex_, fixedRate) .withEffectiveDate(valueDate(fixingDate)) .withFixedLegCalendar(fixingCalendar()) .withFixedLegDayCount(dayCounter_) .withFixedLegTenor(fixedLegTenor_) .withFixedLegConvention(fixedLegConvention_) .withFixedLegTerminationDateConvention(fixedLegConvention_); lastFixingDate_ = fixingDate; } return lastSwap_; }
VanillaSwap::VanillaSwap( const shared_ptr<ObjectHandler::ValueObject>& properties, const QuantLib::Period& swapTenor, const shared_ptr<QuantLib::IborIndex>& index, QuantLib::Rate fixedRate, const QuantLib::Date& immDate, const QuantLib::DayCounter& fixDayCounter, QuantLib::Spread floatingLegSpread, bool permanent) : Swap(properties, permanent) { QuantLib::Date effectiveDate = immDate; if (effectiveDate==QuantLib::Date()) effectiveDate = QuantLib::IMM::nextDate(); QuantLib::Date terminationDate = effectiveDate+swapTenor; terminationDate = QuantLib::Date::nthWeekday(3, QuantLib::Wednesday, terminationDate.month(), terminationDate.year()); libraryObject_ = MakeVanillaSwap(swapTenor, index, fixedRate) .withEffectiveDate(effectiveDate) .withTerminationDate(terminationDate) .withRule(QuantLib::DateGeneration::ThirdWednesday) .withFixedLegDayCount(fixDayCounter) .withFloatingLegSpread(floatingLegSpread) .operator shared_ptr<QuantLib::VanillaSwap>(); }
void SwapRateHelper::initializeDates() { // 1. do not pass the spread here, as it might be a Quote // i.e. it can dinamically change // 2. input discount curve Handle might be empty now but it could // be assigned a curve later; use a RelinkableHandle here swap_ = MakeVanillaSwap(tenor_, iborIndex_, 0.0, fwdStart_) .withSettlementDays(settlementDays_) .withDiscountingTermStructure(discountRelinkableHandle_) .withFixedLegDayCount(fixedDayCount_) .withFixedLegTenor(Period(fixedFrequency_)) .withFixedLegConvention(fixedConvention_) .withFixedLegTerminationDateConvention(fixedConvention_) .withFixedLegCalendar(calendar_) .withFloatingLegCalendar(calendar_); earliestDate_ = swap_->startDate(); // Usually... latestDate_ = swap_->maturityDate(); // ...but due to adjustments, the last floating coupon might // need a later date for fixing #ifdef QL_USE_INDEXED_COUPON shared_ptr<FloatingRateCoupon> lastFloating = boost::dynamic_pointer_cast<FloatingRateCoupon>( swap_->floatingLeg().back()); Date fixingValueDate = iborIndex_->valueDate(lastFloating->fixingDate()); Date endValueDate = iborIndex_->maturityDate(fixingValueDate); latestDate_ = std::max(latestDate_, endValueDate); #endif }
Real HullWhiteSmileSection::volatilityImpl(Rate strike) const { boost::shared_ptr<VanillaSwap> underlying = MakeVanillaSwap(swapLength_,swapIndex_->iborIndex(),strike) .withEffectiveDate(swapIndex_->valueDate(optionDate_)) .withFixedLegCalendar(swapIndex_->fixingCalendar()) .withFixedLegDayCount(swapIndex_->dayCounter()) .withFixedLegTenor(swapIndex_->fixedLegTenor()) .withFixedLegConvention(swapIndex_->fixedLegConvention()) .withFixedLegTerminationDateConvention(swapIndex_->fixedLegConvention()) .withType(VanillaSwap::Payer); underlying->setPricingEngine(discountingEngine_); boost::shared_ptr<Exercise> exercise(new EuropeanExercise(optionDate_)); Swaption swaption(underlying,exercise); swaption.setPricingEngine(jamshidianEngine_); Real npv = swaption.NPV(); Real annuity = fabs(underlying->fixedLegBPS() * 10000.0); //Real blackNpv=blackFormula(Option::Call,strike,atm,0.30*sqrt(exerciseTime())); //std::cout << std::setprecision(8) << "SECTION atm=" << atm_ << " annuity=" << annuity << " npv=" << npv << " strike= " << strike << std::endl; Real vol=0.0; try { vol=blackFormulaImpliedStdDev(Option::Call,strike,atm_,npv,annuity) / sqrt(exerciseTime()); } catch(QuantLib::Error) { //std::cout << " can not imply vol for npv " << npv << " black(300%)=" << blackFormula(Option::Call,strike,atm_,sqrt(exerciseTime())*3.00,annuity) << // " black(1%)=" << blackFormula(Option::Call,strike,atm_,sqrt(exerciseTime())*0.01,annuity) << std::endl; if(npv>blackFormula(Option::Call,strike,atm_,3.00,annuity)) vol =3.0/sqrt(exerciseTime()); else vol=0.0; } return vol; }
MakeSwaption::operator ext::shared_ptr<Swaption>() const { const Calendar& fixingCalendar = swapIndex_->fixingCalendar(); Date refDate = Settings::instance().evaluationDate(); // if the evaluation date is not a business day // then move to the next business day refDate = fixingCalendar.adjust(refDate); if (fixingDate_ == Null<Date>()) fixingDate_ = fixingCalendar.advance(refDate, optionTenor_, optionConvention_); if (exerciseDate_ == Null<Date>()) { exercise_ = ext::shared_ptr<Exercise>(new EuropeanExercise(fixingDate_)); } else { QL_REQUIRE(exerciseDate_ <= fixingDate_, "exercise date (" << exerciseDate_ << ") must be less " "than or equal to fixing date (" << fixingDate_ << ")"); exercise_ = ext::shared_ptr<Exercise>(new EuropeanExercise(exerciseDate_)); } Rate usedStrike = strike_; if (strike_ == Null<Rate>()) { // ATM on curve(s) attached to index QL_REQUIRE(!swapIndex_->forwardingTermStructure().empty(), "null term structure set to this instance of " << swapIndex_->name()); ext::shared_ptr<VanillaSwap> temp = swapIndex_->underlyingSwap(fixingDate_); temp->setPricingEngine( ext::shared_ptr<PricingEngine>(new DiscountingSwapEngine( swapIndex_->exogenousDiscount() ? swapIndex_->discountingTermStructure() : swapIndex_->forwardingTermStructure(), false))); usedStrike = temp->fairRate(); } BusinessDayConvention bdc = swapIndex_->fixedLegConvention(); underlyingSwap_ = MakeVanillaSwap(swapIndex_->tenor(), swapIndex_->iborIndex(), usedStrike) .withEffectiveDate(swapIndex_->valueDate(fixingDate_)) .withFixedLegCalendar(swapIndex_->fixingCalendar()) .withFixedLegDayCount(swapIndex_->dayCounter()) .withFixedLegTenor(swapIndex_->fixedLegTenor()) .withFixedLegConvention(bdc) .withFixedLegTerminationDateConvention(bdc) .withType(underlyingType_) .withNominal(nominal_); ext::shared_ptr<Swaption> swaption(new Swaption(underlyingSwap_, exercise_, delivery_)); swaption->setPricingEngine(engine_); return swaption; }
MakeCapFloor::MakeCapFloor(CapFloor::Type capFloorType, const Period& tenor, const shared_ptr<IborIndex>& iborIndex, Rate strike, const Period& forwardStart) : capFloorType_(capFloorType), strike_(strike), firstCapletExcluded_(forwardStart==0*Days), asOptionlet_(false), // setting the fixed leg tenor avoids that MakeVanillaSwap throws // because of an unknown fixed leg default tenor for a currency, // notice that only the floating leg of the swap is used anyway makeVanillaSwap_(MakeVanillaSwap(tenor, iborIndex, 0.0, forwardStart) .withFixedLegTenor(1*Years).withFixedLegDayCount(Actual365Fixed())) {}
MakeSwaption::operator boost::shared_ptr<Swaption>() const { const Date& evaluationDate = Settings::instance().evaluationDate(); const Calendar& fixingCalendar = swapIndex_->fixingCalendar(); fixingDate_ = fixingCalendar.advance(evaluationDate, optionTenor_, optionConvention_); if (exerciseDate_ == Null<Date>()) { exercise_ = boost::shared_ptr<Exercise>(new EuropeanExercise(fixingDate_)); } else { QL_REQUIRE(exerciseDate_ <= fixingDate_, "exercise date (" << exerciseDate_ << ") must be less " "than or equal to fixing date (" << fixingDate_ << ")"); exercise_ = boost::shared_ptr<Exercise>(new EuropeanExercise(exerciseDate_)); } Rate usedStrike = strike_; if (strike_ == Null<Rate>()) { // ATM on the forecasting curve QL_REQUIRE(!swapIndex_->forwardingTermStructure().empty(), "null term structure set to this instance of " << swapIndex_->name()); boost::shared_ptr<VanillaSwap> temp = swapIndex_->underlyingSwap(fixingDate_); temp->setPricingEngine(boost::shared_ptr<PricingEngine>( new DiscountingSwapEngine( swapIndex_->forwardingTermStructure(), false))); usedStrike = temp->fairRate(); } BusinessDayConvention bdc = swapIndex_->fixedLegConvention(); underlyingSwap_ = MakeVanillaSwap(swapIndex_->tenor(), swapIndex_->iborIndex(), usedStrike) .withEffectiveDate(swapIndex_->valueDate(fixingDate_)) .withFixedLegCalendar(swapIndex_->fixingCalendar()) .withFixedLegDayCount(swapIndex_->dayCounter()) .withFixedLegConvention(bdc) .withFixedLegTerminationDateConvention(bdc); boost::shared_ptr<Swaption> swaption(new Swaption(underlyingSwap_, exercise_, delivery_)); swaption->setPricingEngine(engine_); return swaption; }
VanillaSwap::VanillaSwap( const shared_ptr<ObjectHandler::ValueObject>& properties, const QuantLib::Period& swapTenor, const shared_ptr<QuantLib::IborIndex>& index, QuantLib::Rate fixedRate, const QuantLib::Period& fwdStart, const QuantLib::DayCounter& fixDayCounter, QuantLib::Spread floatingLegSpread, bool permanent) : Swap(properties, permanent) { libraryObject_ = MakeVanillaSwap(swapTenor, index, fixedRate, fwdStart) .withFixedLegDayCount(fixDayCounter) .withFloatingLegSpread(floatingLegSpread) .operator shared_ptr<QuantLib::VanillaSwap>(); }
HullWhiteSmileSection::HullWhiteSmileSection(const Date& optionDate, const Period& swapLength, boost::shared_ptr<SwapIndex> swapIndex, const Handle<YieldTermStructure>& yts, const Real reversion, const Real sigma) : SmileSection(optionDate,yts->dayCounter(),yts->referenceDate()), optionDate_(optionDate), swapLength_(swapLength), swapIndex_(swapIndex), yts_(yts), reversion_(reversion), sigma_(sigma) { //std::cout << "model reversion = " << reversion << " sigma=" << sigma << std::endl; model_ = boost::shared_ptr<HullWhite>(new HullWhite(yts_,reversion,sigma)); jamshidianEngine_ = boost::shared_ptr<JamshidianSwaptionEngine>(new JamshidianSwaptionEngine(model_)); discountingEngine_ = boost::shared_ptr<DiscountingSwapEngine>(new DiscountingSwapEngine(yts_)); boost::shared_ptr<VanillaSwap> underlying = MakeVanillaSwap(swapLength_,swapIndex_->iborIndex(),0.03) // dummy strike .withEffectiveDate(swapIndex_->valueDate(optionDate_)) .withFixedLegCalendar(swapIndex_->fixingCalendar()) .withFixedLegDayCount(swapIndex_->dayCounter()) .withFixedLegTenor(swapIndex_->fixedLegTenor()) .withFixedLegConvention(swapIndex_->fixedLegConvention()) .withFixedLegTerminationDateConvention(swapIndex_->fixedLegConvention()); underlying->setPricingEngine(discountingEngine_); atm_ = underlying->fairRate(); //std::cout << "SECTION option date " << optionDate << " tenor " << swapLength << std::setprecision(8) << " atm " << atm_ << std::endl; }
void CounterpartyAdjSwapEngine::calculate() const { /* both DTS, YTS ref dates and pricing date consistency checks? settlement... */ QL_REQUIRE(!discountCurve_.empty(), "no discount term structure set"); QL_REQUIRE(!defaultTS_.empty(), "no ctpty default term structure set"); QL_REQUIRE(!swaptionletEngine_.empty(), "no swap option engine set"); Date priceDate = defaultTS_->referenceDate(); Real cumOptVal = 0., cumPutVal = 0.; // Vanilla swap so 0 leg is floater std::vector<Date>::const_iterator nextFD = arguments_.fixedPayDates.begin(); Date swapletStart = priceDate; while(*nextFD < priceDate) nextFD++; // Compute fair spread for strike value: // copy args into the non risky engine Swap::arguments * noCVAArgs = dynamic_cast<Swap::arguments*>( baseSwapEngine_->getArguments()); QL_REQUIRE(noCVAArgs != 0, "wrong argument type"); noCVAArgs->legs = this->arguments_.legs; noCVAArgs->payer = this->arguments_.payer; baseSwapEngine_->calculate(); boost::shared_ptr<FixedRateCoupon> coupon = boost::dynamic_pointer_cast<FixedRateCoupon>(arguments_.legs[0][0]); QL_REQUIRE(coupon,"dynamic cast of fixed leg coupon failed."); Rate baseSwapRate = coupon->rate(); const Swap::results * vSResults = dynamic_cast<const Swap::results *>(baseSwapEngine_->getResults()); QL_REQUIRE(vSResults != 0, "wrong result type"); Rate baseSwapFairRate = -baseSwapRate * vSResults->legNPV[1] / vSResults->legNPV[0]; Real baseSwapNPV = vSResults->value; VanillaSwap::Type reversedType = arguments_.type == VanillaSwap::Payer ? VanillaSwap::Receiver : VanillaSwap::Payer; // Swaplet options summatory: while(nextFD != arguments_.fixedPayDates.end()) { // iFD coupon not fixed, create swaptionlet: boost::shared_ptr<FloatingRateCoupon> floatCoupon = boost::dynamic_pointer_cast<FloatingRateCoupon>(arguments_.legs[1][0]); QL_REQUIRE(floatCoupon,"dynamic cast of floating leg coupon failed."); boost::shared_ptr<IborIndex> swapIndex = boost::dynamic_pointer_cast<IborIndex>(floatCoupon->index()); QL_REQUIRE(swapIndex,"dynamic cast of floating leg index failed."); // Alternatively one could cap this period to, say, 1M // Period swapPeriod = boost::dynamic_pointer_cast<FloatingRateCoupon>( // arguments_.legs[1][0])->index()->tenor(); Period baseSwapsTenor(arguments_.fixedPayDates.back().serialNumber() - swapletStart.serialNumber(), Days); boost::shared_ptr<VanillaSwap> swaplet = MakeVanillaSwap( baseSwapsTenor, swapIndex, baseSwapFairRate // strike ) .withType(arguments_.type) .withNominal(arguments_.nominal) //////// .withSettlementDays(2) .withEffectiveDate(swapletStart) .withTerminationDate(arguments_.fixedPayDates.back()); boost::shared_ptr<VanillaSwap> revSwaplet = MakeVanillaSwap( baseSwapsTenor, swapIndex, baseSwapFairRate // strike ) .withType(reversedType) .withNominal(arguments_.nominal) ///////// .withSettlementDays(2) .withEffectiveDate(swapletStart) .withTerminationDate(arguments_.fixedPayDates.back()); Swaption swaptionlet(swaplet, boost::make_shared<EuropeanExercise>(swapletStart)); Swaption putSwaplet(revSwaplet, boost::make_shared<EuropeanExercise>(swapletStart)); swaptionlet.setPricingEngine(swaptionletEngine_.currentLink()); putSwaplet.setPricingEngine(swaptionletEngine_.currentLink()); // atm underlying swap means that the value of put = value // call so this double pricing is not needed cumOptVal += swaptionlet.NPV() * defaultTS_->defaultProbability( swapletStart, *nextFD); cumPutVal += putSwaplet.NPV() * invstDTS_->defaultProbability( swapletStart, *nextFD); swapletStart = *nextFD; nextFD++; } results_.value = baseSwapNPV - (1.-ctptyRecoveryRate_) * cumOptVal + (1.-invstRecoveryRate_) * cumPutVal; results_.fairRate = -baseSwapRate * (vSResults->legNPV[1] - (1.-ctptyRecoveryRate_) * cumOptVal + (1.-invstRecoveryRate_) * cumPutVal ) / vSResults->legNPV[0]; }