예제 #1
0
FirstDerivativeOp::FirstDerivativeOp(
    Size direction,
    const boost::shared_ptr<FdmMesher>& mesher)
    : TripleBandLinearOp(direction, mesher) {

    const boost::shared_ptr<FdmLinearOpLayout> layout = mesher->layout();
    const FdmLinearOpIterator endIter = layout->end();

    for (FdmLinearOpIterator iter = layout->begin(); iter!=endIter; ++iter) {
        const Size i = iter.index();
        const Real hm = mesher->dminus(iter, direction_);
        const Real hp = mesher->dplus(iter, direction_);

        const Real zetam1 = hm*(hm+hp);
        const Real zeta0  = hm*hp;
        const Real zetap1 = hp*(hm+hp);

        if (iter.coordinates()[direction_] == 0) {
            //upwinding scheme
            lower_[i] = 0.0;
            diag_[i]  = -(upper_[i] = 1/hp);
        }
        else if (   iter.coordinates()[direction_]
                    == layout->dim()[direction]-1) {
            // downwinding scheme
            lower_[i] = -(diag_[i] = 1/hm);
            upper_[i] = 0.0;
        }
        else {
            lower_[i] = -hp/zetam1;
            diag_[i]  = (hp-hm)/zeta0;
            upper_[i] = hm/zetap1;
        }
    }
}
    FdmHestonHullWhiteEquityPart::FdmHestonHullWhiteEquityPart(
        const boost::shared_ptr<FdmMesher>& mesher,
        const boost::shared_ptr<HullWhite>& hwModel,
        const boost::shared_ptr<YieldTermStructure>& qTS)
    : x_(mesher->locations(2)),
      varianceValues_(0.5*mesher->locations(1)),
      dxMap_ (FirstDerivativeOp(0, mesher)),
      dxxMap_(SecondDerivativeOp(0, mesher).mult(0.5*mesher->locations(1))),
      mapT_   (0, mesher),
      hwModel_(hwModel),
      mesher_ (mesher),
      qTS_(qTS) {

        // on the boundary s_min and s_max the second derivative
        // d²V/dS² is zero and due to Ito's Lemma the variance term
        // in the drift should vanish.
        const boost::shared_ptr<FdmLinearOpLayout> layout = mesher_->layout();
        const FdmLinearOpIterator endIter = layout->end();
        for (FdmLinearOpIterator iter = layout->begin(); iter != endIter;
            ++iter) {
            if (   iter.coordinates()[0] == 0
                || iter.coordinates()[0] == layout->dim()[0]-1) {
                varianceValues_[iter.index()] = 0.0;
            }
        }
        volatilityValues_ = Sqrt(2*varianceValues_);
    }
예제 #3
0
    Size FdmLinearOpLayout::neighbourhood(const FdmLinearOpIterator& iterator,
                                          Size i1, Integer offset1,
                                          Size i2, Integer offset2) const {

        Size myIndex = iterator.index()
            - iterator.coordinates()[i1]*spacing_[i1]
            - iterator.coordinates()[i2]*spacing_[i2];

        Integer coorOffset1 = Integer(iterator.coordinates()[i1])+offset1;
        if (coorOffset1 < 0) {
            coorOffset1=-coorOffset1;
        }
        else if (Size(coorOffset1) >= dim_[i1]) {
            coorOffset1 = 2*(dim_[i1]-1) - coorOffset1;
        }

        Integer coorOffset2 = Integer(iterator.coordinates()[i2])+offset2;
        if (coorOffset2 < 0) {
            coorOffset2=-coorOffset2;
        }
        else if (Size(coorOffset2) >= dim_[i2]) {
            coorOffset2 = 2*(dim_[i2]-1) - coorOffset2;
        }

        return myIndex + coorOffset1*spacing_[i1]+coorOffset2*spacing_[i2];
    }
