📄 proxygreekengine.cpp
字号:
/* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
Copyright (C) 2006 Mark Joshi
This file is part of QuantLib, a free-software/open-source library
for financial quantitative analysts and developers - http://quantlib.org/
QuantLib is free software: you can redistribute it and/or modify it
under the terms of the QuantLib license. You should have received a
copy of the license along with this program; if not, please email
<quantlib-dev@lists.sf.net>. The license is also available online at
<http://quantlib.org/license.shtml>.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the license for more details.
*/
#include <ql/models/marketmodels/proxygreekengine.hpp>
#include <ql/models/marketmodels/evolutiondescription.hpp>
#include <ql/models/marketmodels/curvestate.hpp>
#include <ql/models/marketmodels/discounter.hpp>
#include <ql/models/marketmodels/constrainedevolver.hpp>
#include <algorithm>
namespace QuantLib {
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 ProxyGreekEngine::singlePathValues(
std::vector<Real>& values,
std::vector<std::vector<std::vector<Real> > >& modifiedValues) {
singleEvolverValues(*originalEvolver_, values, true);
for (Size i=0; i<constrainedEvolvers_.size(); ++i) {
for (Size j=0; j<constrainedEvolvers_[i].size(); ++j) {
constrainedEvolvers_[i][j]->setThisConstraint(
constraints_, constraintsActive_);
singleEvolverValues(*(constrainedEvolvers_[i][j]),
modifiedValues[i][j]);
}
}
}
void ProxyGreekEngine::multiplePathValues(
SequenceStatistics& stats,
std::vector<std::vector<SequenceStatistics> >& modifiedStats,
Size numberOfPaths) {
Size N = product_->numberOfProducts();
std::vector<Real> values(N);
std::vector<std::vector<std::vector<Real> > > modifiedValues;
modifiedValues.resize(constrainedEvolvers_.size());
for (Size i=0; i<modifiedValues.size(); ++i) {
modifiedValues[i].resize(constrainedEvolvers_[i].size());
for (Size j=0; j<modifiedValues[i].size(); ++j)
modifiedValues[i][j].resize(N);
}
std::vector<Real> results(N);
for (Size i=0; i<numberOfPaths; ++i) {
singlePathValues(values, modifiedValues);
stats.add(values);
for (Size j=0; j<diffWeights_.size(); ++j) {
for (Size k=0; k<diffWeights_[j].size(); ++k) {
const std::vector<Real>& weights = diffWeights_[j][k];
for (Size l=0; l<N; ++l) {
results[l] = weights[0]*values[l];
for (Size n=1; n<weights.size(); ++n)
results[l] += weights[n]*modifiedValues[j][n-1][l];
}
modifiedStats[j][k].add(results);
}
}
}
}
void ProxyGreekEngine::singleEvolverValues(MarketModelEvolver& evolver,
std::vector<Real>& values,
bool storeRates) {
std::fill(numerairesHeld_.begin(), numerairesHeld_.end(), 0.0);
Real weight = evolver.startNewPath();
product_->reset();
Real principalInNumerairePortfolio = 1.0;
if (storeRates) {
std::fill(constraintsActive_.begin(),
constraintsActive_.end(),
false);
}
bool done = false;
do {
Size thisStep = evolver.currentStep();
weight *= evolver.advanceStep();
done = product_->nextTimeStep(evolver.currentState(),
numberCashFlowsThisStep_,
cashFlowsGenerated_);
if (storeRates) {
constraints_[thisStep] = evolver.currentState().swapRate(
startIndexOfConstraint_[thisStep],
endIndexOfConstraint_[thisStep]);
constraintsActive_[thisStep] = true;
}
Size numeraire =
evolver.numeraires()[thisStep];
// for each product...
for (Size i=0; i<numberProducts_; ++i) {
// ...and each cash flow...
const std::vector<MarketModelMultiProduct::CashFlow>& cashflows =
cashFlowsGenerated_[i];
for (Size j=0; j<numberCashFlowsThisStep_[i]; ++j) {
// ...convert the cash flow to numeraires.
// This is done by calculating the number of
// numeraire bonds corresponding to such cash flow...
const MarketModelDiscounter& discounter =
discounters_[cashflows[j].timeIndex];
Real bonds = cashflows[j].amount *
discounter.numeraireBonds(evolver.currentState(),
numeraire);
// ...and adding the newly bought bonds to the number
// of numeraires held.
numerairesHeld_[i] +=
weight*bonds/principalInNumerairePortfolio;
}
}
if (!done) {
// The numeraire might change between steps. This implies
// that we might have to convert the numeraire bonds for
// this step into a corresponding amount of numeraire
// bonds for the next step. This can be done by changing
// the principal of the numeraire and updating the number
// of bonds in the numeraire portfolio accordingly.
Size nextNumeraire = evolver.numeraires()[thisStep+1];
principalInNumerairePortfolio *=
evolver.currentState().discountRatio(numeraire,
nextNumeraire);
}
} while (!done);
for (Size i=0; i<numerairesHeld_.size(); ++i)
values[i] = numerairesHeld_[i] * initialNumeraireValue_;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -