コード例 #1
0
 inline void Observable::notifyObservers() {
     bool successful = true;
     std::string errMsg;
     for (iterator i=observers_.begin(); i!=observers_.end(); ++i) {
         try {
             (*i)->update();
         } catch (std::exception& e) {
             // quite a dilemma. If we don't catch the exception,
             // other observers will not receive the notification
             // and might be left in an incorrect state. If we do
             // catch it and continue the loop (as we do here) we
             // lose the exception. The least evil might be to try
             // and notify all observers, while raising an
             // exception if something bad happened.
             successful = false;
             errMsg = e.what();
         } catch (...) {
             successful = false;
         }
     }
     QL_ENSURE(successful,
               "could not notify one or more observers: " << errMsg);
 }
コード例 #2
0
    AmortizingFixedRateBond::AmortizingFixedRateBond(
                                      Natural settlementDays,
                                      const std::vector<Real>& notionals,
                                      const Schedule& schedule,
                                      const std::vector<Rate>& coupons,
                                      const DayCounter& accrualDayCounter,
                                      BusinessDayConvention paymentConvention,
                                      const Date& issueDate)
    : Bond(settlementDays, schedule.calendar(), issueDate),
      frequency_(schedule.tenor().frequency()),
      dayCounter_(accrualDayCounter) {

        maturityDate_ = schedule.endDate();

        cashflows_ = FixedRateLeg(schedule)
            .withNotionals(notionals)
            .withCouponRates(coupons, accrualDayCounter)
            .withPaymentAdjustment(paymentConvention);

        addRedemptionsToCashflows();

        QL_ENSURE(!cashflows().empty(), "bond with no cashflows!");
    }
コード例 #3
0
ファイル: xlSwapDV01.cpp プロジェクト: vermosen/xlObjectTools
        /* Fonction de calcul de l'accrued des instruments */
DLLEXPORT xloper * xlSwapDV01 (const char * instrumentId_,
                               const char * curveId_,
                               const char * conventionId_,
                               xloper * trigger_) {


         boost::shared_ptr<ObjectHandler::FunctionCall> functionCall(
            new ObjectHandler::FunctionCall("xlSwapDV01")) ;


         try {


                QL_ENSURE(! functionCall->calledByFunctionWizard(), "") ;

                    // trigger pour provoquer le recalcul
                ObjectHandler::validateRange(trigger_, "trigger") ;

                QuantLib::Real returnValue ;

                    // on récupère la courbe
                OH_GET_OBJECT(curvePtr, curveId_, ObjectHandler::Object)

                    // on récupère la convention de taux
                OH_GET_OBJECT(conventionPtr, conventionId_, QuantLibAddin::interestRateConventionObject)

                QuantLib::Handle<QuantLib::YieldTermStructure> curveLibPtr =
                    QuantLibAddin::CoerceHandle<QuantLibAddin::YieldTermStructure, QuantLib::YieldTermStructure>()(curvePtr) ;

                QuantLib::Handle<QuantLib::Quote> mySpread(
                    new QuantLib::SimpleQuote(1.0 / 100)) ; // 1 bp

                QuantLib::Handle<QuantLib::YieldTermStructure> myShiftedCurve( 
                    new QuantLib::ZeroSpreadedTermStructure(curveLibPtr, 
                                                            mySpread, 
                                                            conventionPtr->compounding(), 
                                                            conventionPtr->frequency(), 
                                                            conventionPtr->daycounter())) ;
                                                            
                    // on récupère l'instrument
                OH_GET_OBJECT(instrumentPtr, instrumentId_, ObjectHandler::Object)

                    /* IRS */
                if (instrumentPtr->properties()->className() == "interestRateSwapValueObject") {
                 
						QuantLib::Handle<QuantLib::vanillaSwap2> swapPtr 
							= QuantLibAddin::CoerceHandle<QuantLibAddin::interestRateSwapObject, 
								QuantLib::vanillaSwap2>()(instrumentPtr) ;

                        returnValue = QuantLib::CashFlows::npv(swapPtr->leg(0),
                                                               ** curveLibPtr,
                                                               QuantLib::Unadjusted, QuantLib::Calendar(),
                                                               false) * swapPtr->receivingLeg(0) ;

                        returnValue += QuantLib::CashFlows::npv(swapPtr->leg(1),
                                                                ** curveLibPtr,
                                                                QuantLib::Unadjusted, QuantLib::Calendar(),
                                                                false) * swapPtr->receivingLeg(1) ;

                        returnValue -= QuantLib::CashFlows::npv(swapPtr->leg(0),
                                                               ** myShiftedCurve,
                                                               QuantLib::Unadjusted, QuantLib::Calendar(),
                                                               false) * swapPtr->receivingLeg(0) ;

                        returnValue -= QuantLib::CashFlows::npv(swapPtr->leg(1),
                                                                ** myShiftedCurve,
                                                                QuantLib::Unadjusted, QuantLib::Calendar(),
                                                                false) * swapPtr->receivingLeg(1) ;

                    }

                    /* jambe fixe */
                else if (instrumentPtr->properties()->className() == "fixedLegAustraliaValueObject" ||
                         instrumentPtr->properties()->className() == "fixedLegUnitedStatesValueObject"||
                         instrumentPtr->properties()->className() == "floatLegAustraliaValueObject" ||
                         instrumentPtr->properties()->className() == "floatLegUnitedStatesValueObject") {


                        OH_GET_REFERENCE(instrumentLibObj, 
                                         instrumentId_, 
                                         QuantLibAddin::Leg,
                                         QuantLib::Leg)

                        returnValue = QuantLib::CashFlows::npv(* instrumentLibObj,
                                                               ** curveLibPtr,
                                                               QuantLib::Unadjusted, QuantLib::Calendar(),
                                                               false) ;

                        returnValue -= QuantLib::CashFlows::npv(* instrumentLibObj,
                                                                ** myShiftedCurve,
                                                                QuantLib::Unadjusted, QuantLib::Calendar(),
                                                                false) ;

                    }

                else { // ici pour les autres instruments
                    
                        QL_FAIL("unknown instrument type") ;

                    }

                static XLOPER returnOper ;
                ObjectHandler::scalarToOper(returnValue, returnOper) ;

                return & returnOper ;

        } catch (std::exception & e) {

                ObjectHandler::RepositoryXL::instance().logError(e.what(), functionCall) ;
                static XLOPER returnOper ;
                returnOper.xltype = xltypeErr ;
                returnOper.val.err = xlerrValue ;

				return & returnOper ;

        }

} ;
コード例 #4
0
    void BinomialVanillaEngine<T>::calculate() const {

        DayCounter rfdc  = process_->riskFreeRate()->dayCounter();
        DayCounter divdc = process_->dividendYield()->dayCounter();
        DayCounter voldc = process_->blackVolatility()->dayCounter();
        Calendar volcal = process_->blackVolatility()->calendar();

        Real s0 = process_->stateVariable()->value();
        QL_REQUIRE(s0 > 0.0, "negative or null underlying given");
        Volatility v = process_->blackVolatility()->blackVol(
            arguments_.exercise->lastDate(), s0);
        Date maturityDate = arguments_.exercise->lastDate();
        Rate r = process_->riskFreeRate()->zeroRate(maturityDate,
            rfdc, Continuous, NoFrequency);
        Rate q = process_->dividendYield()->zeroRate(maturityDate,
            divdc, Continuous, NoFrequency);
        Date referenceDate = process_->riskFreeRate()->referenceDate();

        // binomial trees with constant coefficient
        Handle<YieldTermStructure> flatRiskFree(
            boost::shared_ptr<YieldTermStructure>(
                new FlatForward(referenceDate, r, rfdc)));
        Handle<YieldTermStructure> flatDividends(
            boost::shared_ptr<YieldTermStructure>(
                new FlatForward(referenceDate, q, divdc)));
        Handle<BlackVolTermStructure> flatVol(
            boost::shared_ptr<BlackVolTermStructure>(
                new BlackConstantVol(referenceDate, volcal, v, voldc)));

        boost::shared_ptr<PlainVanillaPayoff> payoff =
            boost::dynamic_pointer_cast<PlainVanillaPayoff>(arguments_.payoff);
        QL_REQUIRE(payoff, "non-plain payoff given");

        Time maturity = rfdc.yearFraction(referenceDate, maturityDate);

        boost::shared_ptr<StochasticProcess1D> bs(
                         new GeneralizedBlackScholesProcess(
                                      process_->stateVariable(),
                                      flatDividends, flatRiskFree, flatVol));

        TimeGrid grid(maturity, timeSteps_);

        boost::shared_ptr<T> tree(new T(bs, maturity, timeSteps_,
                                        payoff->strike()));

        boost::shared_ptr<BlackScholesLattice<T> > lattice(
            new BlackScholesLattice<T>(tree, r, maturity, timeSteps_));

        DiscretizedVanillaOption option(arguments_, *process_, grid);

        option.initialize(lattice, maturity);

        // Partial derivatives calculated from various points in the
        // binomial tree (Odegaard)

        // Rollback to third-last step, and get underlying price (s2) &
        // option values (p2) at this point
        option.rollback(grid[2]);
        Array va2(option.values());
        QL_ENSURE(va2.size() == 3, "Expect 3 nodes in grid at second step");
        Real p2h = va2[2]; // high-price
        Real s2 = lattice->underlying(2, 2); // high price

        // Rollback to second-last step, and get option value (p1) at
        // this point
        option.rollback(grid[1]);
        Array va(option.values());
        QL_ENSURE(va.size() == 2, "Expect 2 nodes in grid at first step");
        Real p1 = va[1];

        // Finally, rollback to t=0
        option.rollback(0.0);
        Real p0 = option.presentValue();
        Real s1 = lattice->underlying(1, 1);

        // Calculate partial derivatives
        Real delta0 = (p1-p0)/(s1-s0);   // dp/ds
        Real delta1 = (p2h-p1)/(s2-s1);  // dp/ds

        // Store results
        results_.value = p0;
        results_.delta = delta0;
        results_.gamma = 2.0*(delta1-delta0)/(s2-s0);    //d(delta)/ds
        results_.theta = blackScholesTheta(process_,
                                           results_.value,
                                           results_.delta,
                                           results_.gamma);
    }