예제 #4
0
    FdmHestonFwdOp::FdmHestonFwdOp(
            const boost::shared_ptr<FdmMesher>& mesher,
            const boost::shared_ptr<HestonProcess>& process)
    : kappa_(process->kappa()),
      theta_(process->theta()),
      sigma_(process->sigma()),
      rho_  (process->rho()),
      v0_   (process->v0()),
      rTS_  (process->riskFreeRate().currentLink()),
      qTS_  (process->dividendYield().currentLink()),
      varianceValues_(0.5*mesher->locations(1)),
      dxMap_ (new FirstDerivativeOp(0, mesher)),
      dxxMap_(new ModTripleBandLinearOp(TripleBandLinearOp(
          SecondDerivativeOp(0, mesher).mult(0.5*mesher->locations(1))))),
      mapX_  (new TripleBandLinearOp(0, mesher)),
      mapY_  (new FdmSquareRootFwdOp(mesher,kappa_,theta_,sigma_, 1)),
      correlation_(new NinePointLinearOp(
          SecondOrderMixedDerivativeOp(0, 1, mesher)
              .mult(rho_*sigma_*mesher->locations(1))))
    {
        const boost::shared_ptr<FdmLinearOpLayout> layout = mesher->layout();

        // zero flux boundary condition
        const Size n = layout->dim()[1];
        const Real alpha = 2*rho_*mapY_->v(0)/sigma_*mapY_->f0();
        const Real beta  = 2*rho_*mapY_->v(n)/sigma_*mapY_->f1();
        ModTripleBandLinearOp fDx(FirstDerivativeOp(0, mesher));

        const FdmLinearOpIterator endIter = layout->end();
        for (FdmLinearOpIterator iter = layout->begin(); iter != endIter;
                ++iter) {
            if (iter.coordinates()[1] == 0) {
                const Size idx = iter.index();

                dxxMap_->upper()[idx]+= alpha*fDx.upper()[idx];
                dxxMap_->diag()[idx] += alpha*fDx.diag()[idx];
                dxxMap_->lower()[idx] += alpha*fDx.lower()[idx];
            }
            else if (iter.coordinates()[1] == n-1) {
                const Size idx = iter.index();

                dxxMap_->upper()[idx]+= beta*fDx.upper()[idx];
                dxxMap_->diag()[idx] += beta*fDx.diag()[idx];
                dxxMap_->lower()[idx] += beta*fDx.lower()[idx];
            }
        }
    }
	void FdmRAStepCondition::applyTo(Array& a, Time t) const {
		if (std::find(accrualTimes_.begin(), accrualTimes_.end(), t) != accrualTimes_.end()) {			
			boost::shared_ptr<FdmLinearOpLayout> layout = mesher_->layout();
			const FdmLinearOpIterator endIter = layout->end();
			for (FdmLinearOpIterator iter = layout->begin(); iter != endIter; ++iter) {
				a[iter.index()] += calculator_->innerValue(iter, t);
			}
		}
	}
예제 #6
0
Disposable<Array> FdmExtOUJumpOp::integro(const Array& r) const {
    Array integral(r.size());
    const boost::shared_ptr<FdmLinearOpLayout> layout = mesher_->layout();
    const Size extraDims=layout->size()/(layout->dim()[0]*layout->dim()[1]);

    std::vector<Array>  y(extraDims, Array(layout->dim()[1]));
    std::vector<Matrix> f(extraDims,
                          Matrix(layout->dim()[1], layout->dim()[0]));

    const FdmLinearOpIterator endIter = layout->end();
    for (FdmLinearOpIterator iter = layout->begin(); iter != endIter;
            ++iter) {
        const Size i = iter.coordinates()[0];
        const Size j = iter.coordinates()[1];
        const Size k = iter.index() / (layout->dim()[0]*layout->dim()[1]);

        y[k][j]    = mesher_->location(iter, 1);
        f[k][j][i] = r[iter.index()];
    }
    std::vector<std::vector<boost::shared_ptr<LinearInterpolation> > >
    interpl(extraDims, std::vector<
            boost::shared_ptr<LinearInterpolation> >(f[0].columns()));

    for (Size k=0; k < extraDims; ++k) {
        for (Size i=0; i < f[k].columns(); ++i) {
            interpl[k][i] = boost::shared_ptr<LinearInterpolation>(
                                new LinearInterpolation(y[k].begin(), y[k].end(),
                                        f[k].column_begin(i)));
        }
    }

    const Real eta = process_->eta();

    for (FdmLinearOpIterator iter=layout->begin(); iter!=endIter; ++iter) {
        const Size i = iter.coordinates()[0];
        const Size j = iter.coordinates()[1];
        const Size k = iter.index() / (layout->dim()[0]*layout->dim()[1]);

        integral[iter.index()] = gaussLaguerreIntegration_(
                                     IntegroIntegrand(interpl[k][i], bcSet_, y[k][j], eta));
    }

    return process_->jumpIntensity()*(integral-r);
}
예제 #7
0
    Disposable<Array> UniformGridMesher::locations(Size d) const {
        Array retVal(layout_->size());

        const FdmLinearOpIterator endIter = layout_->end();
        for (FdmLinearOpIterator iter = layout_->begin();
            iter != endIter; ++iter) {
            retVal[iter.index()] = locations_[d][iter.coordinates()[d]];
        }

        return retVal;
    }
예제 #8
0
    Disposable<Array> FdmMesherComposite::locations(Size direction) const {
        Array retVal(layout_->size());

        const FdmLinearOpIterator endIter = layout_->end();
        for (FdmLinearOpIterator iter = layout_->begin();
             iter != endIter; ++iter) {
            retVal[iter.index()] =
                mesher_[direction]->locations()[iter.coordinates()[direction]];
        }

        return retVal;
    }
