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];
    }
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;
        }
    }
}
Beispiel #3
0
    Disposable<Array> FdmHestonEquityPart::getLeverageFctSlice(Time t1, Time t2)
    const {
        const boost::shared_ptr<FdmLinearOpLayout> layout=mesher_->layout();
        Array v(layout->size(), 1.0);

        if (!leverageFct_) {
            return v;
        }
        const Real t = 0.5*(t1+t2);
        const Time time = std::min(leverageFct_->maxTime(), t);

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

            if (iter.coordinates()[1] == 0) {
                const Real x = std::exp(mesher_->location(iter, 0));
                const Real spot = std::min(leverageFct_->maxStrike(),
                                           std::max(leverageFct_->minStrike(), x));
                v[nx] = std::max(0.01, leverageFct_->localVol(time, spot, true));
            }
            else {
                v[iter.index()] = v[nx];
            }
        }
        return v;
    }
    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_);
    }
FdmAddPayoffCondition::
		FdmAddPayoffCondition(const boost::shared_ptr<FdmExprInnerValue>& payoffGrid,
								const std::vector<boost::shared_ptr<Domain>>& domain,
								Time t)
: domain_(domain), t_(t)
{
	const boost::shared_ptr<Mesher>& mesher = payoffGrid->mesher();
	const boost::shared_ptr<FdmLinearOpLayout> layout = mesher->layout();

	const FdmLinearOpIterator endIter = layout->end();

	Array x(mesher_->layout()->dim().size());

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

		for (Size i=0 ; i < x.size(); ++i) 
		{
			x[i] = mesher_->location(iter, i);
		}
				
		if(domain[j](x))
		{
			locationIndexes_.push_back(iter.index());
			payoffValues_.push_back(innerValue(iter));
		}
	}
}
    void FdmSimpleSwingCondition::applyTo(Array& a, Time t) const {
        const std::vector<Time>::const_iterator iter
            = std::find(exerciseTimes_.begin(), exerciseTimes_.end(), t);
        const Size maxExerciseValue=mesher_->layout()->dim()[swingDirection_]-1;

        if (iter != exerciseTimes_.end()) {
            Array retVal= a;

            const Size d = std::distance(iter, exerciseTimes_.end());

            const boost::shared_ptr<FdmLinearOpLayout> layout=mesher_->layout();
            const FdmLinearOpIterator endIter = layout->end();
            
            for (FdmLinearOpIterator iter = layout->begin(); iter != endIter;
                 ++iter) {
                
                const std::vector<Size>& coor = iter.coordinates();
                
                const Size exercisesUsed = coor[swingDirection_];
                
                if (exercisesUsed < maxExerciseValue) {
                    const Real cashflow = calculator_->innerValue(iter, t);
                    const Real currentValue = a[iter.index()];
                    const Real valuePlusOneExercise
                         = a[layout->neighbourhood(iter, swingDirection_, 1)];
                    
                    if (   currentValue < valuePlusOneExercise + cashflow
                        || exercisesUsed + d <=  minExercises_) {
                        retVal[iter.index()] = valuePlusOneExercise + cashflow;
                    }
                }
            }
            a = retVal;
        }
    }
Beispiel #7
0
    TripleBandLinearOp::TripleBandLinearOp(
        Size direction,
        const boost::shared_ptr<FdmMesher>& mesher)
    : direction_(direction),
      i0_       (new Size[mesher->layout()->size()]),
      i2_       (new Size[mesher->layout()->size()]),
      reverseIndex_ (new Size[mesher->layout()->size()]),
      lower_    (new Real[mesher->layout()->size()]),
      diag_     (new Real[mesher->layout()->size()]),
      upper_    (new Real[mesher->layout()->size()]),
      mesher_(mesher) {

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

        std::vector<Size> newDim(layout->dim());
        std::iter_swap(newDim.begin(), newDim.begin()+direction_);
        std::vector<Size> newSpacing = FdmLinearOpLayout(newDim).spacing();
        std::iter_swap(newSpacing.begin(), newSpacing.begin()+direction_);

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

            i0_[i] = layout->neighbourhood(iter, direction, -1);
            i2_[i] = layout->neighbourhood(iter, direction,  1);

            const std::vector<Size>& coordinates = iter.coordinates();
            const Size newIndex =
                  std::inner_product(coordinates.begin(), coordinates.end(),
                                     newSpacing.begin(), Size(0));
            reverseIndex_[newIndex] = i;
        }
    }
