2015-07-02 103 views
0

我想充分了解Quantlib的解算器的工作原理來計算Z-利差給出的預測利率期限結構的浮動利率債券和折現期限結構。要做到這一點,首先我創建了一個簡單的輔助類,計算收率到我將使用隨着解算器(我選擇布倫特)來比較BondFunctions ::產量產量計算的鍵的成熟。儘管如此,我得到了三個樣本債券的兩個不同的結果,我不明白爲什麼。Quantlib求解器不產生相同的到期收益率作爲BondFunctions ::產量

首先創建一個輔助類使用quantlib的求解器

class ytmsolver{ 
private: 
    const Real obsPrice; 
    const Bond& bondObject; 
    const Date& date; 
    DayCounter dayCounter; 
    Compounding compounding; 
    Frequency frequency; 
public: 
    //constructor 
    ytmsolver(const Bond &bond, Real &price, Date &settlementDate, DayCounter& dc, Compounding& comp, 
      Frequency& freq):bondObject(bond),obsPrice(price),date(settlementDate), dayCounter(dc), 
      compounding(comp),frequency(freq){}; 

    //overloaded operator to be used in the solver 
    Real operator()(const Rate& rate)const{ 
     return (bondObject.cleanPrice(rate,dayCounter,compounding,frequency)-obsPrice); 
    } 

}來計算數值的產率債券到期;

然後我創建浮動速率鍵工廠與索引,forecating術語結構(假定爲平面爲計算的時刻的簡單)和定價引擎創建一個浮子。

FloatingRateBond flatTermStructureFloaterFactory(Natural indexTenor, Frequency freq, Date tradeDate, 
    Date settlementDate,Natural settlementDays, Real faceAmount, const Schedule &schedule, 
    const Calendar& calendar,const Real &currentLiborFixing,const Real& lastResetDateLiborFixing, 
    const DayCounter &accrualDayCounter, 
    BusinessDayConvention paymentConvention=Following, Natural fixingDays=Null<Natural>(), 
    const std::vector<Real> &gearings=std::vector<Real>(1, 1.0), 
    const std::vector<Spread> &spreads=std::vector<Spread>(1, 0.0), 
    const std::vector<Rate> &caps=std::vector<Rate>(), 
    const std::vector<Rate> &floors=std::vector<Rate>(), 
    bool inArrears=false, Real redemption=100.0, const Date &issueDate=Date()){ 



//***********Term structure declaration*********** 

//term structure for the cash flows using a libor index 
RelinkableHandle<YieldTermStructure> liborTermStructure; 

//Libor index which is tied to the Frequency of payments or index tenor 
boost::shared_ptr<IborIndex> libor(new USDLibor(Period(indexTenor,Months),liborTermStructure)); 

//term structure to forecast rest of cash flows 
boost::shared_ptr<YieldTermStructure> flatforecast(
     new FlatForward(settlementDate, currentLiborFixing, accrualDayCounter, Simple, freq)); 
    liborTermStructure.linkTo(flatforecast); 

//Relinkable handle to assign to the price engine. 
RelinkableHandle<YieldTermStructure> discountingTermStructure; 

//***********Bond object creation*********** 
FloatingRateBond floatingRateBondInstance(settlementDays, faceAmount, 
         schedule, libor, accrualDayCounter, 
         paymentConvention, fixingDays, 
         // gearings 
         gearings, 
         // spreads 
         spreads); 

//*********Finds the last reset date**************** 
Date lastResetDate; 
Leg cashflows=floatingRateBondInstance.cashflows(); 
/* 
Finds the last reset date by browsing through the cashflow dates and offsetting them by 
the number of fixing days and a provided calendar. 
(ONLY WORKS WITH BONDS WITH THE SAME INDEX AS PERIODICITY) 

If this date is provided by the flat file then this search is completely unnecessary 
*/ 
for (Size i=0; i<cashflows.size()-1; i++) { 
     //Takes the lastResetDate to be the las ocurred date prior the the tradeDate 
     if ((cashflows[i]->hasOccurred(tradeDate, true))) { 
      lastResetDate=calendar.advance(cashflows[i]->date(),-fixingDays, Days,paymentConvention); 
      //cout<<lastResetDate<<endl; //used to print the dates as a debug method.    
     } 
    } 

    cout<<"lastResetDate: "<<lastResetDate<<endl; //prints it to ensure that its correct. 


//*********Adds the previous libor rate associated to the last reset date************* 
libor->addFixing(lastResetDate, lastResetDateLiborFixing); //last reset date minus fixing days 


//***********Bond Engine declaration*********** 
    boost::shared_ptr<PricingEngine> bondEngine(new DiscountingBondEngine (discountingTermStructure)); 
    floatingRateBondInstance.setPricingEngine(bondEngine); //setting the pricing engine for the bond 

return floatingRateBondInstance;  

}