예제 #9
0
    Size FdmLinearOpLayout::neighbourhood(const FdmLinearOpIterator& iterator,
                                          Size i, Integer offset) const {
        Size myIndex = iterator.index()
            - iterator.coordinates()[i]*spacing_[i];

        Integer coorOffset = Integer(iterator.coordinates()[i])+offset;
        if (coorOffset < 0) {
            coorOffset=-coorOffset;
        }
        else if (Size(coorOffset) >= dim_[i]) {
            coorOffset = 2*(dim_[i]-1) - coorOffset;
        }
        return myIndex + coorOffset*spacing_[i];
    }
    void FdmExtendedOrnsteinUhlenbackOp::setTime(Time t1, Time t2) {
        const Rate r = rTS_->forwardRate(t1, t2, Continuous).rate();

        const boost::shared_ptr<FdmLinearOpLayout> layout=mesher_->layout();
        const FdmLinearOpIterator endIter = layout->end();

        Array drift(layout->size());
        for (FdmLinearOpIterator iter = layout->begin();
             iter!=endIter; ++iter) {
            const Size i = iter.index();
            drift[i] = process_->drift(0.5*(t1+t2), x_[i]);
        }
        mapX_.axpyb(drift, dxMap_, dxxMap_, Array(1, -r));
    }
예제 #11
0
    FdmHestonSolver::FdmHestonSolver(
        const Handle<HestonProcess>& process,
        const boost::shared_ptr<FdmMesher>& mesher,
        const FdmBoundaryConditionSet& bcSet,
        const boost::shared_ptr<FdmStepConditionComposite> & condition,
        const boost::shared_ptr<FdmInnerValueCalculator>& calculator,
        const Time maturity,
        const Size timeSteps,
        Size dampingSteps,
        FdmBackwardSolver::FdmSchemeType schemeType,
        Real theta, Real mu,
        const Handle<FdmQuantoHelper>& quantoHelper)
    : process_(process),
      mesher_(mesher),
      bcSet_(bcSet),
      thetaCondition_(new FdmSnapshotCondition(
        0.99*std::min(1.0/365.0,
                      condition->stoppingTimes().empty() ? maturity :
                                 condition->stoppingTimes().front()))),
      condition_(addCondition(thetaCondition_, condition)),
      maturity_(maturity),
      timeSteps_(timeSteps),
      dampingSteps_(dampingSteps),
      schemeType_(schemeType),
      theta_(theta),
      mu_(mu),
      quantoHelper_(quantoHelper),
      initialValues_(mesher->layout()->size()),
      resultValues_(mesher->layout()->dim()[1], mesher->layout()->dim()[0]) {
        registerWith(process_);
        registerWith(quantoHelper_);

        x_.reserve(mesher->layout()->dim()[0]);
        v_.reserve(mesher->layout()->dim()[1]);

        const boost::shared_ptr<FdmLinearOpLayout> layout = mesher->layout();
        const FdmLinearOpIterator endIter = layout->end();
        for (FdmLinearOpIterator iter = layout->begin(); iter != endIter;
             ++iter) {
            initialValues_[iter.index()] = calculator->avgInnerValue(iter);

            if (!iter.coordinates()[1]) {
                x_.push_back(mesher->location(iter, 0));
            }
            if (!iter.coordinates()[0]) {
                v_.push_back(mesher->location(iter, 1));
            }
        }
    }
예제 #12
0
    void Fdm2dBlackScholesOp::setTime(Time t1, Time t2) {
        opX_.setTime(t1, t2);
        opY_.setTime(t1, t2);
        
        if (localVol1_) {
            const boost::shared_ptr<FdmLinearOpLayout> layout=mesher_->layout();
            const FdmLinearOpIterator endIter = layout->end();

            Array vol1(layout->size()), vol2(layout->size());
            for (FdmLinearOpIterator iter = layout->begin();
                 iter!=endIter; ++iter) {
                const Size i = iter.index();

                if (illegalLocalVolOverwrite_ < 0.0) {
                    vol1[i] = localVol1_->localVol(0.5*(t1+t2), x_[i], true);
                    vol2[i] = localVol2_->localVol(0.5*(t1+t2), y_[i], true);
                }
                else {
                    try {
                        vol1[i] = localVol1_->localVol(0.5*(t1+t2), x_[i],true);
                    } catch (Error&) {
                        vol1[i] = illegalLocalVolOverwrite_;
                    }
                    try {
                        vol2[i] = localVol2_->localVol(0.5*(t1+t2), y_[i],true);
                    } catch (Error&) {
                        vol2[i] = illegalLocalVolOverwrite_;
                    }

                }
            }
            corrMapT_ = corrMapTemplate_.mult(vol1*vol2);
        }
        else {
            const Real vol1 = p1_
                    ->blackVolatility()->blackForwardVol(t1, t2, p1_->x0());
    
            const Real vol2 = p2_
                    ->blackVolatility()->blackForwardVol(t1, t2, p2_->x0());
            
            corrMapT_ = corrMapTemplate_
                      .mult(Array(mesher_->layout()->size(), vol1*vol2));
        }
        
        currentForwardRate_ = p1_->riskFreeRate()
                                 ->forwardRate(t1, t2, Continuous).rate();
    }
