Main Content

Select Cheapest-to-Deliver Bond Using BondFuture Instrument

This example shows how to select the cheapest-to-deliver (CTD) bond for Treasury bond future contracts using a BondFuture instrument. It demonstrates two workflows for selecting the CTD bond:

When a Treasury bond future contract matures, the party that is in the short position of the contract can deliver the underlying bond to the party that is in the long position of the contract. Typically, there can be many different bonds that satisfy the terms of the contract during the delivery month. For example, you can meet the delivery obligation for a 30-year US Treasury bond future contract with any US Treasury bond that has at least 15 years to maturity at the time of delivery. Furthermore, these deliverable bonds can have different coupons and maturities. Since the party in the short position has the option to choose which bond to deliver from these deliverable bonds, it is in the interest of that party to select the CTD bond that minimizes the delivery cost. You can select the CTD bond at the time of delivery during the delivery month of the future contract using the current market prices. Alternatively, you can predict the CTD bond several months before the delivery month based on the current zero curve.

Select CTD Bond at Time of Delivery

In this workflow, you determine the delivery cost by comparing the invoice price that the short position receives from the long position against the price of the deliverable bond. For a particular deliverable bond, the invoice price that the short position receives from the long position is:

InvoicePrice = (QuotedFuturePrice x ConversionFactor + AccruedInterest)/BondPrincipal x FutureNotional

For example, in the 30-year US Treasury bond futures market, typically, BondPrincipal is $100 and FutureNotional is $100,000. In return, the short position delivers the bond to the long position by buying the deliverable bond that has the following purchase cost in the market:

PurchaseCost = (SpotPrice + AccruedInterest)/BondPrincipal x FutureNotional

Here, SpotPrice is the clean market price of the bond at the time of delivery. From this purchase cost, subtracting the invoice amount to be received by the short position from the long position gives the following formula for the overall delivery cost:

OverallDeliveryCost = (SpotPrice - QuotedFuturePrice x ConversionFactor)/BondPrincipal x FutureNotional

You can compute the delivery cost for every deliverable bond and determine the CTD bond by selecting the bond with the lowest delivery cost. The OverallDeliveryCost formula applies only at the time of delivery. This method is equivalent to using the cashsettle method of the BondFuture instrument at the time of delivery. To demonstrate this workflow, the following example uses fictitious data, and selects the CTD bond using the BondFuture instrument on the delivery day of a hypothetical 30-year US Treasury bond future contract maturing in December 2021.

% Create a zero curve.
Settle = datetime(2021,12,21);
ZeroDates = Settle + [calmonths([1 2 3 6]) calyears([1 2 3 5 7 10 20 30])]';
ZeroRates = [0.06 0.04 0.06 0.07 0.21 0.60 0.95 1.34 1.60 1.69 2.15 2.05]'./100;
ZeroCurve = ratecurve("zero",Settle,ZeroDates,ZeroRates,Compounding=2);

% Define the data for the deliverable bonds.
ReferenceDate = datetime(2021,12,1);
BondMaturity = datetime(datevec(["2/15/2045","2/15/2037","8/15/2040",...
    "5/15/2041","5/15/2037","2/15/2042","11/15/2043","11/15/2044",...
    "5/15/2038","2/15/2041"],'mm/dd/yyyy'));
CouponRate = [2.5 4.75 3.875 2.25 5.0 3.125 3.75 3.0 4.5 4.75]'/100;
IssueDate = datetime(datevec(["2/17/2015","2/15/2007","8/16/2010",...
    "6/1/2021","8/15/2007","2/15/2012","11/15/2013","11/17/2014",...
    "8/15/2008","2/15/2011"],'mm/dd/yyyy'));
SpotPrice = [109.06;140.78;130.60;104.04;144.02;119.03;131.05;118.23;138.08;145.25];
NumBonds = length(BondMaturity);
BondID = (1:NumBonds)';

