Ejemplo n.º 1
0
    void SquareRootAndersen::DoOneSubStep(Real& vt, Real z, Size j)
    {

        Real eminuskT = eMinuskDt_[j];
        Real m = theta_+(vt-theta_)*eminuskT;
        Real s2= vt*epsilon_*epsilon_*eminuskT*(1-eminuskT)/k_
                + theta_*epsilon_*epsilon_*(1- eminuskT)*(1- eminuskT)/(2*k_);
        Real s = std::sqrt(s2);
        Real psi = s*s/(m*m);
        if (psi<= PsiC_)
        {
            Real psiinv = 1.0/psi;
            Real b2 = 2.0*psiinv -1+std::sqrt(2*psiinv*(2*psiinv-1.0));
            Real b = std::sqrt(b2);
            Real a= m/(1+b2);
            vt= a*(b+z)*(b+z);
        }
        else
        {
            Real p = (psi-1.0)/(psi+1.0);
            Real beta = (1.0-p)/m;
            Real u = CumulativeNormalDistribution()(z);

            if (u < p)
            {
                vt=0;
                return;
            }

             vt = std::log((1.0-p)/(1.0-u))/beta;
        }

    }
	void DoubleExponentialCalibration::compute() {
        if (vegaWeighted_) {
            Real weightsSum = 0.0;
            for (Size i=0; i<times_.size() ; i++) {
                Real stdDev = std::sqrt(blackVols_[i]* blackVols_[i]* times_[i]);
                // when strike==forward, the blackFormulaStdDevDerivative becomes
                weights_[i] = CumulativeNormalDistribution().derivative(.5*stdDev);
                weightsSum += weights_[i];
            }
            // weight normalization
            for (Size i=0; i<times_.size() ; i++) {
                weights_[i] /= weightsSum;
            }
        }

        // there is nothing to optimize
        if (sigmaIsFixed_ && b1IsFixed_ && b2IsFixed_ && lambdaIsFixed_) {
			dblexpEndCriteria_ = EndCriteria::None;
            //error_ = interpolationError();
            //maxError_ = interpolationMaxError();
            return;
        } else {

			DoubleExponentialError costFunction(this);

            Array guess(4);
            guess[0] = sigma_;
            guess[1] = b1_;
            guess[2] = b2_;
            guess[3] = lambda_;

            std::vector<bool> parameterAreFixed(4);
            parameterAreFixed[0] = sigmaIsFixed_;
            parameterAreFixed[1] = b1IsFixed_;
            parameterAreFixed[2] = b2IsFixed_;
            parameterAreFixed[3] = lambdaIsFixed_;

            ProjectedCostFunction projectedDoubleExponentialCostFunction(costFunction,
									guess, parameterAreFixed);

            Array projectedGuess
				(projectedDoubleExponentialCostFunction.project(guess));

            // NoConstraint constraint;
			//PositiveConstraint constraint;
			BoundaryConstraint constraint(0.0, 1.0);
			Problem problem(projectedDoubleExponentialCostFunction, constraint, projectedGuess);
			dblexpEndCriteria_ = optMethod_->minimize(problem, *endCriteria_);
            Array projectedResult(problem.currentValue());
			Array result(projectedDoubleExponentialCostFunction.include(projectedResult));

            sigma_ = result[0];
            b1_ = result[1];
            b2_ = result[2];
            lambda_ = result[3];

            validateDoubleExponentialParameters(sigma_, b1_, b2_, lambda_);
        }
    }
Ejemplo n.º 3
0
    //-----------------------------------------------------------------------
    Real OneFactorGaussianCopula::testCumulativeY (Real y) const {
    //-----------------------------------------------------------------------
        Real c = correlation_->value();

        if (c == 0)
            return CumulativeNormalDistribution()(y);

        if (c == 1)
            return CumulativeNormalDistribution()(y);

        NormalDistribution dz;
        NormalDistribution dm;

        Real minimum = -10;
        Real maximum = +10;
        int steps = 200;

        Real delta = (maximum - minimum) / steps;
        Real cumulated = 0;
        if (c < 0.5) {
            // outer integral -> 1 for c -> 0
            // inner integral -> CumulativeNormal()(y) for c-> 0
            for (Real m = minimum; m < maximum; m += delta)
                for (Real z = minimum; z < (y - std::sqrt(c) * m) / std::sqrt (1. - c);
                     z += delta)
                    cumulated += dm (m) * dz (z);
        }
        else {
            // outer integral -> 1 for c -> 1
            // inner integral -> CumulativeNormal()(y) for c-> 1
            for (Real z = minimum; z < maximum; z += delta)
                for (Real m = minimum; m < (y - std::sqrt(1.0 - c) * z) / std::sqrt(c);
                     m += delta)
                    cumulated += dm (m) * dz (z);
        }
        cumulated *= (delta * delta);

        return cumulated;
    }
