void SimpleRangeAccrualRateETI::initializeImpl(const TimeGrid& timeGrid,
				const boost::shared_ptr<YieldTermStructure>& discountCurve,
				const boost::shared_ptr<PathGeneratorFactory>& pathGenFactory)
{
	referenceCalculation_->initialize(timeGrid,discountCurve,pathGenFactory);
	this->payoffDateInfo_->initialize(timeGrid,discountCurve,pathGenFactory);

	this->rangeNum_ = simpleRangeRateList_.size();
	this->assetNum_ = pathGenFactory->numAssets();
	
	Date today = Settings::instance().evaluationDate();
	
	DayCounter dayCounter = Actual365Fixed();

	double fixingStartTime = dayCounter.yearFraction( today , calculationStartDate_ );
	Size fixingStartPosition = timeGrid.closestIndex(fixingStartTime);

	double fixingEndTime = dayCounter.yearFraction( today , calculationEndDate_ );
	Size fixingEndPosition = timeGrid.closestIndex(fixingEndTime);

	Size fixingSize = fixingEndPosition - fixingStartPosition;
	
	this->fixingDatePositions_ = std::valarray<Size>(fixingSize);

	for ( Size position = 0 ; fixingSize ; position++ )
	{
		fixingDatePositions_[position] = fixingStartPosition + position;
	}

	for ( Size rng = 0 ; this->rangeNum_ ; rng++ )
	{
		simpleRangeRateList_[rng]->initialize(timeGrid,discountCurve,pathGenFactory);
	}
	
}
        boost::shared_ptr<path_generator_type> pathGenerator() const {

            Size numAssets = processes_->size();

            TimeGrid grid = timeGrid();

			Calendar calendar = this->arguments_.sp_payoff->calendar();
			
            typename RNG::rsg_type gen =
                RNG::make_sequence_generator(numAssets*(grid.size()-1),seed_);

			boost::shared_ptr<path_generator_type> pgPtr 
				= boost::shared_ptr<path_generator_type>(
					       new path_generator_type(processes_,
                                                 grid, 
												 gen));

			PathInformation::instance().initialize(pgPtr->multiPath(),calendar);

			//history setting here..

			//index의 Calendar와 product의 Calendar(calculation Date Calendar)는 따로 가야함
			//과거 index fixing은 각각 클래스에서 fixing하는데 그 방법은 pathmanager가 indexHistory를 가지고 있어서 거기에 문의해서, 
			//따로 클래스 내에 가져와서 fixing 시켜놈. 결과만 저장해서 나중에 함침.
			//그러므로 path에 따로 무언가를 붙일 필요는 없음.
			//MultiPath Grid는 product calendar로 grid숫자 계산함.

            return pgPtr;
        }
コード例 #3
0
ファイル: mctvaengine.hpp プロジェクト: eefelix/MAFS5220
		//! Return shared pointer to path generator who generates sample pathes in simulation
		virtual boost::shared_ptr<path_generator_type> pathGenerator() const {
			Size factors = this->process()->factors();
			TimeGrid grid = timeGrid();
			Size steps = grid.size() - 1;
			typename RNG::rsg_type gen = RNG::make_sequence_generator(factors * steps, seed_);
			return boost::make_shared<path_generator_type>(this->process(), grid, gen, false);
		}
コード例 #4
0
ファイル: mcdigitalengine.hpp プロジェクト: SePTimO7/QuantLib
    inline
    ext::shared_ptr<typename MCDigitalEngine<RNG,S>::path_pricer_type>
    MCDigitalEngine<RNG,S>::pathPricer() const {

        ext::shared_ptr<CashOrNothingPayoff> payoff =
            ext::dynamic_pointer_cast<CashOrNothingPayoff>(
                this->arguments_.payoff);
        QL_REQUIRE(payoff, "wrong payoff given");

        ext::shared_ptr<AmericanExercise> exercise =
            ext::dynamic_pointer_cast<AmericanExercise>(
                this->arguments_.exercise);
        QL_REQUIRE(exercise, "wrong exercise given");

        ext::shared_ptr<GeneralizedBlackScholesProcess> process =
            ext::dynamic_pointer_cast<GeneralizedBlackScholesProcess>(
                                                              this->process_);
        QL_REQUIRE(process, "Black-Scholes process required");

        TimeGrid grid = this->timeGrid();
        PseudoRandom::ursg_type sequenceGen(grid.size()-1,
                                            PseudoRandom::urng_type(76));

        return ext::shared_ptr<
                        typename MCDigitalEngine<RNG,S>::path_pricer_type>(
          new DigitalPathPricer(payoff,
                                exercise,
                                process->riskFreeRate(),
                                process,
                                sequenceGen));
    }
    inline void MultiPathGeneratorFixedPath<GSG>::next() const 
	{
        typedef typename GSG::sample_type sequence_type;
        const sequence_type& sequence_ = generator_.nextSequence();

        Size m = process_->size();
        Size n = process_->factors();

        MultiPath& path = *nextPtr_;

        Array asset = process_->initialValues();
        
		for (Size j=0; j<m; j++)
            path[j].front() = asset[j];

        Array temp(n);

        TimeGrid timeGrid = path[0].timeGrid();
        Time t, dt;
        
		for (Size i = 1; i < path.pathSize(); i++) {
            Size offset = (i-1)*n;
            t = timeGrid[i-1];
            dt = timeGrid.dt(i-1);
            
			std::copy(sequence_.value.begin()+offset,
                            sequence_.value.begin()+offset+n,
                            temp.begin());

            asset = process_->evolve(t, asset, dt, temp,i-1);

            for (Size j=0; j<m; j++)
                path[j][i] = asset[j];
		}
    }
コード例 #6
0
        boost::shared_ptr<path_generator_type> pathGenerator() const {

            TimeGrid grid = this->timeGrid();
            typename RNG::rsg_type gen =
                RNG::make_sequence_generator(grid.size()-1,seed_);
            return boost::shared_ptr<path_generator_type>(
                         new path_generator_type(process_, grid,
                                                 gen, brownianBridge_));
        }
コード例 #7
0
        boost::shared_ptr<path_generator_type> pathGenerator() const {

            Size dimensions = process_->factors();
            TimeGrid grid = this->timeGrid();
            typename RNG::rsg_type generator =
                RNG::make_sequence_generator(dimensions*(grid.size()-1),seed_);
            return boost::shared_ptr<path_generator_type>(
                   new path_generator_type(process_, grid,
                                           generator, brownianBridge_));
        }
