This example shows the use of interest-rate market models.
#if !defined(BOOST_ALL_NO_LIB) && defined(BOOST_MSVC)
#endif
#include <sstream>
#include <iostream>
#include <ctime>
std::vector<std::vector<Matrix>>
theVegaBumps(bool factorwiseBumping, const ext::shared_ptr<MarketModel>& marketModel, bool doCaps) {
Real multiplierCutOff = 50.0;
Real projectionTolerance = 1E-4;
Size numberRates= marketModel->numberOfRates();
std::vector<VolatilityBumpInstrumentJacobian::Cap> caps;
if (doCaps)
{
Rate capStrike = marketModel->initialRates()[0];
for (
Size i=0; i< numberRates-1; i=i+1)
{
caps.push_back(nextCap);
}
}
std::vector<VolatilityBumpInstrumentJacobian::Swaption> swaptions(numberRates);
for (
Size i=0; i < numberRates; ++i)
{
swaptions[i].startIndex_ = i;
swaptions[i].endIndex_ = numberRates;
}
factorwiseBumping);
swaptions,
caps,
multiplierCutOff,
projectionTolerance);
std::vector<std::vector<Matrix>> theBumps;
return theBumps;
}
int Bermudan()
{
std::vector<Real> rateTimes(numberRates+1);
for (
Size i=0; i < rateTimes.size(); ++i)
rateTimes[i] = firstTime + i*accrual;
std::vector<Real> paymentTimes(numberRates);
std::vector<Real> accruals(numberRates,accrual);
for (
Size i=0; i < paymentTimes.size(); ++i)
paymentTimes[i] = firstTime + (i+1)*accrual;
std::vector<Real> strikes(numberRates,fixedRate);
MultiStepSwap payerSwap(rateTimes, accruals, accruals, paymentTimes,
fixedRate, true);
MultiStepSwap receiverSwap(rateTimes, accruals, accruals, paymentTimes,
fixedRate, false);
std::vector<Rate> exerciseTimes(rateTimes);
exerciseTimes.pop_back();
std::vector<Rate> swapTriggers(exerciseTimes.size(), fixedRate);
std::vector<std::vector<NodeData>> collectedData;
std::vector<std::vector<Real>> basisCoefficients;
Size trainingPaths = 65536;
Size vegaPaths = 16384*64;
std::cout << "training paths, " << trainingPaths << "\n";
std::cout << "paths, " << paths << "\n";
std::cout << "vega Paths, " << vegaPaths << "\n";
#ifdef _DEBUG
trainingPaths = 512;
paths = 1024;
vegaPaths = 1024;
#endif
Real initialNumeraireValue = 0.95;
Size numberOfFactors = std::min<Size>(5,numberRates);
Spread displacementLevel =0.02;
std::vector<Rate> initialRates(numberRates,rateLevel);
std::vector<Volatility> volatilities(numberRates, volLevel);
std::vector<Spread> displacements(numberRates, displacementLevel);
rateTimes,volLevel,
beta,gamma);
volatilities,
ext::make_shared<ExponentialForwardCorrelation>(correlations),
evolution,
numberOfFactors,
initialRates,
displacements);
auto marketModel = ext::make_shared<FlatVol>(calibration);
SobolBrownianGenerator::Diagonal, seed);
std::vector<Size> numeraires( moneyMarketMeasure(evolution));
generatorFactory,
numeraires
);
auto evolverPtr = ext::make_shared<LogNormalFwdRatePc>(evolver);
int t1= clock();
collectNodeData(evolver,
receiverSwap,
basisSystem,
nullRebate,
control,
trainingPaths,
collectedData);
int t2 = clock();
genericLongstaffSchwartzRegression(collectedData,
basisCoefficients);
basisSystem, basisCoefficients,
evolution, numeraires,
nullRebate, control);
exerciseStrategy, payerSwap);
receiverSwap, exerciseStrategy,
allProducts.
add(payerSwap);
allProducts.
add(receiverSwap);
allProducts.
add(bermudanProduct);
allProducts.
add(callableProduct);
initialNumeraireValue);
accounter.multiplePathValues (stats,paths);
int t3 = clock();
std::vector<Real> means(stats.
mean());
std::cout << mean << "\n";
std::cout <<
" time to build strategy, " << (t2-t1)/
static_cast<Real>(CLOCKS_PER_SEC)<<
", seconds.\n";
std::cout <<
" time to price, " << (t3-t2)/
static_cast<Real>(CLOCKS_PER_SEC)<<
", seconds.\n";
Size pathsToDoVegas = vegaPaths;
for (
Size i=0; i < 4; ++i)
{
bool allowFactorwiseBumping = i % 2 > 0 ;
bool doCaps = i / 2 > 0 ;
generatorFactory,
numeraires
) ;
accruals,
strikes,
receive);
exerciseStrategy);
std::vector<std::vector<Matrix>> theBumps(theVegaBumps(allowFactorwiseBumping,
marketModel,
doCaps));
accountingEngineVegas(ext::make_shared<LogNormalFwdRateEuler>(evolverEuler),
callableProductPathwisePtr,
marketModel,
theBumps,
initialNumeraireValue);
std::vector<Real> values,errors;
accountingEngineVegas.multiplePathValues(values,errors,pathsToDoVegas);
std::cout << "vega output \n";
std::cout << " factorwise bumping " << allowFactorwiseBumping << "\n";
std::cout << " doCaps " << doCaps << "\n";
std::cout <<
" price estimate, " << values[
r++] <<
"\n";
for (
Size i=0; i < numberRates; ++i, ++
r)
std::cout <<
" Delta, " << i <<
", " << values[
r] <<
", " << errors[
r] <<
"\n";
for (;
r < values.size(); ++
r)
{
std::cout <<
" vega, " <<
r - 1 - numberRates<<
", " << values[
r] <<
" ," << errors[
r] <<
"\n";
}
std::cout << " total Vega, " << totalVega << "\n";
}
auto upperEvolver = ext::make_shared<LogNormalFwdRatePc>(ext::make_shared<FlatVol>(calibration),
uFactory,
numeraires
);
std::vector<ext::shared_ptr<MarketModelEvolver>> innerEvolvers;
for (
Size s=0;
s < isExerciseTime.size(); ++
s)
{
{
auto e = ext::make_shared<LogNormalFwdRatePc>(ext::make_shared<FlatVol>(calibration),
uFactory,
numeraires,
innerEvolvers.push_back(e);
}
}
innerEvolvers,
receiverSwap,
nullRebate,
receiverSwap,
nullRebate,
exerciseStrategy,
initialNumeraireValue);
int t4 = clock();
uEngine.multiplePathValues(uStats,outerPaths,innerPaths);
Real upperBound = uStats.mean();
Real upperSE = uStats.errorEstimate();
int t5=clock();
std::cout << " Upper - lower is, " << upperBound << ", with standard error " << upperSE << "\n";
std::cout <<
" time to compute upper bound is, " << (t5-t4)/
static_cast<Real>(CLOCKS_PER_SEC) <<
", seconds.\n";
return 0;
}
int InverseFloater(
Real rateLevel)
{
Real fixedMultiplier = 2.0;
Real floatingSpread =0.0;
bool payer = true;
std::vector<Real> rateTimes(numberRates+1);
for (
Size i=0; i < rateTimes.size(); ++i)
rateTimes[i] = firstTime + i*accrual;
std::vector<Real> paymentTimes(numberRates);
std::vector<Real> accruals(numberRates,accrual);
std::vector<Real> fixedStrikes(numberRates,strike);
std::vector<Real> floatingSpreads(numberRates,floatingSpread);
std::vector<Real> fixedMultipliers(numberRates,fixedMultiplier);
for (
Size i=0; i < paymentTimes.size(); ++i)
paymentTimes[i] = firstTime + (i+1)*accrual;
rateTimes,
accruals,
accruals,
fixedStrikes,
fixedMultipliers,
floatingSpreads,
paymentTimes,
payer);
std::vector<Rate> exerciseTimes(rateTimes);
exerciseTimes.pop_back();
std::vector<Rate> swapTriggers(exerciseTimes.size(), trigger);
std::vector<std::vector<NodeData>> collectedData;
std::vector<std::vector<Real>> basisCoefficients;
Size trainingPaths = 65536;
#ifdef _DEBUG
trainingPaths = 8192;
paths = 8192;
vegaPaths = 1024;
#endif
std::cout << " inverse floater \n";
std::cout << " fixed strikes : " << strike << "\n";
std::cout << " number rates : " << numberRates << "\n";
std::cout << "training paths, " << trainingPaths << "\n";
std::cout << "paths, " << paths << "\n";
std::cout << "vega Paths, " << vegaPaths << "\n";
std::cout << " rate level " << rateLevel << "\n";
Real initialNumeraireValue = 0.95;
Size numberOfFactors = std::min<Size>(5,numberRates);
Spread displacementLevel =0.02;
std::vector<Rate> initialRates(numberRates,rateLevel);
std::vector<Volatility> volatilities(numberRates, volLevel);
std::vector<Spread> displacements(numberRates, displacementLevel);
rateTimes,volLevel,
beta,gamma);
volatilities,
ext::make_shared<ExponentialForwardCorrelation>(correlations),
evolution,
numberOfFactors,
initialRates,
displacements);
auto marketModel = ext::make_shared<FlatVol>(calibration);
SobolBrownianGenerator::Diagonal, seed);
generatorFactory,
numeraires
);
auto evolverPtr = ext::make_shared<LogNormalFwdRatePc>(evolver);
int t1= clock();
inverseFloater,
basisSystem,
nullRebate,
control,
trainingPaths,
collectedData);
int t2 = clock();
basisCoefficients);
basisSystem, basisCoefficients,
evolution, numeraires,
nullRebate, control);
inverseFloater, exerciseStrategy,
allProducts.
add(inverseFloater);
allProducts.
add(callableProduct);
initialNumeraireValue);
accounter.multiplePathValues (stats,paths);
int t3 = clock();
std::vector<Real> means(stats.
mean());
std::cout << mean << "\n";
std::cout <<
" time to build strategy, " << (t2-t1)/
static_cast<Real>(CLOCKS_PER_SEC)<<
", seconds.\n";
std::cout <<
" time to price, " << (t3-t2)/
static_cast<Real>(CLOCKS_PER_SEC)<<
", seconds.\n";
Size pathsToDoVegas = vegaPaths;
for (
Size i=0; i < 4; ++i)
{
bool allowFactorwiseBumping = i % 2 > 0 ;
bool doCaps = i / 2 > 0 ;
generatorFactory,
numeraires
) ;
rateTimes,
accruals,
accruals,
fixedStrikes,
fixedMultipliers,
floatingSpreads,
paymentTimes,
payer);
exerciseStrategy);
std::vector<std::vector<Matrix>> theBumps(theVegaBumps(allowFactorwiseBumping,
marketModel,
doCaps));
accountingEngineVegas(ext::make_shared<LogNormalFwdRateEuler>(evolverEuler),
callableProductPathwisePtr,
marketModel,
theBumps,
initialNumeraireValue);
std::vector<Real> values,errors;
accountingEngineVegas.multiplePathValues(values,errors,pathsToDoVegas);
std::cout << "vega output \n";
std::cout << " factorwise bumping " << allowFactorwiseBumping << "\n";
std::cout << " doCaps " << doCaps << "\n";
std::cout <<
" price estimate, " << values[
r++] <<
"\n";
for (
Size i=0; i < numberRates; ++i, ++
r)
std::cout <<
" Delta, " << i <<
", " << values[
r] <<
", " << errors[
r] <<
"\n";
for (;
r < values.size(); ++
r)
{
std::cout <<
" vega, " <<
r - 1 - numberRates<<
", " << values[
r] <<
" ," << errors[
r] <<
"\n";
}
std::cout << " total Vega, " << totalVega << "\n";
}
auto upperEvolver = ext::make_shared<LogNormalFwdRatePc>(ext::make_shared<FlatVol>(calibration),
uFactory,
numeraires
);
std::vector<ext::shared_ptr<MarketModelEvolver>> innerEvolvers;
for (
Size s=0;
s < isExerciseTime.size(); ++
s)
{
{
auto e = ext::make_shared<LogNormalFwdRatePc>(ext::make_shared<FlatVol>(calibration),
uFactory,
numeraires ,
innerEvolvers.push_back(e);
}
}
innerEvolvers,
inverseFloater,
nullRebate,
inverseFloater,
nullRebate,
exerciseStrategy,
initialNumeraireValue);
int t4 = clock();
uEngine.multiplePathValues(uStats,outerPaths,innerPaths);
Real upperBound = uStats.mean();
Real upperSE = uStats.errorEstimate();
int t5=clock();
std::cout << " Upper - lower is, " << upperBound << ", with standard error " << upperSE << "\n";
std::cout <<
" time to compute upper bound is, " << (t5-t4)/
static_cast<Real>(CLOCKS_PER_SEC) <<
", seconds.\n";
return 0;
}
int main()
{
try {
for (
Size i=5; i < 10; ++i)
InverseFloater(i/100.0);
return 0;
} catch (std::exception& e) {
std::cerr << e.what() << std::endl;
return 1;
} catch (...) {
std::cerr << "unknown error" << std::endl;
return 1;
}
}
Black-formula calculator class.
Engine collecting cash flows along a market-model simulation.
const EvolutionDescription & evolution() const override
cloning proxy to an underlying object
Market-model evolution description.
const std::vector< Time > & evolutionTimes() const
empirical-distribution risk measures
Statistics analysis of N-dimensional (sequence) data.
std::vector< Real > mean() const
void add(const Clone< MarketModelMultiProduct > &, Real multiplier=1.0)
Composition of one or more market-model products.
void GetVegaBumps(std::vector< std::vector< Matrix > > &theBumps) const
Engine collecting cash flows along a market-model simulation for doing pathwise computation of Deltas...
Market-model engine for upper-bound estimation.
statistics tool with risk measures
exponential correlation matrix
Real Spread
spreads on interest rates
std::size_t Size
size of a container
volatility model for libor market models
exponential correlation model for libor market models
Real genericLongstaffSchwartzRegression(std::vector< std::vector< NodeData > > &simulationData, std::vector< std::vector< Real > > &basisCoefficients)
returns the biased estimate obtained while regressing
std::valarray< bool > isInSubset(const std::vector< Time > &set, const std::vector< Time > &subset)
void collectNodeData(MarketModelEvolver &evolver, MarketModelMultiProduct &product, MarketModelNodeDataProvider &dataProvider, MarketModelExerciseValue &rebate, MarketModelExerciseValue &control, Size numberOfPaths, std::vector< std::vector< NodeData > > &collectedData)
std::vector< Size > moneyMarketMeasure(const EvolutionDescription &evol)
Calendar for reproducing theoretical calculations.
ext::shared_ptr< YieldTermStructure > r
Global definitions and compiler switches.
Integral of a one-dimensional function using segment algorithm.
Simple day counter for reproducing theoretical calculations.
Simplex optimization method.