コード例 #5
0
    void IterativeBootstrap<Curve>::calculate() const {

        Size n = ts_->instruments_.size();

        // ensure rate helpers are sorted
        std::sort(ts_->instruments_.begin(), ts_->instruments_.end(),
                  detail::BootstrapHelperSorter());

        // check that there is no instruments with the same maturity
        for (Size i=1; i<n; ++i) {
            Date m1 = ts_->instruments_[i-1]->latestDate(),
                 m2 = ts_->instruments_[i]->latestDate();
            QL_REQUIRE(m1 != m2,
                       "two instruments have the same maturity ("<< m1 <<")");
        }

        // check that there is no instruments with invalid quote
        for (Size i=0; i<n; ++i)
            QL_REQUIRE(ts_->instruments_[i]->quote()->isValid(),
                       io::ordinal(i+1) << " instrument (maturity: " <<
                       ts_->instruments_[i]->latestDate() <<
                       ") has an invalid quote");

        // setup instruments
        for (Size i=0; i<n; ++i) {
            // don't try this at home!
            // This call creates instruments, and removes "const".
            // There is a significant interaction with observability.
            ts_->instruments_[i]->setTermStructure(const_cast<Curve*>(ts_));
        }

        // calculate dates and times
        ts_->dates_ = std::vector<Date>(n+1);
        ts_->times_ = std::vector<Time>(n+1);
        ts_->dates_[0] = Traits::initialDate(ts_);
        ts_->times_[0] = ts_->timeFromReference(ts_->dates_[0]);
        for (Size i=0; i<n; ++i) {
            ts_->dates_[i+1] = ts_->instruments_[i]->latestDate();
            ts_->times_[i+1] = ts_->timeFromReference(ts_->dates_[i+1]);
        }

        // set initial guess only if the current curve cannot be used as guess
        if (validCurve_) {
            QL_ENSURE(ts_->data_.size() == n+1,
                      "dimension mismatch: expected " << n+1 <<
                      ", actual " << ts_->data_.size());
        } else {
            ts_->data_ = std::vector<Rate>(n+1);
            ts_->data_[0] = Traits::initialValue(ts_);
            for (Size i=0; i<n; ++i)
                ts_->data_[i+1] = Traits::initialGuess();
        }

        Brent solver;
        Size maxIterations = Traits::maxIterations();

        for (Size iteration=0; ; ++iteration) {
            std::vector<Rate> previousData = ts_->data_;
            // restart from the previous interpolation
            if (validCurve_) {
                ts_->interpolation_ = ts_->interpolator_.interpolate(
                                                      ts_->times_.begin(),
                                                      ts_->times_.end(),
                                                      ts_->data_.begin());
            }
            for (Size i=1; i<n+1; ++i) {

                // calculate guess before extending interpolation
                // to ensure that any extrapolation is performed
                // using the curve bootstrapped so far and no more
                boost::shared_ptr<typename Traits::helper> instrument =
                    ts_->instruments_[i-1];
                Rate guess = 0.0;
                if (validCurve_ || iteration>0) {
                    guess = ts_->data_[i];
                } else if (i==1) {
                    guess = Traits::initialGuess();
                } else {
                    // most traits extrapolate
                    guess = Traits::guess(ts_, ts_->dates_[i]);
                }

                // bracket
                Real min = Traits::minValueAfter(i, ts_->data_);
                Real max = Traits::maxValueAfter(i, ts_->data_);
                if (guess<=min || guess>=max)
                    guess = (min+max)/2.0;

                if (!validCurve_ && iteration == 0) {
                    // extend interpolation a point at a time
                    try {
                        ts_->interpolation_ = ts_->interpolator_.interpolate(
                                                      ts_->times_.begin(),
                                                      ts_->times_.begin()+i+1,
                                                      ts_->data_.begin());
                    } catch(...) {
                        if (!Interpolator::global)
                            throw; // no chance to fix it in a later iteration

                        // otherwise, if the target interpolation is
                        // not usable yet
                        ts_->interpolation_ = Linear().interpolate(
                                                      ts_->times_.begin(),
                                                      ts_->times_.begin()+i+1,
                                                      ts_->data_.begin());
                    }
                }
                // required because we just changed the data
                // is it really required?
                ts_->interpolation_.update();

                try {
                    BootstrapError<Curve> error(ts_, instrument, i);
                    Real r = solver.solve(error,ts_->accuracy_,guess,min,max);
                    // redundant assignment (as it has been already performed
                    // by BootstrapError in solve procedure), but safe
                    ts_->data_[i] = r;
                } catch (std::exception &e) {
                    validCurve_ = false;
                    QL_FAIL(io::ordinal(iteration+1) << " iteration: "
                            "failed at " << io::ordinal(i) << " instrument"
                            ", maturity " << ts_->dates_[i] <<
                            ", reference date " << ts_->dates_[0] <<
                            ": " << e.what());
                }
            }

            if (!Interpolator::global)
                break;      // no need for convergence loop
            else if (!validCurve_ && iteration == 0) {
                // ensure the target interpolation is used
                ts_->interpolation_ =
                    ts_->interpolator_.interpolate(ts_->times_.begin(),
                                                   ts_->times_.end(),
                                                   ts_->data_.begin());
                // at least one more iteration is needed to check convergence
                continue;
            }

            // exit conditions
            Real improvement = 0.0;
            for (Size i=1; i<n+1; ++i)
                improvement=std::max(improvement,
                                     std::fabs(ts_->data_[i]-previousData[i]));
            if (improvement<=ts_->accuracy_)  // convergence reached
                break;

            QL_REQUIRE(iteration+1 < maxIterations,
                       "convergence not reached after " <<
                       iteration+1 << " iterations; last improvement " <<
                       improvement << ", required accuracy " <<
                       ts_->accuracy_);
        }
        validCurve_ = true;
    }
コード例 #6
0
    void LocalBootstrap<Curve>::calculate() const {

        validCurve_ = false;
        Size nInsts = ts_->instruments_.size();

        // ensure rate helpers are sorted
        std::sort(ts_->instruments_.begin(), ts_->instruments_.end(),
                  detail::BootstrapHelperSorter());

        // check that there is no instruments with the same maturity
        for (Size i=1; i<nInsts; ++i) {
            Date m1 = ts_->instruments_[i-1]->latestDate(),
                 m2 = ts_->instruments_[i]->latestDate();
            QL_REQUIRE(m1 != m2,
                       "two instruments have the same maturity ("<< m1 <<")");
        }

        // check that there is no instruments with invalid quote
        for (Size i=0; i<nInsts; ++i)
            QL_REQUIRE(ts_->instruments_[i]->quote()->isValid(),
                       io::ordinal(i+1) << " instrument (maturity: " <<
                       ts_->instruments_[i]->latestDate() <<
                       ") has an invalid quote");

        // setup instruments
        for (Size i=0; i<nInsts; ++i) {
            // don't try this at home!
            // This call creates instruments, and removes "const".
            // There is a significant interaction with observability.
            ts_->instruments_[i]->setTermStructure(const_cast<Curve*>(ts_));
        }
        // set initial guess only if the current curve cannot be used as guess
        if (validCurve_)
            QL_ENSURE(ts_->data_.size() == nInsts+1,
                      "dimension mismatch: expected " << nInsts+1 <<
                      ", actual " << ts_->data_.size());
        else {
            ts_->data_ = std::vector<Rate>(nInsts+1);
            ts_->data_[0] = Traits::initialValue(ts_);
        }

        // calculate dates and times
        ts_->dates_ = std::vector<Date>(nInsts+1);
        ts_->times_ = std::vector<Time>(nInsts+1);
        ts_->dates_[0] = Traits::initialDate(ts_);
        ts_->times_[0] = ts_->timeFromReference(ts_->dates_[0]);
        for (Size i=0; i<nInsts; ++i) {
            ts_->dates_[i+1] = ts_->instruments_[i]->latestDate();
            ts_->times_[i+1] = ts_->timeFromReference(ts_->dates_[i+1]);
            if (!validCurve_)
                ts_->data_[i+1] = ts_->data_[i];
        }

        LevenbergMarquardt solver(ts_->accuracy_,
                                  ts_->accuracy_,
                                  ts_->accuracy_);
        EndCriteria endCriteria(100, 10, 0.00, ts_->accuracy_, 0.00);
        PositiveConstraint posConstraint;
        NoConstraint noConstraint;
        Constraint& solverConstraint = forcePositive_ ?
            static_cast<Constraint&>(posConstraint) :
            static_cast<Constraint&>(noConstraint);

        // now start the bootstrapping.
        Size iInst = localisation_-1;

        Size dataAdjust = Curve::interpolator_type::dataSizeAdjustment;

        do {
            Size initialDataPt = iInst+1-localisation_+dataAdjust;
            Array startArray(localisation_+1-dataAdjust);
            for (Size j = 0; j < startArray.size()-1; ++j)
                startArray[j] = ts_->data_[initialDataPt+j];

            // here we are extending the interpolation a point at a
            // time... but the local interpolator can make an
            // approximation for the final localisation period.
            // e.g. if the localisation is 2, then the first section
            // of the curve will be solved using the first 2
            // instruments... with the local interpolator making
            // suitable boundary conditions.
            ts_->interpolation_ =
                ts_->interpolator_.localInterpolate(
                                              ts_->times_.begin(),
                                              ts_->times_.begin()+(iInst + 2),
                                              ts_->data_.begin(),
                                              localisation_,
                                              ts_->interpolation_,
                                              nInsts+1);

            if (iInst >= localisation_) {
                startArray[localisation_-dataAdjust] =
                    Traits::guess(iInst, ts_, false, 0); // ?
            } else {
                startArray[localisation_-dataAdjust] = ts_->data_[0];
            }

            PenaltyFunction<Curve> currentCost(
                        ts_,
                        initialDataPt,
                        ts_->instruments_.begin() + (iInst - localisation_+1),
                        ts_->instruments_.begin() + (iInst+1));

            Problem toSolve(currentCost, solverConstraint, startArray);

            EndCriteria::Type endType = solver.minimize(toSolve, endCriteria);

            // check the end criteria
            QL_REQUIRE(endType == EndCriteria::StationaryFunctionAccuracy ||
                       endType == EndCriteria::StationaryFunctionValue,
                       "Unable to strip yieldcurve to required accuracy " );
            ++iInst;
        } while ( iInst < nInsts );
        validCurve_ = true;
    }
