Logo
Fully annotated reference manual - version 1.8.12
Loading...
Searching...
No Matches
Classes | Public Member Functions | Private Member Functions | Private Attributes | List of all members
FdConvertibleBondEvents Class Reference

#include <qle/pricingengines/fdconvertiblebondevents.hpp>

+ Collaboration diagram for FdConvertibleBondEvents:

Classes

struct  CallData
 
struct  ConversionData
 
struct  ConversionResetData
 
struct  DividendPassThroughData
 
struct  MandatoryConversionData
 

Public Member Functions

 FdConvertibleBondEvents (const Date &today, const DayCounter &dc, const Real N0, const QuantLib::ext::shared_ptr< QuantExt::EquityIndex2 > &equity, const QuantLib::ext::shared_ptr< FxIndex > &fxConversion)
 
void registerBondCashflow (const QuantLib::ext::shared_ptr< CashFlow > &c)
 
void registerCall (const ConvertibleBond2::CallabilityData &c)
 
void registerMakeWhole (const ConvertibleBond2::MakeWholeData &c)
 
void registerPut (const ConvertibleBond2::CallabilityData &c)
 
void registerConversionRatio (const ConvertibleBond2::ConversionRatioData &c)
 
void registerConversion (const ConvertibleBond2::ConversionData &c)
 
void registerMandatoryConversion (const ConvertibleBond2::MandatoryConversionData &c)
 
void registerConversionReset (const ConvertibleBond2::ConversionResetData &c)
 
void registerDividendProtection (const ConvertibleBond2::DividendProtectionData &c)
 
const std::set< Real > & times () const
 
void finalise (const TimeGrid &grid)
 
bool hasBondCashflow (const Size i) const
 
bool hasCall (const Size i) const
 
bool hasPut (const Size i) const
 
bool hasConversion (const Size i) const
 
bool hasMandatoryConversion (const Size i) const
 
bool hasContingentConversion (const Size i) const
 
bool hasNoConversionPlane (const Size i) const
 
bool hasConversionReset (const Size i) const
 
bool hasDividendPassThrough (const Size i) const
 
Real getBondCashflow (const Size i) const
 
Real getBondFinalRedemption (const Size i) const
 
const CallDatagetCallData (const Size i) const
 
const CallDatagetPutData (const Size i) const
 
const ConversionDatagetConversionData (const Size i) const
 
const MandatoryConversionDatagetMandatoryConversionData (const Size i) const
 
const ConversionResetDatagetConversionResetData (const Size i) const
 
const DividendPassThroughDatagetDividendPassThroughData (const Size i) const
 
bool hasStochasticConversionRatio (const Size i) const
 
Real getInitialConversionRatio () const
 
Real getCurrentConversionRatio (const Size i) const
 
Real getCurrentFxConversion (const Size i) const
 
Date getAssociatedDate (const Size i) const
 
const std::map< std::string, boost::any > & additionalResults () const
 

Private Member Functions

Date nextExerciseDate (const Date &d, const std::vector< ConvertibleBond2::CallabilityData > &data) const
 
Date nextConversionDate (const Date &d) const
 
Real time (const Date &d) const
 
void processBondCashflows ()
 
void processExerciseData (const std::vector< ConvertibleBond2::CallabilityData > &sourceData, std::vector< bool > &targetFlags, std::vector< CallData > &targetData)
 
void processMakeWholeData ()
 
void processConversionAndDivProtData ()
 
void processMandatoryConversionData ()
 

Private Attributes

Date today_
 
DayCounter dc_
 
Real N0_
 
QuantLib::ext::shared_ptr< QuantExt::EquityIndex2equity_
 
QuantLib::ext::shared_ptr< FxIndexfxConversion_
 
std::set< Real > times_
 
TimeGrid grid_
 
bool finalised_ = false
 
Date lastRedemptionDate_
 
std::vector< QuantLib::ext::shared_ptr< CashFlow > > registeredBondCashflows_
 
std::vector< ConvertibleBond2::CallabilityDataregisteredCallData_
 
std::vector< ConvertibleBond2::CallabilityDataregisteredPutData_
 
std::vector< ConvertibleBond2::ConversionRatioDataregisteredConversionRatioData_
 
std::vector< ConvertibleBond2::ConversionDataregisteredConversionData_
 
std::vector< ConvertibleBond2::MandatoryConversionDataregisteredMandatoryConversionData_
 
std::vector< ConvertibleBond2::ConversionResetDataregisteredConversionResetData_
 
std::vector< ConvertibleBond2::DividendProtectionDataregisteredDividendProtectionData_
 
ConvertibleBond2::MakeWholeData registeredMakeWholeData_
 
std::vector< boolhasBondCashflow_
 
std::vector< boolhasCall_
 
std::vector< boolhasPut_
 
std::vector< boolhasConversion_
 
std::vector< boolhasMandatoryConversion_
 
std::vector< boolhasContingentConversion_
 
std::vector< boolhasConversionInfoSet_
 
std::vector< boolhasNoConversionPlane_
 
std::vector< boolhasConversionReset_
 
std::vector< boolhasDividendPassThrough_
 
std::vector< Real > bondCashflow_
 
std::vector< Real > bondFinalRedemption_
 
std::vector< CallDatacallData_
 
std::vector< CallDataputData_
 
std::vector< ConversionDataconversionData_
 
std::vector< MandatoryConversionDatamandatoryConversionData_
 
std::vector< ConversionResetDataconversionResetData_
 
std::vector< DividendPassThroughDatadividendPassThroughData_
 
std::vector< boolstochasticConversionRatio_
 
Real initialConversionRatio_
 
std::vector< Real > currentConversionRatio_
 
std::vector< Real > currentFxConversion_
 
std::vector< Date > associatedDate_
 
std::map< std::string, boost::any > additionalResults_
 
QuantLib::Array mw_cr_inc_x_
 
QuantLib::Array mw_cr_inc_y_
 
QuantLib::Matrix mw_cr_inc_z_
 

Detailed Description

