Skip to content
Open
Show file tree
Hide file tree
Changes from 14 commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
93e3a24
First alignment ORE/QL ON coupon and ON coupon pricer
paolodelia99 Aug 7, 2025
85216a2
Add test for the overnightLeg
paolodelia99 Aug 7, 2025
633167f
Fix tolerance in overnightleg test
paolodelia99 Aug 10, 2025
121b3f3
Added blackovernigthindexedcouponpricer and updated pricesetter methods
paolodelia99 Aug 18, 2025
1dc90fd
Update generated headers
github-actions[bot] Aug 18, 2025
5092a67
Update copyright list in license
github-actions[bot] Aug 19, 2025
c8a9a43
Fix typo in vcxproj file
paolodelia99 Aug 19, 2025
8081384
Removed pragma once and use ifdef
paolodelia99 Aug 19, 2025
fabeac9
removed redundant attributes, add first test for black pricer and ref…
paolodelia99 Aug 22, 2025
c4deaad
add test for capped-floored on coupons and leg
paolodelia99 Aug 22, 2025
a16c479
Fix at par Coupon error
paolodelia99 Aug 22, 2025
cf06707
add a futher cap and floor rate to match the schedule size in the tests
paolodelia99 Aug 29, 2025
db54efa
More realistic tests when calculating ON leg npv
paolodelia99 Aug 31, 2025
25c0cd5
Initialize flags properly
lballabio Sep 3, 2025
c84af72
Adjustements to the ON coupon pricers class as suggested
paolodelia99 Oct 4, 2025
9ad665a
made some ctors explicit
paolodelia99 Oct 4, 2025
40fb327
Make onIndexedCouponPricer the base class for the blackONPricers, adj…
paolodelia99 Oct 10, 2025
972bace
Fix compilation error, overload virtual functions
paolodelia99 Oct 10, 2025
87f381b
use ext::dynamic_pointer_cast
paolodelia99 Oct 10, 2025
12f9d13
ovveride cap/floorletRate(Real, bool) and in direct childs
paolodelia99 Oct 10, 2025
b8a116f
Small adjustments as suggested in the PR
paolodelia99 Oct 17, 2025
6399fca
Added adj in ONCoupoon ctor, fix bug when computing the effectiveInde…
paolodelia99 Nov 26, 2025
282e742
fix win compilation error using static_cast of lookbackDays
paolodelia99 Nov 26, 2025
a55e725
return plain spread in case simple avg ONCopoun
paolodelia99 Dec 8, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion LICENSE.TXT
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ Copyright (C) 2016 Nicholas Bertocchi
Copyright (C) 2016 Stefano Fondi
Copyright (C) 2016, 2017 Fabrice Lecuyer
Copyright (C) 2016, 2019, 2020 Eisuke Tani
Copyright (C) 2016, 2022 Quaternion Risk Management Ltd
Copyright (C) 2016, 2020, 2022 Quaternion Risk Management Ltd