コード例 #7
0
ファイル: schedule.cpp プロジェクト: 21hub/QuantLib
    Schedule::Schedule(Date effectiveDate,
                       const Date& terminationDate,
                       const Period& tenor,
                       const Calendar& cal,
                       BusinessDayConvention convention,
                       BusinessDayConvention terminationDateConvention,
                       DateGeneration::Rule rule,
                       bool endOfMonth,
                       const Date& first,
                       const Date& nextToLast)
    : tenor_(tenor), calendar_(cal), convention_(convention),
      terminationDateConvention_(terminationDateConvention), rule_(rule),
      endOfMonth_(allowsEndOfMonth(tenor) ? endOfMonth : false),
      firstDate_(first==effectiveDate ? Date() : first),
      nextToLastDate_(nextToLast==terminationDate ? Date() : nextToLast)
    {
        // sanity checks
        QL_REQUIRE(terminationDate != Date(), "null termination date");

        // in many cases (e.g. non-expired bonds) the effective date is not
        // really necessary. In these cases a decent placeholder is enough
        if (effectiveDate==Date() && first==Date()
                                  && rule==DateGeneration::Backward) {
            Date evalDate = Settings::instance().evaluationDate();
            QL_REQUIRE(evalDate < terminationDate, "null effective date");
            Natural y;
            if (nextToLast != Date()) {
                y = (nextToLast - evalDate)/366 + 1;
                effectiveDate = nextToLast - y*Years;
            } else {
                y = (terminationDate - evalDate)/366 + 1;
                effectiveDate = terminationDate - y*Years;
            }
        } else
            QL_REQUIRE(effectiveDate != Date(), "null effective date");

        QL_REQUIRE(effectiveDate < terminationDate,
                   "effective date (" << effectiveDate
                   << ") later than or equal to termination date ("
                   << terminationDate << ")");

        if (tenor.length()==0)
            rule_ = DateGeneration::Zero;
        else
            QL_REQUIRE(tenor.length()>0,
                       "non positive tenor (" << tenor << ") not allowed");

        if (firstDate_ != Date()) {
            switch (*rule_) {
              case DateGeneration::Backward:
              case DateGeneration::Forward:
                QL_REQUIRE(firstDate_ > effectiveDate &&
                           firstDate_ < terminationDate,
                           "first date (" << firstDate_ <<
                           ") out of effective-termination date range [" <<
                           effectiveDate << ", " << terminationDate << ")");
                // we should ensure that the above condition is still
                // verified after adjustment
                break;
              case DateGeneration::ThirdWednesday:
                  QL_REQUIRE(IMM::isIMMdate(firstDate_, false),
                             "first date (" << firstDate_ <<
                             ") is not an IMM date");
                break;
              case DateGeneration::Zero:
              case DateGeneration::Twentieth:
              case DateGeneration::TwentiethIMM:
              case DateGeneration::OldCDS:
              case DateGeneration::CDS:
                QL_FAIL("first date incompatible with " << *rule_ <<
                        " date generation rule");
              default:
                QL_FAIL("unknown rule (" << Integer(*rule_) << ")");
            }
        }
        if (nextToLastDate_ != Date()) {
            switch (*rule_) {
              case DateGeneration::Backward:
              case DateGeneration::Forward:
                QL_REQUIRE(nextToLastDate_ > effectiveDate &&
                           nextToLastDate_ < terminationDate,
                           "next to last date (" << nextToLastDate_ <<
                           ") out of effective-termination date range (" <<
                           effectiveDate << ", " << terminationDate << "]");
                // we should ensure that the above condition is still
                // verified after adjustment
                break;
              case DateGeneration::ThirdWednesday:
                QL_REQUIRE(IMM::isIMMdate(nextToLastDate_, false),
                           "next-to-last date (" << nextToLastDate_ <<
                           ") is not an IMM date");
                break;
              case DateGeneration::Zero:
              case DateGeneration::Twentieth:
              case DateGeneration::TwentiethIMM:
              case DateGeneration::OldCDS:
              case DateGeneration::CDS:
                QL_FAIL("next to last date incompatible with " << *rule_ <<
                        " date generation rule");
              default:
                QL_FAIL("unknown rule (" << Integer(*rule_) << ")");
            }
        }


        // calendar needed for endOfMonth adjustment
        Calendar nullCalendar = NullCalendar();
        Integer periods = 1;
        Date seed, exitDate;
        switch (*rule_) {

          case DateGeneration::Zero:
            tenor_ = 0*Years;
            dates_.push_back(effectiveDate);
            dates_.push_back(terminationDate);
            isRegular_.push_back(true);
            break;

          case DateGeneration::Backward:

            dates_.push_back(terminationDate);

            seed = terminationDate;
            if (nextToLastDate_ != Date()) {
                dates_.insert(dates_.begin(), nextToLastDate_);
                Date temp = nullCalendar.advance(seed,
                    -periods*(*tenor_), convention, *endOfMonth_);
                if (temp!=nextToLastDate_)
                    isRegular_.insert(isRegular_.begin(), false);
                else
                    isRegular_.insert(isRegular_.begin(), true);
                seed = nextToLastDate_;
            }

            exitDate = effectiveDate;
            if (firstDate_ != Date())
                exitDate = firstDate_;

            for (;;) {
                Date temp = nullCalendar.advance(seed,
                    -periods*(*tenor_), convention, *endOfMonth_);
                if (temp < exitDate) {
                    if (firstDate_ != Date() &&
                        (calendar_.adjust(dates_.front(),convention)!=
                         calendar_.adjust(firstDate_,convention))) {
                        dates_.insert(dates_.begin(), firstDate_);
                        isRegular_.insert(isRegular_.begin(), false);
                    }
                    break;
                } else {
                    // skip dates that would result in duplicates
                    // after adjustment
                    if (calendar_.adjust(dates_.front(),convention)!=
                        calendar_.adjust(temp,convention)) {
                        dates_.insert(dates_.begin(), temp);
                        isRegular_.insert(isRegular_.begin(), true);
                    }
                    ++periods;
                }
            }

            if (calendar_.adjust(dates_.front(),convention)!=
                calendar_.adjust(effectiveDate,convention)) {
                dates_.insert(dates_.begin(), effectiveDate);
                isRegular_.insert(isRegular_.begin(), false);
            }
            break;

          case DateGeneration::Twentieth:
          case DateGeneration::TwentiethIMM:
          case DateGeneration::ThirdWednesday:
          case DateGeneration::OldCDS:
          case DateGeneration::CDS:
            QL_REQUIRE(!*endOfMonth_,
                       "endOfMonth convention incompatible with " << *rule_ <<
                       " date generation rule");
          // fall through
          case DateGeneration::Forward:

            if (*rule_ == DateGeneration::CDS) {
                dates_.push_back(previousTwentieth(effectiveDate,
                                                   DateGeneration::CDS));
            } else {
                dates_.push_back(effectiveDate);
            }

            seed = dates_.back();

            if (firstDate_!=Date()) {
                dates_.push_back(firstDate_);
                Date temp = nullCalendar.advance(seed, periods*(*tenor_),
                                                 convention, *endOfMonth_);
                if (temp!=firstDate_)
                    isRegular_.push_back(false);
                else
                    isRegular_.push_back(true);
                seed = firstDate_;
            } else if (*rule_ == DateGeneration::Twentieth ||
                       *rule_ == DateGeneration::TwentiethIMM ||
                       *rule_ == DateGeneration::OldCDS ||
                       *rule_ == DateGeneration::CDS) {
                Date next20th = nextTwentieth(effectiveDate, *rule_);
                if (*rule_ == DateGeneration::OldCDS) {
                    // distance rule inforced in natural days
                    static const BigInteger stubDays = 30;
                    if (next20th - effectiveDate < stubDays) {
                        // +1 will skip this one and get the next
                        next20th = nextTwentieth(next20th + 1, *rule_);
                    }
                }
                if (next20th != effectiveDate) {
                    dates_.push_back(next20th);
                    isRegular_.push_back(false);
                    seed = next20th;
                }
            }

            exitDate = terminationDate;
            if (nextToLastDate_ != Date())
                exitDate = nextToLastDate_;

            for (;;) {
                Date temp = nullCalendar.advance(seed, periods*(*tenor_),
                                                 convention, *endOfMonth_);
                if (temp > exitDate) {
                    if (nextToLastDate_ != Date() &&
                        (calendar_.adjust(dates_.back(),convention)!=
                         calendar_.adjust(nextToLastDate_,convention))) {
                        dates_.push_back(nextToLastDate_);
                        isRegular_.push_back(false);
                    }
                    break;
                } else {
                    // skip dates that would result in duplicates
                    // after adjustment
                    if (calendar_.adjust(dates_.back(),convention)!=
                        calendar_.adjust(temp,convention)) {
                        dates_.push_back(temp);
                        isRegular_.push_back(true);
                    }
                    ++periods;
                }
            }

            if (calendar_.adjust(dates_.back(),terminationDateConvention)!=
                calendar_.adjust(terminationDate,terminationDateConvention)) {
                if (*rule_ == DateGeneration::Twentieth ||
                    *rule_ == DateGeneration::TwentiethIMM ||
                    *rule_ == DateGeneration::OldCDS ||
                    *rule_ == DateGeneration::CDS) {
                    dates_.push_back(nextTwentieth(terminationDate, *rule_));
                    isRegular_.push_back(true);
                } else {
                    dates_.push_back(terminationDate);
                    isRegular_.push_back(false);
                }
            }

            break;

          default:
            QL_FAIL("unknown rule (" << Integer(*rule_) << ")");
        }

        // adjustments
        if (*rule_==DateGeneration::ThirdWednesday)
            for (Size i=1; i<dates_.size()-1; ++i)
                dates_[i] = Date::nthWeekday(3, Wednesday,
                                             dates_[i].month(),
                                             dates_[i].year());

        if (*endOfMonth_ && calendar_.isEndOfMonth(seed)) {
            // adjust to end of month
            if (convention == Unadjusted) {
                for (Size i=1; i<dates_.size()-1; ++i)
                    dates_[i] = Date::endOfMonth(dates_[i]);
            } else {
                for (Size i=1; i<dates_.size()-1; ++i)
                    dates_[i] = calendar_.endOfMonth(dates_[i]);
            }
            if (terminationDateConvention != Unadjusted) {
                dates_.front() = calendar_.endOfMonth(dates_.front());
                dates_.back() = calendar_.endOfMonth(dates_.back());
            } else {
                // the termination date is the first if going backwards,
                // the last otherwise.
                if (*rule_ == DateGeneration::Backward)
                    dates_.back() = Date::endOfMonth(dates_.back());
                else
                    dates_.front() = Date::endOfMonth(dates_.front());
            }
        } else {
            // first date not adjusted for CDS schedules
            if (*rule_ != DateGeneration::OldCDS)
                dates_[0] = calendar_.adjust(dates_[0], convention);
            for (Size i=1; i<dates_.size()-1; ++i)
                dates_[i] = calendar_.adjust(dates_[i], convention);

            // termination date is NOT adjusted as per ISDA
            // specifications, unless otherwise specified in the
            // confirmation of the deal or unless we're creating a CDS
            // schedule
            if (terminationDateConvention != Unadjusted
                || *rule_ == DateGeneration::Twentieth
                || *rule_ == DateGeneration::TwentiethIMM
                || *rule_ == DateGeneration::OldCDS
                || *rule_ == DateGeneration::CDS) {
                dates_.back() = calendar_.adjust(dates_.back(),
                                                terminationDateConvention);
            }
        }

        // Final safety checks to remove extra next-to-last date, if
        // necessary.  It can happen to be equal or later than the end
        // date due to EOM adjustments (see the Schedule test suite
        // for an example).
        if (dates_.size() >= 2 && dates_[dates_.size()-2] >= dates_.back()) {
            isRegular_[dates_.size()-2] =
                (dates_[dates_.size()-2] == dates_.back());
            dates_[dates_.size()-2] = dates_.back();
            dates_.pop_back();
            isRegular_.pop_back();
        }
        if (dates_.size() >= 2 && dates_[1] <= dates_.front()) {
            isRegular_[1] =
                (dates_[1] == dates_.front());
            dates_[1] = dates_.front();
            dates_.erase(dates_.begin());
            isRegular_.erase(isRegular_.begin());
        }

        QL_ENSURE(dates_.size()>1,
            "degenerate single date (" << dates_[0] << ") schedule" <<
            "\n seed date: " << seed <<
            "\n exit date: " << exitDate <<
            "\n effective date: " << effectiveDate <<
            "\n first date: " << first <<
            "\n next to last date: " << nextToLast <<
            "\n termination date: " << terminationDate <<
            "\n generation rule: " << *rule_ <<
            "\n end of month: " << *endOfMonth_);

    }
コード例 #8
0
    void SwaptionVolCube1::sabrCalibrationSection(
                                            const Cube& marketVolCube,
                                            Cube& parametersCube,
                                            const Period& swapTenor) const {

        const std::vector<Time>& optionTimes = marketVolCube.optionTimes();
        const std::vector<Time>& swapLengths = marketVolCube.swapLengths();
        const std::vector<Date>& optionDates = marketVolCube.optionDates();
        const std::vector<Period>& swapTenors = marketVolCube.swapTenors();

        Size k = std::find(swapTenors.begin(), swapTenors.end(),
                           swapTenor) - swapTenors.begin();
        QL_REQUIRE(k != swapTenors.size(), "swap tenor not found");

        std::vector<Real> calibrationResult(8,0.);
        const std::vector<Matrix>& tmpMarketVolCube = marketVolCube.points();

        std::vector<Real> strikes(strikeSpreads_.size());
        std::vector<Real> volatilities(strikeSpreads_.size());

        for (Size j=0; j<optionTimes.size(); j++) {
            Rate atmForward = atmStrike(optionDates[j], swapTenors[k]);
            strikes.clear();
            volatilities.clear();
            for (Size i=0; i<nStrikes_; i++){
                Real strike = atmForward+strikeSpreads_[i];
                if(strike>=MINSTRIKE) {
                    strikes.push_back(strike);
                    volatilities.push_back(tmpMarketVolCube[i][j][k]);
                }
            }

            const std::vector<Real>& guess = parametersGuess_.operator()(
                optionTimes[j], swapLengths[k]);

            const boost::shared_ptr<SABRInterpolation> sabrInterpolation =
                boost::shared_ptr<SABRInterpolation>(new
                    SABRInterpolation(strikes.begin(), strikes.end(),
                                      volatilities.begin(),
                                      optionTimes[j], atmForward,
                                      guess[0], guess[1],
                                      guess[2], guess[3],
                                      isParameterFixed_[0],
                                      isParameterFixed_[1],
                                      isParameterFixed_[2],
                                      isParameterFixed_[3],
                                      vegaWeightedSmileFit_,
                                      endCriteria_,
                                      optMethod_,
                                      errorAccept_,
                                      useMaxError_,
                                      maxGuesses_));

            sabrInterpolation->update();
            Real interpolationError = sabrInterpolation->rmsError();
            calibrationResult[0]=sabrInterpolation->alpha();
            calibrationResult[1]=sabrInterpolation->beta();
            calibrationResult[2]=sabrInterpolation->nu();
            calibrationResult[3]=sabrInterpolation->rho();
            calibrationResult[4]=atmForward;
            calibrationResult[5]=interpolationError;
            calibrationResult[6]=sabrInterpolation->maxError();
            calibrationResult[7]=sabrInterpolation->endCriteria();

            QL_ENSURE(calibrationResult[7]!=EndCriteria::MaxIterations,
                      "section calibration failed: "
                      "option tenor " << optionDates[j] <<
                      ", swap tenor " << swapTenors[k] <<
                      ": max iteration (" <<
                      endCriteria_->maxIterations() << ")" <<
                          ", alpha " <<  calibrationResult[0]<<
                          ", beta "  <<  calibrationResult[1] <<
                          ", nu "    <<  calibrationResult[2]   <<
                          ", rho "   <<  calibrationResult[3]  <<
                          ", max error " << calibrationResult[6] <<
                          ", error " <<  calibrationResult[5]
                          );

            QL_ENSURE(useMaxError_ ? calibrationResult[6] : calibrationResult[5] < maxErrorTolerance_,
                      "section calibration failed: "
                      "option tenor " << optionDates[j] <<
                      ", swap tenor " << swapTenors[k] <<
                      (useMaxError_ ? ": max error " : ": error ") <<
                      (useMaxError_ ? calibrationResult[6] : calibrationResult[5]) <<
                          ", alpha " <<  calibrationResult[0] <<
                          ", beta "  <<  calibrationResult[1] <<
                          ", nu "    <<  calibrationResult[2] <<
                          ", rho "   <<  calibrationResult[3] <<
                      (useMaxError_ ? ": error" : ": max error ") <<
                      (useMaxError_ ? calibrationResult[5] : calibrationResult[6])
            );

            parametersCube.setPoint(optionDates[j], swapTenors[k],
                                    optionTimes[j], swapLengths[k],
                                    calibrationResult);
            parametersCube.updateInterpolators();
        }

    }