예제 #13
0
    template <Size N> inline
    FdmNdimSolver<N>::FdmNdimSolver(
                        const FdmSolverDesc& solverDesc,
                        const FdmSchemeDesc& schemeDesc,
                        const boost::shared_ptr<FdmLinearOpComposite>& op)
    : solverDesc_(solverDesc),
      schemeDesc_(schemeDesc),
      op_(op),
      thetaCondition_(new FdmSnapshotCondition(
        0.99*std::min(1.0/365.0,
                solverDesc.condition->stoppingTimes().empty()
                ? solverDesc.maturity :
                  solverDesc.condition->stoppingTimes().front()))),
      conditions_(FdmStepConditionComposite::joinConditions(thetaCondition_,
                                                        solverDesc.condition)),
      x_            (solverDesc.mesher->layout()->dim().size()),
      initialValues_(solverDesc.mesher->layout()->size()),
      extrapolation_(std::vector<bool>(N, true)) {

        const boost::shared_ptr<FdmMesher> mesher = solverDesc.mesher;
        const boost::shared_ptr<FdmLinearOpLayout> layout = mesher->layout();

        QL_REQUIRE(layout->dim().size() == N, "solver dim " << N
                    << "does not fit to layout dim " << layout->size());

        for (Size i=0; i < N; ++i) {
            x_[i].reserve(layout->dim()[i]);
        }

        const FdmLinearOpIterator endIter = layout->end();
        for (FdmLinearOpIterator iter = layout->begin(); iter != endIter;
             ++iter) {

            initialValues_[iter.index()] = solverDesc_.calculator
                                ->avgInnerValue(iter, solverDesc.maturity);

            const std::vector<Size>& c = iter.coordinates();
            for (Size i=0; i < N; ++i) {
                if (!(std::accumulate(c.begin(), c.end(), 0)-c[i])) {
                    x_[i].push_back(mesher->location(iter, i));
                }
            }
        }

        f_ = boost::shared_ptr<data_table>(new data_table(x_));
    }
예제 #14
0
    Fdm3DimSolver::Fdm3DimSolver(
                        const FdmSolverDesc& solverDesc,
                        const FdmSchemeDesc& schemeDesc,
                        const boost::shared_ptr<FdmLinearOpComposite>& op)
    : solverDesc_(solverDesc),
      schemeDesc_(schemeDesc),
      op_(op),
      thetaCondition_(boost::make_shared<FdmSnapshotCondition>(
        0.99*std::min(1.0/365.0,
                solverDesc.condition->stoppingTimes().empty()
                ? solverDesc.maturity :
                  solverDesc.condition->stoppingTimes().front()))),
      conditions_(FdmStepConditionComposite::joinConditions(thetaCondition_,
                                                         solverDesc.condition)),
      initialValues_(solverDesc.mesher->layout()->size()),
      resultValues_ (solverDesc.mesher->layout()->dim()[2],
                     Matrix(solverDesc.mesher->layout()->dim()[1],
                            solverDesc.mesher->layout()->dim()[0])),
      interpolation_(solverDesc.mesher->layout()->dim()[2]) {

        const boost::shared_ptr<FdmMesher> mesher = solverDesc.mesher;
        const boost::shared_ptr<FdmLinearOpLayout> layout = mesher->layout();

        x_.reserve(layout->dim()[0]);
        y_.reserve(layout->dim()[1]);
        z_.reserve(layout->dim()[2]);

        const FdmLinearOpIterator endIter = layout->end();
        for (FdmLinearOpIterator iter = layout->begin(); iter != endIter;
             ++iter) {
            initialValues_[iter.index()]
               = solverDesc.calculator->avgInnerValue(iter,
                                                      solverDesc.maturity);


            if (!iter.coordinates()[1] && !iter.coordinates()[2]) {
                x_.push_back(mesher->location(iter, 0));
            }
            if (!iter.coordinates()[0] && !iter.coordinates()[2]) {
                y_.push_back(mesher->location(iter, 1));
            }
            if (!iter.coordinates()[0] && !iter.coordinates()[1]) {
                z_.push_back(mesher->location(iter, 2));
            }
        }
    }