Definition at line 37 of file fdconvertiblebondevents.hpp.

Constructor & Destructor Documentation

◆ FdConvertibleBondEvents()

FdConvertibleBondEvents ( const Date &  today,
const DayCounter &  dc,
const Real  N0,
const QuantLib::ext::shared_ptr< QuantExt::EquityIndex2 > &  equity,
const QuantLib::ext::shared_ptr< FxIndex > &  fxConversion 
)

Definition at line 36 of file fdconvertiblebondevents.cpp.

Member Function Documentation

◆ registerBondCashflow()

void registerBondCashflow ( const QuantLib::ext::shared_ptr< CashFlow > &  c)

Definition at line 43 of file fdconvertiblebondevents.cpp.

43 {
44 if (c->date() > today_) {
45 registeredBondCashflows_.push_back(c);
46 times_.insert(time(c->date()));
47 }
48}
std::vector< QuantLib::ext::shared_ptr< CashFlow > > registeredBondCashflows_
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ registerCall()

void registerCall ( const ConvertibleBond2::CallabilityData c)

Definition at line 50 of file fdconvertiblebondevents.cpp.

50 {
51 registeredCallData_.push_back(c);
52 if (c.exerciseDate > today_) {
53 times_.insert(time(c.exerciseDate));
54 }
55}
std::vector< ConvertibleBond2::CallabilityData > registeredCallData_
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ registerMakeWhole()

void registerMakeWhole ( const ConvertibleBond2::MakeWholeData c)

Definition at line 57 of file fdconvertiblebondevents.cpp.

57 {
59}
ConvertibleBond2::MakeWholeData registeredMakeWholeData_
+ Here is the caller graph for this function:

◆ registerPut()

void registerPut ( const ConvertibleBond2::CallabilityData c)

Definition at line 61 of file fdconvertiblebondevents.cpp.

61 {
62 registeredPutData_.push_back(c);
63 if (c.exerciseDate > today_) {
64 times_.insert(time(c.exerciseDate));
65 }
66}
std::vector< ConvertibleBond2::CallabilityData > registeredPutData_
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ registerConversionRatio()

void registerConversionRatio ( const ConvertibleBond2::ConversionRatioData c)

Definition at line 68 of file fdconvertiblebondevents.cpp.

68 {
70 if (c.fromDate > today_) {
71 times_.insert(time(c.fromDate));
72 }
73}
std::vector< ConvertibleBond2::ConversionRatioData > registeredConversionRatioData_
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ registerConversion()

void registerConversion ( const ConvertibleBond2::ConversionData c)

Definition at line 75 of file fdconvertiblebondevents.cpp.

75 {
76 registeredConversionData_.push_back(c);
77 if (c.exerciseDate > today_) {
78 times_.insert(time(c.exerciseDate));
79 }
80}
std::vector< ConvertibleBond2::ConversionData > registeredConversionData_
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ registerMandatoryConversion()

void registerMandatoryConversion ( const ConvertibleBond2::MandatoryConversionData c)

Definition at line 82 of file fdconvertiblebondevents.cpp.

82 {
84 if (c.exerciseDate > today_) {
85 times_.insert(time(c.exerciseDate));
86 }
87}
std::vector< ConvertibleBond2::MandatoryConversionData > registeredMandatoryConversionData_
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ registerConversionReset()

void registerConversionReset ( const ConvertibleBond2::ConversionResetData c)

Definition at line 89 of file fdconvertiblebondevents.cpp.

89 {
91 if (c.resetDate > today_) {
92 times_.insert(time(c.resetDate));
93 }
94}
std::vector< ConvertibleBond2::ConversionResetData > registeredConversionResetData_
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ registerDividendProtection()

void registerDividendProtection ( const ConvertibleBond2::DividendProtectionData c)

Definition at line 96 of file fdconvertiblebondevents.cpp.

96 {
98 if (c.protectionDate > today_) {
99 times_.insert(time(c.protectionDate));
100 }
101}
std::vector< ConvertibleBond2::DividendProtectionData > registeredDividendProtectionData_
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ times()

const std::set< Real > & times ( ) const

Definition at line 103 of file fdconvertiblebondevents.cpp.

103{ return times_; }
+ Here is the caller graph for this function:

◆ finalise()

void finalise ( const TimeGrid &  grid)

Definition at line 571 of file fdconvertiblebondevents.cpp.

571 {
572 QL_REQUIRE(!finalised_, "FdConvertibleBondEvents: internal error, events already finalised");
573 finalised_ = true;
574 grid_ = grid;
575
576 hasBondCashflow_.resize(grid.size(), false);
577 hasCall_.resize(grid.size(), false);
578 hasPut_.resize(grid.size(), false);
579 hasConversion_.resize(grid.size(), false);
580 hasMandatoryConversion_.resize(grid.size(), false);
581 hasContingentConversion_.resize(grid.size(), false);
582 hasConversionInfoSet_.resize(grid.size(), false);
583 hasNoConversionPlane_.resize(grid.size(), false);
584 hasConversionReset_.resize(grid.size(), false);
585 hasDividendPassThrough_.resize(grid.size(), false);
586
587 bondCashflow_.resize(grid.size(), 0.0);
588 bondFinalRedemption_.resize(grid.size(), 0.0);
589 callData_.resize(grid.size());
590 putData_.resize(grid.size());
591 conversionData_.resize(grid.size());
592 conversionResetData_.resize(grid.size());
593 dividendPassThroughData_.resize(grid.size());
594 mandatoryConversionData_.resize(grid.size());
595
596 stochasticConversionRatio_.resize(grid.size(), false);
597 currentConversionRatio_.resize(grid.size(), 0.0);
598 currentFxConversion_.resize(grid.size(), 1.0);
599 associatedDate_.resize(grid.size(), Null<Date>());
600
602
603 // fill fx conversion rate on grid
604
605 if (fxConversion_ != nullptr) {
606 auto source = fxConversion_->sourceCurve();
607 auto target = fxConversion_->targetCurve();
608 Real spot = fxConversion_->fixing(today_);
609 for (Size i = 0; i < grid_.size(); ++i) {
610 Real fx = spot * source->discount(grid_[i]) / target->discount(grid_[i]);
611 currentFxConversion_[i] = fx;
612 }
613 }
614
615 // process data
616
623
624 // checks
625
626 Size lastRedemptionIndex = grid_.index(time(lastRedemptionDate_));
627 for (Size k = lastRedemptionIndex + 1; k < grid_.size(); ++k) {
628 QL_REQUIRE(!hasConversion(k) && !hasMandatoryConversion(k),
629 "FdConvertibleBondEvents: conversion right after last bond redemption flow not allowed");
630 }
631}
bool hasMandatoryConversion(const Size i) const
std::vector< DividendPassThroughData > dividendPassThroughData_
std::vector< ConversionData > conversionData_
std::vector< MandatoryConversionData > mandatoryConversionData_
std::vector< ConversionResetData > conversionResetData_
void processExerciseData(const std::vector< ConvertibleBond2::CallabilityData > &sourceData, std::vector< bool > &targetFlags, std::vector< CallData > &targetData)
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ hasBondCashflow()