コード例 #9
0
        /* enregistre un TIPS */
DLLEXPORT xloper * xlInitiateAussieNote (const char * objectID_,
                                         const double * issueDate_,
                                         xloper * effectiveDate_,
                                         xloper * firstCouponDate_,
                                         xloper * lastCouponDate_,
                                         const double * maturityDate_,
                                         const double * couponRate_,
                                         xloper * trigger_) {

    boost::shared_ptr<ObjectHandler::FunctionCall> functionCall(
        new ObjectHandler::FunctionCall("xlInitiateAussieNote")) ;

    try {


            QL_ENSURE(! functionCall->calledByFunctionWizard(), "") ;

                // trigger pour provoquer le recalcul
            ObjectHandler::validateRange(trigger_, "trigger") ;

            ObjectHandler::validateRange(effectiveDate_, "effective Date") ;

            ObjectHandler::validateRange(firstCouponDate_, "first Coupon Date") ;

            ObjectHandler::validateRange(lastCouponDate_, "last Coupon Date") ;


            ObjectHandler::ConvertOper myOper1(* effectiveDate_) ;

            ObjectHandler::ConvertOper myOper2(* firstCouponDate_) ;

            ObjectHandler::ConvertOper myOper3(* lastCouponDate_) ;


            QuantLib::Date issueDate(static_cast<QuantLib::BigInteger>(* issueDate_)) ;

            QuantLib::Date effectiveDate(myOper1.missing() ? 
                issueDate : 
                static_cast<QuantLib::Date>(myOper1)) ;

            QuantLib::Date firstCouponDate(myOper2.missing() ? 
                QuantLib::Date() : 
                static_cast<QuantLib::Date>(myOper2)) ;

            QuantLib::Date lastCouponDate(myOper3.missing() ? 
                QuantLib::Date() : 
                static_cast<QuantLib::Date>(myOper3)) ;

            QuantLib::Date maturityDate(static_cast<QuantLib::BigInteger>(* maturityDate_)) ;
                                         

                // Construction du value object
            boost::shared_ptr<QuantLibAddin::ValueObjects::australianTreasuryNoteValueObject> myBondValueObject(
				new QuantLibAddin::ValueObjects::australianTreasuryNoteValueObject(objectID_,
                                                                       true)) ;

                // instanciation de l'instrument
            boost::shared_ptr<QuantLibAddin::australianTreasuryNoteObject> myBondObject(
				new QuantLibAddin::australianTreasuryNoteObject(myBondValueObject,
                                                    issueDate,
                                                    effectiveDate,
                                                    firstCouponDate,
                                                    lastCouponDate,
                                                    maturityDate,
                                                    QuantLib::Rate(* couponRate_),
                                                    true)) ;

                // stockage de l'objet
            std::string returnValue =
                ObjectHandler::RepositoryXL::instance().storeObject(objectID_, 
                                                                    myBondObject, 
                                                                    true) ; // on force la réécriture

            static XLOPER returnOper ;
            ObjectHandler::scalarToOper(returnValue, returnOper) ;
            return & returnOper ;

        } catch (std::exception & e) {

                ObjectHandler::RepositoryXL::instance().logError(e.what(), functionCall) ;
                static XLOPER returnOper ;
                ObjectHandler::scalarToOper(e.what(), returnOper) ;
                return & returnOper ;

			}

    } ;
コード例 #10
0
        /* enregistre un helper pour un depôt */
DLLEXPORT xloper * xlInitiateDepositBootstrapHelper (const char * objectId_,
                                                     const char * depositId_,
                                                     const double * depositPrice_,
                                                     const xloper * trigger_) {
    
        boost::shared_ptr<ObjectHandler::FunctionCall> functionCall(
            new ObjectHandler::FunctionCall("xlInitiateDepositBootstrapHelper")) ;

         try {

                QL_ENSURE(! functionCall->calledByFunctionWizard(), "") ;

                    // trigger pour provoquer le recalcul
                ObjectHandler::validateRange(trigger_, "trigger") ;


                OH_GET_REFERENCE(depositPtr,
                                 depositId_,
                                 QuantLibAddin::depositObject,
                                 QuantLib::deposit)


                    // creation de la quote
                boost::shared_ptr<QuantLib::Quote> myQuote(
                    new QuantLib::SimpleQuote(* depositPrice_)) ;


                    // création du handler
                QuantLib::Handle<QuantLib::Quote> quoteHandler(myQuote) ;


                    // creation du value object
                boost::shared_ptr<QuantLibAddin::ValueObjects::depositBootstrapHelperValueObject> depositValueObject(
                    new QuantLibAddin::ValueObjects::depositBootstrapHelperValueObject(objectId_,
                                                                                       true)) ;

                    // creation du helper
                boost::shared_ptr<QuantLibAddin::depositBootstrapHelperObject> depositBootstrapObject(
                    new QuantLibAddin::depositBootstrapHelperObject(depositValueObject,
                                                                    depositPtr,
                                                                    quoteHandler,
                                                                    true)) ;

                    // stockage de l'objet
                std::string returnValue =
                    ObjectHandler::RepositoryXL::instance().storeObject(objectId_,
                                                                        depositBootstrapObject,
                                                                        true) ; // on force la réécriture


                static XLOPER returnOper ;

                ObjectHandler::scalarToOper(returnValue, returnOper) ;

                return & returnOper ;


            } catch (std::exception & e) {


                    ObjectHandler::RepositoryXL::instance().logError(e.what(), functionCall) ;

                    static XLOPER returnOper ;

                    ObjectHandler::scalarToOper(e.what(), returnOper) ;

                    return & returnOper ;


            }


    } ;
コード例 #11
0
/* register a deposit for curve fitting */
DLLEXPORT xloper * xlInitiateDepositBootstrapHelper2 (const char * objectId_,
                                                      const char * tenor_,
													  const xloper * calendar_,
													  const xloper * settlementDays_,
                                                      const double * depositYield_,
													  const xloper * annualBasis_,
                                                      const xloper * trigger_) {
    
        boost::shared_ptr<ObjectHandler::FunctionCall> functionCall(
            new ObjectHandler::FunctionCall("xlInitiateDepositBootstrapHelper2")) ;

         try {

                QL_ENSURE(! functionCall->calledByFunctionWizard(), "");

                // range validation
                ObjectHandler::validateRange(trigger_       , "trigger"        );
				ObjectHandler::validateRange(calendar_      , "calendar"       );
				ObjectHandler::validateRange(settlementDays_, "settlement days");
				ObjectHandler::validateRange(annualBasis_   , "annual basis"   );

				// OPER management
				ObjectHandler::ConvertOper myOper1(* calendar_      ),
										   myOper2(* settlementDays_),
										   myOper3(* annualBasis_   );

                // creates a value object
                boost::shared_ptr<QuantLibAddin::ValueObjects::depositBootstrapHelperValueObject> depositValueObject(
                    new QuantLibAddin::ValueObjects::depositBootstrapHelperValueObject(
						objectId_, true)) ;
				    
				// quantlib objects
                QuantLib::Natural settlementDays(
                    myOper2.missing() ? 
                    2 :  static_cast<long>(myOper2)) ;

                QuantLib::Calendar calendar(
                    myOper1.missing() ? 
                    QuantLib::UnitedStates(
						QuantLib::UnitedStates::Settlement) : 
                    ObjectHandler::calendarFactory()(
						static_cast<std::string>(myOper1)));

                QuantLib::Date valueDate(
					calendar.advance(
						QuantLib::Settings::instance().evaluationDate().value(), 
						settlementDays, QuantLib::Days)) ;

				QuantLib::DayCounter annualBasis(
                    myOper3.missing() ? 
                    QuantLib::Actual360() :
                    ObjectHandler::daycountFactory()(
						static_cast<std::string>(myOper3)));

				// creates the deposit
				boost::shared_ptr<QuantLib::deposit> myDepositPtr (
					new QuantLib::deposit(
						valueDate,
						calendar.advance(valueDate, ObjectHandler::periodFactory()(tenor_)),
						calendar,
						settlementDays,
						QuantLib::Unadjusted));

                    // creates the helper
                boost::shared_ptr<QuantLibAddin::depositBootstrapHelperObject> depositBootstrapObject(
                    new QuantLibAddin::depositBootstrapHelperObject(
						depositValueObject,
                        myDepositPtr,
						QuantLib::Handle<QuantLib::Quote>(
							boost::shared_ptr<QuantLib::Quote>(
								new QuantLib::SimpleQuote(
									myDepositPtr->cleanPrice(
										*depositYield_,
										annualBasis,
										QuantLib::Simple,
										QuantLib::Once,
										QuantLib::Unadjusted,
										valueDate)))),
                        true));

                    // storage of the object
                std::string returnValue =
                    ObjectHandler::RepositoryXL::instance().storeObject(
						objectId_,
                        depositBootstrapObject,
                        true);

                static XLOPER returnOper ;
                ObjectHandler::scalarToOper(returnValue, returnOper) ;
                return & returnOper ;

            } catch (std::exception & e) 
			{
                    ObjectHandler::RepositoryXL::instance().logError(e.what(), functionCall) ;
                    static XLOPER returnOper ;
                    ObjectHandler::scalarToOper(e.what(), returnOper) ;
                    return & returnOper ;
            }
    };