Ejemplo n.º 4
0
    void GaussianRandomDefaultModel::nextSequence(Real tmax) {
        const std::vector<Real>& values = rsg_.nextSequence().value;
        Real a = sqrt(copula_->correlation());
        for (Size j = 0; j < pool_->size(); j++) {
            const string name = pool_->names()[j];
            const Handle<DefaultProbabilityTermStructure>&
                dts = pool_->get(name).defaultProbability(defaultKeys_[j]);

            Real y = a * values[0] + sqrt(1-a*a) * values[j+1];
            Real p = CumulativeNormalDistribution()(y);

            if (dts->defaultProbability(tmax) < p)
                pool_->setTime(name, tmax+1);
            else
                pool_->setTime(name, Brent().solve(Root(dts,p),accuracy_,0,1));
        }
    }
    //-------------------------------------------------------------------------
    Real OneFactorStudentGaussianCopula::cumulativeYintegral (Real y) const {
    //-------------------------------------------------------------------------
        Real c = correlation_->value();

        if (c == 0)
            return CumulativeNormalDistribution()(y);

        if (c == 1)
            return CumulativeStudentDistribution(nm_)(y / scaleM_);


        StudentDistribution dm (nm_);
        NormalDistribution dz;

        // FIXME:
        // Find a sensitive way of setting these parameters,
        // e.g. depending on nm and nz, and the desired table range
        Real minimum = -10;
        Real maximum = +10;
        int steps = 400;

        Real delta = (maximum - minimum) / steps;
        Real cumulated = 0;

        if (c < 0.5) {
            // outer integral -> 1 for c -> 0
            // inner integral -> cumulativeNormal(y) for c-> 0
            for (Real m = minimum + delta/2; m < maximum; m += delta)
                for (Real z = minimum + delta/2;
                     z < (y - std::sqrt(c) * m) / std::sqrt (1. - c);
                     z += delta)
                    cumulated += dm (m / scaleM_) / scaleM_ * dz (z);
        }
        else {
            // outer integral -> 1 for c -> 1
            // inner integral -> cumulativeStudent(nm)(y) for c-> 1
            for (Real z = minimum + delta/2; z < maximum; z += delta)
                for (Real m = minimum + delta/2;
                     m < (y - std::sqrt(1.0 - c) * z) / std::sqrt(c);
                     m += delta)
                    cumulated += dm (m / scaleM_) / scaleM_ * dz (z);
        }

        return cumulated * delta * delta;
    }
Ejemplo n.º 6
0
    Disposable<Array> HestonSLVProcess::evolve(
        Time t0, const Array& x0, Time dt, const Array& dw) const {
        Array retVal(2);

        const Real ex = std::exp(-kappa_*dt);

        const Real m  =  theta_+(x0[1]-theta_)*ex;
        const Real s2 =  x0[1]*sigma_*sigma_*ex/kappa_*(1-ex)
                       + theta_*sigma_*sigma_/(2*kappa_)*(1-ex)*(1-ex);
        const Real psi = s2/(m*m);

        if (psi < 1.5) {
            const Real b2 = 2/psi-1+std::sqrt(2/psi*(2/psi-1));
            const Real b  = std::sqrt(b2);
            const Real a  = m/(1+b2);

            retVal[1] = a*(b+dw[1])*(b+dw[1]);
        }
        else {
            const Real p = (psi-1)/(psi+1);
            const Real beta = (1-p)/m;
            const Real u = CumulativeNormalDistribution()(dw[1]);

            retVal[1] = ((u <= p) ? 0.0 : std::log((1-p)/(1-u))/beta);
        }

        const Real mu = riskFreeRate()->forwardRate(t0, t0+dt, Continuous)
             - dividendYield()->forwardRate(t0, t0+dt, Continuous);

        const Real rho1 = std::sqrt(1-rho_*rho_);

        const Volatility l_0 = leverageFct_->localVol(t0, x0[0], true);
        const Real v_0 = 0.5*(x0[1]+retVal[1])*l_0*l_0;

        retVal[0] = x0[0]*std::exp(mu*dt - 0.5*v_0*dt
            + rho_/sigma_*l_0 * (
                  retVal[1] - kappa_*theta_*dt
                  + 0.5*(x0[1]+retVal[1])*kappa_*dt - x0[1])
            + rho1*std::sqrt(v_0*dt)*dw[0]);

        return retVal;
    }