bool hasBondCashflow ( const Size  i) const

Definition at line 633 of file fdconvertiblebondevents.cpp.

633{ return hasBondCashflow_.at(i); }
+ Here is the caller graph for this function:

◆ hasCall()

bool hasCall ( const Size  i) const

Definition at line 634 of file fdconvertiblebondevents.cpp.

634{ return hasCall_.at(i); }
+ Here is the caller graph for this function:

◆ hasPut()

bool hasPut ( const Size  i) const

Definition at line 635 of file fdconvertiblebondevents.cpp.

635{ return hasPut_.at(i); }
+ Here is the caller graph for this function:

◆ hasConversion()

bool hasConversion ( const Size  i) const

Definition at line 636 of file fdconvertiblebondevents.cpp.

636{ return hasConversion_.at(i); }
+ Here is the caller graph for this function:

◆ hasMandatoryConversion()

bool hasMandatoryConversion ( const Size  i) const

Definition at line 637 of file fdconvertiblebondevents.cpp.

637{ return hasMandatoryConversion_.at(i); }
+ Here is the caller graph for this function:

◆ hasContingentConversion()

bool hasContingentConversion ( const Size  i) const

Definition at line 638 of file fdconvertiblebondevents.cpp.

638{ return hasContingentConversion_.at(i); }
+ Here is the caller graph for this function:

◆ hasNoConversionPlane()

bool hasNoConversionPlane ( const Size  i) const

Definition at line 639 of file fdconvertiblebondevents.cpp.

639{ return hasNoConversionPlane_.at(i); }
+ Here is the caller graph for this function:

◆ hasConversionReset()

bool hasConversionReset ( const Size  i) const

Definition at line 640 of file fdconvertiblebondevents.cpp.

640{ return hasConversionReset_.at(i); }
+ Here is the caller graph for this function:

◆ hasDividendPassThrough()

bool hasDividendPassThrough ( const Size  i) const

Definition at line 641 of file fdconvertiblebondevents.cpp.

641{ return hasDividendPassThrough_.at(i); }
+ Here is the caller graph for this function:

◆ getBondCashflow()

Real getBondCashflow ( const Size  i) const

Definition at line 643 of file fdconvertiblebondevents.cpp.

643{ return bondCashflow_.at(i); }
+ Here is the caller graph for this function:

◆ getBondFinalRedemption()

Real getBondFinalRedemption ( const Size  i) const

Definition at line 644 of file fdconvertiblebondevents.cpp.

644{ return bondFinalRedemption_.at(i); }
+ Here is the caller graph for this function:

◆ getCallData()

const FdConvertibleBondEvents::CallData & getCallData ( const Size  i) const

Definition at line 646 of file fdconvertiblebondevents.cpp.

646 {
647 return callData_.at(i);
648}
+ Here is the caller graph for this function:

◆ getPutData()

const FdConvertibleBondEvents::CallData & getPutData ( const Size  i) const

Definition at line 650 of file fdconvertiblebondevents.cpp.

650 {
651 return putData_.at(i);
652}
+ Here is the caller graph for this function:

◆ getConversionData()

const FdConvertibleBondEvents::ConversionData & getConversionData ( const Size  i) const

Definition at line 654 of file fdconvertiblebondevents.cpp.

654 {
655 return conversionData_.at(i);
656}
+ Here is the caller graph for this function:

◆ getMandatoryConversionData()

const FdConvertibleBondEvents::MandatoryConversionData & getMandatoryConversionData ( const Size  i) const

Definition at line 659 of file fdconvertiblebondevents.cpp.

659 {
660 return mandatoryConversionData_.at(i);
661}
+ Here is the caller graph for this function:

◆ getConversionResetData()

const FdConvertibleBondEvents::ConversionResetData & getConversionResetData ( const Size  i) const

Definition at line 664 of file fdconvertiblebondevents.cpp.

664 {
665 return conversionResetData_.at(i);
666}
+ Here is the caller graph for this function:

◆ getDividendPassThroughData()

const FdConvertibleBondEvents::DividendPassThroughData & getDividendPassThroughData ( const Size  i) const

Definition at line 669 of file fdconvertiblebondevents.cpp.

669 {
670 return dividendPassThroughData_.at(i);
671}
+ Here is the caller graph for this function:

◆ hasStochasticConversionRatio()

bool hasStochasticConversionRatio ( const Size  i) const

Definition at line 673 of file fdconvertiblebondevents.cpp.

673 {
674 return stochasticConversionRatio_.at(i);
675}
+ Here is the caller graph for this function:

◆ getInitialConversionRatio()

Real getInitialConversionRatio ( ) const

Definition at line 679 of file fdconvertiblebondevents.cpp.

679{ return initialConversionRatio_; }
+ Here is the caller graph for this function:

◆ getCurrentConversionRatio()

Real getCurrentConversionRatio ( const Size  i) const

Definition at line 677 of file fdconvertiblebondevents.cpp.

