CallableBond - Issuer delays 1 day on making a decision


What are the consequences of an issuer making a decision 1 day after the firstCoupon date (adjusted)?
In the test bellow the issuer electAndVerifyPaymentEffects 1 day after.

  • The first coupon passes the test.
  • The second coupon on the second coupon date fails (the instrument is not evolved)

I wonder why this happens.


runFloating = script do
  [custodian, issuer, investor, calendarDataProvider, publicParty] <-
    createParties ["Custodian", "Issuer", "Investor", "Calendar Data Provider", "PublicParty"]

  -- Account and holding factory
  let pp = [("FactoryProvider", S.singleton publicParty)]

  -- Originate commercial-bank cash
  now <- getTime
  cashInstrumentCid <- originate custodian issuer "USD" "US Dollar" pp now

  -- Create and distribute bond
  -- Libor + 0.1% coupon every 3M
    issueDate = date 2022 Jan 15
    firstCouponDate = date 2022 Apr 15
    maturityDate = date 2024 Jan 15
    notional = 1.0
    couponRate = 0.001
    capRate = None
    floorRate = None
    couponPeriod = M
    couponPeriodMultiplier = 3
    dayCountConvention = Act360
    businessDayConvention = Following
    referenceRateId = "USD/LIBOR/3M"
    floatingRate = Some FloatingRate with
      resetRelativeTo = CalculationPeriodStartDate
      fixingDates = FixingDates with
        periodMultiplier = 0
        period = D
        dayType = Some Business
        businessDayConvention = NoAdjustment
        businessCenters = ["USD"]
    observations = M.fromList
      [ (dateToDateClockTime $ date 2022 Jan 17, 0.010)
      , (dateToDateClockTime $ date 2022 Apr 15, 0.010)
      , (dateToDateClockTime $ date 2022 Jul 15, 0.010)
    holidayCalendarIds = ["USD"]
    cal =
      HolidayCalendarData with
        id = "USD"
        weekend = [Saturday, Sunday]
        holidays = []

  -- A reference data provider publishes the holiday calendar on the ledger
  calendarCid <- submit calendarDataProvider do
    createCmd HolidayCalendar with
      provider = calendarDataProvider
      calendar = cal
      observers = M.fromList pp

  observableCid <- toInterfaceContractId <$> submit issuer do
    createCmd Observation with
      provider = issuer; id = Id $ referenceRateId; observations; observers = M.empty

  bondInstrument <- originateCallableBond issuer issuer "BONDTEST1" "Callable Bond" pp now
    issueDate holidayCalendarIds calendarDataProvider firstCouponDate maturityDate
    dayCountConvention businessDayConvention floatingRate couponRate capRate floorRate couponPeriod
    couponPeriodMultiplier cashInstrumentCid notional

  -- One day before the first coupon date: try to lifecycle and verify that there are no lifecycle
  -- effects.
  verifyNoLifecycleEffects [publicParty] (subtractDays firstCouponDate 1) bondInstrument issuer

    amount = 1.0
    electorIsOwner = False

  -- Coupon date 1 + 1 : Lifecycle and verify that there is an effect for one coupon.
    expectedConsumed = []
    expectedProduced = [qty 0.0026888889 cashInstrumentCid]
  (Some bondInstrumentAfterCoupon1, effectCid) <- electAndVerifyPaymentEffects (date 2022 Apr 16)
    amount bondInstrument electorIsOwner issuer investor [publicParty] "NOT CALLED" [observableCid]
    expectedConsumed expectedProduced

  -- Coupon date 2: Lifecycle and verify that there is an effect for one coupon.
    expectedConsumed = []
    expectedProduced = [qty 0.0027805556 cashInstrumentCid]
  (Some bondInstrumentAfterCoupon2, effectCid) <- electAndVerifyPaymentEffects (date 2022 Jul 15)
    amount bondInstrumentAfterCoupon1 electorIsOwner issuer investor [publicParty] "NOT CALLED"
    [observableCid] expectedConsumed expectedProduced

  pure ()

I’ve just checked that with the new version on main the result of electAndVerifyPaymentEffects 1 day after the coupon date is the following failure:

“Election not possible on this date”

which makes sense.

The question now is: If the issuer delays on making the decision, is there some way of recovering from that?


Hi @jvelasco.intellecteu,

The election needs to be made as of at the right time for the contract to be life-cycled correctly. Specifically, this means that the Election contract needs to contain the right date (2022 Apr 15 for the first coupon).

For lifecycling purposes, it doesn’t really matter when the Election contract is created (real time), but only what date is stored in the contract.

This is to avoid cases where an instrument ends up in a “frozen state” where it can no longer be life-cycled without introducing custom lifecycling rules.

Your election workflow needs to decide how to handle the case where the issuer delays making a decision (meaning that no Election contract is created before a specified real time T). Some options are

  • a default election is processed (“CALLED” or “NOT CALLED”)
  • you let the issuer create an election “retroactively”, so an election for 15 Apr is created on 16 Apr

The nature of the delay should probably drive what behaviour is chosen.

I hope this helps,

1 Like