예제 #15
0
    NinePointLinearOp::NinePointLinearOp(
        Size d0, Size d1,
        const boost::shared_ptr<FdmMesher>& mesher)
    : d0_(d0), d1_(d1),
      i00_(new Size[mesher->layout()->size()]),
      i10_(new Size[mesher->layout()->size()]),
      i20_(new Size[mesher->layout()->size()]),
      i01_(new Size[mesher->layout()->size()]),
      i21_(new Size[mesher->layout()->size()]),
      i02_(new Size[mesher->layout()->size()]),
      i12_(new Size[mesher->layout()->size()]),
      i22_(new Size[mesher->layout()->size()]),
      a00_(new Real[mesher->layout()->size()]),
      a10_(new Real[mesher->layout()->size()]),
      a20_(new Real[mesher->layout()->size()]),
      a01_(new Real[mesher->layout()->size()]),
      a11_(new Real[mesher->layout()->size()]),
      a21_(new Real[mesher->layout()->size()]),
      a02_(new Real[mesher->layout()->size()]),
      a12_(new Real[mesher->layout()->size()]),
      a22_(new Real[mesher->layout()->size()]),
      mesher_(mesher) {

        QL_REQUIRE(   d0_ != d1_
            && d0_ < mesher->layout()->dim().size()
            && d1_ < mesher->layout()->dim().size(),
            "inconsistent derivative directions");

        const boost::shared_ptr<FdmLinearOpLayout> layout = mesher->layout();
        const FdmLinearOpIterator endIter = layout->end();

        for (FdmLinearOpIterator iter = layout->begin(); iter!=endIter; ++iter) {
            const Size i = iter.index();

            i10_[i] = layout->neighbourhood(iter, d1_, -1);
            i01_[i] = layout->neighbourhood(iter, d0_, -1);
            i21_[i] = layout->neighbourhood(iter, d0_,  1);
            i12_[i] = layout->neighbourhood(iter, d1_,  1);
            i00_[i] = layout->neighbourhood(iter, d0_, -1, d1_, -1);
            i20_[i] = layout->neighbourhood(iter, d0_,  1, d1_, -1);
            i02_[i] = layout->neighbourhood(iter, d0_, -1, d1_,  1);
            i22_[i] = layout->neighbourhood(iter, d0_,  1, d1_,  1);
        }
    }
예제 #16
0
	void FdmAutocallStepCondition::applyTo(Array& a, Time t) const {
		if (std::find(exerciseTimes_.begin(), exerciseTimes_.end(), t) != exerciseTimes_.end()) {

			boost::shared_ptr<FdmLinearOpLayout> layout = mesher_->layout();
			const FdmLinearOpIterator endIter = layout->end();

			const Size dims = layout->dim().size();
			Array locations(dims);
			for (FdmLinearOpIterator iter = layout->begin(); iter != endIter; ++iter) {
				for (Size i = 0; i < dims; ++i)
					locations[i] = std::exp(mesher_->location(iter, i));				
				if ((*condition_)(locations)) {
					Real innerValue = calculator_->innerValue(iter, t);
					a[iter.index()] = innerValue;
				}
			}

		}
	}
예제 #17
0
    template <Size N> inline
    Real FdmNdimSolver<N>::thetaAt(const std::vector<Real>& x) const {
        QL_REQUIRE(conditions_->stoppingTimes().front() > 0.0,
                   "stopping time at zero-> can't calculate theta");
        calculate();
        const Array& rhs = thetaCondition_->getValues();
        const boost::shared_ptr<FdmLinearOpLayout> layout
                                            = solverDesc_.mesher->layout();

        data_table f(x_);

        const FdmLinearOpIterator endIter = layout->end();
        for (FdmLinearOpIterator iter = layout->begin(); iter != endIter;
             ++iter) {
            setValue(f, iter.coordinates(), rhs[iter.index()]);
        }

        return (MultiCubicSpline<N>(x_, f)(x)
                        - interpolateAt(x)) / thetaCondition_->getTime();
    }
예제 #18
0
    template <Size N> inline
    void FdmNdimSolver<N>::performCalculations() const {
        Array rhs(initialValues_.size());
        std::copy(initialValues_.begin(), initialValues_.end(), rhs.begin());

        FdmBackwardSolver(op_, solverDesc_.bcSet, conditions_, schemeDesc_)
                 .rollback(rhs, solverDesc_.maturity, 0.0,
                           solverDesc_.timeSteps, solverDesc_.dampingSteps);

        const boost::shared_ptr<FdmLinearOpLayout> layout
                                               = solverDesc_.mesher->layout();

        const FdmLinearOpIterator endIter = layout->end();
        for (FdmLinearOpIterator iter = layout->begin(); iter != endIter;
             ++iter) {
            setValue(*f_, iter.coordinates(), rhs[iter.index()]);
        }

        interp_ = boost::shared_ptr<MultiCubicSpline<N> >(
            new MultiCubicSpline<N>(x_, *f_, extrapolation_));
    }