677{ return currentConversionRatio_.at(i); }
+ Here is the caller graph for this function:

◆ getCurrentFxConversion()

Real getCurrentFxConversion ( const Size  i) const

Definition at line 678 of file fdconvertiblebondevents.cpp.

678{ return currentFxConversion_.at(i); }
+ Here is the caller graph for this function:

◆ getAssociatedDate()

Date getAssociatedDate ( const Size  i) const

Definition at line 680 of file fdconvertiblebondevents.cpp.

680{ return associatedDate_.at(i); }
+ Here is the caller graph for this function:

◆ additionalResults()

const std::map< std::string, boost::any > & additionalResults ( ) const

Definition at line 150 of file fdconvertiblebondevents.hpp.

150{ return additionalResults_; }
std::map< std::string, boost::any > additionalResults_
+ Here is the caller graph for this function:

◆ nextExerciseDate()

Date nextExerciseDate ( const Date &  d,
const std::vector< ConvertibleBond2::CallabilityData > &  data 
) const
private

Definition at line 105 of file fdconvertiblebondevents.cpp.

106 {
107 Date result = Date::maxDate();
108 for (auto const& x : data) {
109 if (x.exerciseDate > d)
110 result = std::min(result, x.exerciseDate);
111 }
112 if (result == Date::maxDate())
113 return Null<Date>();
114 return result;
115}
+ Here is the caller graph for this function:

◆ nextConversionDate()

Date nextConversionDate ( const Date &  d) const
private

Definition at line 117 of file fdconvertiblebondevents.cpp.

117 {
118 Date result = Date::maxDate();
119 for (auto const& x : registeredConversionData_) {
120 if (x.exerciseDate > d)
121 result = std::min(result, x.exerciseDate);
122 }
123 if (result == Date::maxDate())
124 return Null<Date>();
125 return result;
126}
+ Here is the caller graph for this function:

◆ time()

Real time ( const Date &  d) const
private

Definition at line 41 of file fdconvertiblebondevents.cpp.

41{ return dc_.yearFraction(today_, d); }
+ Here is the caller graph for this function:

◆ processBondCashflows()

void processBondCashflows ( )
private

Definition at line 128 of file fdconvertiblebondevents.cpp.

128 {
129 lastRedemptionDate_ = Date::minDate();
130 for (auto const& c : registeredBondCashflows_) {
131 if (QuantLib::ext::dynamic_pointer_cast<Coupon>(c) == nullptr)
132 lastRedemptionDate_ = std::max(lastRedemptionDate_, c->date());
133 }
134 for (auto const& d : registeredBondCashflows_) {
135 bool isRedemption = QuantLib::ext::dynamic_pointer_cast<Coupon>(d) == nullptr;
136 Size index = grid_.index(time(d->date()));
137 hasBondCashflow_[index] = true;
138 associatedDate_[index] = d->date();
139 if (isRedemption && d->date() == lastRedemptionDate_)
140 bondFinalRedemption_[index] += d->amount();
141 else
142 bondCashflow_[index] += d->amount();
143 }
144}
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ processExerciseData()

void processExerciseData ( const std::vector< ConvertibleBond2::CallabilityData > &  sourceData,
std::vector< bool > &  targetFlags,
std::vector< CallData > &  targetData 
)
private

Definition at line 146 of file fdconvertiblebondevents.cpp.

147 {
148 for (auto const& c : sourceData) {
149 if (c.exerciseDate <= today_ && c.exerciseType == ConvertibleBond2::CallabilityData::ExerciseType::OnThisDate)
150 continue;
151 Size indexStart = grid_.index(time(std::max(c.exerciseDate, today_)));
152 Size indexEnd;
153 associatedDate_[indexStart] = std::max(c.exerciseDate, today_);
155 indexEnd = indexStart;
157 Date nextDate = nextExerciseDate(c.exerciseDate, sourceData);
158 QL_REQUIRE(nextDate != Null<Date>(),
159 "FdConvertibleBondEvents::processExerciseData(): internal error: did not find a next exercise "
160 "date after "
161 << c.exerciseDate
162 << ", the last exercise date should not have exercise type FromThisDateOn");
163 if (nextDate <= today_)
164 continue;
165 indexEnd = grid_.index(time(nextDate)) - 1;
166 } else {
167 QL_FAIL("FdConvertibleBondEvents: internal error, exercise type not "
168 "recognized");
169 }
170 for (Size i = indexStart; i <= indexEnd; ++i) {
171 targetFlags[i] = true;
172 targetData[i] = CallData{c.price, c.priceType, c.includeAccrual,
173 c.isSoft, c.softTriggerRatio, std::function<Real(Real, Real)>()};
174 }
175 }
176}
Date nextExerciseDate(const Date &d, const std::vector< ConvertibleBond2::CallabilityData > &data) const
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ processMakeWholeData()

void processMakeWholeData ( )
private

Definition at line 178 of file fdconvertiblebondevents.cpp.