PathGeneratorFactory::PathGeneratorFactory(const boost::shared_ptr<StochasticProcessArray>& processes,
										   const TimeGrid& timeGrid)
: processes_(processes), grid_(timeGrid)
{
	unsigned long myseed = static_cast<unsigned long>(1);
	rand_ = std::tr1::mt19937(myseed);

	this->numAssets_ = processes->size();
	this->pathSize_ = timeGrid.size();

	PseudoRandom::rsg_type gen =
		PseudoRandom::make_sequence_generator(numAssets_*(timeGrid.size()-1),1);

	gen_ = boost::shared_ptr<MultiVariate<PseudoRandom>::path_generator_type>(new MultiVariate<PseudoRandom>::path_generator_type(processes,
                                timeGrid, gen, false));
				
	this->next_ = MultiPath(numAssets_,this->grid_);

	S0_ = std::valarray<double>(numAssets_);
	randArrs_ = std::valarray<double>(numAssets_);

	//this->testRandom_ = Array(numAssets_ * pathSize_);
	previousRand_ = Matrix(numAssets_, pathSize_);

	Matrix corr = processes->correlation();
	chol_=CholeskyDecomposition(corr);

	random_ = MultiPath(numAssets_,timeGrid);

	// num - 1
	this->muGrid_ = Matrix(numAssets_, timeGrid.size() - 1);
	this->volGrid_ = Matrix(numAssets_,timeGrid.size() - 1);

	antitheticFlag_ = false;

	for (Size asset = 0 ; asset<numAssets_ ;++asset)
	{
		//초기화 수익률 or 절대값
		S0_[asset] = processes->process(asset)->x0() / processes->process(asset)->basePrice();

		for (Size t = 0 ; t < pathSize_ - 1 ;++t)
		{
			double mu_t = processes->process(asset)->drift(timeGrid[t],1.0);
			double sigma_t = processes->process(asset)->diffusion(timeGrid[t],1.0);
			double dt_t = timeGrid.dt(t);

			// exp( ( mu[t] - 0.5 * vol[t] * vol[t] ) * dt[t] )
			muGrid_[asset][t] = std::exp( ( mu_t - 0.5 * sigma_t * sigma_t ) * dt_t );

			//  vol[t] * sqrt(dt[t]) 
			volGrid_[asset][t] = sigma_t * std::sqrt(dt_t);
		}

	}
}
コード例 #9
0
ファイル: mcpagodaengine.hpp プロジェクト: SePTimO7/QuantLib
        ext::shared_ptr<path_generator_type> pathGenerator() const {

            Size numAssets = processes_->size();

            TimeGrid grid = timeGrid();
            typename RNG::rsg_type gen =
                RNG::make_sequence_generator(numAssets*(grid.size()-1),seed_);

            return ext::shared_ptr<path_generator_type>(
                         new path_generator_type(processes_,
                                                 grid, gen, brownianBridge_));
        }
コード例 #10
0
    inline
    boost::shared_ptr<typename
    MCLongstaffSchwartzEngine<GenericEngine,MC,RNG,S>::path_generator_type>
    MCLongstaffSchwartzEngine<GenericEngine,MC,RNG,S>::pathGenerator() const {

        Size dimensions = process_->factors();
        TimeGrid grid = this->timeGrid();
        typename RNG::rsg_type generator =
            RNG::make_sequence_generator(dimensions*(grid.size()-1),seed_);
        return boost::shared_ptr<path_generator_type>(
                   new path_generator_type(process_,
                                           grid, generator, brownianBridge_));
    }
コード例 #11
0
 DiscretizedVanillaOption::DiscretizedVanillaOption(
                                      const VanillaOption::arguments& args,
                                      const StochasticProcess& process,
                                      const TimeGrid& grid)
 : arguments_(args) {
     stoppingTimes_.resize(args.exercise->dates().size());
     for (Size i=0; i<stoppingTimes_.size(); ++i) {
         stoppingTimes_[i] =
             process.time(args.exercise->date(i));
         if (!grid.empty()) {
             // adjust to the given grid
             stoppingTimes_[i] = grid.closestTime(stoppingTimes_[i]);
         }
     }
 }
コード例 #12
0
    boost::shared_ptr<Lattice>
    BlackKarasinski::tree(const TimeGrid& grid) const {

        TermStructureFittingParameter phi(termStructure());

        boost::shared_ptr<ShortRateDynamics> numericDynamics(
                                             new Dynamics(phi, a(), sigma()));

        boost::shared_ptr<TrinomialTree> trinomial(
                         new TrinomialTree(numericDynamics->process(), grid));
        boost::shared_ptr<ShortRateTree> numericTree(
                         new ShortRateTree(trinomial, numericDynamics, grid));

        typedef TermStructureFittingParameter::NumericalImpl NumericalImpl;
        boost::shared_ptr<NumericalImpl> impl =
            boost::dynamic_pointer_cast<NumericalImpl>(phi.implementation());
        impl->reset();
        Real value = 1.0;
        Real vMin = -50.0;
        Real vMax = 50.0;
        for (Size i=0; i<(grid.size() - 1); i++) {
            Real discountBond = termStructure()->discount(grid[i+1]);
            Real xMin = trinomial->underlying(i, 0);
            Real dx = trinomial->dx(i);
            Helper finder(i, xMin, dx, discountBond, numericTree);
            Brent s1d;
            s1d.setMaxEvaluations(1000);
            value = s1d.solve(finder, 1e-7, value, vMin, vMax);
            impl->set(grid[i], value);
            // vMin = value - 10.0;
            // vMax = value + 10.0;
        }
        return numericTree;
    }