Ejemplo n.º 7
0
    Real blackFormulaStdDevDerivative(Rate strike,
                                      Rate forward,
                                      Real stdDev,
                                      Real discount,
                                      Real displacement)
    {
        checkParameters(strike, forward, displacement);
        QL_REQUIRE(stdDev>=0.0,
                   "stdDev (" << stdDev << ") must be non-negative");
        QL_REQUIRE(discount>0.0,
                   "discount (" << discount << ") must be positive");

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

        if (stdDev==0.0 || strike==0.0)
            return 0.0;

        Real d1 = std::log(forward/strike)/stdDev + .5*stdDev;
        return discount * forward *
            CumulativeNormalDistribution().derivative(d1);
    }
Ejemplo n.º 8
0
namespace QuantLib {

    CumulativeNormalDistribution const GaussianLHPLossModel::phi_ = 
        CumulativeNormalDistribution();

    GaussianLHPLossModel::GaussianLHPLossModel(
            const Handle<Quote>& correlQuote,
            const std::vector<Handle<RecoveryRateQuote> >& quotes)
        : LatentModel<GaussianCopulaPolicy>(sqrt(correlQuote->value()),
            quotes.size(),
            //g++ complains default value not seen as typename
            GaussianCopulaPolicy::initTraits()),
          sqrt1minuscorrel_(std::sqrt(1.-correlQuote->value())),
          correl_(correlQuote),
          rrQuotes_(quotes), 
          beta_(sqrt(correlQuote->value())),
          biphi_(-sqrt(correlQuote->value()))
        {
            registerWith(correl_);
            for(Size i=0; i<quotes.size(); i++)
                registerWith(quotes[i]);
    }

    GaussianLHPLossModel::GaussianLHPLossModel(
            Real correlation,
            const std::vector<Real>& recoveries)
        : LatentModel<GaussianCopulaPolicy>(sqrt(correlation),
            recoveries.size(),
            //g++ complains default value not seen as typename
            GaussianCopulaPolicy::initTraits()),
          sqrt1minuscorrel_(std::sqrt(1.-correlation)),
          correl_(Handle<Quote>(boost::make_shared<SimpleQuote>(correlation))),
          beta_(sqrt(correlation)),
          biphi_(-sqrt(correlation))
        {
            for(Size i=0; i<recoveries.size(); i++)
                rrQuotes_.push_back(Handle<RecoveryRateQuote>(
                boost::make_shared<RecoveryRateQuote>(recoveries[i])));
        }

        GaussianLHPLossModel::GaussianLHPLossModel(
            const Handle<Quote>& correlQuote,
            const std::vector<Real>& recoveries)
        : LatentModel<GaussianCopulaPolicy>(sqrt(correlQuote->value()),
            recoveries.size(),
            //g++ complains default value not seen as typename
            GaussianCopulaPolicy::initTraits()),
          sqrt1minuscorrel_(std::sqrt(1.-correlQuote->value())),
          correl_(correlQuote),
          beta_(sqrt(correlQuote->value())),
          biphi_(-sqrt(correlQuote->value()))
        {
            registerWith(correl_);
            for(Size i=0; i<recoveries.size(); i++)
                rrQuotes_.push_back(Handle<RecoveryRateQuote>(
                boost::make_shared<RecoveryRateQuote>(recoveries[i])));
        }