178 {
180
181 // init and checks
182
183 auto const& stockPrices = (*registeredMakeWholeData_.crIncreaseData).stockPrices;
184 auto const& effDates = (*registeredMakeWholeData_.crIncreaseData).effectiveDates;
185 auto const& crInc = (*registeredMakeWholeData_.crIncreaseData).crIncrease;
186 QL_REQUIRE(stockPrices.size() >= 2,
187 "FdConvertibleBondEvents::processMakeWholeData(): at least two stock prices required (cr increase)");
188 QL_REQUIRE(
189 effDates.size() >= 2,
190 "FdConvertibleBondEvents::processMakeWholeData(): at least two effective dates required (cr increase)");
191 QL_REQUIRE(effDates.size() == crInc.size(), "FdConvertibleBondEvents::processMakeWholeData(): effective dates ("
192 << effDates.size() << ") must match cr increase rows ("
193 << crInc.size() << ") (cr increase)");
194 for (auto const& c : crInc) {
195 QL_REQUIRE(c.size() == stockPrices.size(),
196 "FdConvertibleBondEvents::processMakeWholeData(): stock prices size ("
197 << stockPrices.size() << ") must match cr increase coluns (" << c.size() << ")");
198 }
199
200 // build interpolation
201
202 mw_cr_inc_x_ = Array(stockPrices.begin(), stockPrices.end());
203 mw_cr_inc_y_ = Array(effDates.size());
204 mw_cr_inc_z_ = Matrix(mw_cr_inc_y_.size(), mw_cr_inc_x_.size());
205
206 for (Size i = 0; i < effDates.size(); ++i) {
207 mw_cr_inc_y_[i] = time(effDates[i]);
208 for (Size j = 0; j < stockPrices.size(); ++j) {
209 mw_cr_inc_z_(i, j) = crInc[i][j];
210 }
211 }
212
213 auto interpolation = QuantLib::ext::make_shared<BilinearInterpolation>(
214 mw_cr_inc_x_.begin(), mw_cr_inc_x_.end(), mw_cr_inc_y_.begin(), mw_cr_inc_y_.end(), mw_cr_inc_z_);
215
216 // init cap (infty if not given)
217
218 Real cap = QL_MAX_REAL;
219 if ((*registeredMakeWholeData_.crIncreaseData).cap != Null<Real>())
221
222 // set effetive mw cr functions on the call data
223
224 for (Size i = 0; i < grid_.size(); ++i) {
225 if (hasCall_[i]) {
226 Real t = grid_[i];
227 callData_[i].mwCr = [interpolation, t, cap](const Real S, const Real cr) {
228 if ((S < interpolation->xMin() && !close_enough(S, interpolation->xMin())) ||
229 (S > interpolation->xMax() && !close_enough(S, interpolation->xMax())) ||
230 (t < interpolation->yMin() && !close_enough(t, interpolation->yMin())) ||
231 (t > interpolation->yMax() && !close_enough(t, interpolation->yMax()))) {
232 return cr;
233 } else {
234 Real tmp = interpolation->operator()(S, t);
235 // apply cap, but if initial cr was already greater than result, keep that
236 return std::max(cr, std::min(cr + tmp, cap));
237 }
238 };
239 }
240 }
241 }
242}
Filter close_enough(const RandomVariable &x, const RandomVariable &y)
boost::optional< CrIncreaseData > crIncreaseData
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ processConversionAndDivProtData()

void processConversionAndDivProtData ( )
private

Definition at line 244 of file fdconvertiblebondevents.cpp.