コード例 #12
0
    SymmetricSchurDecomposition::SymmetricSchurDecomposition(const Matrix & s)
    : diagonal_(s.rows()), eigenVectors_(s.rows(), s.columns(), 0.0) {

        QL_REQUIRE(s.rows() > 0 && s.columns() > 0, "null matrix given");
        QL_REQUIRE(s.rows()==s.columns(), "input matrix must be square");

        Size size = s.rows();
        for (Size q=0; q<size; q++) {
            diagonal_[q] = s[q][q];
            eigenVectors_[q][q] = 1.0;
        }
        Matrix ss = s;

        std::vector<Real> tmpDiag(diagonal_.begin(), diagonal_.end());
        std::vector<Real> tmpAccumulate(size, 0.0);
        Real threshold, epsPrec = 1e-15;
        bool keeplooping = true;
        Size maxIterations = 100, ite = 1;
        do {
            //main loop
            Real sum = 0;
            for (Size a=0; a<size-1; a++) {
                for (Size b=a+1; b<size; b++) {
                    sum += std::fabs(ss[a][b]);
                }
            }

            if (sum==0) {
                keeplooping = false;
            } else {
                /* To speed up computation a threshold is introduced to
                   make sure it is worthy to perform the Jacobi rotation
                */
                if (ite<5) threshold = 0.2*sum/(size*size);
                else       threshold = 0.0;

                Size j, k, l;
                for (j=0; j<size-1; j++) {
                    for (k=j+1; k<size; k++) {
                        Real sine, rho, cosin, heig, tang, beta;
                        Real smll = std::fabs(ss[j][k]);
                        if(ite> 5 &&
                           smll<epsPrec*std::fabs(diagonal_[j]) &&
                           smll<epsPrec*std::fabs(diagonal_[k])) {
                                ss[j][k] = 0;
                        } else if (std::fabs(ss[j][k])>threshold) {
                            heig = diagonal_[k]-diagonal_[j];
                            if (smll<epsPrec*std::fabs(heig)) {
                                tang = ss[j][k]/heig;
                            } else {
                                beta = 0.5*heig/ss[j][k];
                                tang = 1.0/(std::fabs(beta)+
                                    std::sqrt(1+beta*beta));
                                if (beta<0)
                                    tang = -tang;
                            }
                            cosin = 1/std::sqrt(1+tang*tang);
                            sine = tang*cosin;
                            rho = sine/(1+cosin);
                            heig = tang*ss[j][k];
                            tmpAccumulate[j] -= heig;
                            tmpAccumulate[k] += heig;
                            diagonal_[j] -= heig;
                            diagonal_[k] += heig;
                            ss[j][k] = 0.0;
                            for (l=0; l+1<=j; l++)
                                jacobiRotate_(ss, rho, sine, l, j, l, k);
                            for (l=j+1; l<=k-1; l++)
                                jacobiRotate_(ss, rho, sine, j, l, l, k);
                            for (l=k+1; l<size; l++)
                                jacobiRotate_(ss, rho, sine, j, l, k, l);
                            for (l=0;   l<size; l++)
                                jacobiRotate_(eigenVectors_,
                                                  rho, sine, l, j, l, k);
                        }
                    }
                }
                for (k=0; k<size; k++) {
                    tmpDiag[k] += tmpAccumulate[k];
                    diagonal_[k] = tmpDiag[k];
                    tmpAccumulate[k] = 0.0;
                }
            }
        } while (++ite<=maxIterations && keeplooping);

        QL_ENSURE(ite<=maxIterations,
                  "Too many iterations (" << maxIterations << ") reached");


        // sort (eigenvalues, eigenvectors)
        std::vector<std::pair<Real, std::vector<Real> > > temp(size);
        std::vector<Real> eigenVector(size);
        Size row, col;
        for (col=0; col<size; col++) {
            std::copy(eigenVectors_.column_begin(col),
                      eigenVectors_.column_end(col), eigenVector.begin());
            temp[col] = std::make_pair(diagonal_[col], eigenVector);
        }
        std::sort(temp.begin(), temp.end(),
            std::greater<std::pair<Real, std::vector<Real> > >());
        Real maxEv = temp[0].first;
        for (col=0; col<size; col++) {
            // check for round-off errors
            diagonal_[col] =
                (std::fabs(temp[col].first/maxEv)<1e-16 ? 0.0 :
                                                          temp[col].first);
            Real sign = 1.0;
            if (temp[col].second[0]<0.0)
                sign = -1.0;
            for (row=0; row<size; row++) {
                eigenVectors_[row][col] = sign * temp[col].second[row];
            }
        }
    }
コード例 #13
0
 inline Real CompositeQuote<BinaryFunction>::value() const {
     QL_ENSURE(isValid(), "invalid CompositeQuote");
     return f_(element1_->value(),element2_->value());
 }
コード例 #14
0
	void ArithmeticAveragedOvernightIndexedCouponPricer::initialize(const FloatingRateCoupon& coupon) {
        coupon_ = dynamic_cast<const OvernightIndexedCoupon*>(&coupon);
        QL_ENSURE(coupon_, "wrong coupon type");
    }
コード例 #15
0
    FloatingRateBond::FloatingRateBond(
                           Natural settlementDays,
                           Real faceAmount,
                           const Date& startDate,
                           const Date& maturityDate,
                           Frequency couponFrequency,
                           const Calendar& calendar,
                           const ext::shared_ptr<IborIndex>& iborIndex,
                           const DayCounter& accrualDayCounter,
                           BusinessDayConvention accrualConvention,
                           BusinessDayConvention paymentConvention,
                           Natural fixingDays,
                           const std::vector<Real>& gearings,
                           const std::vector<Spread>& spreads,
                           const std::vector<Rate>& caps,
                           const std::vector<Rate>& floors,
                           bool inArrears,
                           Real redemption,
                           const Date& issueDate,
                           const Date& stubDate,
                           DateGeneration::Rule rule,
                           bool endOfMonth)
    : Bond(settlementDays, calendar, issueDate) {

        maturityDate_ = maturityDate;

        Date firstDate, nextToLastDate;
        switch (rule) {
          case DateGeneration::Backward:
            firstDate = Date();
            nextToLastDate = stubDate;
            break;
          case DateGeneration::Forward:
            firstDate = stubDate;
            nextToLastDate = Date();
            break;
          case DateGeneration::Zero:
          case DateGeneration::ThirdWednesday:
          case DateGeneration::Twentieth:
          case DateGeneration::TwentiethIMM:
            QL_FAIL("stub date (" << stubDate << ") not allowed with " <<
                    rule << " DateGeneration::Rule");
          default:
            QL_FAIL("unknown DateGeneration::Rule (" << Integer(rule) << ")");
        }

        Schedule schedule(startDate, maturityDate_, Period(couponFrequency),
                          calendar_, accrualConvention, accrualConvention,
                          rule, endOfMonth,
                          firstDate, nextToLastDate);

        cashflows_ = IborLeg(schedule, iborIndex)
            .withNotionals(faceAmount)
            .withPaymentDayCounter(accrualDayCounter)
            .withPaymentAdjustment(paymentConvention)
            .withFixingDays(fixingDays)
            .withGearings(gearings)
            .withSpreads(spreads)
            .withCaps(caps)
            .withFloors(floors)
            .inArrears(inArrears);

        addRedemptionsToCashflows(std::vector<Real>(1, redemption));

        QL_ENSURE(!cashflows().empty(), "bond with no cashflows!");
        QL_ENSURE(redemptions_.size() == 1, "multiple redemptions created");

        registerWith(iborIndex);
    }
コード例 #16
0
        /* enregistre une jambe à taux flottant */
DLLEXPORT xloper * xlInitiateFloatLegUnitedStates (const char * objectID_,
                                                   const double * effectiveDate_,
                                                   xloper * firstCouponDate_,
                                                   xloper * lastCouponDate_,
                                                   const double * maturityDate_,
                                                   xloper * notional_,
                                                   const char * indexId_,
                                                   xloper * frequency_,
                                                   xloper * daycounter_,
                                                   xloper * spread_,
                                                   xloper * trigger_) {

    boost::shared_ptr<ObjectHandler::FunctionCall> functionCall(
        new ObjectHandler::FunctionCall("xlInitiatefloatLegUnitedStates")) ;

     try {


        QL_ENSURE(! functionCall->calledByFunctionWizard(), "") ;


            // vérification des codes erreur
        ObjectHandler::validateRange(trigger_, "trigger") ;

        ObjectHandler::validateRange(firstCouponDate_, "first Coupon Date") ;

        ObjectHandler::validateRange(lastCouponDate_, "last Coupon Date") ;

        ObjectHandler::validateRange(notional_, "notional") ;

        ObjectHandler::validateRange(frequency_, "frequency") ;

        ObjectHandler::validateRange(daycounter_, "daycounter") ;

        ObjectHandler::validateRange(spread_, "spread") ;

            // Création des oper
        ObjectHandler::ConvertOper myOper1(* firstCouponDate_),
                                   myOper2(* lastCouponDate_),
                                   myOper3(* notional_),
                                   myOper4(* frequency_),
                                   myOper5(* daycounter_),
                                   myOper6(* spread_) ;

            // création des dates et contrôles sur les dates intermédiaires
        QuantLib::Date effectiveDate(QuantLib::Date(static_cast<QuantLib::BigInteger>(* effectiveDate_))) ;

        QuantLib::Date maturityDate(QuantLib::Date(static_cast<QuantLib::BigInteger>(* maturityDate_))) ;

        QuantLib::Date firstCouponDate(myOper1.missing() ? 
            QuantLib::Date() : 
            QuantLib::Date(static_cast<QuantLib::BigInteger>(myOper1))) ;

        QuantLib::Date lastCouponDate(myOper2.missing() ? 
            QuantLib::Date() : 
            QuantLib::Date(static_cast<QuantLib::BigInteger>(myOper2))) ;

        QuantLib::Real notional(myOper3.missing() ? 
            100.0 : 
            static_cast<QuantLib::Real>(myOper3)) ;

        QuantLib::Frequency frequency(myOper4.missing() ? 
            QuantLib::Quarterly : 
            ObjectHandler::frequencyFactory()(static_cast<std::string>(myOper4))) ;

        QuantLib::DayCounter daycounter(myOper5.missing() ? 
            QuantLib::Actual360() : 
            ObjectHandler::daycountFactory()(static_cast<std::string>(myOper5))) ;

		QuantLib::Spread spread(myOper6.missing() ? 
            0.0 : 
            static_cast<QuantLib::Spread>(myOper6)) ;


            // on récupère l'index libor
        OH_GET_REFERENCE(iborIndexPtr, 
                         std::string(indexId_), 
                         QuantLibAddin::iborIndexObject,
                         QuantLib::IborIndex)    


            // Construction du value object
        boost::shared_ptr<QuantLibAddin::ValueObjects::floatLegUnitedStatesValueObject> myLegValueObject(
            new QuantLibAddin::ValueObjects::floatLegUnitedStatesValueObject(objectID_,
                                                                   true)) ;

            // instanciation de l'instrument
        boost::shared_ptr<QuantLibAddin::floatLegUnitedStatesObject> myLegObject(
            new QuantLibAddin::floatLegUnitedStatesObject(myLegValueObject,
                                                effectiveDate,
                                                firstCouponDate,
                                                lastCouponDate,
                                                maturityDate,
                                                iborIndexPtr,
                                                2,
                                                frequency,
                                                daycounter,
                                                notional,
                                                spread,
                                                QuantLib::ModifiedFollowing,
                                                QuantLib::ModifiedFollowing, 
                                                true, true)) ;


            // stockage de l'objet
        std::string returnValue =
            ObjectHandler::RepositoryXL::instance().storeObject(objectID_, 
                                                                myLegObject, 
                                                                true) ; // on force la réécriture

        static XLOPER returnOper ;

        ObjectHandler::scalarToOper(returnValue, returnOper) ;

        return & returnOper ;

    } catch (std::exception & e) {

            ObjectHandler::RepositoryXL::instance().logError(e.what(), functionCall) ;

            static XLOPER returnOper ;

            ObjectHandler::scalarToOper(e.what(), returnOper) ;

            return & returnOper ;

    }

} ;
コード例 #17
0
    SwaptionVolCube1::Cube
    SwaptionVolCube1::sabrCalibration(const Cube& marketVolCube) const {

        const std::vector<Time>& optionTimes = marketVolCube.optionTimes();
        const std::vector<Time>& swapLengths = marketVolCube.swapLengths();
        const std::vector<Date>& optionDates = marketVolCube.optionDates();
        const std::vector<Period>& swapTenors = marketVolCube.swapTenors();
        Matrix alphas(optionTimes.size(), swapLengths.size(),0.);
        Matrix betas(alphas);
        Matrix nus(alphas);
        Matrix rhos(alphas);
        Matrix forwards(alphas);
        Matrix errors(alphas);
        Matrix maxErrors(alphas);
        Matrix endCriteria(alphas);

        const std::vector<Matrix>& tmpMarketVolCube = marketVolCube.points();

        std::vector<Real> strikes(strikeSpreads_.size());
        std::vector<Real> volatilities(strikeSpreads_.size());

        for (Size j=0; j<optionTimes.size(); j++) {
            for (Size k=0; k<swapLengths.size(); k++) {
                Rate atmForward = atmStrike(optionDates[j], swapTenors[k]);
                strikes.clear();
                volatilities.clear();
                for (Size i=0; i<nStrikes_; i++){
                    Real strike = atmForward+strikeSpreads_[i];
                    if(strike>=MINSTRIKE) {
                        strikes.push_back(strike);
                        volatilities.push_back(tmpMarketVolCube[i][j][k]);
                    }
                }

                const std::vector<Real>& guess = parametersGuess_.operator()(
                    optionTimes[j], swapLengths[k]);

                const boost::shared_ptr<SABRInterpolation> sabrInterpolation =
                    boost::shared_ptr<SABRInterpolation>(new
                        SABRInterpolation(strikes.begin(), strikes.end(),
                                          volatilities.begin(),
                                          optionTimes[j], atmForward,
                                          guess[0], guess[1],
                                          guess[2], guess[3],
                                          isParameterFixed_[0],
                                          isParameterFixed_[1],
                                          isParameterFixed_[2],
                                          isParameterFixed_[3],
                                          vegaWeightedSmileFit_,
                                          endCriteria_,
                                          optMethod_,
                                          errorAccept_,
                                          useMaxError_,
                                          maxGuesses_));
                sabrInterpolation->update();

                Real rmsError = sabrInterpolation->rmsError();
                Real maxError = sabrInterpolation->maxError();
                alphas     [j][k] = sabrInterpolation->alpha();
                betas      [j][k] = sabrInterpolation->beta();
                nus        [j][k] = sabrInterpolation->nu();
                rhos       [j][k] = sabrInterpolation->rho();
                forwards   [j][k] = atmForward;
                errors     [j][k] = rmsError;
                maxErrors  [j][k] = maxError;
                endCriteria[j][k] = sabrInterpolation->endCriteria();

                QL_ENSURE(endCriteria[j][k]!=EndCriteria::MaxIterations,
                          "global swaptions calibration failed: "
                          "MaxIterations reached: " << "\n" <<
                          "option maturity = " << optionDates[j] << ", \n" <<
                          "swap tenor = " << swapTenors[k] << ", \n" <<
                          "error = " << io::rate(errors[j][k])  << ", \n" <<
                          "max error = " << io::rate(maxErrors[j][k]) << ", \n" <<
                          "   alpha = " <<  alphas[j][k] << "n" <<
                          "   beta = " <<  betas[j][k] << "\n" <<
                          "   nu = " <<  nus[j][k]   << "\n" <<
                          "   rho = " <<  rhos[j][k]  << "\n"
                          );

                QL_ENSURE(useMaxError_ ? maxError : rmsError < maxErrorTolerance_,
                      "global swaptions calibration failed: "
                      "option tenor " << optionDates[j] <<
                      ", swap tenor " << swapTenors[k] <<
                      (useMaxError_ ? ": max error " : ": error") <<
                      (useMaxError_ ? maxError : rmsError) <<
                          "   alpha = " <<  alphas[j][k] << "n" <<
                          "   beta = " <<  betas[j][k] << "\n" <<
                          "   nu = " <<  nus[j][k]   << "\n" <<
                          "   rho = " <<  rhos[j][k]  << "\n" <<
                      (useMaxError_ ? ": error" : ": max error ") <<
                      (useMaxError_ ? rmsError :maxError)
                );

            }
        }
        Cube sabrParametersCube(optionDates, swapTenors,
                                optionTimes, swapLengths, 8);
        sabrParametersCube.setLayer(0, alphas);
        sabrParametersCube.setLayer(1, betas);
        sabrParametersCube.setLayer(2, nus);
        sabrParametersCube.setLayer(3, rhos);
        sabrParametersCube.setLayer(4, forwards);
        sabrParametersCube.setLayer(5, errors);
        sabrParametersCube.setLayer(6, maxErrors);
        sabrParametersCube.setLayer(7, endCriteria);

        return sabrParametersCube;

    }