Copyright (C) 2017 BN Algorithms Ltd
Copyright (C) 2017 Joseph Jeisman
Expand Down
2 changes: 2 additions & 0 deletions QuantLib.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -510,6 +510,7 @@
<ItemGroup>
<ClInclude Include="ql\cashflows\all.hpp" />
<ClInclude Include="ql\cashflows\averagebmacoupon.hpp" />
<ClInclude Include="ql\cashflows\blackovernightindexedcouponpricer.hpp" />
<ClInclude Include="ql\cashflows\capflooredcoupon.hpp" />
<ClInclude Include="ql\cashflows\capflooredinflationcoupon.hpp" />
<ClInclude Include="ql\cashflows\cashflows.hpp" />
Expand Down Expand Up @@ -1924,6 +1925,7 @@
</ItemGroup>
<ItemGroup>
<ClCompile Include="ql\cashflows\averagebmacoupon.cpp" />
<ClCompile Include="ql\cashflows\blackovernightindexedcouponpricer.cpp" />
<ClCompile Include="ql\cashflows\capflooredcoupon.cpp" />
<ClCompile Include="ql\cashflows\capflooredinflationcoupon.cpp" />
<ClCompile Include="ql\cashflows\cashflows.cpp" />
Expand Down
6 changes: 6 additions & 0 deletions QuantLib.vcxproj.filters
Original file line number Diff line number Diff line change
Expand Up @@ -495,6 +495,9 @@
<ClInclude Include="ql\cashflows\averagebmacoupon.hpp">
<Filter>cashflows</Filter>
</ClInclude>
<ClInclude Include="ql\cashflows\blackovernightindexedcouponpricer.hpp">
<Filter>cashflows</Filter>
</ClInclude>
<ClInclude Include="ql\cashflows\capflooredcoupon.hpp">
<Filter>cashflows</Filter>
</ClInclude>
Expand Down Expand Up @@ -4529,6 +4532,9 @@
<ClCompile Include="ql\cashflows\averagebmacoupon.cpp">
<Filter>cashflows</Filter>
</ClCompile>
<ClCompile Include="ql\cashflows\blackovernightindexedcouponpricer.cpp">
<Filter>cashflows</Filter>
</ClCompile>
<ClCompile Include="ql\cashflows\capflooredcoupon.cpp">
<Filter>cashflows</Filter>
</ClCompile>
Expand Down
2 changes: 2 additions & 0 deletions ql/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
set(QL_SOURCES
cashflow.cpp
cashflows/averagebmacoupon.cpp
cashflows/blackovernightindexedcouponpricer.cpp
cashflows/capflooredcoupon.cpp
cashflows/capflooredinflationcoupon.cpp
cashflows/cashflows.cpp
Expand Down Expand Up @@ -951,6 +952,7 @@ set(QL_HEADERS
auto_link.hpp
cashflow.hpp
cashflows/averagebmacoupon.hpp
cashflows/blackovernightindexedcouponpricer.hpp
cashflows/capflooredcoupon.hpp
cashflows/capflooredinflationcoupon.hpp
cashflows/cashflows.hpp
Expand Down
2 changes: 2 additions & 0 deletions ql/cashflows/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ this_includedir=${includedir}/${subdir}
this_include_HEADERS = \
all.hpp \
averagebmacoupon.hpp \
blackovernightindexedcouponpricer.hpp \
capflooredcoupon.hpp \
capflooredinflationcoupon.hpp \
cashflows.hpp \
Expand Down Expand Up @@ -42,6 +43,7 @@ this_include_HEADERS = \

cpp_files = \
averagebmacoupon.cpp \
blackovernightindexedcouponpricer.cpp \
capflooredcoupon.cpp \
capflooredinflationcoupon.cpp \
cashflows.cpp \
Expand Down
1 change: 1 addition & 0 deletions ql/cashflows/all.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
/* Add the files to be included into Makefile.am instead. */

#include <ql/cashflows/averagebmacoupon.hpp>
#include <ql/cashflows/blackovernightindexedcouponpricer.hpp>
#include <ql/cashflows/capflooredcoupon.hpp>
#include <ql/cashflows/capflooredinflationcoupon.hpp>
#include <ql/cashflows/cashflows.hpp>
Expand Down
513 changes: 513 additions & 0 deletions ql/cashflows/blackovernightindexedcouponpricer.cpp

Large diffs are not rendered by default.

93 changes: 93 additions & 0 deletions ql/cashflows/blackovernightindexedcouponpricer.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
/* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */

/*
Copyright (C) 2020 Quaternion Risk Management Ltd

This file is part of QuantLib, a free-software/open-source library
for financial quantitative analysts and developers - http://quantlib.org/

QuantLib is free software: you can redistribute it and/or modify it
under the terms of the QuantLib license. You should have received a
copy of the license along with this program; if not, please email
<[email protected]>. The license is also available online at
<http://quantlib.org/license.shtml>.


This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the license for more details.
*/

/*! \file blackovernightindexedcouponpricer.hpp
\brief black coupon pricer for capped / floored ON indexed coupons
*/

#ifndef quantlib_black_overnight_indexed_coupon_pricer_hpp
#define quantlib_black_overnight_indexed_coupon_pricer_hpp

#include <ql/cashflows/overnightindexedcoupon.hpp>
#include <ql/cashflows/overnightindexedcouponpricer.hpp>

#include <ql/termstructures/volatility/optionlet/optionletvolatilitystructure.hpp>

namespace QuantLib {

//! Black compounded overnight coupon pricer
/* The methods that are implemented here to price capped / floored compounded ON coupons are
highly experimental and ad-hoc. As soon as a market best practice has evolved, the pricer
should be revised. */
class BlackOvernightIndexedCouponPricer : public CappedFlooredOvernightIndexedCouponPricer {
public:
using CappedFlooredOvernightIndexedCouponPricer::CappedFlooredOvernightIndexedCouponPricer;
//! \name FloatingRateCoupon interface
//@{
void initialize(const FloatingRateCoupon& coupon) override;
Real swapletPrice() const override;
Rate swapletRate() const override;
Real capletPrice(Rate effectiveCap) const override;
Rate capletRate(Rate effectiveCap) const override;
Real floorletPrice(Rate effectiveFloor) const override;
Rate floorletRate(Rate effectiveFloor) const override;
//@}
private:
Real optionletRateGlobal(Option::Type optionType, Real effStrike) const;
Real optionletRateLocal(Option::Type optionType, Real effStrike) const;

Real gearing_;
ext::shared_ptr<IborIndex> index_;
Real effectiveIndexFixing_, swapletRate_;

const CappedFlooredOvernightIndexedCoupon* coupon_;
};

//! Black averaged overnight coupon pricer
/* The methods that are implemented here to price capped / floored average ON coupons are
highly experimental and ad-hoc. As soon as a market best practice has evolved, the pricer
should be revised. */
class BlackAverageONIndexedCouponPricer : public CappedFlooredOvernightIndexedCouponPricer {
public:
using CappedFlooredOvernightIndexedCouponPricer::CappedFlooredOvernightIndexedCouponPricer;
//! \name FloatingRateCoupon interface
//@{
void initialize(const FloatingRateCoupon& coupon) override;
Real swapletPrice() const override;
Rate swapletRate() const override;
Real capletPrice(Rate effectiveCap) const override;
Rate capletRate(Rate effectiveCap) const override;
Real floorletPrice(Rate effectiveFloor) const override;
Rate floorletRate(Rate effectiveFloor) const override;
//@}
private:
Real optionletRateGlobal(Option::Type optionType, Real effStrike) const;
Real optionletRateLocal(Option::Type optionType, Real effStrike) const;

Real gearing_;
ext::shared_ptr<IborIndex> index_;
Real swapletRate_, forwardRate_;

const CappedFlooredOvernightIndexedCoupon* coupon_;
};

}

#endif
33 changes: 33 additions & 0 deletions ql/cashflows/couponpricer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@
#include <ql/cashflows/digitaliborcoupon.hpp>
#include <ql/cashflows/rangeaccrual.hpp>
#include <ql/cashflows/multipleresetscoupon.hpp>
#include <ql/cashflows/overnightindexedcoupon.hpp>
#include <ql/cashflows/overnightindexedcouponpricer.hpp>
#include <ql/cashflows/blackovernightindexedcouponpricer.hpp>
#include <ql/experimental/coupons/cmsspreadcoupon.hpp> /* internal */
#include <ql/experimental/coupons/digitalcmsspreadcoupon.hpp> /* internal */
#include <ql/pricingengines/blackformula.hpp>
Expand Down Expand Up @@ -249,6 +252,8 @@ namespace QuantLib {
public Visitor<CappedFlooredIborCoupon>,
public Visitor<CappedFlooredCmsCoupon>,
public Visitor<CappedFlooredCmsSpreadCoupon>,
public Visitor<OvernightIndexedCoupon>,
public Visitor<CappedFlooredOvernightIndexedCoupon>,
public Visitor<DigitalIborCoupon>,
public Visitor<DigitalCmsCoupon>,
public Visitor<DigitalCmsSpreadCoupon>,
Expand All @@ -266,6 +271,8 @@ namespace QuantLib {
void visit(CappedFlooredCoupon& c) override;
void visit(IborCoupon& c) override;
void visit(CappedFlooredIborCoupon& c) override;
void visit(OvernightIndexedCoupon& c) override;
void visit(CappedFlooredOvernightIndexedCoupon& c) override;
void visit(DigitalIborCoupon& c) override;
void visit(CmsCoupon& c) override;
void visit(CmsSpreadCoupon& c) override;
Expand Down Expand Up @@ -330,6 +337,32 @@ namespace QuantLib {
c.setPricer(iborCouponPricer);
}

void PricerSetter::visit(OvernightIndexedCoupon& c) {
if (c.averagingMethod() == RateAveraging::Compound) {
const ext::shared_ptr<CompoundingOvernightIndexedCouponPricer> overnightCouponPricer =
ext::dynamic_pointer_cast<CompoundingOvernightIndexedCouponPricer>(pricer_);
QL_REQUIRE(overnightCouponPricer,
"pricer not compatible with overnight indexed coupon");
c.setPricer(overnightCouponPricer);
} else {
const ext::shared_ptr<ArithmeticAveragedOvernightIndexedCouponPricer> overnightCouponPricer =
ext::dynamic_pointer_cast<ArithmeticAveragedOvernightIndexedCouponPricer>(pricer_);
QL_REQUIRE(overnightCouponPricer,
"pricer not compatible with arithmetic averaged overnight indexed coupon");
c.setPricer(overnightCouponPricer);
}
}

void PricerSetter::visit(CappedFlooredOvernightIndexedCoupon& c) {
const ext::shared_ptr<CappedFlooredOvernightIndexedCouponPricer> p =
ext::dynamic_pointer_cast<CappedFlooredOvernightIndexedCouponPricer>(pricer_);
// we can set a pricer for the capped floored on coupon or the underlying on coupon
if (p)
c.setPricer(p);
else
c.underlying()->accept(*this);
}

void PricerSetter::visit(CmsCoupon& c) {
const ext::shared_ptr<CmsCouponPricer> cmsCouponPricer =
ext::dynamic_pointer_cast<CmsCouponPricer>(pricer_);
Expand Down
Loading
Loading