% Use convfactor to compute the conversion factors.
ConversionFactor = convfactor(ReferenceDate,BondMaturity,CouponRate)
ConversionFactor = 10×1

    0.5664
    0.8775
    0.7645
    0.5752
    0.9009
    0.6677
    0.7286
    0.6302
    0.8456
    0.8594

% Create a vector of FixedBond instruments.
BondPrincipal = 100;
DeliverableBonds = fininstrument("FixedBond",Maturity=BondMaturity,...
    CouponRate=CouponRate,IssueDate=IssueDate,Principal=BondPrincipal)
DeliverableBonds=10×1 FixedBond array with properties:
    CouponRate
    Period
    Basis
    EndMonthRule
    Principal
    DaycountAdjustedCashFlow
    BusinessDayConvention
    Holidays
    IssueDate
    FirstCouponDate
    LastCouponDate
    StartDate
    Maturity
    Name

% Create a vector of BondFuture instruments.
FutureMaturity = datetime(2021,12,21);
QuotedFuturePrice = 159.53;
FutureNotional = 100000;
BondFutureContracts = fininstrument("BondFuture",Maturity=FutureMaturity,...
    QuotedPrice=QuotedFuturePrice,Bond=DeliverableBonds,...
    ConversionFactor=ConversionFactor,Notional=FutureNotional)
BondFutureContracts=10×1 BondFuture array with properties:
    Maturity
    QuotedPrice
    Bond
    ConversionFactor
    Notional
    Name

To compute the delivery cost, use the cashsettle method of the BondFuture instrument to compute the delivery cost because this method estimates the undiscounted net cash settlement amount that could be paid by the short position to the long position at future maturity instead of physical delivery.

% Use the cashsettle method to compute the delivery costs.
DeliveryCost = nan(NumBonds,1);
for k=1:NumBonds
    outCS = cashsettle(BondFutureContracts(k), SpotPrice(k), ZeroCurve);
    DeliveryCost(k) = outCS.CashSettleAmount;
end

% List the deliverable bonds and delivery costs in a table.
DeliverableBondTable = table(BondID, BondMaturity, IssueDate, ...
    CouponRate, SpotPrice, ConversionFactor, DeliveryCost)
DeliverableBondTable=10×7 table
    BondID    BondMaturity     IssueDate     CouponRate    SpotPrice    ConversionFactor    DeliveryCost
    ______    ____________    ___________    __________    _________    ________________    ____________

       1      15-Feb-2045     17-Feb-2015       0.025       109.06          0.56643             18697   
       2      15-Feb-2037     15-Feb-2007      0.0475       140.78           0.8775            792.87   
       3      15-Aug-2040     16-Aug-2010     0.03875        130.6          0.76447            8643.6   
       4      15-May-2041     01-Jun-2021      0.0225       104.04          0.57524             12272   
       5      15-May-2037     15-Aug-2007        0.05       144.02           0.9009            299.73   
       6      15-Feb-2042     15-Feb-2012     0.03125       119.03          0.66773             12508   
       7      15-Nov-2043     15-Nov-2013      0.0375       131.05          0.72859             14818   
       8      15-Nov-2044     17-Nov-2014        0.03       118.23          0.63022             17690   
       9      15-May-2038     15-Aug-2008       0.045       138.08          0.84558            3185.1   
      10      15-Feb-2041     15-Feb-2011      0.0475       145.25          0.85942            8146.4   

Once you have computed the delivery costs for all of the deliverable bonds, you can determine the CTD bond by selecting the bond with the lowest delivery cost.

% Determine the CTD bond with the lowest delivery cost.
[~,CTDBondIdx] = min(DeliverableBondTable.DeliveryCost);
CTDBondTableDecember2021 = DeliverableBondTable(CTDBondIdx,:)
CTDBondTableDecember2021=1×7 table
    BondID    BondMaturity     IssueDate     CouponRate    SpotPrice    ConversionFactor    DeliveryCost
    ______    ____________    ___________    __________    _________    ________________    ____________

      5       15-May-2037     15-Aug-2007       0.05        144.02           0.9009            299.73   

