Real vega(const Real strike, const Real atmForward, const Real stdDev, const Real exerciseTime, const Real annuity, const Real displacement) { return std::sqrt(exerciseTime) * blackFormulaStdDevDerivative(strike, atmForward, stdDev, annuity, displacement); }
Real blackFormulaStdDevDerivative( const boost::shared_ptr<PlainVanillaPayoff>& payoff, Real forward, Real stdDev, Real discount, Real displacement) { return blackFormulaStdDevDerivative(payoff->strike(), forward, stdDev, discount, displacement); }
Real blackFormulaVolDerivative(Rate strike, Rate forward, Real stdDev, Real expiry, Real discount, Real displacement) { return blackFormulaStdDevDerivative(strike, forward, stdDev, discount, displacement)*std::sqrt(expiry); }
void BlackCapFloorEngine::calculate() const { Real value = 0.0; Real vega = 0.0; Size optionlets = arguments_.startDates.size(); std::vector<Real> values(optionlets, 0.0); std::vector<Real> vegas(optionlets, 0.0); std::vector<Real> stdDevs(optionlets, 0.0); CapFloor::Type type = arguments_.type; Date today = vol_->referenceDate(); Date settlement = discountCurve_->referenceDate(); for (Size i=0; i<optionlets; ++i) { Date paymentDate = arguments_.endDates[i]; // handling of settlementDate, npvDate and includeSettlementFlows // should be implemented. // For the time being just discard expired caplets if (paymentDate > settlement) { DiscountFactor d = arguments_.nominals[i] * arguments_.gearings[i] * discountCurve_->discount(paymentDate) * arguments_.accrualTimes[i]; Rate forward = arguments_.forwards[i]; Date fixingDate = arguments_.fixingDates[i]; Time sqrtTime = 0.0; if (fixingDate > today) sqrtTime = std::sqrt(vol_->timeFromReference(fixingDate)); if (type == CapFloor::Cap || type == CapFloor::Collar) { Rate strike = arguments_.capRates[i]; if (sqrtTime>0.0) { stdDevs[i] = std::sqrt(vol_->blackVariance(fixingDate, strike)); vegas[i] = blackFormulaStdDevDerivative(strike, forward, stdDevs[i], d, displacement_) * sqrtTime; } // include caplets with past fixing date values[i] = blackFormula(Option::Call, strike, forward, stdDevs[i], d, displacement_); } if (type == CapFloor::Floor || type == CapFloor::Collar) { Rate strike = arguments_.floorRates[i]; Real floorletVega = 0.0; if (sqrtTime>0.0) { stdDevs[i] = std::sqrt(vol_->blackVariance(fixingDate, strike)); floorletVega = blackFormulaStdDevDerivative(strike, forward, stdDevs[i], d, displacement_) * sqrtTime; } Real floorlet = blackFormula(Option::Put, strike, forward, stdDevs[i], d, displacement_); if (type == CapFloor::Floor) { values[i] = floorlet; vegas[i] = floorletVega; } else { // a collar is long a cap and short a floor values[i] -= floorlet; vegas[i] -= floorletVega; } } value += values[i]; vega += vegas[i]; } } results_.value = value; results_.additionalResults["vega"] = vega; results_.additionalResults["optionletsPrice"] = values; results_.additionalResults["optionletsVega"] = vegas; results_.additionalResults["optionletsAtmForward"] = arguments_.forwards; if (type != CapFloor::Collar) results_.additionalResults["optionletsStdDev"] = stdDevs; }
void BlackSwaptionEngine::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); Real stdDev = std::sqrt(variance); results_.additionalResults["stdDev"] = stdDev; Option::Type w = (arguments_.type==VanillaSwap::Payer) ? Option::Call : Option::Put; results_.value = blackFormula(w, strike, atmForward, stdDev, annuity, displacement_); Time exerciseTime = vol_->timeFromReference(exerciseDate); results_.additionalResults["vega"] = std::sqrt(exerciseTime) * blackFormulaStdDevDerivative(strike, atmForward, stdDev, annuity, displacement_); }