コード例 #13
0
ファイル: hullwhite.cpp プロジェクト: androidYibo/documents
    boost::shared_ptr<Lattice> HullWhite::tree(const TimeGrid& grid) const {

        TermStructureFittingParameter phi(termStructure());
        boost::shared_ptr<ShortRateDynamics> numericDynamics(
                                             new Dynamics(phi, a(), sigma()));
        boost::shared_ptr<TrinomialTree> trinomial(
                         new TrinomialTree(numericDynamics->process(), grid));
        boost::shared_ptr<ShortRateTree> numericTree(
                         new ShortRateTree(trinomial, numericDynamics, grid));

        typedef TermStructureFittingParameter::NumericalImpl NumericalImpl;
        boost::shared_ptr<NumericalImpl> impl =
            boost::dynamic_pointer_cast<NumericalImpl>(phi.implementation());
        impl->reset();
        for (Size i=0; i<(grid.size() - 1); i++) {
            Real discountBond = termStructure()->discount(grid[i+1]);
            const Array& statePrices = numericTree->statePrices(i);
            Size size = numericTree->size(i);
            Time dt = numericTree->timeGrid().dt(i);
            Real dx = trinomial->dx(i);
            Real x = trinomial->underlying(i,0);
            Real value = 0.0;
            for (Size j=0; j<size; j++) {
                value += statePrices[j]*std::exp(-x*dt);
                x += dx;
            }
            value = std::log(value/discountBond)/dt;
            impl->set(grid[i], value);
        }
        return numericTree;
    }
コード例 #14
0
    inline boost::shared_ptr<LongstaffSchwartzMultiPathPricer>
    MCAmericanPathEngine<RNG>::lsmPathPricer() const {

        boost::shared_ptr<StochasticProcessArray> processArray =
            boost::dynamic_pointer_cast<StochasticProcessArray>(this->process_);
        QL_REQUIRE(processArray && processArray->size()>0,
                   "Stochastic process array required");

        boost::shared_ptr<GeneralizedBlackScholesProcess> process =
            boost::dynamic_pointer_cast<GeneralizedBlackScholesProcess>(
               processArray->process(0));
        QL_REQUIRE(process, "generalized Black-Scholes process required");

        const TimeGrid theTimeGrid = this->timeGrid();

        const std::vector<Time> & times = theTimeGrid.mandatoryTimes();
        const Size numberOfTimes = times.size();

        const std::vector<Date> & fixings = this->arguments_.fixingDates;

        QL_REQUIRE(fixings.size() == numberOfTimes, "Invalid dates/times");

        std::vector<Size> timePositions(numberOfTimes);
        Array discountFactors(numberOfTimes);
        std::vector<Handle<YieldTermStructure> > forwardTermStructures(numberOfTimes);

        const Handle<YieldTermStructure> & riskFreeRate = process->riskFreeRate();

        for (Size i = 0; i < numberOfTimes; ++i) {
            timePositions[i] = theTimeGrid.index(times[i]);
            discountFactors[i] = riskFreeRate->discount(times[i]);
            forwardTermStructures[i] = Handle<YieldTermStructure>(
                boost::make_shared<ImpliedTermStructure>(riskFreeRate,
                                                         fixings[i]));
        }

        const Size polynomialOrder = 2;
        const LsmBasisSystem::PolynomType polynomType = LsmBasisSystem::Monomial;

        return boost::shared_ptr<LongstaffSchwartzMultiPathPricer> (
            new LongstaffSchwartzMultiPathPricer(this->arguments_.payoff,
                                                 timePositions,
                                                 forwardTermStructures,
                                                 discountFactors,
                                                 polynomialOrder,
                                                 polynomType));
    }
コード例 #15
0
    template <class PathType> inline
    LongstaffSchwartzPathPricer<PathType>::LongstaffSchwartzPathPricer(
        const TimeGrid& times,
        const boost::shared_ptr<EarlyExercisePathPricer<PathType> >&
            pathPricer,
        const boost::shared_ptr<YieldTermStructure>& termStructure)
    : calibrationPhase_(true),
      pathPricer_(pathPricer),
      coeff_     (new Array[times.size()-1]),
      dF_        (new DiscountFactor[times.size()-1]),
      v_         (pathPricer_->basisSystem()) {

        for (Size i=0; i<times.size()-1; ++i) {
            dF_[i] =   termStructure->discount(times[i+1])
                     / termStructure->discount(times[i]);
        }
    }
コード例 #16
0
    DiscretizedBarrierOption::DiscretizedBarrierOption(
                                         const BarrierOption::arguments& args,
                                         const StochasticProcess& process,
                                         const TimeGrid& grid)
    : arguments_(args), vanilla_(arguments_, process, grid) {
        QL_REQUIRE(args.exercise->dates().size(), "specify at least one stopping date");

        stoppingTimes_.resize(args.exercise->dates().size());
        for (Size i=0; i<stoppingTimes_.size(); ++i) {
            stoppingTimes_[i] =
                process.time(args.exercise->date(i));
            if (!grid.empty()) {
                // adjust to the given grid
                stoppingTimes_[i] = grid.closestTime(stoppingTimes_[i]);
            }
        }
    }
コード例 #17
0
        boost::shared_ptr<path_generator_type> pathGenerator() const {

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

            Size numAssets = processes_->size();

            TimeGrid grid = timeGrid();
            typename RNG::rsg_type gen =
                RNG::make_sequence_generator(numAssets*(grid.size()-1),seed_);

            return boost::shared_ptr<path_generator_type>(
                         new path_generator_type(processes_,
                                                 grid, gen, brownianBridge_));
        }
コード例 #18
0
    inline
    boost::shared_ptr<typename MCPathBasketEngine<RNG,S>::path_generator_type>
    MCPathBasketEngine<RNG,S>::pathGenerator() const {

        boost::shared_ptr<PathPayoff> payoff = arguments_.payoff;
        QL_REQUIRE(payoff, "non-basket payoff given");

        Size numAssets = process_->size();

        TimeGrid grid = timeGrid();

        typename RNG::rsg_type gen =
            RNG::make_sequence_generator(numAssets * (grid.size() - 1), seed_);

        return boost::shared_ptr<path_generator_type>(
                         new path_generator_type(process_,
                                                 grid, gen, brownianBridge_));
    }
