//! discount factor implied by the rate compounded between two dates DiscountFactor discountFactor(const Date& d1, const Date& d2, const Date& refStart = Date(), const Date& refEnd = Date()) const { QL_REQUIRE(d2>=d1, "d1 (" << d1 << ") " "later than d2 (" << d2 << ")"); Time t = dc_.yearFraction(d1, d2, refStart, refEnd); return discountFactor(t); }
Real LiborCurve::swapAnnuity(Size reference, Size fixing, Size length, Size payFreq) { QL_REQUIRE(reference<=fixing,"reference index " << reference << " must be leq fixing " << fixing); Size pf = payFreq; double sum=0.0; double p=1.0; for(int j=fixing;j<fixing+length;j++) { p*=1.0/(1.0+(rateTimes_[j+1]-rateTimes_[j])*rates_[j]); if(--pf == 0) { sum+=p*(rateTimes_[j+1]-rateTimes_[j+1-payFreq]); pf=payFreq; } } //printf("swap Annuity=%1.11f\n",discountFactor(reference,fixing)*sum); return discountFactor(reference,fixing)*sum; }
void FFTEngine::precalculate(const std::vector<boost::shared_ptr<Instrument> >& optionList) { // Group payoffs by expiry date // as with FFT we can compute a bunch of these at once resultMap_.clear(); typedef std::vector<boost::shared_ptr<StrikedTypePayoff> > PayoffList; typedef std::map<Date, PayoffList> PayoffMap; PayoffMap payoffMap; for (std::vector<boost::shared_ptr<Instrument> >::const_iterator optIt = optionList.begin(); optIt != optionList.end(); optIt++) { boost::shared_ptr<VanillaOption> option = boost::dynamic_pointer_cast<VanillaOption>(*optIt); QL_REQUIRE(option, "instrument must be option"); QL_REQUIRE(option->exercise()->type() == Exercise::European, "not an European Option"); boost::shared_ptr<StrikedTypePayoff> payoff = boost::dynamic_pointer_cast<StrikedTypePayoff>(option->payoff()); QL_REQUIRE(payoff, "non-striked payoff given"); payoffMap[option->exercise()->lastDate()].push_back(payoff); } std::complex<Real> i1(0, 1); Real alpha = 1.25; for (PayoffMap::const_iterator payIt = payoffMap.begin(); payIt != payoffMap.end(); payIt++) { Date expiryDate = payIt->first; // Calculate n large enough for maximum strike, and round up to a power of 2 Real maxStrike = 0.0; for (PayoffList::const_iterator it = payIt->second.begin(); it != payIt->second.end(); it++) { boost::shared_ptr<StrikedTypePayoff> payoff = *it; if (payoff->strike() > maxStrike) maxStrike = payoff->strike(); } Real nR = 2.0 * (std::log(maxStrike) + lambda_) / lambda_; Size log2_n = (static_cast<Size>((std::log(nR) / std::log(2.0))) + 1); Size n = 1 << log2_n; // Strike range (equation 19,20) Real b = n * lambda_ / 2.0; // Grid spacing (equation 23) Real eta = 2.0 * M_PI / (lambda_ * n); // Discount factor Real df = discountFactor(expiryDate); Real div = dividendYield(expiryDate); // Input to fourier transform std::vector<std::complex<Real> > fti; fti.resize(n); // Precalculate any discount factors etc. precalculateExpiry(expiryDate); for (Size i=0; i<n; i++) { Real k_u = -b + lambda_ * i; Real v_j = eta * i; Real sw = eta * (3.0 + ((i % 2) == 0 ? -1.0 : 1.0) - ((i == 0) ? 1.0 : 0.0)) / 3.0; std::complex<Real> psi = df * complexFourierTransform(v_j - (alpha + 1)* i1); psi = psi / (alpha*alpha + alpha - v_j*v_j + i1 * (2 * alpha + 1.0) * v_j); fti[i] = std::exp(i1 * b * v_j) * sw * psi; } // Perform fft std::vector<std::complex<Real> > results(n); FastFourierTransform fft(log2_n); fft.transform(fti.begin(), fti.end(), results.begin()); // Call prices std::vector<Real> prices, strikes; prices.resize(n); strikes.resize(n); for (Size i=0; i<n; i++) { Real k_u = -b + lambda_ * i; prices[i] = (std::exp(-alpha * k_u) / M_PI) * results[i].real(); strikes[i] = std::exp(k_u); } for (PayoffList::const_iterator it = payIt->second.begin(); it != payIt->second.end(); it++) { boost::shared_ptr<StrikedTypePayoff> payoff = *it; Real callPrice = LinearInterpolation(strikes.begin(), strikes.end(), prices.begin())(payoff->strike()); switch (payoff->optionType()) { case Option::Call: resultMap_[expiryDate][payoff] = callPrice; break; case Option::Put: resultMap_[expiryDate][payoff] = callPrice - process_->x0() * div + payoff->strike() * df; break; default: QL_FAIL("Invalid option type"); } } } }
Real LiborCurve::swap2TerminalMeasure(Size reference, Size fixing, Size delay, Size length, Size payFreq) { return discountFactor(reference,fixing+delay)/discountFactorT0(0,fixing+delay) * swapAnnuityT0(fixing,length,payFreq)/swapAnnuity(reference,fixing,length,payFreq); }
Real LiborCurve::rRate(Size reference, Size fixing, Size delay, Size length, Size payFreq) { QL_REQUIRE(reference<=fixing,"reference index " << reference << " must be leq fixing " << fixing); double sumD=rateTimes_[fixing+length]-rateTimes_[fixing]; return swapAnnuityT0(fixing,length,payFreq)/(discountFactorT0(0,fixing+delay)*sumD)* (discountFactor(reference,fixing+delay)*sumD/swapAnnuity(reference,fixing,length,payFreq)-1.0); }
double CCRate::forwardRate(double t1, double t2) { double f = 1.0 / (t2 - t1) * (discountFactor(t1) / discountFactor(t2) - 1); return f; }