예제 #19
0
void FdmBlackScholesOp::setTime(Time t1, Time t2) {
    const Rate r = rTS_->forwardRate(t1, t2, Continuous).rate();
    const Rate q = qTS_->forwardRate(t1, t2, Continuous).rate();

    if (localVol_) {
        const boost::shared_ptr<FdmLinearOpLayout> layout=mesher_->layout();
        const FdmLinearOpIterator endIter = layout->end();

        Array v(layout->size());
        for (FdmLinearOpIterator iter = layout->begin();
                iter!=endIter; ++iter) {
            const Size i = iter.index();

            if (illegalLocalVolOverwrite_ < 0.0) {
                v[i] = square<Real>()(
                           localVol_->localVol(0.5*(t1+t2), x_[i], true));
            }
            else {
                try {
                    v[i] = square<Real>()(
                               localVol_->localVol(0.5*(t1+t2), x_[i], true));
                } catch (Error&) {
                    v[i] = square<Real>()(illegalLocalVolOverwrite_);
                }

            }
        }
        mapT_.axpyb(r - q - 0.5*v, dxMap_,
                    dxxMap_.mult(0.5*v), Array(1, -r));
    }
    else {
        const Real v
            = volTS_->blackForwardVariance(t1, t2, strike_)/(t2-t1);
        mapT_.axpyb(Array(1, r - q - 0.5*v), dxMap_,
                    dxxMap_.mult(0.5*Array(mesher_->layout()->size(), v)),
                    Array(1, -r));
    }
}
예제 #20
0
    FdmDirichletBoundary::FdmDirichletBoundary(
                            const boost::shared_ptr<FdmMesher>& mesher,
                            Real valueOnBoundary, Size direction,
                            FdmDirichletBoundary::Side side)
    : side_(side),
      valueOnBoundary_(valueOnBoundary) {
                                
        const boost::shared_ptr<FdmLinearOpLayout> layout = mesher->layout();
                                
        std::vector<Size> newDim(layout->dim());
        newDim[direction] = 1;
        const Size hyperSize = std::accumulate(newDim.begin(), newDim.end(),
                                               Size(1), std::multiplies<Size>());
        indicies_.resize(hyperSize);

        Size i=0;
        const FdmLinearOpIterator endIter = layout->end();
        for (FdmLinearOpIterator iter = layout->begin(); iter != endIter;
            ++iter) {
            if (   (side == Lower && iter.coordinates()[direction] == 0)
                || (side == Upper && iter.coordinates()[direction] 
                                            == layout->dim()[direction]-1)) {

                QL_REQUIRE(hyperSize > i, "index missmatch");
                indicies_[i++] = iter.index();
            }
        }
        
        if (side_ == Lower) {
            xExtreme_ = mesher->locations(direction)[0];
        }
        else if (side_ == Upper) {
            xExtreme_ 
                = mesher->locations(direction)[layout->dim()[direction]-1];
        }
    }
예제 #21
0
    Disposable<Array> FdmBatesOp::integro(const Array& r) const {
        const shared_ptr<FdmLinearOpLayout> layout = mesher_->layout();
        
        QL_REQUIRE(layout->dim().size() == 2, "invalid layout dimension");

        Array x(layout->dim()[0]);
        Matrix f(layout->dim()[1], layout->dim()[0]);
        
        const FdmLinearOpIterator endIter = layout->end();
        for (FdmLinearOpIterator iter = layout->begin(); iter != endIter;
            ++iter) {
            const Size i = iter.coordinates()[0];
            const Size j = iter.coordinates()[1];
            
            x[i]    = mesher_->location(iter, 0);
            f[j][i] = r[iter.index()];
            
        }
        std::vector<shared_ptr<LinearInterpolation> > interpl(f.rows());
        for (Size i=0; i < f.rows(); ++i) {
            interpl[i] = shared_ptr<LinearInterpolation>(
                new LinearInterpolation(x.begin(), x.end(), f.row_begin(i)));
        }
        
        Array integral(r.size());
        for (FdmLinearOpIterator iter=layout->begin(); iter!=endIter; ++iter) {
            const Size i = iter.coordinates()[0];
            const Size j = iter.coordinates()[1];

            integral[iter.index()] = M_1_SQRTPI* 
                gaussHermiteIntegration_(
                      IntegroIntegrand(interpl[j], bcSet_, x[i], delta_, nu_));
        }

        return lambda_*(integral-r);
    }