244 {
245
246 // set the initial conversion ratio
247
248 std::set<std::pair<Date, Real>> crSchedule;
249 for (const auto& d : registeredConversionRatioData_) {
250 crSchedule.insert(std::make_pair(d.fromDate, d.conversionRatio));
251 }
252 if (!crSchedule.empty()) {
253 initialConversionRatio_ = crSchedule.begin()->second;
254 }
256 additionalResults_["historicEvents.initialConversionRatio"] = initialConversionRatio_;
257
258 // collect all relevant conversion events
259 // - cd: cr reset event
260 // - dd: dp event (with cr adjustment or pass-through)
261 // - vd: voluntary conversion (with coco possibly)
262 // - newCr: cr changed (or initially set to) specific value
263
264 struct AdjEvent {
265 ConvertibleBond2::ConversionResetData* cd = nullptr;
266 ConvertibleBond2::DividendProtectionData* dd = nullptr;
267 ConvertibleBond2::ConversionData* vd = nullptr;
268 Real newCr = Null<Real>(); // set cr to specific value on event date
269 };
270
271 std::map<Date, AdjEvent> adjEvents;
272
273 for (auto& d : registeredConversionResetData_) {
274 adjEvents[d.resetDate].cd = &d;
275 }
276
277 for (auto& d : registeredDividendProtectionData_) {
278 adjEvents[d.protectionDate].dd = &d;
279 }
280
281 for (auto& d : registeredConversionRatioData_) {
282 adjEvents[d.fromDate].newCr = d.conversionRatio;
283 }
284
285 for (auto& d : registeredConversionData_) {
286 adjEvents[d.exerciseDate].vd = &d;
287 }
288
289 // step through the events and process them (historical and future events)
290
291 Real currentCr = initialConversionRatio_;
292 Size lastDividendProtectionTimeIndex = Null<Size>();
293 bool haveStochasticCr = false;
294
295 for (auto const& event : adjEvents) {
296
297 if (event.second.cd != nullptr) {
298 const ConvertibleBond2::ConversionResetData& c = *event.second.cd;
299 if (c.resetDate <= today_) {
300
301 // historical conversion ratio reset event
302
303 Real S = equity_->fixing(equity_->fixingCalendar().adjust(c.resetDate, Preceding));
304 Real fx = 1.0;
305 if (fxConversion_ != nullptr) {
306 fx = fxConversion_->fixing(JointCalendar(equity_->fixingCalendar(), fxConversion_->fixingCalendar())
307 .adjust(c.resetDate, Preceding));
308 }
310 ? currentCr
312 Real referenceCP = N0_ / cr;
313 additionalResults_["historicEvents.crReset_" + getDateStr(event.first) + "_S"] = S;
314 additionalResults_["historicEvents.crReset_" + getDateStr(event.first) + "_threshold"] = c.threshold;
315 additionalResults_["historicEvents.crReset_" + getDateStr(event.first) + "_referenceCP"] = referenceCP;
316 additionalResults_["historicEvents.crReset_" + getDateStr(event.first) + "_gearing"] = c.gearing;
317 additionalResults_["historicEvents.crReset_" + getDateStr(event.first) + "_floor"] = c.floor;
318 additionalResults_["historicEvents.crReset_" + getDateStr(event.first) + "_globalFloor"] =
319 c.globalFloor * fx;
320 additionalResults_["historicEvents.crReset_" + getDateStr(event.first) + "_fxConversion"] = fx;
321 additionalResults_["historicEvents.crReset_" + getDateStr(event.first) + "_currentCr"] = currentCr;
322 if (!close_enough(cr, 0.0) && S < c.threshold * referenceCP) {
323 Real adjustedConversionRatio = QL_MAX_REAL;
324 if (!close_enough(c.gearing, 0.0)) {
325 adjustedConversionRatio = std::min(adjustedConversionRatio, N0_ / (c.gearing * S));
326 }
327 if (!close_enough(c.floor, 0.0)) {
328 adjustedConversionRatio = std::min(adjustedConversionRatio, N0_ / (c.floor * referenceCP));
329 }
330 if (!close_enough(c.globalFloor * fx, 0.0)) {
331 adjustedConversionRatio = std::min(adjustedConversionRatio, N0_ / (c.globalFloor * fx));
332 }
333 adjustedConversionRatio = std::max(
334 currentCr, adjustedConversionRatio != QL_MAX_REAL ? adjustedConversionRatio : -QL_MAX_REAL);
335 currentCr = std::max(currentCr, adjustedConversionRatio);
336 }
337 additionalResults_["historicEvents.crReset_" + getDateStr(event.first) + "_adjustedCr"] = currentCr;
338 } else {
339
340 // future conversion ratio reset event
341
342 Size index = grid_.index(time(event.first));
343 associatedDate_[index] = event.first;
344 hasConversionReset_[index] = true;
345 const ConvertibleBond2::ConversionResetData& c = *event.second.cd;
346 conversionResetData_[index].resetActive = true;
347 conversionResetData_[index].reference = c.referenceType;
348 conversionResetData_[index].gearing = c.gearing;
349 conversionResetData_[index].floor = c.floor;
350 conversionResetData_[index].globalFloor = c.globalFloor * currentFxConversion_[index];
351 conversionResetData_[index].threshold = c.threshold;
352 for (Size i = index + 1; i < grid_.size(); ++i) {
354 }
355 haveStochasticCr = true;
356 }
357 }
358
359 if (event.second.dd != nullptr) {
360 const ConvertibleBond2::DividendProtectionData& c = *event.second.dd;
361 if (c.protectionDate <= today_) {
366
367 // historic dividend protection event with conversion ratio adjustment
368
369 Real fx = 1.0;
370 if (fxConversion_ != nullptr) {
371 fx = fxConversion_->fixing(
372 JointCalendar(equity_->fixingCalendar(), fxConversion_->fixingCalendar())
373 .adjust(c.protectionDate, Preceding));
374 }
375 Real S = equity_->fixing(equity_->fixingCalendar().adjust(c.protectionDate, Preceding));
376 Real D = equity_->dividendsBetweenDates(c.startDate, c.protectionDate);
377 Real H = c.threshold * fx;
378
379 additionalResults_["historicEvents.crReset_DP_" + getDateStr(event.first) + "_div_" +
380 getDateStr(c.startDate) + "_" + getDateStr(c.protectionDate)] = D;
381 additionalResults_["historicEvents.crReset_DP_" + getDateStr(event.first) + "_S"] = S;
382 additionalResults_["historicEvents.crReset_DP_" + getDateStr(event.first) + "_threshold"] = H;
383 additionalResults_["historicEvents.crReset_DP_" + getDateStr(event.first) + "_fxConversion"] = fx;
384 additionalResults_["historicEvents.crReset_DP_" + getDateStr(event.first) + "_currentCr"] =
385 currentCr;
386
389 bool absolute =
391 Real d = absolute ? D : D / S;
392 Real C =
394 ? std::max(d - H, 0.0)
395 : d - H;
396 currentCr *= absolute ? S / std::max(S - C, 1E-4) : (1.0 + C);
397 } else {
398 Real f = std::max(S - H, 0.0) / std::max(S - D, 1E-4);
400 f = std::max(f, 1.0);
401 currentCr *= f;
402 }
403
404 additionalResults_["historicEvents.crReset_DP_" + getDateStr(event.first) + "_adjustedCr"] =
405 currentCr;
406 }
407 } else {
408
413
414 // future dividend protection event with conversion ratio adjustment
415
416 Size index = grid_.index(time(event.first));
417 associatedDate_[index] = event.first;
418 hasConversionReset_[index] = true;
419 const ConvertibleBond2::DividendProtectionData& c = *event.second.dd;
420 conversionResetData_[index].divProtActive = true;
421 conversionResetData_[index].adjustmentStyle = c.adjustmentStyle;
422 conversionResetData_[index].dividendType = c.dividendType;
423 conversionResetData_[index].divThreshold = c.threshold * currentFxConversion_[index];
424 if (lastDividendProtectionTimeIndex == Null<Size>()) {
425 conversionResetData_[index].lastDividendProtectionTimeIndex = 0;
426 conversionResetData_[index].accruedHistoricalDividends =
427 equity_->dividendsBetweenDates(c.startDate, today_);
428 additionalResults_["historicEvents.accruedDividends_" + getDateStr(c.startDate) + "_" +
429 getDateStr(today_)] = conversionResetData_[index].accruedHistoricalDividends;
430 } else {
431 conversionResetData_[index].lastDividendProtectionTimeIndex = lastDividendProtectionTimeIndex;
432 conversionResetData_[index].accruedHistoricalDividends = 0.0;
433 }
434 lastDividendProtectionTimeIndex = index;
435 for (Size i = index + 1; i < grid_.size(); ++i) {
437 }
438 haveStochasticCr = true;
439
440 } else {
441
442 // future dividend pass through event
443 Size index = grid_.index(time(c.protectionDate));
444 associatedDate_[index] = c.protectionDate;
445 hasDividendPassThrough_[index] = true;
446 dividendPassThroughData_[index].adjustmentStyle = c.adjustmentStyle;
447 dividendPassThroughData_[index].dividendType = c.dividendType;
448 dividendPassThroughData_[index].divThreshold = c.threshold;
449 if (lastDividendProtectionTimeIndex == Null<Size>()) {
450 dividendPassThroughData_[index].lastDividendProtectionTimeIndex = 0;
451 dividendPassThroughData_[index].accruedHistoricalDividends =
452 equity_->dividendsBetweenDates(c.startDate, today_);
453 additionalResults_["historicEvents.accruedDividends_" + getDateStr(c.startDate) + "_" +
454 getDateStr(today_)] =
455 dividendPassThroughData_[index].accruedHistoricalDividends;
456 } else {
457 dividendPassThroughData_[index].lastDividendProtectionTimeIndex =
458 lastDividendProtectionTimeIndex;
459 dividendPassThroughData_[index].accruedHistoricalDividends = 0.0;
460 }
461 lastDividendProtectionTimeIndex = index;
462 }
463 }
464 }
465
466 if (event.second.vd != nullptr) {
467
468 // voluntary conversion data (possibly with coco)
469
470 const ConvertibleBond2::ConversionData& vd = *event.second.vd;
471
472 Date nextConvDate = nextConversionDate(vd.exerciseDate);
473 if (nextConvDate > today_) {
474 bool conversionIsProhibited = false;
475 Size indexStart = grid_.index(time(std::max(vd.exerciseDate, today_)));
476 Size indexEnd;
477 associatedDate_[indexStart] = std::max(vd.exerciseDate, today_);
479 indexEnd = indexStart;
481 QL_REQUIRE(nextConvDate != Null<Date>(),
482 "FdConvertibleBondEvents::processConversionData(): internal error: did not find a next "
483 "conversion "
484 "date after "
485 << vd.exerciseDate
486 << ", the last conversione date should not have exercise type FromThisDateOn");
487 indexEnd = grid_.index(time(nextConvDate));
488 // check whether conversion is prohibited for the future due to past coco condition check
490 vd.exerciseDate <= today_) {
491 Real S = equity_->fixing(equity_->fixingCalendar().adjust(vd.exerciseDate, Preceding));
492 conversionIsProhibited = S * currentCr <= vd.cocoBarrier;
493 additionalResults_["historicEvents.coco_" + getDateStr(vd.exerciseDate) + "_S"] = S;
494 additionalResults_["historicEvents.coco_" + getDateStr(vd.exerciseDate) + "_currentCr"] =
495 currentCr;
496 additionalResults_["historicEvents.coco_" + getDateStr(vd.exerciseDate) + "_cocoBarrier"] =
497 vd.cocoBarrier;
498 additionalResults_["historicEvents.coco_" + getDateStr(vd.exerciseDate) + "_triggered"] =
499 !conversionIsProhibited;
500 }
501 } else {
502 QL_FAIL("FdConvertibleBondEvents: internal error, exercise type not recognized");
503 }
504 // update the grid info
505 for (Size i = indexStart; i <= indexEnd; ++i) {
506 // if we have set conversion information already and the current is the last conversion
507 // date, we do not modify the exisiting information, because then the current date is the
508 // end date of the last american period.
509 if (nextConvDate == Null<Date>() && hasConversionInfoSet_[i])
510 continue;
511 // otherwise mark the index as set
512 hasConversionInfoSet_[i] = true;
513 // if the conversion is not allowed, do not set the hasConversion flag
514 if (conversionIsProhibited)
515 continue;
516 // if the conversion is allowed, set the conversion flag ...
517 hasConversion_[i] = true;
518 // ... and the conversion data
519 conversionData_[i] = ConversionData{vd.cocoBarrier};
520 // a start of period coco check should only be done, if the date is > today, otherwise it's
521 // done already
523 hasContingentConversion_[i] = true;
524 } else if (vd.exerciseDate > today_ &&
526 hasContingentConversion_[i] = true;
527 hasNoConversionPlane_[i] = i > indexStart;
528 }
529 }
530 }
531 }
532
533 if (event.second.newCr != Null<Real>()) {
534 // update current cr
535 currentCr = event.second.newCr;
536 if (event.first >= today_) {
537 associatedDate_[grid_.index(time(event.first))] = event.first;
538 if (haveStochasticCr) {
539 // we know event.first >= today if haveStochasticCr is true
540 Size index = grid_.index(time(event.first));
541 hasConversionReset_[index] = true;
542 conversionResetData_[index].resetToSpecificValue = true;
543 conversionResetData_[index].newCr = currentCr;
544 }
545 }
546 }
547
548 // update current cr on grid
549
550 for (Size i = grid_.index(time(std::max(event.first, today_))); i < grid_.size(); ++i) {
551 currentConversionRatio_[i] = currentCr;
552 }
553
554 } // for adjEvents
555
556} // processConversionData()
Date nextConversionDate(const Date &d) const
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ processMandatoryConversionData()

