Пример #1
0
    Real blackFormulaImpliedStdDev(Option::Type optionType,
                                   Real strike,
                                   Real forward,
                                   Real blackPrice,
                                   Real discount,
                                   Real displacement,
                                   Real guess,
                                   Real accuracy,
                                   Natural maxIterations)
    {
        checkParameters(strike, forward, displacement);

        QL_REQUIRE(discount>0.0,
                   "discount (" << discount << ") must be positive");

        QL_REQUIRE(blackPrice>=0.0,
                   "option price (" << blackPrice << ") must be non-negative");
        // check the price of the "other" option implied by put-call paity
        Real otherOptionPrice = blackPrice - optionType*(forward-strike)*discount;
        QL_REQUIRE(otherOptionPrice>=0.0,
                   "negative " << Option::Type(-1*optionType) <<
                   " price (" << otherOptionPrice <<
                   ") implied by put-call parity. No solution exists for " <<
                   optionType << " strike " << strike <<
                   ", forward " << forward <<
                   ", price " << blackPrice <<
                   ", deflator " << discount);

        // solve for the out-of-the-money option which has
        // greater vega/price ratio, i.e.
        // it is numerically more robust for implied vol calculations
        if (optionType==Option::Put && strike>forward) {
            optionType = Option::Call;
            blackPrice = otherOptionPrice;
        }
        if (optionType==Option::Call && strike<forward) {
            optionType = Option::Put;
            blackPrice = otherOptionPrice;
        }

        strike = strike + displacement;
        forward = forward + displacement;

        if (guess==Null<Real>())
            guess = blackFormulaImpliedStdDevApproximation(
                optionType, strike, forward, blackPrice, discount, displacement);
        else
            QL_REQUIRE(guess>=0.0,
                       "stdDev guess (" << guess << ") must be non-negative");
        BlackImpliedStdDevHelper f(optionType, strike, forward,
                                   blackPrice/discount);
        NewtonSafe solver;
        solver.setMaxEvaluations(maxIterations);
        Real minSdtDev = 0.0, maxStdDev = 24.0; // 24 = 300% * sqrt(60)
        Real stdDev = solver.solve(f, accuracy, guess, minSdtDev, maxStdDev);
        QL_ENSURE(stdDev>=0.0,
                  "stdDev (" << stdDev << ") must be non-negative");
        return stdDev;
    }
boost::shared_ptr<SmileSection>
Gaussian1dSwaptionVolatility::smileSectionImpl(Time optionTime,
                                               Time swapLength) const {
    DateHelper hlp(*this, optionTime);
    NewtonSafe newton;
    Date d(static_cast<BigInteger>(newton.solve(
        hlp, 0.1,
        365.25 * optionTime + static_cast<Real>(referenceDate().serialNumber()),
        1.0)));
    Period tenor(
        static_cast<Integer>(Rounding(0).operator()(swapLength * 12.0)),
        Months);
    d = indexBase_->fixingCalendar().adjust(d);
    return smileSectionImpl(d, tenor);
}
    Volatility CapFloor::impliedVolatility(Real targetValue,
                                           const Handle<YieldTermStructure>& d,
                                           Volatility guess,
                                           Real accuracy,
                                           Natural maxEvaluations,
                                           Volatility minVol,
                                           Volatility maxVol) const {
        //calculate();
        QL_REQUIRE(!isExpired(), "instrument expired");

        ImpliedVolHelper f(*this, d, targetValue);
        //Brent solver;
        NewtonSafe solver;
        solver.setMaxEvaluations(maxEvaluations);
        return solver.solve(f, accuracy, guess, minVol, maxVol);
    }
Пример #4
0
        Real solveImpl(const F& f,
                       Real xAccuracy) const {

            /* The implementation of the algorithm was inspired by
               Press, Teukolsky, Vetterling, and Flannery,
               "Numerical Recipes in C", 2nd edition,
               Cambridge University Press
            */

            Real froot, dfroot, dx;

            froot = f(root_);
            dfroot = f.derivative(root_);
            QL_REQUIRE(dfroot != Null<Real>(),
                       "Newton requires function's derivative");
            ++evaluationNumber_;

            while (evaluationNumber_<=maxEvaluations_) {
                dx = froot/dfroot;
                root_ -= dx;
                // jumped out of brackets, switch to NewtonSafe
                if ((xMin_-root_)*(root_-xMax_) < 0.0) {
                    NewtonSafe s;
                    s.setMaxEvaluations(maxEvaluations_-evaluationNumber_);
                    return s.solve(f, xAccuracy, root_+dx, xMin_, xMax_);
                }
                if (std::fabs(dx) < xAccuracy) {
                    f(root_);
                    ++evaluationNumber_;
                    return root_;
                }
                froot = f(root_);
                dfroot = f.derivative(root_);
                ++evaluationNumber_;
            }

            QL_FAIL("maximum number of function evaluations ("
                    << maxEvaluations_ << ") exceeded");
        }
 boost::shared_ptr<SmileSection>
 SingleSabrSwaptionVolatility::smileSectionImpl(Time optionTime,
                                              Time swapLength) const {
     std::vector<Real> params(4);
     params[0] = alpha_;
     params[1] = beta_;
     params[2] = nu_;
     params[3] = rho_;
     DateHelper hlp(*this,optionTime);
     NewtonSafe newton;
     Date d(static_cast<BigInteger>(newton.solve(
         hlp, 0.1, 365.25 * optionTime +
                       static_cast<Real>(referenceDate().serialNumber()),
         1.0)));
     Period tenor(static_cast<Integer>(Rounding(0).operator()(swapLength*12.0)), Months);
     d = indexBase_->fixingCalendar().adjust(d);
     Real forward = indexBase_->clone(tenor)->fixing(d);
     boost::shared_ptr<SmileSection> raw(new SabrSmileSection(optionTime,forward,params,shift_));
     // make it arbitrage free
     //boost::shared_ptr<SmileSection> af(new KahaleSmileSection(raw));
     //return af;
     return raw;
 }