예제 #22
0
FdmExtOUJumpOp::FdmExtOUJumpOp(
    const boost::shared_ptr<FdmMesher>& mesher,
    const boost::shared_ptr<ExtOUWithJumpsProcess>& process,
    const boost::shared_ptr<YieldTermStructure>& rTS,
    const FdmBoundaryConditionSet& bcSet,
    Size integroIntegrationOrder)
    : mesher_ (mesher),
      process_(process),
      rTS_    (rTS),
      bcSet_  (bcSet),
      gaussLaguerreIntegration_(integroIntegrationOrder),
      x_      (mesher->locations(0)),
      ouOp_   (new FdmExtendedOrnsteinUhlenbackOp(
                   mesher,
                   process->getExtendedOrnsteinUhlenbeckProcess(), rTS, bcSet)),
      dyMap_  (FirstDerivativeOp(1, mesher)
               .mult(-process->beta()*mesher->locations(1)))
{
#if !defined(QL_NO_UBLAS_SUPPORT)
    const Real eta     = process_->eta();
    const Real lambda  = process_->jumpIntensity();

    const Array yInt   = gaussLaguerreIntegration_.x();
    const Array weights= gaussLaguerreIntegration_.weights();

    integroPart_ = SparseMatrix(mesher_->layout()->size(),
                                mesher_->layout()->size());

    const boost::shared_ptr<FdmLinearOpLayout> layout = mesher_->layout();
    const FdmLinearOpIterator endIter = layout->end();

    Array yLoc(mesher_->layout()->dim()[1]);
    for (FdmLinearOpIterator iter = layout->begin(); iter != endIter;
            ++iter) {
        yLoc[iter.coordinates()[1]] = mesher_->location(iter, 1);
    }

    for (FdmLinearOpIterator iter = layout->begin(); iter != endIter;
            ++iter) {

        const Size diag = iter.index();
        integroPart_(diag, diag) -= lambda;

        const Real y = mesher_->location(iter, 1);
        const Integer yIndex = iter.coordinates()[1];

        for (Size i=0; i < yInt.size(); ++i) {
            const Real weight = std::exp(-yInt[i])*weights[i];

            const Real ys = y + yInt[i]/eta;
            const Integer l = (ys > yLoc.back()) ? yLoc.size()-2
                              : std::upper_bound(yLoc.begin(),
                                                 yLoc.end()-1, ys) - yLoc.begin()-1;

            const Real s = (ys-yLoc[l])/(yLoc[l+1]-yLoc[l]);
            integroPart_(diag, layout->neighbourhood(iter, 1, l-yIndex))
            += weight*lambda*(1-s);
            integroPart_(diag, layout->neighbourhood(iter, 1, l+1-yIndex))
            += weight*lambda*s;
        }
    }
#endif
}
    SecondOrderMixedDerivativeOp::SecondOrderMixedDerivativeOp(
        Size d0, Size d1,
        const boost::shared_ptr<FdmMesher>& mesher)
    : NinePointLinearOp(d0, d1, mesher) {

        const boost::shared_ptr<FdmLinearOpLayout> layout = mesher->layout();
        const FdmLinearOpIterator endIter = layout->end();

        for (FdmLinearOpIterator iter = layout->begin(); iter!=endIter; ++iter) {
            const Size i = iter.index();
            const Real hm_d0 = mesher->dminus(iter, d0_);
            const Real hp_d0 = mesher->dplus(iter, d0_);
            const Real hm_d1 = mesher->dminus(iter, d1_);
            const Real hp_d1 = mesher->dplus(iter, d1_);

            const Real zetam1 = hm_d0*(hm_d0+hp_d0);
            const Real zeta0  = hm_d0*hp_d0;
            const Real zetap1 = hp_d0*(hm_d0+hp_d0);
            const Real phim1  = hm_d1*(hm_d1+hp_d1);
            const Real phi0   = hm_d1*hp_d1;
            const Real phip1  = hp_d1*(hm_d1+hp_d1);

            const Size c0 = iter.coordinates()[d0_];
            const Size c1 = iter.coordinates()[d1_];
            if (c0 == 0 && c1 == 0) {
                // lower left corner
                a00_[i] = a01_[i] = a02_[i] = a10_[i] = a20_[i] = 0.0;
                a21_[i] = a12_[i] = -(a11_[i] = a22_[i] = 1.0/(hp_d0*hp_d1));
            }
            else if (c0 == layout->dim()[d0_]-1 && c1 == 0) {
                // upper left corner
                a22_[i] = a21_[i] = a20_[i] = a10_[i] = a00_[i] = 0.0;
                a11_[i] = a02_[i] = -(a01_[i] = a12_[i] = 1.0/(hm_d0*hp_d1));
            }
            else if (c0 == 0 && c1 == layout->dim()[d1_]-1) {
                // lower right corner
                a00_[i] = a01_[i] = a02_[i] = a12_[i] = a22_[i] = 0.0;
                a20_[i] = a11_[i] = -(a10_[i] = a21_[i] = 1.0/(hp_d0*hm_d1));
            }
            else if (c0 == layout->dim()[d0_]-1 && c1 == layout->dim()[d1_]-1) {
                // upper right corner
                a20_[i] = a21_[i] = a22_[i] = a12_[i] = a02_[i] = 0.0;
                a10_[i] = a01_[i] = -(a00_[i] = a11_[i] = 1.0/(hm_d0*hm_d1));
            }
            else if (c0 == 0) {
                // lower side
                a00_[i] = a01_[i] = a02_[i] = 0.0;

                a20_[i] = -(a10_[i] = hp_d1/(hp_d0*phim1));
                a11_[i] = -(a21_[i] = (hp_d1-hm_d1)/(hp_d0*phi0));
                a12_[i] = -(a22_[i] = hm_d1/(hp_d0*phip1));
            }
            else if (c0 == layout->dim()[d0_]-1) {
                // upper side
                a20_[i] = a21_[i] = a22_[i] = 0.0;

                a10_[i] = -(a00_[i] = hp_d1/(hm_d0*phim1));
                a01_[i] = -(a11_[i] = (hp_d1-hm_d1)/(hm_d0*phi0));
                a02_[i] = -(a12_[i] = hm_d1/(hm_d0*phip1));
            }
            else if (c1 == 0) {
                // left side
                a00_[i] = a10_[i] = a20_[i] = 0.0;

                a02_[i] = -(a01_[i] = hp_d0/(zetam1*hp_d1));
                a11_[i] = -(a12_[i] = (hp_d0-hm_d0)/(zeta0*hp_d1));
                a21_[i] = -(a22_[i] = hm_d0/(zetap1*hp_d1));
            }
            else if (c1 == layout->dim()[d1_]-1) {
                // right side
                a22_[i] = a12_[i] = a02_[i] = 0.0;

                a01_[i] = -(a00_[i] = hp_d0/(zetam1*hm_d1));
                a10_[i] = -(a11_[i] = (hp_d0-hm_d0)/(zeta0*hm_d1));
                a20_[i] = -(a21_[i] = hm_d0/(zetap1*hm_d1));
            }
            else {
                a00_[i] =  hp_d0*hp_d1/(zetam1*phim1);
                a10_[i] = -(hp_d0-hm_d0)*hp_d1/(zeta0*phim1);
                a20_[i] = -hm_d0*hp_d1/(zetap1*phim1);
                a01_[i] = -hp_d0*(hp_d1-hm_d1)/(zetam1*phi0);
                a11_[i] = (hp_d0-hm_d0)*(hp_d1-hm_d1)/(zeta0*phi0);
                a21_[i] =  hm_d0*(hp_d1-hm_d1)/(zetap1*phi0);
                a02_[i] = -hp_d0*hm_d1/(zetam1*phip1);
                a12_[i] =  hm_d1*(hp_d0-hm_d0)/(zeta0*phip1);
                a22_[i] =  hm_d0*hm_d1/(zetap1*phip1);
            }
        }
    }
