28#include <ql/indexes/indexmanager.hpp>
29#include <ql/math/integrals/gausslobattointegral.hpp>
30#include <ql/math/integrals/segmentintegral.hpp>
31#include <ql/pricingengines/blackformula.hpp>
32#include <ql/time/calendars/jointcalendar.hpp>
33#include <ql/time/daycounters/actualactual.hpp>
42 const QuantLib::ext::shared_ptr<Index>& index1,
const QuantLib::ext::shared_ptr<Index>& index2,
43 const QuantLib::ext::shared_ptr<GeneralizedBlackScholesProcess>& process1,
44 const QuantLib::ext::shared_ptr<GeneralizedBlackScholesProcess>& process2,
const Handle<YieldTermStructure>& discountingTS,
45 Handle<Quote> correlation)
46 : index1_(index1), index2_(index2), process1_(process1), process2_(process2), discountingTS_(discountingTS),
47 correlation_(correlation) {
58 QL_REQUIRE(!
discountingTS_.empty(),
"Empty discounting term structure handle");
62 Date today = QuantLib::Settings::instance().evaluationDate();
63 const Date& maturityDate =
arguments_.settlementDate;
65 if (today > maturityDate)
85 results_.basketVariance = basketVariance;
91 if (!QuantLib::close_enough(
arguments_.floor, 0.0)) {
93 variance1 = std::max(floor * strike1, variance1);
94 variance2 = std::max(floor * strike2, variance2);
95 basketVariance = std::max(floor * basketStrike, basketVariance);
98 if (!QuantLib::close_enough(
arguments_.cap, 0.0)) {
100 variance1 = std::min(cap * strike1, variance1);
101 variance2 = std::min(cap * strike2, variance2);
102 basketVariance = std::min(cap * basketStrike, basketVariance);
105 results_.finalVariance1 = variance1;
106 results_.finalVariance2 = variance2;
107 results_.finalBasketVariance = basketVariance;
108 results_.additionalResults[
"finalVariance1"] = variance1;
109 results_.additionalResults[
"finalVariance2"] = variance2;
110 results_.additionalResults[
"finalBasketVariance"] = basketVariance;
114 Real currentBasketNotional = 10000.0 *
arguments_.basketNotional / (2.0 * 100.0 *
arguments_.basketStrike);
116 results_.additionalResults[
"varianceAmount1"] = currentNotional1;
117 results_.additionalResults[
"varianceAmount2"] = currentNotional2;
118 results_.additionalResults[
"basketVarianceAmount"] = currentBasketNotional;
120 Real equityAmount1 = currentNotional1 * (variance1 - strike1);
121 Real equityAmount2 = currentNotional2 * (variance2 - strike2);
122 Real equityAmountBasket = currentBasketNotional * (basketVariance - basketStrike);
124 results_.equityAmount1 = equityAmount1;
125 results_.equityAmount2 = equityAmount2;
126 results_.equityAmountBasket = equityAmountBasket;
127 results_.additionalResults[
"equityAmount1"] = equityAmount1;
128 results_.additionalResults[
"equityAmount2"] = equityAmount2;
129 results_.additionalResults[
"equityAmountBasket"] = equityAmountBasket;
131 Real pairwiseEquityAmount = equityAmount1 + equityAmount2 + equityAmountBasket;
133 results_.pairwiseEquityAmount = pairwiseEquityAmount;
135 if (!QuantLib::close_enough(
arguments_.payoffLimit, 0.0)) {
136 Real equityAmountCap =
138 Real equityAmountFloor = -1.0 * equityAmountCap;
139 pairwiseEquityAmount = std::max(equityAmountFloor, pairwiseEquityAmount);
140 pairwiseEquityAmount = std::min(equityAmountCap, pairwiseEquityAmount);
143 results_.finalEquityAmount = pairwiseEquityAmount;
144 results_.additionalResults[
"finalEquityAmount"] = pairwiseEquityAmount;
146 Real multiplier =
arguments_.position == Position::Long ? 1.0 : -1.0;
149 results_.value = multiplier * df * pairwiseEquityAmount;
153 const Schedule& laggedValuationSchedule,
154 const Date& evalDate)
const {
156 const Date& accrStartDate = valuationSchedule.dates().back();
157 const Date& accrEndDate = laggedValuationSchedule.dates().back();
161 for (Size i = 0; i < valuationSchedule.size(); i++) {
162 const Date& vd = valuationSchedule.dates()[i];
163 const Date& lvd = laggedValuationSchedule.dates()[i];
166 if (lvd <= evalDate) {
167 Real price1 =
index1_->fixing(vd);
168 Real laggedPrice1 =
index1_->fixing(lvd);
169 Real variation1 = std::log(laggedPrice1 / price1);
172 Real price2 =
index2_->fixing(vd);
173 Real laggedPrice2 =
index2_->fixing(lvd);
174 Real variation2 = std::log(laggedPrice2 / price2);
177 Real basketPrice = price1 + price2;
178 Real laggedBasketPrice = laggedPrice1 + laggedPrice2;
179 Real basketVariation = std::log(laggedBasketPrice / basketPrice);
183 Real expectedN = valuationSchedule.dates().size() - 1.0;
184 Real factor = 252 / (expectedN *
arguments_.accrualLag);
190 Real t = ActualActual(ActualActual::ISDA).yearFraction(evalDate, accrEndDate);
196 Real variance1 =
process1_->blackVolatility()->blackVariance(t, F1);
197 Real variance2 =
process2_->blackVolatility()->blackVariance(t, F2);
198 Real basketVariance =
199 variance1 + variance2 + 2.0 * std::sqrt(variance1) * std::sqrt(variance2) *
correlation_->value();
209 JointCalendar(std::vector<Calendar>{valuationSchedule.calendar(), laggedValuationSchedule.calendar(),
211 Real accrTime = std::abs(jointCal.businessDaysBetween(accrStartDate, evalDate,
true,
true));
212 Real futTime = std::abs(jointCal.businessDaysBetween(evalDate, accrEndDate,
true,
false));
213 Real totalTime = accrTime + futTime;
214 Real accrFactor = accrTime / totalTime;
215 Real futFactor = futTime / totalTime;
const Instrument::results * results_
Handle< Quote > correlation_
QuantLib::ext::shared_ptr< Index > index2_
void calculate() const override
Handle< YieldTermStructure > discountingTS_
PairwiseVarianceSwapEngine(const QuantLib::ext::shared_ptr< QuantLib::Index > &index1, const QuantLib::ext::shared_ptr< QuantLib::Index > &index2, const QuantLib::ext::shared_ptr< GeneralizedBlackScholesProcess > &process1, const QuantLib::ext::shared_ptr< GeneralizedBlackScholesProcess > &process2, const Handle< YieldTermStructure > &discountingTS, Handle< Quote > correlation)
Variances calculateVariances(const Schedule &valuationSchedule, const Schedule &laggedValuationSchedule, const Date &evalDate) const
QuantLib::ext::shared_ptr< GeneralizedBlackScholesProcess > process2_
QuantLib::ext::shared_ptr< GeneralizedBlackScholesProcess > process1_
QuantLib::ext::shared_ptr< Index > index1_
equity index class for holding equity fixing histories and forwarding.
pairwise variance swap engine
Real futureBasketVariance
Real accruedBasketVariance
Swap::arguments * arguments_