Skip to content

Instantly share code, notes, and snippets.

@tomwhoiscontrary
Created October 1, 2019 14:48
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tomwhoiscontrary/63a539e33e9d5f9b6bcb25fedbd293ec to your computer and use it in GitHub Desktop.
Save tomwhoiscontrary/63a539e33e9d5f9b6bcb25fedbd293ec to your computer and use it in GitHub Desktop.
Failing to price a seasoned SONIA OIS with QuantLib
#! /bin/bash -eu
cd "$(dirname "$0")"
$GCC_HOME/bin/g++ -std=c++17 -Wall -g -I $QL_PATH/include -L $QL_PATH ${GCC_OPTS:-} sonia_demo.cpp -lQuantLib -o sonia_demo
LD_LIBRARY_PATH=$QL_PATH ./sonia_demo
#include <iostream>
#include <map>
#include <memory>
#include <vector>
#include <ql/config.hpp>
#include <ql/handle.hpp>
#include <ql/indexes/ibor/sonia.hpp>
#include <ql/indexes/iborindex.hpp>
#include <ql/math/interpolations/convexmonotoneinterpolation.hpp>
#include <ql/pricingengines/swap/discountingswapengine.hpp>
#include <ql/quote.hpp>
#include <ql/settings.hpp>
#include <ql/termstructures/yield/bootstraptraits.hpp>
#include <ql/termstructures/yield/oisratehelper.hpp>
#include <ql/termstructures/yield/piecewiseyieldcurve.hpp>
#include <ql/termstructures/yieldtermstructure.hpp>
#include <ql/time/date.hpp>
#include <ql/time/period.hpp>
using QuantLib::Actual365Fixed;
using QuantLib::BusinessDayConvention;
using QuantLib::Calendar;
using QuantLib::ConvexMonotone;
using QuantLib::Date;
using QuantLib::DateGeneration;
using QuantLib::DiscountingSwapEngine;
using QuantLib::ForwardRate;
using QuantLib::Handle;
using QuantLib::Month;
using QuantLib::OISRateHelper;
using QuantLib::OvernightIndex;
using QuantLib::OvernightIndexedSwap;
using QuantLib::Period;
using QuantLib::PiecewiseYieldCurve;
using QuantLib::Quote;
using QuantLib::RateHelper;
using QuantLib::RelinkableHandle;
using QuantLib::Schedule;
using QuantLib::Settings;
using QuantLib::SimpleQuote;
using QuantLib::Sonia;
using QuantLib::TimeUnit;
using QuantLib::YieldTermStructure;
int main() {
Date today = Date(1, Month::Oct, 2019);
Settings::instance().evaluationDate() = today;
RelinkableHandle<YieldTermStructure> curveHandle;
std::shared_ptr<OvernightIndex> index = std::make_shared<Sonia>(curveHandle);
// past
std::map<Date, double> fixings = {{Date(9, Month::Sep, 2019), 0.7096}, //
{Date(10, Month::Sep, 2019), 0.7087}, //
{Date(11, Month::Sep, 2019), 0.7091}, //
{Date(12, Month::Sep, 2019), 0.7096}, //
{Date(13, Month::Sep, 2019), 0.708}, //
{Date(16, Month::Sep, 2019), 0.7099}, //
{Date(17, Month::Sep, 2019), 0.711}, //
{Date(18, Month::Sep, 2019), 0.7104}, //
{Date(19, Month::Sep, 2019), 0.7104}, //
{Date(20, Month::Sep, 2019), 0.7093}, //
{Date(23, Month::Sep, 2019), 0.7099}, //
{Date(24, Month::Sep, 2019), 0.7105}, //
{Date(25, Month::Sep, 2019), 0.7099}, //
{Date(26, Month::Sep, 2019), 0.7109}, //
{Date(27, Month::Sep, 2019), 0.7109}};
std::vector<Date> fixingDates;
std::vector<double> fixingRates;
for (const std::pair<Date, double>& dateAndRate : fixings) {
fixingDates.push_back(dateAndRate.first);
fixingRates.push_back(dateAndRate.second);
}
index->addFixings(fixingDates.cbegin(), fixingDates.cend(), fixingRates.cbegin());
// future
int settlementDays = 1;
std::map<Period, double> tenorsAndRates = {{Period(7, TimeUnit::Days), 0.00713}, //
{Period(14, TimeUnit::Days), 0.00713}, //
{Period(1, TimeUnit::Months), 0.00713}, //
{Period(2, TimeUnit::Months), 0.00688925}, //
{Period(3, TimeUnit::Months), 0.00673}, //
{Period(4, TimeUnit::Months), 0.00658}, //
{Period(5, TimeUnit::Months), 0.0064}, //
{Period(6, TimeUnit::Months), 0.00626}, //
{Period(9, TimeUnit::Months), 0.005845}, //
{Period(1, TimeUnit::Years), 0.00552}, //
{Period(2, TimeUnit::Years), 0.004695}, //
{Period(3, TimeUnit::Years), 0.0043152}, //
{Period(4, TimeUnit::Years), 0.0041625}, //
{Period(5, TimeUnit::Years), 0.004108}, //
{Period(7, TimeUnit::Years), 0.0041963}, //
{Period(10, TimeUnit::Years), 0.0045982}, //
{Period(12, TimeUnit::Years), 0.0048575}, //
{Period(15, TimeUnit::Years), 0.0051275}, //
{Period(20, TimeUnit::Years), 0.0053178}, //
{Period(25, TimeUnit::Years), 0.0053353}, //
{Period(30, TimeUnit::Years), 0.005325}, //
{Period(40, TimeUnit::Years), 0.0052702}, //
{Period(50, TimeUnit::Years), 0.0051374}};
std::vector<std::shared_ptr<RateHelper>> helpers;
for (const std::pair<Period, double>& tenorAndRate : tenorsAndRates) {
helpers.push_back(std::make_shared<OISRateHelper>(settlementDays,
tenorAndRate.first,
Handle<Quote>(std::make_shared<SimpleQuote>(tenorAndRate.second)),
index));
}
std::shared_ptr<PiecewiseYieldCurve<ForwardRate, ConvexMonotone>> curve =
std::make_shared<PiecewiseYieldCurve<ForwardRate, ConvexMonotone>>(today, helpers, index->dayCounter());
curve->enableExtrapolation();
curveHandle.linkTo(curve);
// price
Date effectiveDate = today - Period(3, TimeUnit::Weeks);
Period tenor = Period(3, TimeUnit::Years);
OvernightIndexedSwap ois = OvernightIndexedSwap(OvernightIndexedSwap::Type::Payer,
1,
Schedule(effectiveDate,
effectiveDate + tenor,
Period(1, TimeUnit::Years),
index->fixingCalendar(),
BusinessDayConvention ::ModifiedFollowing,
BusinessDayConvention ::ModifiedFollowing,
DateGeneration::Rule::Backward,
false),
0,
Actual365Fixed(),
index,
0.0, // default spread
0, // default paymentLag
BusinessDayConvention::Following, // default paymentAdjustment
Calendar(), // default paymentCalendar
true);
ois.setPricingEngine(std::make_shared<DiscountingSwapEngine>(curveHandle));
std::cout << "fairRate " << ois.fairRate() << '\n';
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment