33#include <boost/preprocessor/iteration/local.hpp>
39 class FdmPCABasketInnerValue:
public FdmInnerValueCalculator {
41 FdmPCABasketInnerValue(
42 ext::shared_ptr<BasketPayoff>
payoff,
43 ext::shared_ptr<FdmMesher> mesher,
44 Array logS0,
const Array& vols,
45 std::vector<ext::shared_ptr<YieldTermStructure>> qTS,
46 ext::shared_ptr<YieldTermStructure> rTS,
51 logS0_(
std::move(logS0)), v_(vols*vols),
54 Q_(
std::move(Q)), l_(
std::move(l)),
55 cachedT_(Null<
Real>()),
58 Real innerValue(
const FdmLinearOpIterator& iter,
Time t)
override {
60 rf_ =
rTS_->discount(
t);
61 for (
Size i=0; i < n_; ++i)
62 qf_[i] = qTS_[i]->discount(
t);
65 for (
Size i=0; i < n_; ++i)
66 x[i] =
mesher_->location(iter, i);
68 const Array
S =
Exp(Q_*x - 0.5*v_*
t + logS0_)*qf_/rf_;
72 Real avgInnerValue(
const FdmLinearOpIterator& iter,
Time t)
override {
73 return innerValue(iter,
t);
78 const ext::shared_ptr<BasketPayoff>
payoff_;
79 const ext::shared_ptr<FdmMesher>
mesher_;
80 const Array logS0_, v_;
81 const std::vector<ext::shared_ptr<YieldTermStructure>> qTS_;
82 const ext::shared_ptr<YieldTermStructure>
rTS_;
92 std::vector<ext::shared_ptr<GeneralizedBlackScholesProcess> > processes,
94 std::vector<Size> xGrids,
97 : processes_(
std::move(processes)),
99 xGrids_(
std::move(xGrids)),
101 dampingSteps_(dampingSteps),
102 schemeDesc_(schemeDesc) {
107 "correlation matrix has the wrong size.");
109 "wrong number of xGrids is given.");
112 [
this](
const auto& p) { registerWith(p); });
116 std::vector<ext::shared_ptr<GeneralizedBlackScholesProcess> > processes,
120 std::move(processes),
std::move(
rho),
std::vector<
Size>(1, xGrid), tGrid, dampingSteps, schemeDesc)
125 #ifndef PDE_MAX_SUPPORTED_DIM
126 #define PDE_MAX_SUPPORTED_DIM 4
129 "This engine does not support " <<
processes_.size() <<
" underlyings. "
131 <<
"Please change preprocessor constant PDE_MAX_SUPPORTED_DIM and recompile "
132 <<
"if a larger number of underlyings is needed.");
136 const Real sqrtT = std::sqrt(maturity);
142 const Array vols = stdDev / sqrtT;
149 const Real eps = 1e-4;
150 std::vector<ext::shared_ptr<Fdm1dMesher> > meshers;
156 QL_REQUIRE(xGrid >= 4,
"minimum grid size is four");
158 const Real xStepStize = (1.0-2*eps)/(xGrid-1);
160 std::vector<Real> x(xGrid);
161 for (
Size j=0; j < xGrid; ++j)
162 x[j] = 1.3*std::sqrt(l[i])*sqrtT
165 meshers.emplace_back(ext::make_shared<Predefined1dMesher>(x));
168 const ext::shared_ptr<FdmMesherComposite> mesher =
169 ext::make_shared<FdmMesherComposite>(meshers);
171 const ext::shared_ptr<BasketPayoff>
payoff
175 const ext::shared_ptr<YieldTermStructure> rTS =
178 std::vector<ext::shared_ptr<YieldTermStructure>> qTS(
processes_.size());
180 qTS[i] =
processes_[i]->dividendYield().currentLink();
182 const ext::shared_ptr<FdmInnerValueCalculator> calculator =
183 ext::make_shared<detail::FdmPCABasketInnerValue>(
185 Log(
s), stdDev/sqrtT,
190 const ext::shared_ptr<FdmStepConditionComposite> conditions
194 rTS->referenceDate(), rTS->dayCounter());
198 = { mesher, boundaries, conditions, calculator,
201 const bool isEuropean =
203 const ext::shared_ptr<FdmWienerOp> op =
204 ext::make_shared<FdmWienerOp>(
206 (isEuropean)? ext::shared_ptr<YieldTermStructure>() : rTS,
210 #define BOOST_PP_LOCAL_MACRO(n) \
212 results_.value = ext::make_shared<FdmNdimSolver<n>>( \
213 solverDesc, schemeDesc_, op)->interpolateAt( \
214 std::vector<Real>(processes_.size(), 0.0)); \
216 #define BOOST_PP_LOCAL_LIMITS (1, PDE_MAX_SUPPORTED_DIM)
217 #include BOOST_PP_LOCAL_ITERATE()
1-D array used in linear algebra.
const_iterator end() const
const_iterator begin() const
static ext::shared_ptr< FdmStepConditionComposite > vanillaComposite(const DividendSchedule &schedule, const ext::shared_ptr< Exercise > &exercise, const ext::shared_ptr< FdmMesher > &mesher, const ext::shared_ptr< FdmInnerValueCalculator > &calculator, const Date &refDate, const DayCounter &dayCounter)
n-dimensional finite-differences Black Scholes vanilla option engine
void calculate() const override
FdndimBlackScholesVanillaEngine(std::vector< ext::shared_ptr< GeneralizedBlackScholesProcess > > processes, Matrix rho, std::vector< Size > xGrids, Size tGrid=50, Size dampingSteps=0, const FdmSchemeDesc &schemeDesc=FdmSchemeDesc::Douglas())
const std::vector< Size > xGrids_
const std::vector< ext::shared_ptr< GeneralizedBlackScholesProcess > > processes_
BasketOption::results results_
BasketOption::arguments arguments_
Inverse cumulative normal distribution function.
Matrix used in linear algebra.
ext::shared_ptr< Exercise > exercise
ext::shared_ptr< Payoff > payoff
symmetric threshold Jacobi algorithm.
const Matrix & eigenvectors() const
const Array & eigenvalues() const
#define QL_REQUIRE(condition, message)
throw an error if the given pre-condition is not verified
#define QL_FAIL(message)
throw an error (possibly with file and line information)
Option exercise classes and payoff function.
const ext::shared_ptr< YieldTermStructure > rTS_
layer of abstraction to calculate the inner value
FdmMesher which is a composite of Fdm1dMesher.
composite of fdm step conditions
#define PDE_MAX_SUPPORTED_DIM
Finite-Differences n-dimensional Black-Scholes vanilla option engine.
const ext::shared_ptr< FdmMesher > mesher_
const ext::shared_ptr< Payoff > payoff_
Covariance matrix calculation.
Real Time
continuous quantity with 1-year units
Real DiscountFactor
discount factor between dates
std::size_t Size
size of a container
ext::shared_ptr< QuantLib::Payoff > payoff
std::vector< ext::shared_ptr< Dividend > > DividendSchedule
Array Log(const Array &v)
Matrix getCovariance(DataIterator stdDevBegin, DataIterator stdDevEnd, const Matrix &corr, Real tolerance=1.0e-12)
Calculation of covariance from correlation and standard deviations.
Array Exp(const Array &v)
Array Sqrt(const Array &v)
bool close_enough(const Quantity &m1, const Quantity &m2, Size n)
OperatorTraits< FdmLinearOp >::bc_set FdmBoundaryConditionSet
normal, cumulative and inverse cumulative distributions
One-dimensional mesher build from a given set of points.
Eigenvalues/eigenvectors of a real symmetric matrix.