Skip to content

Commit

Permalink
Add BondFunctions::dirtyPrice() functions
Browse files Browse the repository at this point in the history
  • Loading branch information
igitur committed Mar 1, 2024
1 parent 28c71b7 commit 95ac5fa
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 2 deletions.
26 changes: 24 additions & 2 deletions ql/pricingengines/bond/bondfunctions.cpp
Expand Up @@ -242,6 +242,15 @@ namespace QuantLib {
if (settlement == Date())
settlement = bond.settlementDate();

return dirtyPrice(bond, discountCurve, settlement) - bond.accruedAmount(settlement);
}

Real BondFunctions::dirtyPrice(const Bond& bond,
const YieldTermStructure& discountCurve,
Date settlement) {
if (settlement == Date())
settlement = bond.settlementDate();

QL_REQUIRE(BondFunctions::isTradable(bond, settlement),
"non tradable at " << settlement <<
" settlement date (maturity being " <<
Expand All @@ -250,7 +259,7 @@ namespace QuantLib {
Real dirtyPrice = CashFlows::npv(bond.cashflows(), discountCurve,
false, settlement) *
100.0 / bond.notional(settlement);
return dirtyPrice - bond.accruedAmount(settlement);
return dirtyPrice;
}

Real BondFunctions::bps(const Bond& bond,
Expand Down Expand Up @@ -508,6 +517,19 @@ namespace QuantLib {
if (settlement == Date())
settlement = bond.settlementDate();

return dirtyPrice(bond, d, zSpread, dc, comp, freq, settlement) - bond.accruedAmount(settlement);
}

Real BondFunctions::dirtyPrice(const Bond& bond,
const ext::shared_ptr<YieldTermStructure>& d,
Spread zSpread,
const DayCounter& dc,
Compounding comp,
Frequency freq,
Date settlement) {
if (settlement == Date())
settlement = bond.settlementDate();

QL_REQUIRE(BondFunctions::isTradable(bond, settlement),
"non tradable at " << settlement <<
" (maturity being " << bond.maturityDate() << ")");
Expand All @@ -516,7 +538,7 @@ namespace QuantLib {
zSpread, dc, comp, freq,
false, settlement) *
100.0 / bond.notional(settlement);
return dirtyPrice - bond.accruedAmount(settlement);
return dirtyPrice;
}

Spread BondFunctions::zSpread(const Bond& bond,
Expand Down
10 changes: 10 additions & 0 deletions ql/pricingengines/bond/bondfunctions.hpp
Expand Up @@ -108,6 +108,9 @@ namespace QuantLib {
static Real cleanPrice(const Bond& bond,
const YieldTermStructure& discountCurve,
Date settlementDate = Date());
static Real dirtyPrice(const Bond& bond,
const YieldTermStructure& discountCurve,
Date settlementDate = Date());
static Real bps(const Bond& bond,
const YieldTermStructure& discountCurve,
Date settlementDate = Date());
Expand Down Expand Up @@ -264,6 +267,13 @@ namespace QuantLib {
Compounding compounding,
Frequency frequency,
Date settlementDate = Date());
static Real dirtyPrice(const Bond& bond,
const ext::shared_ptr<YieldTermStructure>& discount,
Spread zSpread,
const DayCounter& dayCounter,
Compounding compounding,
Frequency frequency,
Date settlementDate = Date());
[[deprecated("Use the version with the Bond::Price argument")]]
static Spread zSpread(const Bond& bond,
Real cleanPrice,
Expand Down
31 changes: 31 additions & 0 deletions test-suite/bonds.cpp
Expand Up @@ -315,6 +315,7 @@ BOOST_AUTO_TEST_CASE(testZspread) {

for (Real spread : spreads) {

// Clean price
Bond::Price price(BondFunctions::cleanPrice(bond, *discountCurve,
spread, bondDayCount, n,
frequency),
Expand All @@ -341,6 +342,36 @@ BOOST_AUTO_TEST_CASE(testZspread) {
"\n clean price': " << price2);
}
}

// Dirty price
price =
Bond::Price(BondFunctions::dirtyPrice(bond, *discountCurve, spread,
bondDayCount, n, frequency),
Bond::Price::Dirty);

calculated = BondFunctions::zSpread(
bond, price, *discountCurve, bondDayCount, n, frequency, Date(),
tolerance, maxEvaluations);

if (std::fabs(spread - calculated) > tolerance) {
// the difference might not matter
Real price2 = BondFunctions::dirtyPrice(
bond, *discountCurve, calculated, bondDayCount, n, frequency);
if (std::fabs(price.amount() - price2) / price.amount() > tolerance) {
BOOST_ERROR("\nZ-spread recalculation failed:"
"\n issue: " << issue <<
"\n maturity: " << maturity <<
"\n coupon: " << io::rate(coupon) <<
"\n frequency: " << frequency <<
"\n Z-spread: " << io::rate(spread) <<
(compounding[n] == Compounded ?
" compounded" : " continuous") <<
std::setprecision(7) <<
"\n dirty price: " << price.amount() <<
"\n Z-spread': " << io::rate(calculated) <<
"\n dirty price': " << price2);
}
}
}
}
}
Expand Down

0 comments on commit 95ac5fa

Please sign in to comment.