        Real GaussianLHPLossModel::expectedTrancheLossImpl(
            Real remainingNot, // << at the given date 'd'
            Real prob, // << at the given date 'd'
            Real averageRR, // << at the given date 'd'
            // these are percentual values:
            Real attachLimit, Real detachLimit) const 
        {

            if (attachLimit >= detachLimit) return 0.;// or is it an error?
            // expected remaining notional:
            if (remainingNot == 0.) return 0.;

            const Real one = 1.0 - 1.0e-12;  // FIXME DUE TO THE INV CUMUL AT 1
            const Real k1 = std::min(one, attachLimit /(1.0 - averageRR)
                ) + QL_EPSILON;
            const Real k2 = std::min(one, detachLimit /(1.0 - averageRR)
                ) + QL_EPSILON;

            if (prob > 0) {
                const Real ip = InverseCumulativeNormal::standard_value(prob);
                const Real invFlightK1 = 
                    (ip-sqrt1minuscorrel_ * 
                        InverseCumulativeNormal::standard_value(k1))/beta_;
                const Real invFlightK2 = (ip-sqrt1minuscorrel_*
                    InverseCumulativeNormal::standard_value(k2))/beta_;

                return remainingNot * (detachLimit * phi_(invFlightK2) 
                    - attachLimit * phi_(invFlightK1) + (1.-averageRR) * 
                    (biphi_(ip, -invFlightK2) - biphi_(ip, -invFlightK1)) );
            }
            else return 0.0;
        }

        Real GaussianLHPLossModel::probOverLoss(const Date& d,
            Real remainingLossFraction) const {
            // these test goes into basket<<<<<<<<<<<<<<<<<<<<<<<<<
            QL_REQUIRE(remainingLossFraction >=0., "Incorrect loss fraction.");
            QL_REQUIRE(remainingLossFraction <=1., "Incorrect loss fraction.");

            Real remainingAttachAmount = basket_->remainingAttachmentAmount();
            Real remainingDetachAmount = basket_->remainingDetachmentAmount();
            // live unerlying portfolio loss fraction (remaining portf fraction)

            const Real remainingBasktNot = basket_->remainingNotional(d);
            const Real attach = 
                std::min(remainingAttachAmount / remainingBasktNot, 1.);
            const Real detach = 
                std::min(remainingDetachAmount / remainingBasktNot, 1.);

            Real portfFract = 
                attach + remainingLossFraction * (detach - attach);

            Real averageRR = averageRecovery(d);
            Real maxAttLossFract = (1.-averageRR);
            if(portfFract > maxAttLossFract) return 0.;

            // for non-equity losses add the probability jump at zero tranche 
            //   losses (since this method returns prob of losing more or 
            //   equal to)
            if(portfFract <= QL_EPSILON) return 1.;

            Probability prob = averageProb(d);

            Real ip = InverseCumulativeNormal::standard_value(prob);
            Real invFlightK = (ip-sqrt1minuscorrel_*
                InverseCumulativeNormal::standard_value(portfFract
                    /(1.-averageRR)))/beta_;

            return  phi_(invFlightK);//probOver
        }

        Real GaussianLHPLossModel::expectedShortfall(const Date& d, 
            Probability perctl) const 
        {
            // loss as a fraction of the live portfolio
            Real ptflLossPerc = percentilePortfolioLossFraction(d, perctl);
            Real remainingAttachAmount = basket_->remainingAttachmentAmount();
            Real remainingDetachAmount = basket_->remainingDetachmentAmount();

            const Real remainingNot = basket_->remainingNotional(d);
            const Real attach = 
                std::min(remainingAttachAmount / remainingNot, 1.);
            const Real detach = 
                std::min(remainingDetachAmount / remainingNot, 1.);

            if(ptflLossPerc >= detach-QL_EPSILON) 
                return remainingNot * (detach-attach);//equivalent

            Real maxLossLevel = std::max(attach, ptflLossPerc);
            Probability prob = averageProb(d);
            Real averageRR = averageRecovery(d);

            Real valA = expectedTrancheLossImpl(remainingNot, prob, 
                averageRR, maxLossLevel, detach);
            Real valB = // probOverLoss(d, maxLossLevel);//in live tranche units
            // from fraction of basket notional to fraction of tranche notional
                probOverLoss(d, std::min(std::max((maxLossLevel - attach)
                /(detach - attach), 0.), 1.));
            return ( valA + (maxLossLevel - attach) * remainingNot * valB )
                / (1.-perctl);
        }