コード例 #19
0
void HifivePricer::initializeImpl(const TimeGrid& timeGrid,
									   const boost::shared_ptr<YieldTermStructure>& discountCurve,
									   const boost::shared_ptr<PathGeneratorFactory>& pathGenFactory)
{
	//this->discount_ = Array(eventTriggerList_.size(),1.0);

	//for ( Size i = 0 ; i < eventTriggerList_.size() ; i++ )
	//{
	//	eventTriggerList_[i]->initialize(timeGrid,discountCurve);

	//	if ( eventTriggerList_[i]->isExpired() )
	//	{
	//		remainEventPosition_ = i + 1;
	//		this->discount_[i] = 1.0;
	//	}else
	//	{
	//		this->discount_[i] = discountCurve_->discount(eventTriggerList_[i]->payoffDate());
	//	}
	//}

	Date today = Settings::instance().evaluationDate();

	remainEventPosition_ = 0;
	autoCallEventPosition_ = timeGrid.size() - 1;

	this->cf_results_ = std::vector<boost::shared_ptr<CashFlowResult>>( this->eventTriggerList_.size() );
	this->calcValue_results_ = std::vector<boost::shared_ptr<CalcValueResult>>(1);

	this->calcValue_results_[0] = boost::shared_ptr<CalcValueResult>(
									new CalcValueResult("NET","KRW"));

	for ( Size i = 0 ; i < eventTriggerList_.size() ; i++ )
	{
		this->eventTriggerList_[i]->initialize(timeGrid,discountCurve,pathGenFactory);
		this->cf_results_[i] =  boost::shared_ptr<CashFlowResult>( 
							new CashFlowResult(i+1,
											   this->eventTriggerList_[i]->getEventDate(),
											   this->eventTriggerList_[i]->getPayoffDate(),
											   "NET",
											   this->currency_,
											   this->payoffDateInfo_->discount()) );

		bool kk = eventTriggerList_[i]->isExpired();

		if ( eventTriggerList_[i]->isExpired() )
		{
			remainEventPosition_ = i + 1;
		}
	}

	this->kiBarrierEventTrigger_->initialize(timeGrid,discountCurve,pathGenFactory);
	//this->nonOccBarrierEventTrigger_->initialize(timeGrid,discountCurve,pathGenFactory);
	//pastkiBarrierEventOcc_ = kiBarrierEventTrigger_->pastEventOcc();

}
    MultiPathGeneratorFixedPath<GSG>::MultiPathGeneratorFixedPath(
                   const boost::shared_ptr<StochasticProcess>& process,
                   const TimeGrid& times,
                   GSG generator,
                   bool brownianBridge)
    : brownianBridge_(brownianBridge), process_(process),
      generator_(generator), next_(boost::shared_ptr<MultiPath>(new MultiPath(process->size(), times)))
	{
		nextPtr_ = next_.get();

        QL_REQUIRE(generator_.dimension() ==
                   process->factors()*(times.size()-1),
                   "dimension (" << generator_.dimension()
                   << ") is not equal to ("
                   << process->factors() << " * " << times.size()-1
                   << ") the number of factors "
                   << "times the number of time steps");
        QL_REQUIRE(times.size() > 1,
                   "no times given");
    }
コード例 #21
0
    inline
    boost::shared_ptr<typename MCPathBasketEngine<RNG,S>::path_pricer_type>
    MCPathBasketEngine<RNG,S>::pathPricer() const {

        boost::shared_ptr<PathPayoff> payoff = arguments_.payoff;
        QL_REQUIRE(payoff, "non-basket payoff given");

        boost::shared_ptr<GeneralizedBlackScholesProcess> process =
            boost::dynamic_pointer_cast<GeneralizedBlackScholesProcess>(
                                                       process_->process(0));
        QL_REQUIRE(process, "Black-Scholes process required");

        const TimeGrid theTimeGrid = timeGrid();

        const std::vector<Time> & times = theTimeGrid.mandatoryTimes();
        const Size numberOfTimes = times.size();

        const std::vector<Date> & fixings = this->arguments_.fixingDates;

        QL_REQUIRE(fixings.size() == numberOfTimes, "Invalid dates/times");

        std::vector<Size> timePositions(numberOfTimes);
        Array discountFactors(numberOfTimes);
        std::vector<Handle<YieldTermStructure> > forwardTermStructures(numberOfTimes);

        const Handle<YieldTermStructure> & riskFreeRate = process->riskFreeRate();

        for (Size i = 0; i < numberOfTimes; ++i) {
            timePositions[i] = theTimeGrid.index(times[i]);
            discountFactors[i] = riskFreeRate->discount(times[i]);
            forwardTermStructures[i] = Handle<YieldTermStructure>(
                        new ImpliedTermStructure(riskFreeRate, fixings[i]));
        }

        return boost::shared_ptr<
            typename MCPathBasketEngine<RNG,S>::path_pricer_type>(
                        new EuropeanPathMultiPathPricer(payoff, timePositions,
                                                        forwardTermStructures,
                                                        discountFactors));
    }
コード例 #22
0
        boost::shared_ptr<path_generator_type> pathGenerator() const {

            Handle<YieldTermStructure> curve = model_->termStructure();
            Date referenceDate = curve->referenceDate();
            DayCounter dayCounter = curve->dayCounter();

            Time forwardMeasureTime =
                dayCounter.yearFraction(referenceDate,
                                        arguments_.endDates.back());
            Array parameters = model_->params();
            Real a = parameters[0], sigma = parameters[1];
            boost::shared_ptr<HullWhiteForwardProcess> process(
                                new HullWhiteForwardProcess(curve, a, sigma));
            process->setForwardMeasureTime(forwardMeasureTime);

            TimeGrid grid = this->timeGrid();
            typename RNG::rsg_type generator =
                RNG::make_sequence_generator(grid.size()-1,seed_);
            return boost::shared_ptr<path_generator_type>(
                             new path_generator_type(process, grid, generator,
                                                     brownianBridge_));
        }
コード例 #23
0
    void simulateMP(const boost::shared_ptr<StochasticProcess>& process,
                    int nbPaths, TimeGrid& grid, BigNatural seed,
                    bool antithetic_variates, double *res) {

        typedef PseudoRandom::rsg_type rsg_type;
        typedef MultiPathGenerator<rsg_type>::sample_type sample_type;
        Size assets = process->factors();
        rsg_type rsg = PseudoRandom::make_sequence_generator(
            (grid.size() - 1) * assets, seed);

        MultiPathGenerator<rsg_type> generator(process, grid, rsg, false);

        // fill simulated paths
        for (int i=0; i<nbPaths; ++i) {
            const bool antithetic = (i%2)==0 ? false : true;

            sample_type sample = antithetic_variates ?
                (antithetic ? generator.antithetic(): generator.next()) :
                generator.next();

            Path p1 = sample.value[0];
            std::copy(p1.begin(), p1.end(), res + i * grid.size());
        }
    }