Beispiel #8
0
    FdmHestonEquityPart::FdmHestonEquityPart(
        const boost::shared_ptr<FdmMesher>& mesher,
        const boost::shared_ptr<YieldTermStructure>& rTS,
        const boost::shared_ptr<YieldTermStructure>& qTS,
        const boost::shared_ptr<FdmQuantoHelper>& quantoHelper,
        const boost::shared_ptr<LocalVolTermStructure>& leverageFct)
    : varianceValues_(0.5*mesher->locations(1)),
      dxMap_ (FirstDerivativeOp(0, mesher)),
      dxxMap_(SecondDerivativeOp(0, mesher).mult(0.5*mesher->locations(1))),
      mapT_  (0, mesher),
      mesher_(mesher),
      rTS_(rTS),
      qTS_(qTS),
      quantoHelper_(quantoHelper),
      leverageFct_(leverageFct) {

        // on the boundary s_min and s_max the second derivative
        // d^2V/dS^2 is zero and due to Ito's Lemma the variance term
        // in the drift should vanish.
        boost::shared_ptr<FdmLinearOpLayout> layout = mesher_->layout();
        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_);
    }
	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);
			}
		}
	}
Beispiel #10
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;
    }
    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;
    }
    void FdmAmericanStepCondition::applyTo(Array& a, Time t) const {
        boost::shared_ptr<FdmLinearOpLayout> layout = mesher_->layout();
        const FdmLinearOpIterator endIter = layout->end();

        for (FdmLinearOpIterator iter = layout->begin(); iter != endIter;
            ++iter) {
            const Real innerValue = calculator_->innerValue(iter, t);
            if (innerValue > a[iter.index()]) {
                a[iter.index()] = innerValue;
            }
        }
    }
    FdmHestonFwdOp::FdmHestonFwdOp(
            const boost::shared_ptr<FdmMesher>& mesher,
            const boost::shared_ptr<HestonProcess>& process,
            FdmSquareRootFwdOp::TransformationType type)
    : type_ (type),
      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, type)),
      correlation_(new NinePointLinearOp(
          SecondOrderMixedDerivativeOp(0, 1, mesher)
              .mult(rho_*sigma_*mesher->locations(1))))
    {
        const boost::shared_ptr<FdmLinearOpLayout> layout = mesher->layout();

        if (type_ == FdmSquareRootFwdOp::Plain) {
            // 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];
                }
            }
        }
    }
    FdmHestonHullWhiteSolver::FdmHestonHullWhiteSolver(
        const Handle<HestonProcess>& hestonProcess,
        const Handle<HullWhiteProcess>& hwProcess,
        Rate corrEquityShortRate,
        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,
        const Size dampingSteps,
        FdmBackwardSolver::FdmSchemeType schemeType, 
        Real theta, Real mu)
    : hestonProcess_(hestonProcess),
      hwProcess_(hwProcess),
      corrEquityShortRate_(corrEquityShortRate),
      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),
      initialValues_(mesher->layout()->size()),
      resultValues_(mesher->layout()->dim()[2], 
                    Matrix(mesher->layout()->dim()[1], 
                           mesher->layout()->dim()[0])),
      interpolation_(mesher->layout()->dim()[2]) {

        registerWith(hestonProcess);
        registerWith(hwProcess);
        
        x_.reserve(mesher->layout()->dim()[0]);
        v_.reserve(mesher->layout()->dim()[1]);
        r_.reserve(mesher->layout()->dim()[2]);

        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] && !iter.coordinates()[2]) {
                x_.push_back(mesher->location(iter, 0));
            }
            if (!iter.coordinates()[0] && !iter.coordinates()[2]) {
                v_.push_back(mesher->location(iter, 1));
            }
            if (!iter.coordinates()[0] && !iter.coordinates()[1]) {
                r_.push_back(mesher->location(iter, 2));
            }
        }
    }
    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));
    }