        Real GaussianLHPLossModel::percentilePortfolioLossFraction(
            const Date& d, Real perctl) const 
        {
            // this test goes into basket<<<<<<<<<<<<<<<<<<<<<<<<<
            QL_REQUIRE(perctl >= 0. && perctl <=1., 
                "Percentile argument out of bounds.");

            if(perctl==0.) return 0.;// portfl == attach
            if(perctl==1.) perctl = 1. - QL_EPSILON; // portfl == detach

            return (1.-averageRecovery(d)) * 
                phi_( ( InverseCumulativeNormal::standard_value(averageProb(d))
                    + beta_ * InverseCumulativeNormal::standard_value(perctl) )
                        /sqrt1minuscorrel_);
        }

}
Ejemplo n.º 9
0
    Disposable<Array> HestonDupireProcess::evolve(Time t0, const Array& x0,
                                            Time dt, const Array& dw) const 
	{
        Array retVal(2);
        Real mu;

        const Real sdt = std::sqrt(dt);
        const Real sqrhov = std::sqrt(1.0 - rho_*rho_);

		Real leverageVal = leverSurf_->localVol(t0, x0[0]);;

        switch (discretization_) 
		{
          case QuadraticExponential:
          {
            // for details of the quadratic exponential discretization scheme
            // see Leif Andersen,
            // Efficient Simulation of the Heston Stochastic Volatility Model
		    // For local freezing of lsv leverage
		    // see Anthonie W Van der Stoep
		    // The heston stochastic local volatility model: efficient monte carlo simulation
            const Real ex = std::exp(-kappa_*dt);

            const Real m  =  theta_+(x0[1]-theta_)*ex;
            const Real s2 =  x0[1]*sigma_*sigma_*ex/kappa_*(1-ex)
                           + theta_*sigma_*sigma_/(2*kappa_)*(1-ex)*(1-ex);
            const Real psi = s2/(m*m);

            const Real g1 =  0.5;
            const Real g2 =  0.5;
                  Real k0 = -rho_*kappa_*theta_*dt/sigma_;
            const Real k1 =  g1*dt*(kappa_*rho_/sigma_-0.5)-rho_/sigma_;
            const Real k2 =  g2*dt*(kappa_*rho_/sigma_-0.5)+rho_/sigma_;
            const Real k3 =  g1*dt*(1-rho_*rho_);
            const Real k4 =  g2*dt*(1-rho_*rho_);
            const Real A  =  k2+0.5*k4;

            if (psi < 1.5) 
			{
                const Real b2 = 2/psi-1+std::sqrt(2/psi*(2/psi-1));
                const Real b  = std::sqrt(b2);
                const Real a  = m/(1+b2);

                retVal[1] = a*(b+dw[1])*(b+dw[1]);
            }
            else 
			{
                const Real p = (psi-1)/(psi+1);
                const Real beta = (1-p)/m;

                const Real u = CumulativeNormalDistribution()(dw[1]);

                retVal[1] = ((u <= p) ? 0.0 : std::log((1-p)/(1-u))/beta);
            }

            mu =   riskFreeRate_->forwardRate(t0, t0+dt, Continuous)
                 - dividendYield_->forwardRate(t0, t0+dt, Continuous);

			// local freezing part
			double c0 = leverageVal*leverageVal*x0[1]*dt;
			double k5 = rho_*(retVal[1]-x0[1]+kappa_*dt*x0[1]-kappa_*dt*theta_)/sigma_;

            retVal[0] = x0[0]*std::exp(mu*dt - 0.5*c0 + k5 + sqrhov*sqrt(c0)*dw[0]);
          }
          break;
          default:
            QL_FAIL("unknown discretization schema");
        }

        return retVal;
    }
Ejemplo n.º 10
0
 Real BSMRNDCalculator::cdf(Real x, Time t) const {
     std::pair<Real, Volatility> p = distributionParams(x, t);
     return CumulativeNormalDistribution(p.first, p.second)(x);
 }