程式

使用 quantlib 定價攤銷可贖回丹麥抵押債券

  • May 9, 2021

我正在嘗試為可贖回固定利率攤銷丹麥抵押債券定價。因為 QuantLib 只有CallableFixedRateBond我創建了一個名為的派生類CallableAmortizedBond,它看起來像AmortizingFixedRateBond

class CallableAmortizedBond : public CallableFixedRateBond
{

public:
   CallableAmortizedBond(
       Natural settlementDays,
       Real faceAmount,
       const Schedule &schedule,
       const vector<Rate> &coupons,
       const DayCounter &accrualDayCounter,
       BusinessDayConvention paymentConvention,
       Real redemption,
       const Date &issueDate,
       const vector<Rate> &notionals,
       const CallabilitySchedule &putCallSchedule)
       : CallableFixedRateBond(settlementDays, faceAmount, schedule, coupons, accrualDayCounter, paymentConvention, redemption, issueDate, putCallSchedule)
   {
       cashflows_ =
           FixedRateLeg(schedule)
               .withNotionals(notionals)
               .withCouponRates(coupons, accrualDayCounter)
               .withPaymentAdjustment(paymentConvention);
   }
};

我添加了一些概念,靈感來自:

Schedule sinkingSchedule(const Date& startDate,
                           const Period& maturityTenor,
                           const Frequency& sinkingFrequency,
                           const Calendar& paymentCalendar)

對於不同的債券,它看起來像這樣:

對於沒有攤銷的債券,它將是一個面值向量,例如,[100.0 .. 100.0] 對於部分攤銷的債券,它將與面值一起,直到攤銷開始然後完全攤銷:[100.0, 100.0 .. 99.0 97.0 .. 0.0] 對於完全攤銷的債券,它將是[100.0, 99.0 .. 0.0]

我使用 swaprates 創建YieldTermStructure具有以下值的 a:

2Y -> -0.13
3Y -> -0.09
4Y -> -0.03
5Y -> -0.03
6Y -> 0.1
7Y -> 0.18
8Y -> 0.25
9Y -> 0.32
10Y -> 0.39
12Y -> 0.51
15Y -> 0.65

像這樣:

Handle<YieldTermStructure> calculateTermStructure(rust::Vec<SwapRates> swapRates, RustDate now)
{
 Calendar calendar = TARGET();
 Date settlementDate(now.day, getMonthFromInt(now.month), now.year);
 Frequency swFixedLegFrequency = Annual;
 BusinessDayConvention swFixedLegConvention = Unadjusted;
 DayCounter swFixedLegDayCounter = dayCounter;
 DayCounter termStructureDayCounter = dayCounter;
 ext::shared_ptr<IborIndex> swFloatingLegIndex(new Euribor1Y);

 const Period forwardStart(1 * Days);

 std::vector<ext::shared_ptr<RateHelper>> swapInstruments;
 for (auto const &swapRate : swapRates)
 {
   ext::shared_ptr<Quote> simpleQuote(new SimpleQuote(swapRate.rate));
   ext::shared_ptr<RateHelper> swapRateHelper(new SwapRateHelper(
       Handle<Quote>(simpleQuote), swapRate.maturity * Years,
       calendar, swFixedLegFrequency,
       swFixedLegConvention, swFixedLegDayCounter,
       swFloatingLegIndex, Handle<Quote>(), forwardStart));
   swapInstruments.push_back(swapRateHelper);
 }

 ext::shared_ptr<YieldTermStructure> swapTermStructure(
     new PiecewiseYieldCurve<Discount, LogLinear>(
         settlementDate, swapInstruments,
         termStructureDayCounter));
 Handle<YieldTermStructure> termStructure(swapTermStructure);

 termStructure->enableExtrapolation();
 return termStructure;
}

CallabilitySchedule使用以下函式創建:

CallabilitySchedule getCallSchedule(rust::Vec<RustDate> callSchedule)
{

 CallabilitySchedule callabilitySchedule;
 Real callPrice = 100.;

 for (auto const &callRustRate : callSchedule)
 {
   Bond::Price bondCallPrice(callPrice, Bond::Price::Clean);

   Date callDate(callRustRate.day, getMonthFromInt(callRustRate.month), callRustRate.year);
   callabilitySchedule.push_back(
       ext::make_shared<Callability>(
           bondCallPrice,
           Callability::Call,
           callDate));
 }

 return callabilitySchedule;
}

然後我用它來為可贖回抵押債券定價:

 Integer gridIntervals = 40;
 Real reversionParameter = .03;

 // output price/yield results for varying volatility parameter

 Real sigma = QL_EPSILON; // core dumps if zero on Cygwin

 ext::shared_ptr<ShortRateModel> hw0(
     new HullWhite(termStructure, reversionParameter, sigma));

 ext::shared_ptr<PricingEngine> engine0(
     new TreeCallableFixedRateBondEngine(hw0, gridIntervals));

 ext::shared_ptr<PricingEngine> bondEngine(
     new DiscountingBondEngine(termStructure));

 vector<Rate> notionalRates;
 for (auto const &notional : notionals)
 {
   notionalRates.push_back(notional);
 }

 CallableAmortizedBond callableAmortizedBond(settlementDays, faceAmount, schedule,
                                             vector<Rate>(1, coupon),
                                             dayCounter, paymentConvention,
                                             redemption, datedDate, notionalRates, callabilitySchedule);

 callableAmortizedBond.setPricingEngine(engine0);

 return callableAmortizedBond.cleanPrice();

使用返回的價格.cleanPrice()遠低於納斯達克的價格。例如,該債券的最後價格為 ,91.210但我使用目前掉期利率的價格88.542沒有攤銷。

另一個問題是,通過攤銷,我得到的價格比沒有攤銷低。這與現實世界中發生的事情相反。那麼,這是為可贖回攤銷抵押債券定價的正確方法嗎?它是為可贖回債券類別添加攤銷的正確方法嗎?

引用自:https://quant.stackexchange.com/questions/63865