BondFutureContracts(CTDBondIdx)
ans = 
  BondFuture with properties:

            Maturity: 21-Dec-2021
         QuotedPrice: 159.5300
                Bond: [1x1 fininstrument.FixedBond]
    ConversionFactor: 0.9009
            Notional: 100000
                Name: ""

Among the ten deliverable bonds, the CTD bond with the lowest delivery cost for the December 2021 future contract is the bond with a 5% coupon rate maturing on May 15, 2037. This CTD bond is determined at the time of delivery on December 21, 2021.

Since the delivery costs in this example are computed at the time of delivery, the delivery costs computed by the cashsettle method of the BondFuture instrument for this future contract are in agreement with those computed using the following formula for the overall delivery cost at delivery:

OverallDeliveryCost = (SpotPrice - QuotedFuturePrice x ConversionFactor)/BondPrincipal x FutureNotional
% Compare calculated delivery cost using cashsettle with the delivery cost formula.
DeliveryCostFormula = ...
    (SpotPrice - QuotedFuturePrice.*ConversionFactor)/BondPrincipal*FutureNotional;
table(DeliveryCostFormula, DeliveryCost)
ans=10×2 table
    DeliveryCostFormula    DeliveryCost
    ___________________    ____________

           18697               18697   
          792.87              792.87   
          8643.6              8643.6   
           12272               12272   
          299.73              299.73   
           12508               12508   
           14818               14818   
           17690               17690   
          3185.1              3185.1   
          8146.4              8146.4   

Select CTD Bond Months Before Delivery Month

The previous overall delivery cost formula applies only at the time of delivery. However, if a current zero curve is available, you can still compute the estimated delivery cost using the cashsettle method of the BondFuture instrument, even when it is several months before the delivery month. In the following example, you select the CTD bond using the BondFuture instrument in November 2021 for a hypothetical 30-year US Treasury bond future contract maturing several months later in June 2022. The overall workflow is similar to the workflow in Select CTD Bond at Time of Delivery, except that you select the CTD bond several months before the delivery month and the overall delivery cost formula no longer applies.

% Create a zero curve.
Settle = datetime(2021,11,22);
ZeroDates = Settle + [calmonths([1 2 3 6]) calyears([1 2 3 5 7 10 20 30])]';
ZeroRates = [0.07 0.04 0.05 0.07 0.20 0.63 0.95 1.34 1.57 1.65 2.09 2.01]'./100;
ZeroCurve = ratecurve("zero",Settle,ZeroDates,ZeroRates,Compounding=2);

% Define the data for the deliverable bonds.
ReferenceDate = datetime(2022,6,1);
BondMaturity = datetime(datevec(["11/15/2046","2/15/2038","11/15/2040",...
    "11/15/2041","5/15/2044","5/15/2042","5/15/2045","8/15/2041",...
    "8/15/2043","8/15/2039"],'mm/dd/yyyy'));
CouponRate = [2.875 4.375 4.25 3.125 3.375 3.0 3.0 1.75 3.625 4.5]'/100;
IssueDate = datetime(datevec(["11/15/2016","2/15/2008","11/15/2010",...
    " 11/15/2011","5/15/2014","5/15/2012","5/15/2015","8/31/2021",...
    "8/15/2013","8/17/2009"],'mm/dd/yyyy'));
SpotPrice = [117.84;137.13;137.53;119.17;125.03;117.34;119.03;95.97;128.84;140.56];
NumBonds = length(BondMaturity);
BondID = 10+(1:NumBonds)';

% Use convfactor to compute the conversion factors.
ConversionFactor = convfactor(ReferenceDate,BondMaturity,CouponRate)
ConversionFactor = 10×1

    0.6033
    0.8375
    0.8074
    0.6743
    0.6834
    0.6555
    0.6302
    0.5220
    0.7185
    0.8415