void processMandatoryConversionData ( )
private

Definition at line 558 of file fdconvertiblebondevents.cpp.

558 {
559 for (auto const& d : registeredMandatoryConversionData_) {
560 if (d.exerciseDate <= today_)
561 continue;
562 Size index = grid_.index(time(d.exerciseDate));
563 associatedDate_[index] = d.exerciseDate;
564 hasMandatoryConversion_[index] = true;
565 mandatoryConversionData_[index] = {d.pepsUpperBarrier * currentFxConversion_[index],
566 d.pepsLowerBarrier * currentFxConversion_[index], d.pepsUpperConversionRatio,
567 d.pepsLowerConversionRatio};
568 }
569}
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

Member Data Documentation

◆ today_

Date today_
private

Definition at line 165 of file fdconvertiblebondevents.hpp.

◆ dc_

DayCounter dc_
private

Definition at line 166 of file fdconvertiblebondevents.hpp.

◆ N0_

Real N0_
private

Definition at line 167 of file fdconvertiblebondevents.hpp.

◆ equity_

QuantLib::ext::shared_ptr<QuantExt::EquityIndex2> equity_
private

Definition at line 168 of file fdconvertiblebondevents.hpp.

◆ fxConversion_

QuantLib::ext::shared_ptr<FxIndex> fxConversion_
private

Definition at line 169 of file fdconvertiblebondevents.hpp.

◆ times_

std::set<Real> times_
private

Definition at line 171 of file fdconvertiblebondevents.hpp.

◆ grid_

TimeGrid grid_
private

Definition at line 172 of file fdconvertiblebondevents.hpp.