예제 #24
0
    Disposable<Array> FdmHestonGreensFct::get(Time t, Algorithm algorithm)
    const {
        const Rate r = process_->riskFreeRate()->forwardRate(0, t, Continuous);
        const Rate q = process_->dividendYield()->forwardRate(0,t, Continuous);

        const Real s0    = process_->s0()->value();
        const Real v0    = process_->v0();
        const Real x0    = std::log(s0) + (r-q-0.5*v0*l0_*l0_)*t;

          const Real rho   = process_->rho();
        const Real theta = process_->theta();
        const Real kappa = process_->kappa();
        const Real sigma = process_->sigma();

        const boost::shared_ptr<FdmLinearOpLayout> layout = mesher_->layout();
        const FdmLinearOpIterator endIter = layout->end();

        Array p(mesher_->layout()->size());
        for (FdmLinearOpIterator iter = layout->begin(); iter != endIter;
            ++iter) {
            const Real x = mesher_->location(iter, 0);
            const Real v = (trafoType_ != FdmSquareRootFwdOp::Log)
                ? mesher_->location(iter, 1)
                : std::exp(mesher_->location(iter, 1));

            Real retVal;
            switch (algorithm) {
              case ZeroCorrelation:
              {
                const Real sd_x = l0_*std::sqrt(v0*t);
                  const Real p_x = M_1_SQRTPI*M_SQRT1_2/sd_x
                          * std::exp(-0.5*square<Real>()((x - x0)/sd_x));
                  const Real p_v = SquareRootProcessRNDCalculator(
                      v0, kappa, theta, sigma).pdf(v, t);

                  retVal = p_v*p_x;
              }
              break;
              case SemiAnalytical:
                retVal = process_->pdf(x, v, t, 1e-4);
              break;
              case Gaussian:
              {
                const Real sd_x = l0_*std::sqrt(v0*t);
                const Real sd_v = sigma*std::sqrt(v0*t);
                const Real z0 = v0 + kappa*(theta - v0)*t;
                retVal = 1.0/(M_TWOPI*sd_x*sd_v*std::sqrt(1-rho*rho))
                    *std::exp(-(  square<Real>()((x-x0)/sd_x)
                                + square<Real>()((v-z0)/sd_v)
                                - 2*rho*(x-x0)*(v-z0)/(sd_x*sd_v))
                              /(2*(1-rho*rho)) );
              }
              break;
              default:
                QL_FAIL("unknown algorithm");
            }

            switch (trafoType_) {
              case FdmSquareRootFwdOp::Log:
                retVal*=v;
                break;
              case FdmSquareRootFwdOp::Plain:
                break;
              case FdmSquareRootFwdOp::Power:
                retVal*=std::pow(v, 1.0 - 2*kappa*theta/(sigma*sigma));
                break;
              default:
                QL_FAIL("unknown transformation type");
            }

            p[iter.index()] = retVal;
        }

        return p;
    }