コード例 #24
0
    boost::shared_ptr<path_generator_type> pathGenerator() const {
        if(ifConst) {
            Date exercisedate = GenericEngine<OneAssetOption::arguments,OneAssetOption::results>::arguments_.exercise->lastDate();
            boost::shared_ptr<BlackScholesConstProcess> constProcess_(
                new BlackScholesConstProcess(
                    exercisedate,
                    realProcess->stateVariable(),
                    realProcess->dividendYield(),
                    realProcess->riskFreeRate(),
                    realProcess->blackVolatility()
                ));

            Size dimensions = constProcess_->factors();
            TimeGrid grid = this->timeGrid();
            typename RNG::rsg_type generator =
                RNG::make_sequence_generator(dimensions*(grid.size()-1),seed_);
            return boost::shared_ptr<path_generator_type>(
                       new path_generator_type(constProcess_, grid,
                                               generator, brownianBridge_));

        } else {
            return MCEuropeanEngine<RNG,S>::pathGenerator();
        }
    };
コード例 #25
0
ファイル: multipathgenerator.hpp プロジェクト: minikie/test
    MultiPathGenerator<GSG>::MultiPathGenerator(
                   const boost::shared_ptr<StochasticProcess>& process,
                   const TimeGrid& times,
                   GSG generator,
                   bool brownianBridge)
    : brownianBridge_(brownianBridge), process_(process),
      generator_(generator), next_(MultiPath(process->size(), times), 1.0) {

		//std::cout << "dimension (" << generator_.dimension()
		//	<< ") is not equal to ("
		//	<< process->factors() << " * " << times.size() - 1
		//	<< ") the number of factors "
		//	<< "times the number of time steps";

        QL_REQUIRE(generator_.dimension() ==
                   process->factors()*(times.size()-1),
                   "dimension (" << generator_.dimension()
                   << ") is not equal to ("
                   << process->factors() << " * " << times.size()-1
                   << ") the number of factors "
                   << "times the number of time steps");
        QL_REQUIRE(times.size() > 1,
                   "no times given");
    }
