如何在 QuantLib 中求和利率曲線
C++ 程式碼取自
Bonds.cpp
並稍作修改:#include <ql/quantlib.hpp> #include <boost/timer.hpp> #include <iostream> #include <iomanip> using namespace QuantLib; int main(int, char* []) { try { // Just a couple of parameters Calendar calendar = TARGET(); Date settlementDate(18, September, 2008); settlementDate = calendar.adjust(settlementDate); Integer fixingDays = 3; Natural settlementDays = 3; Date todaysDate = calendar.advance(settlementDate, -fixingDays, Days); Settings::instance().evaluationDate() = todaysDate; /* Now let's introduce two curves: the first one is a swap curve built from deposits and IRS, the second one is a credit spread curve which should be added to the former one to get a proper yield curve */ // Swap curve DayCounter termStructureDayCounter = ActualActual(ActualActual::ISDA); double tolerance = 1.0e-5; // Deposits Rate d1wQuote = 0.043375; Rate d1mQuote = 0.031875; Rate d3mQuote = 0.0320375; Rate d6mQuote = 0.03385; Rate d9mQuote = 0.0338125; Rate d1yQuote = 0.0335125; boost::shared_ptr<Quote> d1wRate(new SimpleQuote(d1wQuote)); boost::shared_ptr<Quote> d1mRate(new SimpleQuote(d1mQuote)); boost::shared_ptr<Quote> d3mRate(new SimpleQuote(d3mQuote)); boost::shared_ptr<Quote> d6mRate(new SimpleQuote(d6mQuote)); boost::shared_ptr<Quote> d9mRate(new SimpleQuote(d9mQuote)); boost::shared_ptr<Quote> d1yRate(new SimpleQuote(d1yQuote)); // IRS Rate s2yQuote = 0.0295; Rate s3yQuote = 0.0323; Rate s5yQuote = 0.0359; Rate s10yQuote = 0.0412; Rate s15yQuote = 0.0433; boost::shared_ptr<Quote> s2yRate(new SimpleQuote(s2yQuote)); boost::shared_ptr<Quote> s3yRate(new SimpleQuote(s3yQuote)); boost::shared_ptr<Quote> s5yRate(new SimpleQuote(s5yQuote)); boost::shared_ptr<Quote> s10yRate(new SimpleQuote(s10yQuote)); boost::shared_ptr<Quote> s15yRate(new SimpleQuote(s15yQuote)); // Rate Helper // Deposits DayCounter depositDayCounter = Actual360(); boost::shared_ptr<RateHelper> d1w(new DepositRateHelper( Handle<Quote>(d1wRate), 1*Weeks, fixingDays, calendar, ModifiedFollowing, true, depositDayCounter)); boost::shared_ptr<RateHelper> d1m(new DepositRateHelper( Handle<Quote>(d1mRate), 1*Months, fixingDays, calendar, ModifiedFollowing, true, depositDayCounter)); boost::shared_ptr<RateHelper> d3m(new DepositRateHelper( Handle<Quote>(d3mRate), 3*Months, fixingDays, calendar, ModifiedFollowing, true, depositDayCounter)); boost::shared_ptr<RateHelper> d6m(new DepositRateHelper( Handle<Quote>(d6mRate), 6*Months, fixingDays, calendar, ModifiedFollowing, true, depositDayCounter)); boost::shared_ptr<RateHelper> d9m(new DepositRateHelper( Handle<Quote>(d9mRate), 9*Months, fixingDays, calendar, ModifiedFollowing, true, depositDayCounter)); boost::shared_ptr<RateHelper> d1y(new DepositRateHelper( Handle<Quote>(d1yRate), 1*Years, fixingDays, calendar, ModifiedFollowing, true, depositDayCounter)); // Setup IRS Frequency swFixedLegFrequency = Annual; BusinessDayConvention swFixedLegConvention = Unadjusted; DayCounter swFixedLegDayCounter = Thirty360(Thirty360::European); boost::shared_ptr<IborIndex> swFloatingLegIndex(new Euribor6M); const Period forwardStart(1*Days); boost::shared_ptr<RateHelper> s2y(new SwapRateHelper( Handle<Quote>(s2yRate), 2*Years, calendar, swFixedLegFrequency, swFixedLegConvention, swFixedLegDayCounter, swFloatingLegIndex, Handle<Quote>(),forwardStart)); boost::shared_ptr<RateHelper> s3y(new SwapRateHelper( Handle<Quote>(s3yRate), 3*Years, calendar, swFixedLegFrequency, swFixedLegConvention, swFixedLegDayCounter, swFloatingLegIndex, Handle<Quote>(),forwardStart)); boost::shared_ptr<RateHelper> s5y(new SwapRateHelper( Handle<Quote>(s5yRate), 5*Years, calendar, swFixedLegFrequency, swFixedLegConvention, swFixedLegDayCounter, swFloatingLegIndex, Handle<Quote>(),forwardStart)); boost::shared_ptr<RateHelper> s10y(new SwapRateHelper( Handle<Quote>(s10yRate), 10*Years, calendar, swFixedLegFrequency, swFixedLegConvention, swFixedLegDayCounter, swFloatingLegIndex, Handle<Quote>(),forwardStart)); boost::shared_ptr<RateHelper> s15y(new SwapRateHelper( Handle<Quote>(s15yRate), 15*Years, calendar, swFixedLegFrequency, swFixedLegConvention, swFixedLegDayCounter, swFloatingLegIndex, Handle<Quote>(),forwardStart)); // A depo-swap curve std::vector<boost::shared_ptr<RateHelper> > depoSwapInstruments; depoSwapInstruments.push_back(d1w); depoSwapInstruments.push_back(d1m); depoSwapInstruments.push_back(d3m); depoSwapInstruments.push_back(d6m); depoSwapInstruments.push_back(d9m); depoSwapInstruments.push_back(d1y); depoSwapInstruments.push_back(s2y); depoSwapInstruments.push_back(s3y); depoSwapInstruments.push_back(s5y); depoSwapInstruments.push_back(s10y); depoSwapInstruments.push_back(s15y); boost::shared_ptr<YieldTermStructure> depoSwapTermStructure( new PiecewiseYieldCurve<Discount,LogLinear>( settlementDate, depoSwapInstruments, termStructureDayCounter, tolerance)); return 0; } catch (std::exception& e) { std::cerr << e.what() << std::endl; return 1; } catch (...) { std::cerr << "unknown error" << std::endl; return 1; } }
如果我沒記錯的話,到目前為止,我們已經獲得了一種無風險貼現曲線。
現在讓我以對象的形式介紹一條額外的信用利差曲線,由
RateHelper
(在上面程式碼的 depo-swap 曲線之後插入的片段):... Rate d1ySpread = 0.013; Rate d2ySpread = 0.011; Rate d3ySpread = 0.022; Rate d6ySpread = 0.0238; Rate d9ySpread = 0.0238; Rate d10ySpread = 0.0239; boost::shared_ptr<Quote> d1ySpreadRate(new SimpleQuote(d1ySpread)); boost::shared_ptr<Quote> d2ySpreadRate(new SimpleQuote(d2ySpread)); boost::shared_ptr<Quote> d3ySpreadRate(new SimpleQuote(d3ySpread)); boost::shared_ptr<Quote> d6ySpreadRate(new SimpleQuote(d6ySpread)); boost::shared_ptr<Quote> d9ySpreadRate(new SimpleQuote(d9ySpread)); boost::shared_ptr<Quote> d10ySpreadRate(new SimpleQuote(d10ySpread)); boost::shared_ptr<RateHelper> credit1y(new SwapRateHelper( Handle<Quote>(d1ySpreadRate), 1*Years, calendar, swFixedLegFrequency, swFixedLegConvention, swFixedLegDayCounter, swFloatingLegIndex, Handle<Quote>(),forwardStart)); boost::shared_ptr<RateHelper> credit2y(new SwapRateHelper( Handle<Quote>(d2ySpreadRate), 2*Years, calendar, swFixedLegFrequency, swFixedLegConvention, swFixedLegDayCounter, swFloatingLegIndex, Handle<Quote>(),forwardStart)); boost::shared_ptr<RateHelper> credit3y(new SwapRateHelper( Handle<Quote>(d3ySpreadRate), 3*Years, calendar, swFixedLegFrequency, swFixedLegConvention, swFixedLegDayCounter, swFloatingLegIndex, Handle<Quote>(),forwardStart)); boost::shared_ptr<RateHelper> credit6y(new SwapRateHelper( Handle<Quote>(d6ySpreadRate), 6*Years, calendar, swFixedLegFrequency, swFixedLegConvention, swFixedLegDayCounter, swFloatingLegIndex, Handle<Quote>(),forwardStart)); boost::shared_ptr<RateHelper> credit9y(new SwapRateHelper( Handle<Quote>(d9ySpreadRate), 9*Years, calendar, swFixedLegFrequency, swFixedLegConvention, swFixedLegDayCounter, swFloatingLegIndex, Handle<Quote>(),forwardStart)); boost::shared_ptr<RateHelper> credit10y(new SwapRateHelper( Handle<Quote>(d10ySpreadRate), 10*Years, calendar, swFixedLegFrequency, swFixedLegConvention, swFixedLegDayCounter, swFloatingLegIndex, Handle<Quote>(),forwardStart)); std::vector<boost::shared_ptr<RateHelper> > creditInstruments; creditInstruments.push_back(credit1y); creditInstruments.push_back(credit2y); creditInstruments.push_back(credit3y); creditInstruments.push_back(credit6y); creditInstruments.push_back(credit9y); creditInstruments.push_back(credit10y); boost::shared_ptr<YieldTermStructure> creditTermStructure( new PiecewiseYieldCurve<Discount,LogLinear>( settlementDate, creditInstruments, termStructureDayCounter, tolerance)); ...
例如,該對象
creditTermStructure
可以表示 CDS 價差曲線或此類期限結構。
depoSwapTermStructure
由上面的程式碼建構和creditTermStructure
建構,我想YieldTermStructure
通過求和depoSwapTermStructure
並考慮creditTermStructure
未對齊的時間節點來生成一個新的類對象,也就是說,程式碼必須按適當的期限對費率求和(1Y depo-swap + 1Y 信用利差,2Y depo-swap + 2Y 信用利差……等等。由於缺乏信用利差到期,比如18Y,應該是插值已知節點)。使用QuantLib怎麼可能做這樣的事情?
目前沒有課程可以根據需要添加兩條曲線,但編寫它並不難。
您將在庫中最接近的是
ZeroSpreadedTermStructure
類,它顯示了一般思想:它繼承自YieldTermStructure
(通過ZeroYieldStructure
)接受 aYieldTermStructure
和傳播(在本例中為常量)並覆蓋其自己的方法,以便它們返回總和兩者之一:例如,Rate ZeroSpreadedTermStructure::forwardImpl(Time t) const { return originalCurve_->forwardRate(t, t, comp_, freq_, true) + spread_->value(); }
在您的情況下,您必須編寫一個類似的類,它需要兩個
Handle
s 來YieldTermStructure
代替。有點令人驚訝的是,這將使您的工作更輕鬆。您仍然可以將ZeroSpreadedTermStructure
其作為其他任務的模型,例如向所需的觀察者註冊,但在這種情況下您所要做的就是YieldTermStructure
直接繼承並覆蓋單個discountImpl
方法:DiscountFactor YourClass::discountImpl(Time t) const { return baseCurve_->discount(t, true) * spreadCurve_->discount(t, true); }
因為利率之和意味著相應折扣因子的乘積。
如果您需要更多資訊,可在http://implementingquantlib.blogspot.com/2013/09/chapter-3-part-2
YieldTermStructure
獲得層次結構及其實現方法的描述(此處包含的內容有點長)-of-n-yield-term.html和以後的文章。當然,一旦您的曲線工作正常,歡迎您將其貢獻給 QuantLib。更簡單的方法是獲取一個 GitHub 帳戶並按照https://github.com/lballabio/quantlib上的自述文件中的說明進行操作。