コード例 #18
0
ファイル: simplequote.hpp プロジェクト: androidYibo/documents
 inline Real SimpleQuote::value() const {
     QL_ENSURE(isValid(), "invalid SimpleQuote");
     return value_;
 }
コード例 #19
0
ファイル: lastfixingquote.cpp プロジェクト: SePTimO7/QuantLib
 Real LastFixingQuote::value() const {
     QL_ENSURE(isValid(),
               index_->name() << " has no fixing");
     return index_->fixing(referenceDate());
 }
コード例 #20
0
// parametric fitted curve
DLLEXPORT char * xlInitiateFittedBondDiscountCurve (const char   * objectID_         ,
        const xloper * evaluationDate_   ,
        const xloper * settlementDate_   ,
        const xloper * instruments_      ,
        const xloper * quote_            ,
        const char   * calendarID_       ,
        const char   * fittingMethodID_  ,
        const xloper * bondSelectionRule_,
        const xloper * trigger_) {

    boost::shared_ptr<ObjectHandler::FunctionCall> functionCall(
        new ObjectHandler::FunctionCall("xlInitiateFittedBondDiscountCurve"));

    try {

        QL_ENSURE(! functionCall->calledByFunctionWizard(), "");						// called by wizard ?

        ObjectHandler::validateRange(trigger_,           "trigger"            );	// validate range
        ObjectHandler::validateRange(settlementDate_,    "settlement Date"    );
        ObjectHandler::validateRange(instruments_,       "instruments"        );
        ObjectHandler::validateRange(quote_,             "quotes"             );
        ObjectHandler::validateRange(bondSelectionRule_, "bond selection rule");

        ObjectHandler::ConvertOper myOper1(* bondSelectionRule_);					// bond selection rule oper

        QuantLib::bondSelectionRule myRule =										// the rule
            (myOper1.missing() ?
             QuantLib::activeRule() :
             ObjectHandler::bondSelectionRuleFactory()(
                 static_cast<std::string>(myOper1)));

        QuantLib::Calendar curveCalendar											// calendar
            = ObjectHandler::calendarFactory()(calendarID_);

        ObjectHandler::ConvertOper oper1(* evaluationDate_);						// evaluation date

        QuantLib::Date evaluationDate(oper1.missing() ?
                                      QuantLib::Date() :
                                      static_cast<QuantLib::Date>(oper1));

        std::vector<std::string> instruments =										// instrument ids
            ObjectHandler::operToVector<std::string>(
                * instruments_, "instruments");

        std::vector<QuantLib::Real> quote =											// quotes
            ObjectHandler::operToVector<double>(
                * quote_, "quote");

        std::vector<boost::shared_ptr<QuantLib::BondHelper> > instrumentsObject;	// helpers

        for (unsigned int i = 0 ; i < instruments.size() ; i++) {					// capture individual bonds

            try {

                OH_GET_REFERENCE(instrumentPtr,										// get a reference
                                 instruments[i],
                                 QuantLibAddin::Bond,
                                 QuantLib::Bond)

                if (quote[i] != 0.0 && instrumentPtr->isTradable()) {				// valid quote ?

                    QuantLib::RelinkableHandle<QuantLib::Quote> quoteHandle;	// the handler

                    quoteHandle.linkTo(boost::shared_ptr<QuantLib::Quote>(		// link to the quote
                                           new QuantLib::SimpleQuote(quote[i])));

                    boost::shared_ptr<QuantLib::BondHelper> noteHelper(			// the helper
                        new QuantLib::BondHelper(quoteHandle, instrumentPtr));

                    instrumentsObject.push_back(noteHelper);					// helper storage

                }

            } catch (...) {}													// nothing on exception

        }

        ObjectHandler::ConvertOper oper2(* settlementDate_);						// settlement date

        QuantLib::Date settlementDate(oper2.missing() ?
                                      instrumentsObject[0]->bond()->settlementDate(evaluationDate) :
                                      static_cast<QuantLib::Date>(oper2));

        OH_GET_OBJECT(fittingMethodTemp,											// fitting method selection
                      fittingMethodID_,
                      ObjectHandler::Object)

        std::string returnValue;

        if (fittingMethodTemp->properties()->className()								// svensson ?
                == "stochasticFittingValueObject") {

            OH_GET_REFERENCE(fittingMethodPtr,
                             fittingMethodID_,
                             QuantLibAddin::stochasticFittingObject,
                             QuantLib::stochasticFittingHelper)

            // build the value object
            boost::shared_ptr<QuantLibAddin::ValueObjects::fittedBondDiscountCurveValueObject> curveValueObject(
                new QuantLibAddin::ValueObjects::fittedBondDiscountCurveValueObject(
                    objectID_,
                    settlementDate.serialNumber(),
                    true));

            boost::shared_ptr<ObjectHandler::Object> myCurve(				// instanciating the curve
                new QuantLibAddin::fittedBondDiscountCurveObject(
                    curveValueObject,
                    settlementDate,
                    myRule.select(instrumentsObject, settlementDate),
                    * fittingMethodPtr->fittingMethod(),
                    fittingMethodPtr->initialVector(),
                    fittingMethodPtr->randomMatrix(),
                    fittingMethodPtr->accuracy(),
                    fittingMethodPtr->maxEvaluationPercycle(),
                    fittingMethodPtr->cyclesPerThread(),
                    fittingMethodPtr->cycles(),
                    1.000,													// simplex lambda
                    true)) ;

            returnValue =													// the value to return
                ObjectHandler::RepositoryXL::instance().storeObject(objectID_,
                        myCurve  ,
                        true      );

        }

        static char ret[XL_MAX_STR_LEN];
        ObjectHandler::stringToChar(returnValue, ret);
        return ret;

    } catch (std::exception & e) {

        static char ret[XL_MAX_STR_LEN];
        ObjectHandler::RepositoryXL::instance().logError(e.what(), functionCall);
        ObjectHandler::stringToChar(std::string(e.what()), ret);
        return ret;

    }

};
コード例 #21
0
    /* Fonction de calcul du carry d'un bond */
DLLEXPORT xloper * xlInstrumentCarry (const char * instrumentId_,
                                      const double * startAccruedDate_,
                                      const double * endAccruedDate_,
                                      const double * instrumentYield_,
                                      const char * conventionId_,
                                      xloper * trigger_) {

     boost::shared_ptr<ObjectHandler::FunctionCall> functionCall(
        new ObjectHandler::FunctionCall("xlInstrumentCarry")) ;

     try {

        QL_ENSURE(! functionCall->calledByFunctionWizard(), "") ;

        double returnValue ;

            // trigger pour provoquer le recalcul
        ObjectHandler::validateRange(trigger_, "trigger") ;

            // on récupère la convention
        OH_GET_REFERENCE(conventionPtr, 
                         conventionId_, 
                         QuantLibAddin::interestRateConventionObject,
						 QuantLib::InterestRate)

            // on récupère l'instrument
        OH_GET_UNDERLYING(myBond, 
                          instrumentId_, 
                          QuantLibAddin::Bond,
                          QuantLib::Bond)

        returnValue = myBond.cleanPrice(* instrumentYield_,
                                        conventionPtr->dayCounter(),
                                        conventionPtr->compounding(),
                                        conventionPtr->frequency(),
                                        conventionPtr->businessDayConvention(),
                                        myBond.settlementDate(
                                            QuantLib::Date(static_cast<QuantLib::BigInteger>(* endAccruedDate_)))) ;

        returnValue -= myBond.cleanPrice(* instrumentYield_,
                                         conventionPtr->dayCounter(),
                                         conventionPtr->compounding(),
                                         conventionPtr->frequency(),
                                         conventionPtr->businessDayConvention(),
                                         myBond.settlementDate(
                                            QuantLib::Date(static_cast<QuantLib::BigInteger>(* startAccruedDate_)))) ;

            // variable de retour
        static XLOPER returnOper ;
        ObjectHandler::scalarToOper(returnValue, returnOper) ;
        return & returnOper ;

    } catch (std::exception & e) {

                ObjectHandler::RepositoryXL::instance().logError(e.what(), functionCall);
                static XLOPER returnOper;
                returnOper.xltype = xltypeErr;
                returnOper.val.err = xlerrValue;
                return & returnOper;

    }

}
コード例 #22
0
	// register an interpolated curve object