% Create a vector of FixedBond instruments.
BondPrincipal = 100;
DeliverableBonds = fininstrument("FixedBond",Maturity=BondMaturity, ...
    CouponRate=CouponRate,IssueDate=IssueDate,Principal=BondPrincipal)
DeliverableBonds=10×1 FixedBond array with properties:
    CouponRate
    Period
    Basis
    EndMonthRule
    Principal
    DaycountAdjustedCashFlow
    BusinessDayConvention
    Holidays
    IssueDate
    FirstCouponDate
    LastCouponDate
    StartDate
    Maturity
    Name

% Create a vector of BondFuture instruments.
FutureMaturity = datetime(2022,6,21);
QuotedFuturePrice = 160.31;
FutureNotional = 100000;
BondFutureContracts = fininstrument("BondFuture",Maturity=FutureMaturity, ...
    QuotedPrice=QuotedFuturePrice,Bond=DeliverableBonds, ...
    ConversionFactor=ConversionFactor,Notional=FutureNotional)
BondFutureContracts=10×1 BondFuture array with properties:
    Maturity
    QuotedPrice
    Bond
    ConversionFactor
    Notional
    Name

% Use the cashsettle method to compute the delivery costs.
DeliveryCost = nan(NumBonds,1);
for k=1:NumBonds
    outCS = cashsettle(BondFutureContracts(k), SpotPrice(k), ZeroCurve);
    DeliveryCost(k) = outCS.CashSettleAmount;
end

% List the deliverable bonds and delivery costs in a table.
DeliverableBondTable = table(BondID, BondMaturity, IssueDate, ...
    CouponRate, SpotPrice, ConversionFactor, DeliveryCost)
DeliverableBondTable=10×7 table
    BondID    BondMaturity     IssueDate     CouponRate    SpotPrice    ConversionFactor    DeliveryCost
    ______    ____________    ___________    __________    _________    ________________    ____________

      11      15-Nov-2046     15-Nov-2016     0.02875       117.84          0.60331             19515   
      12      15-Feb-2038     15-Feb-2008     0.04375       137.13           0.8375            409.62   
      13      15-Nov-2040     15-Nov-2010      0.0425       137.53          0.80741            5695.6   
      14      15-Nov-2041     15-Nov-2011     0.03125       119.17          0.67433            9314.9   
      15      15-May-2044     15-May-2014     0.03375       125.03          0.68337             13582   
      16      15-May-2042     15-May-2012        0.03       117.34          0.65551             10574   
      17      15-May-2045     15-May-2015        0.03       119.03          0.63022             16318   
      18      15-Aug-2041     31-Aug-2021      0.0175        95.97          0.52204             11320   
      19      15-Aug-2043     15-Aug-2013     0.03625       128.84          0.71855             11618   
      20      15-Aug-2039     17-Aug-2009       0.045       140.56          0.84151            3125.4   

% Determine the CTD bond with the lowest delivery cost.
[~,CTDBondIdx] = min(DeliverableBondTable.DeliveryCost);
CTDBondTableJune2022 = DeliverableBondTable(CTDBondIdx,:)
CTDBondTableJune2022=1×7 table
    BondID    BondMaturity     IssueDate     CouponRate    SpotPrice    ConversionFactor    DeliveryCost
    ______    ____________    ___________    __________    _________    ________________    ____________

      12      15-Feb-2038     15-Feb-2008     0.04375       137.13           0.8375            409.62   

BondFutureContracts(CTDBondIdx)
ans = 
  BondFuture with properties:

            Maturity: 21-Jun-2022
         QuotedPrice: 160.3100
                Bond: [1x1 fininstrument.FixedBond]
    ConversionFactor: 0.8375
            Notional: 100000
                Name: ""

Among the ten deliverable bonds, the CTD bond with the lowest delivery cost for the June 2022 future contract is the bond with a 4.375% coupon rate maturing on February 15, 2038. This CTD bond is predicted using the zero curve available on November 22, 2021, which is several months before the delivery month in June 2022.

See Also

Functions