在此之後,我創建一個簡單的函數調用Quantlib的bondfunctions並計算債券收益率(這是我作爲計算給定的浮動利率債券的收益率的一種方式使用。

Real priceToYieldFlatTermStructure(const Bond& bond, 
          Real cleanPrice, 
          const DayCounter& dayCounter, 
          Compounding compounding, 
          Frequency frequency, 
          Date settlement, 
          Real accuracy=1e-50, 
          Size maxIterations=10000){ 

//Calls the bond function yield which takes a bond, a clean price, a day count, a compounding, 
//a frequency of payments, a settlement date, a degree of accuracy and the number of max iterations to 
//reach the yield. 
Real irr=BondFunctions::yield(bond,cleanPrice,dayCounter,compounding,frequency, 
     settlement,accuracy,maxIterations); 
return irr; 

}

,然後我嘗試使用Quantlib的求解器來獲得這些債券的收益率定一個乾淨的價格,我得到使用FOL不同的結果降脂代碼:

int main(){ 
try { 
    Brent solver; 
    Real accuracy=1e-30, guess=0.00, min=-1.0, max=0.5; 

    cout<<"*******************************************"<<endl; 
    cout<<"Bond # 1: US4042Q0HC65"<<endl; 
    cout<<"*******************************************"<<endl; 
    //***********Input declaration*********** 
    Natural settlementDays = 3; 
    Natural fixingdays=2; 
    Natural indexTenor=6; 
    Date tradeDate(02,Mar,2015); 
    Date issueDate(9,Aug,2006); 
    Date maturityDate(22,Aug,2016); 
    Real resetMargin=0.016; 
    Real indexMultiplier=1.0; 
    Frequency frequency=Semiannual; 
    Calendar holidayCalendar=UnitedStates(UnitedStates::NYSE); 
    BusinessDayConvention businessDayConvention= BusinessDayConvention(ModifiedFollowing); 
    DayCounter dayCounter=Actual360(); 
    Real lastResetDateLiborFixing=0.003853; 
    Real currentLiborFixing=0.003842; 
    Real redemption=100; 
    string settlementcode="BDY"; //internal settlementcode 
    string settlementvalue="3"; //internal settlementvalue 
    Date settlementDate=getSettlementDate(tradeDate,holidayCalendar,settlementcode,settlementvalue); //function call to get the settlement date (this is working properly) 
    cout<<"settlementDate :"<<settlementDate<<endl; 
    Compounding compounding=Compounded; 
    Real faceAmount = redemption; 
    Real obsprice=101.431; 
    Schedule schedule(issueDate, maturityDate, Period(frequency), 
        holidayCalendar, businessDayConvention, businessDayConvention, 
        DateGeneration::Backward, true); 


    //***********Bond creation to be priced*********** 
    FloatingRateBond floatingRateBondInstance1=flatTermStructureFloaterFactory(indexTenor,frequency,tradeDate,settlementDate, 
      settlementDays,faceAmount,schedule,holidayCalendar,currentLiborFixing,lastResetDateLiborFixing, 
      dayCounter,businessDayConvention,fixingdays,std::vector<Real>(1, indexMultiplier), 
      std::vector<Rate>(1, resetMargin)); 

    Real ytm=priceToYieldFlatTermStructure(floatingRateBondInstance1,obsprice,dayCounter,compounding,frequency,settlementDate); 

    //***********Bond pricing, yield and discount marging computation***********  
    cout<<"Clean price: "<<floatingRateBondInstance1.cleanPrice(ytm,dayCounter,compounding,frequency,settlementDate)<<endl; 
    cout<<"Dirty price: "<<floatingRateBondInstance1.dirtyPrice(ytm,dayCounter,compounding,frequency,settlementDate)<<endl; 
    cout<<"Accrued interest: "<<floatingRateBondInstance1.accruedAmount(settlementDate)<<endl; 

    cout<<"Yield: "<<ytm*100<<"%"<<endl; 
    cout<<"Discount Margin: "<<(ytm-currentLiborFixing)*100<<"%"<<endl; 

    //***************solver testing*************** 
    Real irr=solver.solve(ytmsolver(floatingRateBondInstance1,obsprice,settlementDate,dayCounter, 
    compounding,frequency),accuracy,guess,min,max); 

    cout<<"irr: "<<irr*100<<"%"<<endl; 
    cout<<"*******************************************"<<endl; 
    cout<<"Bond # 2: US4042Q0HB82"<<endl; 
    cout<<"*******************************************"<<endl; 

    //***********Input declaration*********** 
    indexTenor=6; 
    issueDate=Date(27,Jul,2006); 
    maturityDate=Date(20,Jul,2016); 
    resetMargin=0.0151; 
    indexMultiplier=1.0; 
    frequency=Semiannual; 
    holidayCalendar=TARGET(); 
    //holidayCalendar=UnitedStates(UnitedStates::NYSE); //not counting martin luther king day, jan 15,15 as last reset date 
    businessDayConvention=BusinessDayConvention(ModifiedFollowing); 
    dayCounter=Actual360(); 
    lastResetDateLiborFixing=0.003549; 
    currentLiborFixing=0.003842; 
    redemption=100; 
    settlementcode="BDY"; //internal settlement code 
    settlementvalue="3"; //internal settlement value 
    settlementDate=getSettlementDate(tradeDate,holidayCalendar,settlementcode,settlementvalue); //function call to get the settlement date (this is working properly) 
    cout<<"settlementDate :"<<settlementDate<<endl; 
    compounding=Compounded; 
    faceAmount = redemption; 
    obsprice=100.429; 
    schedule=Schedule(issueDate, maturityDate, Period(frequency), 
        holidayCalendar, businessDayConvention, businessDayConvention, 
        DateGeneration::Backward, true); 


    //***********Bond creation to be priced*********** 

    FloatingRateBond floatingRateBondInstance2=flatTermStructureFloaterFactory(indexTenor,frequency,tradeDate,settlementDate, 
      settlementDays,faceAmount,schedule,holidayCalendar,currentLiborFixing,lastResetDateLiborFixing, 
      dayCounter,businessDayConvention,fixingdays,std::vector<Real>(1, indexMultiplier), 
      std::vector<Rate>(1, resetMargin)); 

    ytm=priceToYieldFlatTermStructure(floatingRateBondInstance2,obsprice,dayCounter,compounding,frequency,settlementDate); 

    //***********Bond pricing, yield and discount marging computation***********  
    cout<<"Clean price: "<<floatingRateBondInstance2.cleanPrice(ytm,dayCounter,compounding,frequency,settlementDate)<<endl; 
    cout<<"Dirty price: "<<floatingRateBondInstance2.dirtyPrice(ytm,dayCounter,compounding,frequency,settlementDate)<<endl; 
    cout<<"Accrued interest: "<<floatingRateBondInstance2.accruedAmount(settlementDate)<<endl; 

    cout<<"Yield: "<<ytm*100<<"%"<<endl; 
    cout<<"Discount Margin: "<<(ytm-currentLiborFixing)*100<<"%"<<endl; 


    //***************solver testing*************** 
    irr=solver.solve(ytmsolver(floatingRateBondInstance2,obsprice,settlementDate,dayCounter, 
    compounding,frequency),accuracy,guess,min,max); 

    cout<<"irr: "<<irr*100<<"%"<<endl; 

    cout<<"*******************************************"<<endl; 
    cout<<"Bond # 3: US59022CCT80"<<endl; 
    cout<<"*******************************************"<<endl; 
    //***********Input declaration*********** 
    indexTenor=3; 
    tradeDate=Date(10,Jun,2015); 
    issueDate=Date(02,May,2007); 
    maturityDate=Date(02,May,2017); 
    resetMargin=0.0055; 
    indexMultiplier=1.0; 
    frequency=Quarterly; 
    holidayCalendar=UnitedStates(UnitedStates::NYSE); //not counting martin luther kind day, jan 15,15 as last reset date 
    businessDayConvention=BusinessDayConvention(ModifiedFollowing); 
    dayCounter=Actual360(); 
    lastResetDateLiborFixing=0.0027875; 
    currentLiborFixing=0.0028785; 
    redemption=100; 
    settlementcode="BDY"; //internal settlement code 
    settlementvalue="3"; //internal settlement value 
    settlementDate=getSettlementDate(tradeDate,holidayCalendar,settlementcode,settlementvalue); //function call to get the settlement date (this is working properly) 
    cout<<"settlementDate :"<<settlementDate<<endl; 
    compounding=Compounded; 
    faceAmount = redemption; 
    obsprice=99.794; 
    schedule=Schedule(issueDate, maturityDate, Period(frequency), 
        holidayCalendar, businessDayConvention, businessDayConvention, 
        DateGeneration::Backward, true); 


    //***********Bond pricing, yield and discount marging computation***********  
    FloatingRateBond floatingRateBondInstance3=flatTermStructureFloaterFactory(indexTenor,frequency,tradeDate,settlementDate, 
      settlementDays,faceAmount,schedule,holidayCalendar,currentLiborFixing,lastResetDateLiborFixing, 
      dayCounter,businessDayConvention,fixingdays,std::vector<Real>(1, indexMultiplier), 
      std::vector<Rate>(1, resetMargin)); 

    ytm=priceToYieldFlatTermStructure(floatingRateBondInstance3,obsprice,dayCounter,compounding,frequency,settlementDate); 
    //***********Bond pricing, yield and discount marging computation***********  
    cout<<"Clean price: "<<floatingRateBondInstance3.cleanPrice(ytm,dayCounter,compounding,frequency,settlementDate)<<endl; 
    cout<<"Dirty price: "<<floatingRateBondInstance3.dirtyPrice(ytm,dayCounter,compounding,frequency,settlementDate)<<endl; 
    cout<<"Accrued interest: "<<floatingRateBondInstance3.accruedAmount(settlementDate)<<endl; 

    cout<<"Yield: "<<ytm*100<<"%"<<endl; 
    cout<<"Discount Margin: "<<(ytm-currentLiborFixing)*100<<"%"<<endl; 

    //***************solver testing*************** 
    irr=solver.solve(ytmsolver(floatingRateBondInstance3,obsprice,settlementDate,dayCounter, 
    compounding,frequency),accuracy,guess,min,max); 

    cout<<"irr: "<<irr*100<<"%"<<endl; 

    return 0; 

} catch (exception& e) { 
    cerr << e.what() << endl; 
    return 1; 
} catch (...) { 
    cerr << "unknown error" << endl; 
    return 1; 
} 

}

,最後我得到的結果如下:


債券#1:US4042Q0HC65

settlementDate:2015年3月5日 lastResetDate:二月19日,2015年 清潔價格:101.431 骯髒價格:101.486 應計利息:0.0551472 產量:1.01286% 折扣保證金:0.628665% IRR:0.72216%


債券#2:US4042Q0HB82

settlementDate:2015年3月5日 lastResetDate:2015年1月16日 清潔價格:100.429 骯髒價格:100.657 應計利息:0.227932 產量:1.57325% 折扣保證金:1.18905% IRR:1.47977%


債券#3:US59022CCT80

settlementDate:2015年6月15日 lastResetDate:2015年4月30日 清潔價格:99.794 全價:99.8907 應計利息:0。0966875 產量:0.945517% 折扣保證金:0.657667% 內部收益率:0.949541%

它是什麼,我做錯了什麼?我不明白爲什麼解算器沒有返回與產量的粘合函數相同的數字。任何想法爲什麼或我在這裏做錯了什麼?

回答

0

我打算假設QuantLib BondFunctions::yield函數返回的收益是正確的,因爲當您將它傳遞給cleanPrice債券的方法時,您將收回您用作輸入的觀察價格。

這讓我們猜測你的函數有什麼問題。通過查看您的ytmsolver課程,我注意到您沒有將結算日期傳遞給債券對象的cleanPrice方法,就像您在重新定價代碼時在main中所做的那樣。

當結算日失蹤時,該方法假定它是今天的結算日期—即距離今天三個工作日。這明顯晚於您想要的結算日期,並且您在main函數中輸出了結果,因此您得到的結果錯誤。一旦您將結算日期傳遞給cleanPrice,解算器將返回預期值。

相關問題