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));
    }
    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));
    }
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_));
}
boost::shared_ptr<IRDLSCallablePricer>
MCIRDLSLSEngine::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<PayoffLeg> payoffLeg = arguments_.payoffLeg;
    QL_REQUIRE(payoffLeg, "IRDLS payoffLeg given");

	//const Handle<YieldTermStructure> &df=arguments_.df;
	//Frequency freq = arguments_.freq;

    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;
	std::vector<Date> remainfixings;

	Date today = Settings::instance().evaluationDate();
	const Size numberOfFixings = fixings.size();
	for(Size i=0;i<numberOfFixings;++i){
		if(fixings[i]>today){
			remainfixings.push_back(fixings[i]);
		}
	}
    const Size numberOfRemainFixings = remainfixings.size();

	additionalStats_.resize(numberOfTimes);

    QL_REQUIRE(numberOfRemainFixings == 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] = discountTS_->discount(times[i]);
	}
      //  forwardTermStructures[i] = Handle<YieldTermStructure>(
        //            new ImpliedTermStructure(riskFreeRate, fixings[i]));
    

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

    return boost::shared_ptr<IRDLSCallablePricer> (
							new IRDLSCallablePricer(payoffLeg,
													 timePositions,
													 process_,
													 discountFactors,
													 additionalStats_,
													 polynomialOrder,
													 polynomType));
}