LongstaffSchwartzExerciseStrategy::LongstaffSchwartzExerciseStrategy( const Clone<MarketModelBasisSystem>& basisSystem, const std::vector<std::vector<Real> >& basisCoefficients, const EvolutionDescription& evolution, const std::vector<Size>& numeraires, const Clone<MarketModelExerciseValue>& exercise, const Clone<MarketModelExerciseValue>& control) : basisSystem_(basisSystem), basisCoefficients_(basisCoefficients), exercise_(exercise), control_(control), numeraires_(numeraires) { checkCompatibility(evolution, numeraires); relevantTimes_ = evolution.evolutionTimes(); isBasisTime_.resize(relevantTimes_.size()); isBasisTime_ = isInSubset(relevantTimes_, basisSystem_->evolution().evolutionTimes()); isRebateTime_.resize(relevantTimes_.size()); isRebateTime_ = isInSubset(relevantTimes_, exercise_->evolution().evolutionTimes()); isControlTime_.resize(relevantTimes_.size()); isControlTime_ = isInSubset(relevantTimes_, control_->evolution().evolutionTimes()); exerciseIndex_ = std::vector<Size>(relevantTimes_.size()); isExerciseTime_.resize(relevantTimes_.size(), false); std::valarray<bool> v = exercise_->isExerciseTime(); Size exercises = 0, idx = 0; Size i; for (i=0; i<relevantTimes_.size(); ++i) { exerciseIndex_[i] = exercises; if (isRebateTime_[i]) { isExerciseTime_[i] = v[idx++]; if (isExerciseTime_[i]) { exerciseTimes_.push_back(relevantTimes_[i]); ++exercises; } } } std::vector<Time> rateTimes = evolution.rateTimes(); std::vector<Time> rebateTimes = exercise_->possibleCashFlowTimes(); rebateDiscounters_.reserve(rebateTimes.size()); for (i=0; i<rebateTimes.size(); ++i) rebateDiscounters_.push_back( MarketModelDiscounter(rebateTimes[i], rateTimes)); std::vector<Time> controlTimes = control_->possibleCashFlowTimes(); controlDiscounters_.reserve(controlTimes.size()); for (i=0; i<controlTimes.size(); ++i) controlDiscounters_.push_back( MarketModelDiscounter(controlTimes[i], rateTimes)); std::vector<Size> basisSizes = basisSystem_->numberOfFunctions(); basisValues_.resize(basisSystem_->numberOfExercises()); for (i=0; i<basisValues_.size(); ++i) basisValues_[i].resize(basisSizes[i]); }
ProxyGreekEngine::ProxyGreekEngine( const boost::shared_ptr<MarketModelEvolver>& evolver, const std::vector< std::vector<boost::shared_ptr<ConstrainedEvolver> > >& constrainedEvolvers, const std::vector<std::vector<std::vector<Real> > >& diffWeights, const std::vector<Size>& startIndexOfConstraint, const std::vector<Size>& endIndexOfConstraint, const Clone<MarketModelMultiProduct>& product, Real initialNumeraireValue) : originalEvolver_(evolver), constrainedEvolvers_(constrainedEvolvers), diffWeights_(diffWeights), startIndexOfConstraint_(startIndexOfConstraint), endIndexOfConstraint_(endIndexOfConstraint), product_(product), initialNumeraireValue_(initialNumeraireValue), numberProducts_(product->numberOfProducts()), numerairesHeld_(product->numberOfProducts()), numberCashFlowsThisStep_(product->numberOfProducts()), cashFlowsGenerated_(product->numberOfProducts()) { for (Size i=0; i<numberProducts_; ++i) cashFlowsGenerated_[i].resize( product_->maxNumberOfCashFlowsPerProductPerStep()); const std::vector<Time>& cashFlowTimes = product_->possibleCashFlowTimes(); const std::vector<Rate>& rateTimes = product_->evolution().rateTimes(); Size n = cashFlowTimes.size(); discounters_.reserve(n); for (Size j=0; j<n; ++j) discounters_.push_back(MarketModelDiscounter(cashFlowTimes[j], rateTimes)); const std::vector<Rate>& evolutionTimes = product_->evolution().evolutionTimes(); constraints_.resize(evolutionTimes.size()); constraintsActive_.resize(evolutionTimes.size()); }
void collectNodeData(MarketModelEvolver& evolver, MarketModelMultiProduct& product, MarketModelNodeDataProvider& dataProvider, MarketModelExerciseValue& rebate, MarketModelExerciseValue& control, Size numberOfPaths, std::vector<std::vector<NodeData> >& collectedData) { std::vector<Real> numerairesHeld; QL_REQUIRE(product.numberOfProducts() == 1, "a single product is required"); // TODO: check that all objects have compatible evolutions // (same rate times; evolution times for product, basis // system, rebate and control must be subsets of the passed // evolution times; rebate, control and basis system must have // the same exercise---not evolution---times) std::vector<Size> numberCashFlowsThisStep(1); std::vector<std::vector<CashFlow> > cashFlowsGenerated(1); cashFlowsGenerated[0].resize( product.maxNumberOfCashFlowsPerProductPerStep()); std::vector<Time> rateTimes = product.evolution().rateTimes(); std::vector<Time> cashFlowTimes = product.possibleCashFlowTimes(); std::vector<Time> rebateTimes = rebate.possibleCashFlowTimes(); std::vector<Time> controlTimes = control.possibleCashFlowTimes(); Size i, n; n = cashFlowTimes.size(); std::vector<MarketModelDiscounter> productDiscounters; productDiscounters.reserve(n); for (i=0; i<n; ++i) productDiscounters.push_back( MarketModelDiscounter(cashFlowTimes[i], rateTimes)); n = rebateTimes.size(); std::vector<MarketModelDiscounter> rebateDiscounters; rebateDiscounters.reserve(n); for (i=0; i<n; ++i) rebateDiscounters.push_back( MarketModelDiscounter(rebateTimes[i], rateTimes)); n = controlTimes.size(); std::vector<MarketModelDiscounter> controlDiscounters; controlDiscounters.reserve(n); for (i=0; i<n; ++i) controlDiscounters.push_back( MarketModelDiscounter(controlTimes[i], rateTimes)); EvolutionDescription evolution = product.evolution(); const std::vector<Size>& numeraires = evolver.numeraires(); std::vector<Time> evolutionTimes = evolution.evolutionTimes(); std::valarray<bool> isProductTime = isInSubset(evolutionTimes, product.evolution().evolutionTimes()); std::valarray<bool> isRebateTime = isInSubset(evolutionTimes, rebate.evolution().evolutionTimes()); std::valarray<bool> isControlTime = isInSubset(evolutionTimes, control.evolution().evolutionTimes()); std::valarray<bool> isBasisTime = isInSubset(evolutionTimes, dataProvider.evolution().evolutionTimes()); std::valarray<bool> isExerciseTime(false,evolutionTimes.size()); std::valarray<bool> v = rebate.isExerciseTime(); Size exercises = 0; for (i=0; i<evolutionTimes.size(); ++i) { if (isRebateTime[i]) { isExerciseTime[i] = v[exercises]; ++exercises; } } collectedData.resize(exercises+1); for (i=0; i<collectedData.size(); ++i) collectedData[i].resize(numberOfPaths); for (i=0; i<numberOfPaths; ++i) { evolver.startNewPath(); product.reset(); rebate.reset(); control.reset(); dataProvider.reset(); Real principalInNumerairePortfolio = 1.0; bool done = false; Size nextExercise = 0; collectedData[0][i].cumulatedCashFlows = 0.0; do { Size currentStep = evolver.currentStep(); evolver.advanceStep(); const CurveState& currentState = evolver.currentState(); Size numeraire = numeraires[currentStep]; if (isRebateTime[currentStep]) rebate.nextStep(currentState); if (isControlTime[currentStep]) control.nextStep(currentState); if (isBasisTime[currentStep]) dataProvider.nextStep(currentState); if (isExerciseTime[currentStep]) { NodeData& data = collectedData[nextExercise+1][i]; CashFlow exerciseValue = rebate.value(currentState); data.exerciseValue = exerciseValue.amount * rebateDiscounters[exerciseValue.timeIndex] .numeraireBonds(currentState, numeraire) / principalInNumerairePortfolio; dataProvider.values(currentState, data.values); CashFlow controlValue = control.value(currentState); data.controlValue = controlValue.amount * controlDiscounters[controlValue.timeIndex] .numeraireBonds(currentState, numeraire) / principalInNumerairePortfolio; data.cumulatedCashFlows = 0.0; data.isValid = true; ++nextExercise; } if (isProductTime[currentStep]) { done = product.nextTimeStep(currentState, numberCashFlowsThisStep, cashFlowsGenerated); for (Size j=0; j<numberCashFlowsThisStep[0]; ++j) { const CashFlow& cf = cashFlowsGenerated[0][j]; collectedData[nextExercise][i].cumulatedCashFlows += cf.amount * productDiscounters[cf.timeIndex] .numeraireBonds(currentState, numeraire) / principalInNumerairePortfolio; } } if (!done) { Size nextNumeraire = numeraires[currentStep+1]; principalInNumerairePortfolio *= currentState.discountRatio(numeraire, nextNumeraire); } } while (!done); // fill the remaining (un)collected data with nulls for (Size j = nextExercise; j < exercises; ++j) { NodeData& data = collectedData[j+1][i]; data.exerciseValue = data.controlValue = 0.0; data.cumulatedCashFlows = 0.0; data.isValid = false; } } }