コード例 #26
0
ファイル: vpp.cpp プロジェクト: vdt/quantlib-1
void VPPTest::testVPPPricing() {
    BOOST_TEST_MESSAGE("Testing VPP pricing using perfect foresight or FDM...");

    SavedSettings backup;

    const Date today = Date(18, December, 2011);
    const DayCounter dc = ActualActual();
    Settings::instance().evaluationDate() = today;

    // vpp paramter
    const Real heatRate       = 2.5;
    const Real pMin           = 8;
    const Real pMax           = 40;
    const Size tMinUp         = 6;
    const Size tMinDown       = 2;
    const Real startUpFuel    = 20;
    const Real startUpFixCost = 100;

    const boost::shared_ptr<SwingExercise> exercise(
                                new SwingExercise(today, today+6, 3600u));

    VanillaVPPOption vppOption(heatRate, pMin, pMax, tMinUp, tMinDown,
                               startUpFuel, startUpFixCost, exercise);

    const boost::shared_ptr<KlugeExtOUProcess> klugeOUProcess
        = createKlugeExtOUProcess();
    const boost::shared_ptr<ExtOUWithJumpsProcess> lnPowerProcess
        = klugeOUProcess->getKlugeProcess();
    const boost::shared_ptr<ExtendedOrnsteinUhlenbeckProcess> ouProcess
        = lnPowerProcess->getExtendedOrnsteinUhlenbeckProcess();
    const boost::shared_ptr<ExtendedOrnsteinUhlenbeckProcess> lnGasProcess
        = klugeOUProcess->getExtOUProcess();

    const Real beta         = lnPowerProcess->beta();
    const Real eta          = lnPowerProcess->eta();
    const Real lambda       = lnPowerProcess->jumpIntensity();
    const Real alpha        = ouProcess->speed();
    const Real volatility_x = ouProcess->volatility();
    const Real kappa        = lnGasProcess->speed();
    const Real volatility_u = lnGasProcess->volatility();

    const Rate irRate       = 0.00;
    const Real fuelCostAddon  = 3.0;

    const boost::shared_ptr<YieldTermStructure> rTS
        = flatRate(today, irRate, dc);

    const Size nHours = LENGTH(powerPrices);

    typedef FdSimpleKlugeExtOUVPPEngine::Shape Shape;
    boost::shared_ptr<Shape> fuelShape(new Shape(nHours));
    boost::shared_ptr<Shape> powerShape(new Shape(nHours));

    for (Size i=0; i < nHours; ++i) {
        const Time t = (i+1)/(365*24.);

        const Real fuelPrice = fuelPrices[i];
        const Real gs = std::log(fuelPrice)-square<Real>()(volatility_u)
                               /(4*kappa)*(1-std::exp(-2*kappa*t));
        (*fuelShape)[i] = Shape::value_type(t, gs);

        const Real powerPrice = powerPrices[i];
        const Real ps = std::log(powerPrice)-square<Real>()(volatility_x)
                 /(4*alpha)*(1-std::exp(-2*alpha*t))
                -lambda/beta*std::log((eta-std::exp(-beta*t))/(eta-1.0));

        (*powerShape)[i] = Shape::value_type(t, ps);
    }

    // Test: intrinsic value
    vppOption.setPricingEngine(boost::shared_ptr<PricingEngine>(
        new DynProgVPPIntrinsicValueEngine(
            std::vector<Real>(fuelPrices, fuelPrices+nHours),
            std::vector<Real>(powerPrices, powerPrices+nHours),
            fuelCostAddon, flatRate(0.0, dc))));

    const Real intrinsic = vppOption.NPV();
    const Real expectedIntrinsic = 2056.04;
    if (std::fabs(intrinsic - expectedIntrinsic) > 0.1) {
        BOOST_ERROR("Failed to reproduce intrinsic value"
                   << "\n    calculated: " << intrinsic
                   << "\n    expected  : " << expectedIntrinsic);
    }

    // Test: finite difference price
    const boost::shared_ptr<PricingEngine> engine(
        new FdSimpleKlugeExtOUVPPEngine(klugeOUProcess, rTS,
                                        fuelShape, powerShape, fuelCostAddon,
                                        1, 25, 11, 10));

    vppOption.setPricingEngine(engine);

    const Real fdmPrice = vppOption.NPV();
    const Real expectedFdmPrice = 5217.68;
    if (std::fabs(fdmPrice - expectedFdmPrice) > 0.1) {
       BOOST_ERROR("Failed to reproduce finite difference price"
                   << "\n    calculated: " << fdmPrice
                   << "\n    expected  : " << expectedFdmPrice);
    }

    // Test: Monte-Carlo perfect foresight price
    VanillaVPPOption::arguments args;
    vppOption.setupArguments(&args);

    const FdmVPPStepConditionFactory stepConditionFactory(args);

    const boost::shared_ptr<FdmMesher> oneDimMesher(new FdmMesherComposite(
        stepConditionFactory.stateMesher()));
    const Size nStates = oneDimMesher->layout()->dim()[0];

    const FdmVPPStepConditionMesher vppMesh = { 0u, oneDimMesher };

    const TimeGrid grid(dc.yearFraction(today, exercise->lastDate()+1),
                        exercise->dates().size());
    typedef PseudoRandom::rsg_type rsg_type;
    typedef MultiPathGenerator<rsg_type>::sample_type sample_type;

    rsg_type rsg = PseudoRandom::make_sequence_generator(
                           klugeOUProcess->factors()*(grid.size()-1), 1234ul);
    MultiPathGenerator<rsg_type> generator(klugeOUProcess, grid, rsg, false);

    GeneralStatistics npv;
    const Size nTrails = 2500;

    for (Size i=0; i < nTrails; ++i) {
        const sample_type& path = generator.next();
        const boost::shared_ptr<FdmVPPStepCondition> stepCondition(
            stepConditionFactory.build(
                vppMesh, fuelCostAddon,
                boost::shared_ptr<FdmInnerValueCalculator>(
                    new PathFuelPrice(path.value, fuelShape)),
                boost::shared_ptr<FdmInnerValueCalculator>(
                    new PathSparkSpreadPrice(heatRate, path.value,
                                             fuelShape, powerShape))));

        Array state(nStates, 0.0);
        for (Size j=exercise->dates().size(); j > 0; --j) {
            stepCondition->applyTo(state, grid.at(j));
            state*=rTS->discount(grid.at(j))/rTS->discount(grid.at(j-1));
        }

        npv.add(state.back());
    }
    Real npvMC = npv.mean();
    Real errorMC = npv.errorEstimate();
    const Real expectedMC = 5250.0;
    if (std::fabs(npvMC-expectedMC) > 3*errorMC) {
        BOOST_ERROR("Failed to reproduce Monte-Carlo price"
                   << "\n    calculated: " << npvMC
                   << "\n    error     ; " << errorMC
                   << "\n    expected  : " << expectedMC);
    }
    npv.reset();

    // Test: Longstaff Schwartz least square Monte-Carlo
    const Size nCalibrationTrails = 1000u;
    std::vector<sample_type> calibrationPaths;
    std::vector<boost::shared_ptr<FdmVPPStepCondition> > stepConditions;
    std::vector<boost::shared_ptr<FdmInnerValueCalculator> > sparkSpreads;

    sparkSpreads.reserve(nCalibrationTrails);
    stepConditions.reserve(nCalibrationTrails);
    calibrationPaths.reserve(nCalibrationTrails);

    for (Size i=0; i < nCalibrationTrails; ++i) {
        calibrationPaths.push_back(generator.next());

        sparkSpreads.push_back(boost::shared_ptr<FdmInnerValueCalculator>(
            new PathSparkSpreadPrice(heatRate, calibrationPaths.back().value,
                                     fuelShape, powerShape)));
        stepConditions.push_back(stepConditionFactory.build(
            vppMesh, fuelCostAddon,
            boost::shared_ptr<FdmInnerValueCalculator>(
                new PathFuelPrice(calibrationPaths.back().value, fuelShape)),
            sparkSpreads.back()));
    }


    const FdmLinearOpIterator iter = oneDimMesher->layout()->begin();

    // prices of all calibration paths for all states
    std::vector<Array> prices(nCalibrationTrails, Array(nStates, 0.0));

    // regression coefficients for all states and all exercise dates
    std::vector<std::vector<Array> > coeff(
        nStates, std::vector<Array>(exercise->dates().size(), Array()));

    // regression functions
    const Size dim = 1u;
    std::vector<boost::function1<Real, Array> > v(
        LsmBasisSystem::multiPathBasisSystem(dim,5u, LsmBasisSystem::Monomial));

    for (Size i=exercise->dates().size(); i > 0u; --i) {
        const Time t = grid.at(i);

        std::vector<Array> x(nCalibrationTrails, Array(dim));

        for (Size j=0; j < nCalibrationTrails; ++j) {
            x[j][0] = sparkSpreads[j]->innerValue(iter, t);
        }

        for (Size k=0; k < nStates; ++k) {
            std::vector<Real> y(nCalibrationTrails);

            for (Size j=0; j < nCalibrationTrails; ++j) {
                y[j] = prices[j][k];
            }
            coeff[k][i-1] = GeneralLinearLeastSquares(x, y, v).coefficients();

            for (Size j=0; j < nCalibrationTrails; ++j) {
                prices[j][k] = 0.0;
                for (Size l=0; l < v.size(); ++l) {
                    prices[j][k] += coeff[k][i-1][l]*v[l](x[j]);
                }
            }
        }

        for (Size j=0; j < nCalibrationTrails; ++j) {
            stepConditions[j]->applyTo(prices[j], grid.at(i));
        }
    }

    Real tmpValue = 0.0;
    for (Size i=0; i < nTrails; ++i) {
        Array x(dim), state(nStates, 0.0), contState(nStates, 0.0);

        const sample_type& path = (i % 2) ? generator.antithetic()
                                          : generator.next();

        const boost::shared_ptr<FdmInnerValueCalculator> fuelPrices(
            new PathFuelPrice(path.value, fuelShape));

        const boost::shared_ptr<FdmInnerValueCalculator> sparkSpreads(
            new PathSparkSpreadPrice(heatRate, path.value,
                                     fuelShape, powerShape));

        for (Size j=exercise->dates().size(); j > 0u; --j) {
            const Time t = grid.at(j);
            const Real fuelPrice = fuelPrices->innerValue(iter, t);
            const Real sparkSpread = sparkSpreads->innerValue(iter, t);
            const Real startUpCost
                    = startUpFixCost + (fuelPrice + fuelCostAddon)*startUpFuel;

            x[0] = sparkSpread;
            for (Size k=0; k < nStates; ++k) {
                contState[k] = 0.0;
                for (Size l=0; l < v.size(); ++l) {
                    contState[k] += coeff[k][j-1][l]*v[l](x);
                }
            }

            const Real pMinFlow = pMin*(sparkSpread - heatRate*fuelCostAddon);
            const Real pMaxFlow = pMax*(sparkSpread - heatRate*fuelCostAddon);

            // rollback continuation states and the path states
            for (Size i=0; i < 2*tMinUp; ++i) {
                if (i < tMinUp) {
                    state[i]    += pMinFlow;
                    contState[i]+= pMinFlow;
                }
                else {
                    state[i]    += pMaxFlow;
                    contState[i]+= pMaxFlow;
                }
            }

            // dynamic programming using the continuation values
            Array retVal(nStates);
            for (Size i=0; i < tMinUp-1; ++i) {
                retVal[i] = retVal[tMinUp + i]
                          = (contState[i+1] > contState[tMinUp + i+1])?
                                          state[i+1] : state[tMinUp + i+1];
            }

            if (contState[2*tMinUp] >=
                std::max(contState[tMinUp-1], contState[2*tMinUp-1])) {
                retVal[tMinUp-1] = retVal[2*tMinUp-1] = state[2*tMinUp];
            }
            else if (contState[tMinUp-1] >= contState[2*tMinUp-1]) {
                retVal[tMinUp-1] = retVal[2*tMinUp-1] = state[tMinUp-1];
            }
            else {
                retVal[tMinUp-1] = retVal[2*tMinUp-1] = state[2*tMinUp-1];
            }

            for (Size i=0; i < tMinDown-1; ++i) {
                retVal[2*tMinUp + i] = state[2*tMinUp + i+1];
            }

            if (contState.back() >=
                std::max(contState.front(), contState[tMinUp]) - startUpCost) {
                retVal.back() = state.back();
            }
            else if (contState.front() >  contState[tMinUp]) {
                retVal.back() = state.front()-startUpCost;
            }
            else {
                retVal.back() = state[tMinUp]-startUpCost;
            }
            state = retVal;
        }
        tmpValue+=0.5*state.back();
        if ((i%2)) {
            npv.add(tmpValue, 1.0);
            tmpValue = 0.0;
        }
    }

    npvMC = npv.mean();
    errorMC = npv.errorEstimate();
    if (std::fabs(npvMC-fdmPrice) > 3*errorMC) {
        BOOST_ERROR("Failed to reproduce Least Square Monte-Carlo price"
                   << "\n    calculated   : " << npvMC
                   << "\n    error        : " << errorMC
                   << "\n    expected FDM : " << fdmPrice);
    }
}
boost::shared_ptr<ELSNotionalProtectedPricer> MCELSNotionalProtectedEngine::pathPricer() const{

   /*boost::shared_ptr<GeneralizedBlackScholesProcess> process =
		  boost::dynamic_pointer_cast<GeneralizedBlackScholesProcess>(
	                                               process_->process(0));
    QL_REQUIRE(process, "Black-Scholes process required");*/

    TimeGrid theTimeGrid = timeGrid();

    const std::vector<Time> & times = theTimeGrid.mandatoryTimes();
    Size numberOfTimes = times.size();
	Size numAssets = process_->size();
	Size pastFixingNum=this->arguments_.pastFixingDateNum;
	const std::vector<Date> & fixings = this->arguments_.fixingDates;
	const std::vector<boost::shared_ptr<StockIndex>>& refIndex=arguments_.refIndex;
	DayCounter dayCounter = this->arguments_.dayCounter;
	std::vector<Real> initialValues = this->arguments_.initialValues;
	std::vector<Real> dividends = this->arguments_.dividends; // 후에 TS로 수정

	Real redemCoupon= this->arguments_.redemCoupon;
	std::vector<Date> remainfixings;
	
	//오늘일자를 TS에서 가져옴.
    Date today = Settings::instance().evaluationDate();

	Size numberOfFixings = fixings.size();

	for(Size i=0;i<numberOfFixings;++i){
		if(fixings[i]>today){
			remainfixings.push_back(fixings[i]);
		}
	}

    Size numberOfRemainFixings = remainfixings.size();

	additionalStats_.resize(numberOfTimes+pastFixingNum);
	underlyingValue_.resize(numAssets);
    QL_REQUIRE(numberOfRemainFixings == numberOfTimes, "Invalid dates/times");
	
    std::vector<Size> timePositions(numberOfTimes);
    Array discountFactors(numberOfTimes);

    for (Size i = 0; i < numberOfTimes; ++i) {
        //timePositions[i] = theTimeGrid.index(times[i]);
        discountFactors[i] = discountTS_->discount(times[i]);
    }
	
	Matrix earlyExValues_Chg(numAssets,numberOfTimes,Null<Real>());

	Array x0(numAssets);
	Array drift(numAssets);
	Array sigma(numAssets);

	const std::vector<Real>& earlyExValues = this->arguments_.earlyExTriggers;

	for(Size i=0;i<numAssets;++i){
		
		if(process_->process(i)->x0()<0.00001){
			
			x0[i]=std::log((refIndex[i]->fixing(Settings::instance().evaluationDate()))/initialValues[i]);
			underlyingValue_[i]=refIndex[i]->fixing(Settings::instance().evaluationDate());
		}else{
			x0[i]=std::log((process_->process(i)->x0())/initialValues[i]);
			underlyingValue_[i]=process_->process(i)->x0();
		}
		
		sigma[i]=process_->process(i)->diffusion(times[0],1.0) ; // 변동성 조정 필요

		if(process_->process(i)->drift(times[0],1.0)<0.00001){
			drift[i]= discountTS_->zeroRate(times.back(),Compounded,Annual,false) - dividends[i]; //discountTS_->zeroRate(times.back(),Compounded,Annual,false);
		}else{
			drift[i]= process_->process(i)->drift(times[0],1.0) - dividends[i]; //discountTS_->zeroRate(times.back(),Compounded,Annual,false);
		}

		//drift 이거  dividend 추가해야함.

		for(Size j=0;j<numberOfTimes;++j){
			earlyExValues_Chg[i][j]=(std::log(earlyExValues[j])-(drift[i]-0.5*sigma[i]*sigma[i])*times[j]);
			
		}
	}

    return boost::shared_ptr<ELSNotionalProtectedPricer>(
                    new ELSNotionalProtectedPricer(times,process_,x0,discountFactors,earlyExValues_Chg,
                                  redemCoupon,pastFixingNum,additionalStats_));
}
コード例 #28
0
    Real DigitalPathPricer::operator()(const Path& path) const {
        Size n = path.length();
        QL_REQUIRE(n>1, "the path cannot be empty");

        Real log_asset_price = std::log(path.front());
        Real x, y;
        Volatility vol;
        TimeGrid timeGrid = path.timeGrid();
        Time dt;
        std::vector<Real> u = sequenceGen_.nextSequence().value;
        Real log_strike = std::log(payoff_->strike());

        Size i;
        switch (payoff_->optionType()) {
          case Option::Call:
            for (i=0; i<n-1; i++) {
                x = std::log(path[i+1]/path[i]);
                // terminal or initial vol?
                vol = diffProcess_->diffusion(timeGrid[i+1],
                                              std::exp(log_asset_price));
                // vol = diffProcess_->diffusion(timeGrid[i+2],
                //                               std::exp(log_asset_price+x));
                dt = timeGrid.dt(i);
                y = log_asset_price +
                    0.5*(x + std::sqrt(x*x-2*vol*vol*dt*std::log((1-u[i]))));
                // cross the strike
                if (y >= log_strike) {
                    if (exercise_->payoffAtExpiry()) {
                        return payoff_->cashPayoff() *
                            discountTS_->discount(path.timeGrid().back());
                    } else {
                        // the discount should be calculated at the exercise
                        // time between path.timeGrid()[i+1] and
                        // path.timeGrid()[i+2]
                        return payoff_->cashPayoff() *
                            discountTS_->discount(path.timeGrid()[i+1]);
                    }
                }
                log_asset_price += x;
            }
            break;
          case Option::Put:
            for (i=0; i<n-1; i++) {
                x = std::log(path[i+1]/path[i]);
                // terminal or initial vol?
                // initial (timeGrid[i+1]) for the time being
                vol = diffProcess_->diffusion(timeGrid[i+1],
                                              std::exp(log_asset_price));
                // vol = diffProcess_->diffusion(timeGrid[i+2],
                //                               std::exp(log_asset_price+x));
                dt = timeGrid.dt(i);
                y = log_asset_price +
                    0.5*(x - std::sqrt(x*x - 2*vol*vol*dt*std::log(u[i])));
                if (y <= log_strike) {
                    if (exercise_->payoffAtExpiry()) {
                        return payoff_->cashPayoff() *
                            discountTS_->discount(path.timeGrid().back());
                    } else {
                        // the discount should be calculated at the exercise
                        // time between path.timeGrid()[i+1] and
                        // path.timeGrid()[i+2]
                        return payoff_->cashPayoff() *
                            discountTS_->discount(path.timeGrid()[i+1]);
                    }
                }
                log_asset_price += x;
            }
            break;
          default:
            QL_FAIL("unknown option type");
        }

        return 0.0;
    }
