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