22#include <boost/lexical_cast.hpp>
33#include <ql/cashflows/simplecashflow.hpp>
34#include <ql/errors.hpp>
35#include <ql/exercise.hpp>
36#include <ql/instruments/bond.hpp>
37#include <ql/instruments/bonds/zerocouponbond.hpp>
38#include <ql/instruments/callabilityschedule.hpp>
39#include <ql/instruments/compositeinstrument.hpp>
40#include <ql/instruments/vanillaoption.hpp>
41#include <ql/termstructures/volatility/swaption/swaptionvolstructure.hpp>
50 DLOG(
"Building Bond Option: " <<
id());
53 additionalData_[
"isdaAssetClass"] = string(
"Interest Rate");
54 additionalData_[
"isdaBaseProduct"] = string(
"Option");
55 additionalData_[
"isdaSubProduct"] = string(
"Debt Option");
56 additionalData_[
"isdaTransaction"] = string(
"");
58 const QuantLib::ext::shared_ptr<Market> market = engineFactory->market();
59 QuantLib::ext::shared_ptr<EngineBuilder> builder = engineFactory->builder(
"BondOption");
60 bondData_ = originalBondData_;
61 bondData_.populateFromBondReferenceData(engineFactory->referenceData());
64 QuantLib::ext::shared_ptr<QuantExt::BondOption> bondoption;
73 legPayers_ = std::vector<bool>(legs_.size(),
false);
75 notional_ =
underlying_->notional() * bondData_.bondNotional();
76 notionalCurrency_ =
underlying_->bondData().currency();
77 maturity_ = std::max(optionData_.premiumData().latestPremiumDate(),
underlying_->maturity());
79 auto qlBondInstr = QuantLib::ext::dynamic_pointer_cast<QuantLib::Bond>(
underlying_->instrument()->qlInstrument());
80 QL_REQUIRE(qlBondInstr,
"BondOption::build(): could not cast to QuantLib::Bond");
82 QL_REQUIRE(!p,
"BondOption::build(): underlying leg must be receiver");
85 boost::variant<QuantLib::Bond::Price, QuantLib::InterestRate> callabilityPrice;
86 if (strike_.type() == TradeStrike::Type::Price) {
87 if (priceType_ ==
"Dirty") {
88 callabilityPrice = QuantLib::Bond::Price(strike_.value(), QuantLib::Bond::Price::Dirty);
89 }
else if (priceType_ ==
"Clean") {
90 callabilityPrice = QuantLib::Bond::Price(strike_.value(), QuantLib::Bond::Price::Clean);
92 QL_FAIL(
"BondOption::build(): price type \"" << priceType_ <<
"\" not recognised.");
96 DayCounter dayCounter = Actual365Fixed();
97 Frequency freq = Annual;
99 if (bondData_.coupons().size() > 0) {
100 auto cn = bondData_.coupons().front();
101 const string& dc = cn.dayCounter();
104 if (cn.schedule().rules().size() > 0)
105 freq =
parsePeriod(cn.schedule().rules().front().tenor()).frequency();
107 callabilityPrice = QuantLib::InterestRate(strike_.value(), dayCounter, strike_.compounding(), freq);
110 Callability::Type callabilityType =
111 parseOptionType(optionData_.callPut()) == Option::Call ? Callability::Call : Callability::Put;
113 QL_REQUIRE(optionData_.exerciseDates().size() == 1,
114 "BondOption::build(): exactly one option date required, found " << optionData_.exerciseDates().size());
115 Date exerciseDate =
parseDate(optionData_.exerciseDates().back());
116 QuantLib::ext::shared_ptr<Callability>
callability;
118 CallabilitySchedule callabilitySchedule = std::vector<QuantLib::ext::shared_ptr<Callability>>(1,
callability);
124 QuantLib::ext::shared_ptr<BondOptionEngineBuilder> bondOptionBuilder =
125 QuantLib::ext::dynamic_pointer_cast<BondOptionEngineBuilder>(builder);
126 QL_REQUIRE(bondOptionBuilder,
"No Builder found for bondOption: " <<
id());
128 QuantLib::ext::shared_ptr<BlackBondOptionEngine> blackEngine = QuantLib::ext::dynamic_pointer_cast<BlackBondOptionEngine>(
129 bondOptionBuilder->engine(
id(), currency, bondData_.creditCurveId(), bondData_.hasCreditRisk(),
130 bondData_.securityId(), bondData_.referenceCurveId(), bondData_.volatilityCurveId()));
131 bondoption->setPricingEngine(blackEngine);
132 setSensitivityTemplate(*bondOptionBuilder);
135 bondData_.bondNotional() * (
parsePositionType(optionData_.longShort()) == Position::Long ? 1.0 : -1.0);
137 std::vector<QuantLib::ext::shared_ptr<Instrument>> additionalInstruments;
138 std::vector<Real> additionalMultipliers;
139 addPremiums(additionalInstruments, additionalMultipliers, multiplier, optionData_.premiumData(),
140 multiplier > 0.0 ? -1.0 : 1.0, currency, engineFactory,
141 bondOptionBuilder->configuration(MarketContext::pricing));
143 instrument_.reset(
new VanillaInstrument(bondoption, multiplier, additionalInstruments, additionalMultipliers));
150 Trade::fromXML(node);
152 XMLNode* bondOptionNode = XMLUtils::getChildNode(node,
"BondOptionData");
153 QL_REQUIRE(bondOptionNode,
"No BondOptionData Node");
154 optionData_.fromXML(XMLUtils::getChildNode(bondOptionNode,
"OptionData"));
155 strike_.fromXML(bondOptionNode,
true,
true);
156 redemption_ = XMLUtils::getChildValueAsDouble(bondOptionNode,
"Redemption",
false, 100.0);
158 if (strike_.type() == TradeStrike::Type::Price)
159 priceType_ = XMLUtils::getChildValue(bondOptionNode,
"PriceType",
true);
160 if (
auto n = XMLUtils::getChildNode(bondOptionNode,
"KnocksOut"))
161 knocksOut_ =
parseBool(XMLUtils::getNodeValue(n));
165 originalBondData_.fromXML(XMLUtils::getChildNode(bondOptionNode,
"BondData"));
166 bondData_ = originalBondData_;
170 XMLNode* node = Trade::toXML(doc);
173 XMLUtils::appendNode(node, bondOptionNode);
174 XMLUtils::appendNode(bondOptionNode, optionData_.toXML(doc));
175 XMLUtils::appendNode(bondOptionNode, strike_.toXML(doc));
176 XMLUtils::addChild(doc, bondOptionNode,
"Redemption", redemption_);
177 if (!priceType_.empty())
178 XMLUtils::addChild(doc, bondOptionNode,
"PriceType", priceType_);
179 XMLUtils::addChild(doc, bondOptionNode,
"KnocksOut", knocksOut_);
181 XMLUtils::appendNode(bondOptionNode, originalBondData_.toXML(doc));
185std::map<AssetClass, std::set<std::string>>
186BondOption::underlyingIndices(
const QuantLib::ext::shared_ptr<ReferenceDataManager>& referenceDataManager)
const {
187 std::map<AssetClass, std::set<std::string>> result;
188 result[AssetClass::BOND] = {bondData_.securityId()};
Bond trade data model and serialization.
bond option data model and serialization
builder that returns an engine to price a bond instrument
Engine builder for bond option.
const CallabilitySchedule & callability() const
const boost::shared_ptr< QuantLib::Bond > underlying_
virtual void build(const QuantLib::ext::shared_ptr< EngineFactory > &) override
Serializable object holding generic trade data, reporting dimensions.
Vanilla Instrument Wrapper.
Small XML Document wrapper class.
XMLNode * allocNode(const string &nodeName)
util functions that wrap rapidxml
Logic for calculating required fixing dates on legs.
Calendar parseCalendar(const string &s)
Convert text to QuantLib::Calendar.
Date parseDate(const string &s)
Convert std::string to QuantLib::Date.
Currency parseCurrency(const string &s)
Convert text to QuantLib::Currency.
Position::Type parsePositionType(const std::string &s)
Convert text to QuantLib::Position::Type.
Period parsePeriod(const string &s)
Convert text to QuantLib::Period.
bool parseBool(const string &s)
Convert text to bool.
DayCounter parseDayCounter(const string &s)
Convert text to QuantLib::DayCounter.
Option::Type parseOptionType(const std::string &s)
Convert text to QuantLib::Option::Type.
Map text representations to QuantLib/QuantExt types.
leg data model and serialization
Classes and functions for log message handling.
#define DLOG(text)
Logging Macro (Level = Debug)
Serializable Credit Default Swap.
Map text representations to QuantLib/QuantExt types.
Swap trade data model and serialization.