コード例 #29
0
		//! \brief Calculate the NPV of the remaining cash flow at default time \f$ \tau \f$.
		//!
		//! The calculation method used here is based on CIR model.
		virtual Real defaultNPV(const MultiPath& path, Time defaultTime) const {
			//find short rate at default time
			TimeGrid timeGrid = path[0].timeGrid();

			auto defaultPos = timeGrid.index(defaultTime);
			Real shortRate = path[0][defaultPos];

			//calculate discount factor from reference time to the default time
			Time previousTime = timeGrid[0];
			Real discountFactor = 1.0;
			for (auto i = 0; i <= defaultPos; ++i){
				discountFactor *= std::exp(-path[0].value(i) * (timeGrid[i] - previousTime));
				previousTime = timeGrid[i];
			}

			boost::shared_ptr<const MCVanillaSwapUCVAEngine> engine = engine_.lock();
			VanillaSwap::arguments* arguments = dynamic_cast<VanillaSwap::arguments*>(engine->getArguments());
			Handle<YieldTermStructure> discountCurve = engine->discountCurve();

			Date referenceDate = discountCurve->referenceDate();
			std::vector<Date> fixedDates = arguments->fixedPayDates;
			std::vector<Date> floatingDates = arguments->floatingPayDates;
			// transfer payment Dates to Times
			std::vector<Real> fixedTimes;
			std::vector<Real> floatingTimes;
			for (int i = 0; i != fixedDates.size(); ++i){
				fixedTimes.push_back(engine->instrument()->fixedDayCount().yearFraction(referenceDate, fixedDates[i]));
			}
			for (int i = 0; i != floatingDates.size(); ++i){
				floatingTimes.push_back(engine->instrument()->floatingDayCount().yearFraction(referenceDate, floatingDates[i]));
			}
			// calculate the corresponding discount factors of each leg to default time
			std::vector<Real> fixedDiscountFactor;
			std::vector<Real> floatingDiscountFactor;
			int fixedIndex = 0;
			int floatingIndex = 0;
			for (int i = 0; i != fixedTimes.size(); ++i){
				if (fixedTimes[i] >= defaultTime){
					fixedDiscountFactor.push_back(engine->Model()->discountBond(0.0, fixedTimes[i] - defaultTime, shortRate));
				}
				else{
					++fixedIndex;
				}
			}
			for (int i = 0; i != floatingTimes.size(); ++i){
				if (floatingTimes[i] >= defaultTime){
					floatingDiscountFactor.push_back(engine->Model()->discountBond(0.0, floatingTimes[i] - defaultTime, shortRate));
				}
				else{
					++floatingIndex;
				}
			}

			//calculate the NPV(tau)
			Real NPVtau = 0.0;
			NPVtau += arguments->nominal * (1. - floatingDiscountFactor.back());
			for (int m = 0; m != floatingDiscountFactor.size(); ++m){
				NPVtau += arguments->nominal * arguments->floatingSpreads[m + floatingIndex] * floatingDiscountFactor[m];
			}
			for (int m = 0; m != fixedDiscountFactor.size(); ++m){
				NPVtau -= arguments->fixedCoupons[m + fixedIndex] * fixedDiscountFactor[m];
			}

			if (arguments->type == QuantLib::VanillaSwap::Payer){
				NPVtau = NPVtau;
			}
			else{
				NPVtau = -NPVtau;
			}
			return NPVtau * discountFactor;
		}
コード例 #30
0
LongstaffSchwartzProxyPathPricer::LongstaffSchwartzProxyPathPricer(
    const TimeGrid &times,
    const boost::shared_ptr<EarlyExercisePathPricer<PathType> > &pricer,
    const boost::shared_ptr<YieldTermStructure> &termStructure)
    : LongstaffSchwartzPathPricer<PathType>(times, pricer, termStructure),
      coeffItm_(times.size() - 1), coeffOtm_(times.size() - 1) {}