DLLEXPORT char * xlInitiateInterpolatedCurve(const char * objectID_       ,
                                             xloper     * calculationDate_,
                                             const char * curveCalendarId_,
                                             xloper     * helperId_       ,
                                             xloper     * trigger_         ) {
    
    boost::shared_ptr<ObjectHandler::FunctionCall> functionCall(
        new ObjectHandler::FunctionCall("xlInitiateInterpolatedCurve")) ;

    try {

        QL_ENSURE(! functionCall->calledByFunctionWizard(), "") ;

            // range validation
        ObjectHandler::validateRange(trigger_        , "trigger"         );
        ObjectHandler::validateRange(helperId_       , "helper Id"       );
        ObjectHandler::validateRange(calculationDate_, "calculation Date");
            
        ObjectHandler::ConvertOper myOper1(* calculationDate_) ;	// xlopers

        std::vector<std::string> helperId = ObjectHandler::operToVector<std::string>(
            * helperId_, "helper Id") ;

        QuantLib::Date currentDate(									// initiate pricing date
            myOper1.missing() ? 
            QuantLib::Date() : 
            QuantLib::Date(static_cast<QuantLib::BigInteger>(myOper1)));

        std::vector<boost::shared_ptr<QuantLib::BootstrapHelper<	// the helpers
			QuantLib::YieldTermStructure> > > helpers;

        for (std::vector<std::string>::const_iterator It = helperId.begin();
			It != helperId.end(); ++It) {

            OH_GET_REFERENCE(helperPtr, * It,						// get helper references
                             QuantLibAddin::RateHelper, 
                             QuantLib::RateHelper);

			helpers.push_back(helperPtr);

        }

            // Construction du value object
        boost::shared_ptr<QuantLibAddin::ValueObjects::interpolatedCurveValueObject> curveValueObject(
            new QuantLibAddin::ValueObjects::interpolatedCurveValueObject(
                objectID_,
                currentDate.serialNumber(),
                true)) ;

            // creates the curve
        boost::shared_ptr<ObjectHandler::Object> myCurve(
            new QuantLibAddin::interpolatedCurveObject(
				curveValueObject,
                currentDate,
				helpers, true,
                std::vector<QuantLib::Handle<QuantLib::Quote> >(),	// empty jump date
                std::vector<QuantLib::Date>(),
                CURVE_DEFAULT_ACCURACY));

		    // object storage
	    std::string returnValue =
            ObjectHandler::RepositoryXL::instance().storeObject(objectID_, 
                                                                myCurve, 
                                                                true);

        static char ret[XL_MAX_STR_LEN] ;
        ObjectHandler::stringToChar(returnValue, ret);
        return ret;

    } catch (std::exception & e) {

        static char ret[XL_MAX_STR_LEN];
        ObjectHandler::RepositoryXL::instance().logError(e.what(), functionCall);
        ObjectHandler::stringToChar(e.what(), ret);
        return ret;

    }

} ;
コード例 #23
0
ファイル: flatvol.cpp プロジェクト: 21hub/QuantLib
    FlatVol::FlatVol(
            const vector<Volatility>& vols,
            const shared_ptr<PiecewiseConstantCorrelation>& corr,
            const EvolutionDescription& evolution,
            Size numberOfFactors,
            const vector<Rate>& initialRates,
            const vector<Spread>& displacements)
    : numberOfFactors_(numberOfFactors),
      numberOfRates_(initialRates.size()),
      numberOfSteps_(evolution.evolutionTimes().size()),
      initialRates_(initialRates),
      displacements_(displacements),
      evolution_(evolution),
      pseudoRoots_(numberOfSteps_, Matrix(numberOfRates_, numberOfFactors_))
    {
        const vector<Time>& rateTimes = evolution.rateTimes();
        QL_REQUIRE(numberOfRates_==rateTimes.size()-1,
                   "mismatch between number of rates (" << numberOfRates_ <<
                   ") and rate times");
        QL_REQUIRE(numberOfRates_==displacements.size(),
                   "mismatch between number of rates (" << numberOfRates_ <<
                   ") and displacements (" << displacements.size() << ")");
        QL_REQUIRE(numberOfRates_==vols.size(),
                   "mismatch between number of rates (" << numberOfRates_ <<
                   ") and vols (" << vols.size() << ")");
        QL_REQUIRE(numberOfRates_<=numberOfFactors_*numberOfSteps_,
                   "number of rates (" << numberOfRates_ <<
                   ") greater than number of factors (" << numberOfFactors_
                   << ") times number of steps (" << numberOfSteps_ << ")");
        QL_REQUIRE(numberOfFactors<=numberOfRates_,
                   "number of factors (" << numberOfFactors <<
                   ") cannot be greater than numberOfRates (" <<
                   numberOfRates_ << ")");
        QL_REQUIRE(numberOfFactors>0,
                   "number of factors (" << numberOfFactors <<
                   ") must be greater than zero");

        Time effStopTime = 0.0;
        const vector<Time>& corrTimes = corr->times();
        const vector<Time>& evolTimes = evolution.evolutionTimes();
        Matrix covariance(numberOfRates_, numberOfRates_);
        for (Size k=0, kk=0; k<numberOfSteps_; ++k) {
            // one covariance per evolution step
            std::fill(covariance.begin(), covariance.end(), 0.0);

            // there might be more than one correlation matrix
            // in a single evolution step
            for (; corrTimes[kk]<evolTimes[k]; ++kk) {
                Time effStartTime = effStopTime;
                effStopTime = corrTimes[kk];
                const Matrix& corrMatrix = corr->correlation(kk);
                for (Size i=0; i<numberOfRates_; ++i) {
                    for (Size j=i; j<numberOfRates_; ++j) {
                        Real cov = flatVolCovariance(effStartTime, effStopTime,
                                                     rateTimes[i], rateTimes[j],
                                                     vols[i], vols[j]);
                        covariance[i][j] += cov * corrMatrix[i][j];
                     }
                }
            }
            // last part in the evolution step
            Time effStartTime = effStopTime;
            effStopTime = evolTimes[k];
            const Matrix& corrMatrix = corr->correlation(kk);
            for (Size i=0; i<numberOfRates_; ++i) {
                for (Size j=i; j<numberOfRates_; ++j) {
                    Real cov = flatVolCovariance(effStartTime, effStopTime,
                                                 rateTimes[i], rateTimes[j],
                                                 vols[i], vols[j]);
                    covariance[i][j] += cov * corrMatrix[i][j];
                 }
            }
            // no more use for the kk-th correlation matrix
            while (kk<corrTimes.size() && corrTimes[kk]<=evolTimes[k])
                ++kk;

            // make it symmetric
            for (Size i=0; i<numberOfRates_; ++i) {
                for (Size j=i+1; j<numberOfRates_; ++j) {
                     covariance[j][i] = covariance[i][j];
                 }
            }

            pseudoRoots_[k] = rankReducedSqrt(covariance,
                                              numberOfFactors, 1.0,
                                              SalvagingAlgorithm::None);

            QL_ENSURE(pseudoRoots_[k].rows()==numberOfRates_,
                      "step " << k
                      << " flat vol wrong number of rows: "
                      << pseudoRoots_[k].rows()
                      << " instead of " << numberOfRates_);
            QL_ENSURE(pseudoRoots_[k].columns()==numberOfFactors,
                      "step " << k
                      << " flat vol wrong number of columns: "
                      << pseudoRoots_[k].columns()
                      << " instead of " << numberOfFactors_);
        }
    }
コード例 #24
0
        /* Fonction de calcul du nombre de flux restant */
DLLEXPORT xloper * xlInstrumentFlowCount (const char * instrumentId_,
                                          xloper * settlementDate_,
                                          xloper * trigger_) {

         boost::shared_ptr<ObjectHandler::FunctionCall> functionCall(
            new ObjectHandler::FunctionCall("xlInstrumentFlowCount")) ;

         try {

            QL_ENSURE(! functionCall->calledByFunctionWizard(), "") ;

                    /* recherche de code erreur */
            ObjectHandler::validateRange(trigger_, "trigger") ;
            ObjectHandler::validateRange(settlementDate_, "settlement Date") ;

                /* on récupère l'instrument */
            OH_GET_UNDERLYING(myBond, 
                              instrumentId_, 
                              QuantLibAddin::Bond,
                              QuantLib::Bond)

                /* les XLOPER des date */
            ObjectHandler::ConvertOper myOper(* settlementDate_) ;

            QuantLib::Date settlementDate(
                    myOper.missing() ? 
                    QuantLib::Date() : 
                    QuantLib::Date(static_cast<QuantLib::BigInteger>(myOper))) ;

			QuantLib::Natural returnValue = 0;

				// increments
			for (std::vector<boost::shared_ptr<QuantLib::CashFlow> >::const_reverse_iterator It = myBond.cashflows().crbegin();
				It != myBond.cashflows().crend(); It++)
			
				It->get()->date() > settlementDate ? returnValue++ : 0;

            static XLOPER returnOper ;
            ObjectHandler::scalarToOper(static_cast<double>(returnValue), returnOper) ;

            return & returnOper ;

        } catch (std::exception & e) {

            #ifdef _DEBUG

				OutputDebugString(e.what()) ;

            #endif

            ObjectHandler::RepositoryXL::instance().logError(e.what(), functionCall) ;
            static XLOPER returnOper ;
            returnOper.xltype = xltypeErr ;
            returnOper.val.err = xlerrValue ;

            return & returnOper ;


        }


    } ;
コード例 #25
0
ファイル: xlSwapNPV.cpp プロジェクト: vermosen/xlObjectTools
	/* Fonction de calcul de la NPV d'un swap ou d'une jambe */
DLLEXPORT xloper * xlSwapNPV (const char * instrumentId_,
                              const char * discountCurveId_,
                              xloper * forwardCurveId_,
                              xloper * trigger_) {


         boost::shared_ptr<ObjectHandler::FunctionCall> functionCall(
            new ObjectHandler::FunctionCall("xlSwapNPV")) ;


         try {


                QL_ENSURE(! functionCall->calledByFunctionWizard(), "") ;

                    // validation
                ObjectHandler::validateRange(trigger_, "trigger") ;
                ObjectHandler::validateRange(forwardCurveId_, "forward Curve") ;

                    // conversion des xloper
                ObjectHandler::ConvertOper myOper(* forwardCurveId_) ;

                    // on récupère la courbe de discounting
                OH_GET_OBJECT(discountCurvePtr, 
                              discountCurveId_, 
                              ObjectHandler::Object)

                QuantLib::Handle<QuantLib::YieldTermStructure> discountCurveHandler =
                    QuantLibAddin::CoerceHandle<QuantLibAddin::YieldTermStructure, QuantLib::YieldTermStructure>()(discountCurvePtr) ;

                    // on récupère l'instrument
                OH_GET_REFERENCE(mySwap,
                                 instrumentId_,
                                 QuantLibAddin::interestRateSwapObject,
                                 QuantLib::vanillaSwap2)

                boost::shared_ptr<QuantLib::PricingEngine> myPricingEngine ;

                     // ligature du pricing engine
                if (myOper.missing()) {
                     
                        myPricingEngine = boost::shared_ptr<QuantLib::PricingEngine>(
                            new QuantLib::DiscountingSwapEngine(discountCurveHandler/*, discountCurveHandler*/)) ;

                        //mySwap->setFixingIndex(* discountCurveHandler) ;
                     
                    } else {
                    
                                // on récupère la courbe forward
                            OH_GET_OBJECT(forwardCurvePtr, 
                                          static_cast<std::string>(myOper), 
                                          ObjectHandler::Object)

                            QuantLib::Handle<QuantLib::YieldTermStructure> forwardCurveHandler =
                                QuantLibAddin::CoerceHandle<QuantLibAddin::YieldTermStructure, QuantLib::YieldTermStructure>()(forwardCurvePtr) ;

                            myPricingEngine = boost::shared_ptr<QuantLib::PricingEngine>(
                                new QuantLib::DiscountingSwapEngine(discountCurveHandler/*, forwardCurveHandler*/)) ;

                            //mySwap->setFixingIndex(* forwardCurveHandler) ;

                        }

                mySwap->setPricingEngine(myPricingEngine) ;
                static XLOPER returnOper ;
                ObjectHandler::scalarToOper(mySwap->NPV(), returnOper) ;
                return & returnOper ;

        } catch (std::exception & e) {

                ObjectHandler::RepositoryXL::instance().logError(e.what(), functionCall) ;
                static XLOPER returnOper ;
				ObjectHandler::scalarToOper(e.what(), returnOper) ;
                return & returnOper ;

        }

} ;
コード例 #26
0
        /* fonction de calcul de la matrice de variance-covariance d'un historique de taux */