Beispiel #17
0
    Disposable<Array>
    TripleBandLinearOp::solve_splitting(const Array& r, Real a, Real b) const {
        const boost::shared_ptr<FdmLinearOpLayout> layout = mesher_->layout();
        QL_REQUIRE(r.size() == layout->size(), "inconsistent size of rhs");

#ifdef QL_EXTRA_SAFETY_CHECKS
        for (FdmLinearOpIterator iter = layout->begin();
             iter!=layout->end(); ++iter) {
            const std::vector<Size>& coordinates = iter.coordinates();
            QL_REQUIRE(   coordinates[direction_] != 0
                       || lower_[iter.index()] == 0,"removing non zero entry!");
            QL_REQUIRE(   coordinates[direction_] != layout->dim()[direction_]-1
                       || upper_[iter.index()] == 0,"removing non zero entry!");
        }
#endif

        Array retVal(r.size()), tmp(r.size());

        const Real* lptr = lower_.get();
        const Real* dptr = diag_.get();
        const Real* uptr = upper_.get();

        // Thomson algorithm to solve a tridiagonal system.
        // Example code taken from Tridiagonalopertor and
        // changed to fit for the triple band operator.
        Size rim1 = reverseIndex_[0];
        Real bet=1.0/(a*dptr[rim1]+b);
        QL_REQUIRE(bet != 0.0, "division by zero");
        retVal[reverseIndex_[0]] = r[rim1]*bet;

        for (Size j=1; j<=layout->size()-1; j++){
            const Size ri = reverseIndex_[j];
            tmp[j] = a*uptr[rim1]*bet;

            bet=b+a*(dptr[ri]-tmp[j]*lptr[ri]);
            QL_ENSURE(bet != 0.0, "division by zero");
            bet=1.0/bet;

            retVal[ri] = (r[ri]-a*lptr[ri]*retVal[rim1])*bet;
            rim1 = ri;
        }
        // cannot be j>=0 with Size j
        for (Size j=layout->size()-2; j>0; --j)
            retVal[reverseIndex_[j]] -= tmp[j+1]*retVal[reverseIndex_[j+1]];
        retVal[reverseIndex_[0]] -= tmp[1]*retVal[reverseIndex_[1]];

        return retVal;
    }
Real FdmLogInnerValue::avgInnerValueCalc(const FdmLinearOpIterator& iter) {
    const Size dim = mesher_->layout()->dim()[direction_];
    const Size coord = iter.coordinates()[direction_];
    const Real loc = mesher_->location(iter,direction_);
    Real a = loc;
    Real b = loc;
    if (coord > 0) {
        a -= mesher_->dminus(iter, direction_)/2.0;
    }
    if (coord < dim-1) {
        b += mesher_->dplus(iter, direction_)/2.0;
    }
    boost::function1<Real, Real> f = compose(
                                         std::bind1st(std::mem_fun(&Payoff::operator()), payoff_.get()),
                                         std::ptr_fun<Real,Real>(std::exp));

    Real retVal;
    try {
        const Real acc
            = ((f(a) != 0.0 || f(b) != 0.0) ? (f(a)+f(b))*5e-5 : 1e-4);
        retVal = SimpsonIntegral(acc, 8)(f, a, b)/(b-a);
    }
    catch (Error&) {
        // use default value
        retVal = innerValue(iter);
    }

    return retVal;
}
    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();
    }
Beispiel #20
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_));
    }
    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);
        }
    }
Beispiel #22
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);
}
	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;
				}
			}

		}
	}
Beispiel #24
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();
    }
Real FdmLogInnerValue::avgInnerValue(const FdmLinearOpIterator& iter) {

    if (avgInnerValues_.empty()) {
        // calculate caching values
        avgInnerValues_.resize(mesher_->layout()->dim()[direction_]);
        std::deque<bool> initialized(avgInnerValues_.size(), false);

        const boost::shared_ptr<FdmLinearOpLayout> layout=mesher_->layout();
        const FdmLinearOpIterator endIter = layout->end();
        for (FdmLinearOpIterator iter = layout->begin(); iter != endIter;
                ++iter) {
            const Size xn = iter.coordinates()[direction_];
            if (!initialized[xn]) {
                initialized[xn]     = true;
                avgInnerValues_[xn] = avgInnerValueCalc(iter);
            }
        }
    }

    return avgInnerValues_[iter.coordinates()[direction_]];
}
Beispiel #26
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_));
    }
Beispiel #27
0
    Fdm2DimSolver::Fdm2DimSolver(
                             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)),
      initialValues_(solverDesc.mesher->layout()->size()),
      resultValues_ (solverDesc.mesher->layout()->dim()[1],
                     solverDesc.mesher->layout()->dim()[0]) {

        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]);

        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]) {
                x_.push_back(mesher->location(iter, 0));
            }
            if (!iter.coordinates()[0]) {
                y_.push_back(mesher->location(iter, 1));
            }
        }
    }
    Real FdmVPPStepCondition::evolve(
                               const FdmLinearOpIterator& iter, Time t) const {

        const Size state = iter.coordinates()[stateDirection_];

        if (stateEvolveFcts_[state].empty()) {
            return 0.0;
        }
        else {
            const Real sparkSpread = sparkSpreadPrice_->innerValue(iter, t);
            return stateEvolveFcts_[state](sparkSpread);
        }
    }
Beispiel #29
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));
    }
}
Beispiel #30
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);
    }