◆ finalised_

bool finalised_ = false
private

Definition at line 173 of file fdconvertiblebondevents.hpp.

◆ lastRedemptionDate_

Date lastRedemptionDate_
private

Definition at line 175 of file fdconvertiblebondevents.hpp.

◆ registeredBondCashflows_

std::vector<QuantLib::ext::shared_ptr<CashFlow> > registeredBondCashflows_
private

Definition at line 178 of file fdconvertiblebondevents.hpp.

◆ registeredCallData_

std::vector<ConvertibleBond2::CallabilityData> registeredCallData_
private

Definition at line 179 of file fdconvertiblebondevents.hpp.

◆ registeredPutData_

std::vector<ConvertibleBond2::CallabilityData> registeredPutData_
private

Definition at line 179 of file fdconvertiblebondevents.hpp.

◆ registeredConversionRatioData_

std::vector<ConvertibleBond2::ConversionRatioData> registeredConversionRatioData_
private

Definition at line 180 of file fdconvertiblebondevents.hpp.

◆ registeredConversionData_

std::vector<ConvertibleBond2::ConversionData> registeredConversionData_
private

Definition at line 181 of file fdconvertiblebondevents.hpp.

◆ registeredMandatoryConversionData_

std::vector<ConvertibleBond2::MandatoryConversionData> registeredMandatoryConversionData_
private

Definition at line 182 of file fdconvertiblebondevents.hpp.

◆ registeredConversionResetData_

std::vector<ConvertibleBond2::ConversionResetData> registeredConversionResetData_
private

Definition at line 183 of file fdconvertiblebondevents.hpp.

◆ registeredDividendProtectionData_

std::vector<ConvertibleBond2::DividendProtectionData> registeredDividendProtectionData_
private

Definition at line 184 of file fdconvertiblebondevents.hpp.

◆ registeredMakeWholeData_

ConvertibleBond2::MakeWholeData registeredMakeWholeData_
private

Definition at line 185 of file fdconvertiblebondevents.hpp.

◆ hasBondCashflow_

std::vector<bool> hasBondCashflow_
private

Definition at line 188 of file fdconvertiblebondevents.hpp.

◆ hasCall_

std::vector<bool> hasCall_
private

Definition at line 188 of file fdconvertiblebondevents.hpp.

◆ hasPut_

std::vector<bool> hasPut_
private

Definition at line 188 of file fdconvertiblebondevents.hpp.

◆ hasConversion_

std::vector<bool> hasConversion_
private

Definition at line 189 of file fdconvertiblebondevents.hpp.

◆ hasMandatoryConversion_

std::vector<bool> hasMandatoryConversion_
private

Definition at line 189 of file fdconvertiblebondevents.hpp.

◆ hasContingentConversion_

std::vector<bool> hasContingentConversion_
private

Definition at line 189 of file fdconvertiblebondevents.hpp.

◆ hasConversionInfoSet_

std::vector<bool> hasConversionInfoSet_
private

Definition at line 189 of file fdconvertiblebondevents.hpp.

◆ hasNoConversionPlane_

std::vector<bool> hasNoConversionPlane_
private

Definition at line 190 of file fdconvertiblebondevents.hpp.

◆ hasConversionReset_

std::vector<bool> hasConversionReset_
private

Definition at line 190 of file fdconvertiblebondevents.hpp.

◆ hasDividendPassThrough_

std::vector<bool> hasDividendPassThrough_
private

Definition at line 191 of file fdconvertiblebondevents.hpp.

◆ bondCashflow_

std::vector<Real> bondCashflow_
private

Definition at line 194 of file fdconvertiblebondevents.hpp.

◆ bondFinalRedemption_

std::vector<Real> bondFinalRedemption_
private

Definition at line 194 of file fdconvertiblebondevents.hpp.

◆ callData_

std::vector<CallData> callData_
private

Definition at line 195 of file fdconvertiblebondevents.hpp.

◆ putData_

std::vector<CallData> putData_
private

Definition at line 195 of file fdconvertiblebondevents.hpp.

◆ conversionData_

std::vector<ConversionData> conversionData_
private

Definition at line 196 of file fdconvertiblebondevents.hpp.

◆ mandatoryConversionData_

std::vector<MandatoryConversionData> mandatoryConversionData_
private

Definition at line 197 of file fdconvertiblebondevents.hpp.

◆ conversionResetData_

std::vector<ConversionResetData> conversionResetData_
private

Definition at line 198 of file fdconvertiblebondevents.hpp.

◆ dividendPassThroughData_

std::vector<DividendPassThroughData> dividendPassThroughData_
private

Definition at line 199 of file fdconvertiblebondevents.hpp.

◆ stochasticConversionRatio_

std::vector<bool> stochasticConversionRatio_
private

Definition at line 201 of file fdconvertiblebondevents.hpp.

◆ initialConversionRatio_

Real initialConversionRatio_
private

Definition at line 202 of file fdconvertiblebondevents.hpp.

◆ currentConversionRatio_

std::vector<Real> currentConversionRatio_
private

Definition at line 203 of file fdconvertiblebondevents.hpp.

◆ currentFxConversion_

std::vector<Real> currentFxConversion_
private

Definition at line 204 of file fdconvertiblebondevents.hpp.

◆ associatedDate_

std::vector<Date> associatedDate_
private

Definition at line 205 of file fdconvertiblebondevents.hpp.

◆ additionalResults_

std::map<std::string, boost::any> additionalResults_
private

Definition at line 208 of file fdconvertiblebondevents.hpp.

◆ mw_cr_inc_x_

QuantLib::Array mw_cr_inc_x_
private

Definition at line 211 of file fdconvertiblebondevents.hpp.

◆ mw_cr_inc_y_

QuantLib::Array mw_cr_inc_y_
private

Definition at line 211 of file fdconvertiblebondevents.hpp.

◆ mw_cr_inc_z_

QuantLib::Matrix mw_cr_inc_z_
private

Definition at line 212 of file fdconvertiblebondevents.hpp.