DLLEXPORT xloper * xlCovarianceMatrixEWMA(const xloper * seriesId_,
                                          const double * decay_,
										  const double * startDate_,
                                          const bool * norm_,
                                          const xloper * trigger_) {

boost::shared_ptr<ObjectHandler::FunctionCall> functionCall(
    new ObjectHandler::FunctionCall("xlCovarianceMatrixEWMA")) ;

     try {

        QL_ENSURE(! functionCall->calledByFunctionWizard(), "") ;

            /* déclaration du trigger */
        ObjectHandler::validateRange(trigger_, "trigger") ;

            /* conversion des xloper */
        std::vector<std::string> seriesId = 
			ObjectHandler::operToVector<std::string>(* seriesId_, "seriesId") ;

            /* contrôle sur les dimensions */
        QL_ENSURE(seriesId.size() >= 2, "unconsistent data set") ;

            /* on récupére les séries variationnelles */
        std::vector<QuantLib::TimeSeries<double> > timeSeriesVector ;

        for (std::vector<std::string>::const_iterator It = seriesId.begin() ; 
			It != seriesId.end() ; ++It) {

                OH_GET_REFERENCE(TimeSeriesPtr, 
								 * It, 
								 QuantLibAddin::TimeSeriesObject<double>,
								 QuantLib::TimeSeries<double>)    
 
                timeSeriesVector.push_back(* TimeSeriesPtr) ;

            }

        std::vector<QuantLib::TimeSeries<double> > nTimeSeriesVector ;

            /* selon le mode choisi */
        if (* norm_ == true) {
            
                std::vector<QuantLib::TimeSeries<double> > deltaSeriesVector ;

                for (unsigned long i = 0 ; i < timeSeriesVector.size() ; i++)
                    
                        deltaSeriesVector.push_back(
							QuantLib::deltaTimeSeries<double>(timeSeriesVector[i])) ;
                    
                    /* création des vecteurs moyenne et std dev */
                std::vector<double> mean ;
                std::vector<double> variance ;

                for (std::vector<QuantLib::TimeSeries<double> >::const_iterator It = deltaSeriesVector.begin() ;
                    It < deltaSeriesVector.end() ; ++It) {

						variance.push_back(covarianceEWMA(* It, 
							* It, QuantLib::Date(static_cast<QuantLib::BigInteger>(* startDate_)), 
							decay_)) ;

                        mean.push_back(meanEWMA(* It, 
							QuantLib::Date(static_cast<QuantLib::BigInteger>(* startDate_)), 
							decay_)) ;

                    }

                    /* Mode normé */
                for (unsigned int i = 0 ; i < deltaSeriesVector.size() ; i++) {


                        std::vector<double> tempValues ;
                        std::vector<QuantLib::Date> tempDates ;

                        for (QuantLib::TimeSeries<double>::const_iterator It = deltaSeriesVector[i].begin() ;
                            It != deltaSeriesVector[i].end() ; ++It) {

                                tempDates.push_back(It->first) ;

                                tempValues.push_back((deltaSeriesVector[i][It->first] - mean[i]) / 
                                    pow((deltaSeriesVector[i].size() + 1) * variance[i], 0.5)) ;

                            }

                        QuantLib::TimeSeries<double> tempSeries(tempDates.begin(),
                                                                tempDates.end(),
                                                                tempValues.begin()) ;

                        nTimeSeriesVector.push_back(tempSeries) ;

                    }    

            }

        else {
            
                    /* Mode non normé */
                std::vector<double> mean ;

                for (std::vector<QuantLib::TimeSeries<double>>::const_iterator It = timeSeriesVector.begin() ;
                    It < timeSeriesVector.end() ; ++It)

                        mean.push_back(meanEWMA(* It, QuantLib::Date(
							static_cast<QuantLib::BigInteger>(* startDate_)), decay_)) ;

                    /* on se contente de centrer les séries */
                for (unsigned int i = 0 ; i < timeSeriesVector.size() ; i++) {

                        std::vector<double> tempValues ;
						std::vector<QuantLib::Date> tempDates ;

                        for (QuantLib::TimeSeries<double>::const_iterator It = timeSeriesVector[i].begin() ;
                            It != timeSeriesVector[i].end() ; ++It) {

                                tempDates.push_back(It->first) ;
                                tempValues.push_back(timeSeriesVector[i][It->first] - mean[i]) ;

                            }

                        QuantLib::TimeSeries<double> tempSeries(tempDates.begin(),
                                                                tempDates.end(),
                                                                tempValues.begin()) ;

                        nTimeSeriesVector.push_back(tempSeries) ;

                    }    
            
            }

            /* création de la matrice de retour */
        QuantLib::Matrix returnMatrix(
			nTimeSeriesVector.size(), nTimeSeriesVector.size()) ;
        
		for (unsigned int i = 0 ; i < nTimeSeriesVector.size() ; i++) {

            for (unsigned int j = 0 ; j <= i ; j++) {

                    returnMatrix[i][j] = covarianceEWMA(nTimeSeriesVector[i], 
														nTimeSeriesVector[j], 
														QuantLib::Date(static_cast<QuantLib::BigInteger>(* startDate_)),
														decay_) ;

					returnMatrix[j][i] = returnMatrix[i][j];

                }

            }

        static OPER returnOper ;
        ObjectHandler::MatrixToOper(returnMatrix, returnOper) ;
		return & returnOper ;

        } catch (std::exception & e) {

                ObjectHandler::RepositoryXL::instance().logError(e.what(), functionCall) ;
				return 0 ;

        }

}
コード例 #27
-1
    void BinomialBarrierEngine<T,D>::calculate() const {

        DayCounter rfdc  = process_->riskFreeRate()->dayCounter();
        DayCounter divdc = process_->dividendYield()->dayCounter();
        DayCounter voldc = process_->blackVolatility()->dayCounter();
        Calendar volcal = process_->blackVolatility()->calendar();

        Real s0 = process_->stateVariable()->value();
        QL_REQUIRE(s0 > 0.0, "negative or null underlying given");
        Volatility v = process_->blackVolatility()->blackVol(
            arguments_.exercise->lastDate(), s0);
        Date maturityDate = arguments_.exercise->lastDate();
        Rate r = process_->riskFreeRate()->zeroRate(maturityDate,
            rfdc, Continuous, NoFrequency);
        Rate q = process_->dividendYield()->zeroRate(maturityDate,
            divdc, Continuous, NoFrequency);
        Date referenceDate = process_->riskFreeRate()->referenceDate();

        // binomial trees with constant coefficient
        Handle<YieldTermStructure> flatRiskFree(
            boost::shared_ptr<YieldTermStructure>(
                new FlatForward(referenceDate, r, rfdc)));
        Handle<YieldTermStructure> flatDividends(
            boost::shared_ptr<YieldTermStructure>(
                new FlatForward(referenceDate, q, divdc)));
        Handle<BlackVolTermStructure> flatVol(
            boost::shared_ptr<BlackVolTermStructure>(
                new BlackConstantVol(referenceDate, volcal, v, voldc)));

        boost::shared_ptr<StrikedTypePayoff> payoff =
            boost::dynamic_pointer_cast<StrikedTypePayoff>(arguments_.payoff);
        QL_REQUIRE(payoff, "non-striked payoff given");

        Time maturity = rfdc.yearFraction(referenceDate, maturityDate);

        boost::shared_ptr<StochasticProcess1D> bs(
                         new GeneralizedBlackScholesProcess(
                                      process_->stateVariable(),
                                      flatDividends, flatRiskFree, flatVol));

        // correct timesteps to ensure a (local) minimum, using Boyle and Lau
        // approach. See Journal of Derivatives, 1/1994,
        // "Bumping up against the barrier with the binomial method"
        // Note: this approach works only for CoxRossRubinstein lattices, so
        // is disabled if T is not a CoxRossRubinstein or derived from it.
        Size optimum_steps = timeSteps_;
        if (boost::is_base_of<CoxRossRubinstein, T>::value && 
            maxTimeSteps_ > timeSteps_ && s0 > 0 && arguments_.barrier > 0) {
            Real divisor;
            if (s0 > arguments_.barrier)
               divisor = std::pow(std::log(s0 / arguments_.barrier), 2);
            else
               divisor = std::pow(std::log(arguments_.barrier / s0), 2);
            if (!close(divisor,0)) {
                for (Size i=1; i < timeSteps_ ; ++i) {
                    Size optimum = Size(( i*i * v*v * maturity) / divisor);
                    if (timeSteps_ < optimum) {
                        optimum_steps = optimum;
                        break; // found first minimum with iterations>=timesteps
                    }
                }
            }

            if (optimum_steps > maxTimeSteps_) 
               optimum_steps = maxTimeSteps_; // too high, limit
        }

        TimeGrid grid(maturity, optimum_steps);

        boost::shared_ptr<T> tree(new T(bs, maturity, optimum_steps,
                                        payoff->strike()));

        boost::shared_ptr<BlackScholesLattice<T> > lattice(
            new BlackScholesLattice<T>(tree, r, maturity, optimum_steps));

        D option(arguments_, *process_, grid);
        option.initialize(lattice, maturity);

        // Partial derivatives calculated from various points in the
        // binomial tree 
        // (see J.C.Hull, "Options, Futures and other derivatives", 6th edition, pp 397/398)

        // Rollback to third-last step, and get underlying prices (s2) &
        // option values (p2) at this point
        option.rollback(grid[2]);
        Array va2(option.values());
        QL_ENSURE(va2.size() == 3, "Expect 3 nodes in grid at second step");
        Real p2u = va2[2]; // up
        Real p2m = va2[1]; // mid
        Real p2d = va2[0]; // down (low)
        Real s2u = lattice->underlying(2, 2); // up price
        Real s2m = lattice->underlying(2, 1); // middle price
        Real s2d = lattice->underlying(2, 0); // down (low) price

        // calculate gamma by taking the first derivate of the two deltas
        Real delta2u = (p2u - p2m)/(s2u-s2m);
        Real delta2d = (p2m-p2d)/(s2m-s2d);
        Real gamma = (delta2u - delta2d) / ((s2u-s2d)/2);

        // Rollback to second-last step, and get option values (p1) at
        // this point
        option.rollback(grid[1]);
        Array va(option.values());
        QL_ENSURE(va.size() == 2, "Expect 2 nodes in grid at first step");
        Real p1u = va[1];
        Real p1d = va[0];
        Real s1u = lattice->underlying(1, 1); // up (high) price
        Real s1d = lattice->underlying(1, 0); // down (low) price

        Real delta = (p1u - p1d) / (s1u - s1d);

        // Finally, rollback to t=0
        option.rollback(0.0);
        Real p0 = option.presentValue();

        // Store results
        results_.value = p0;
        results_.delta = delta;
        results_.gamma = gamma;
        // theta can be approximated by calculating the numerical derivative
        // between mid value at third-last step and at t0. The underlying price
        // is the same, only time varies.
        results_.theta = (p2m - p0) / grid[2];
    }