digital-asset / daml-finance

Apache License 2.0
17 stars 16 forks source link

Composability of instrument features #120

Open GeorgSchneider opened 2 years ago

GeorgSchneider commented 2 years ago

The question came up looking at the four different CC-backed bond templates we now have:

One could think of those as actually being a zero-coupon bond with:

One could represent this in a single instrument using types, eg. as:

type Coupon =
  | None
  | Fixed with rate : Decimal
  | Floating with rateIndex : Text; spread : Decimal

type Redemption =
  | AtNotional
  | InflationAdjusted with inflationIndex : Text; inflationBaseValue : Decimal

The benefit of having a single template would be to reduce code redundancy and generally have less code to maintain. A downside is that for a customer they now represent what they might consider different instruments in a single template, and they'd have to inspect the template fields in order to classify what it actually represents.

Also, this representation would not be extensible, eg. if we wanted to model a bond that pays fixed for some periods and the floating subsequently (as do some mortgages for example), we couldn't add that without breaking the API for the bond template.

I'm thinking if there's an option to represent certain product features in separate template with interfaces, that could then optionally be linked from a "base template" to pull in certain features. For example, one could define a "coupon" template that implements maybe the HasClaims interface, and have implementations that cover zero, fixed, and floating variants. Or maybe a better example is the redemption: Have an interface that represents a single redemption payment, and implementations for "at notional" and "inflation-linked". One could then use the "inflation-linked redemption" template to add this feature eg. onto a structured product (provided this template uses the "linked redemption" approach as well).

This all goes a bit into the direction of storing sub-trees on the ledger which can then be composed in different ways. So kind of like representing some of the building block helper functions in CC explicitly on the ledger, which might make it a bit more accessible to users. In the extreme, this would actually result in the approach to store individual tree nodes as contracts on the ledger, something that Luciano has previously thought about. I probably wouldn't want to go that far, but I could see some middle ground approach where we have reusable sub-trees encapsulated in templates and pulled in through interfaces into an instrument template, in order to add specific reusable product features (like inflation-linkage).

There are definitely lots of implications in this, one being that then the state / logic / terms of an instrument are not fixed at compile time anymore, but depend on the runtime state of the ledger.

So this is just a thought right now, nothing to action. But interesting to hear opinions.

GeorgSchneider commented 2 years ago

johan-da:

To reduce code redundancy of the existing code, I like what you suggest with the sum types ^^. If we use a generic bond template or a template per bond is a separate thing. A fixed-bond and floating-bond template could use the same code but with different values for the sum types (in the template body), whereas a generic template could have the sum types as template fields.

But ^ only works for a fixed set of bond types (as you say), if we, e.g., want to have a coupon conditional on some event (like if the company pays dividends or not) we would probably need to modify the sum type.

Maybe retroactive interfaces could help. Assume we define a "fat" fixed-income bond interface (using the Fixed with rate : Decimal value for the coupon sum type). If we later decide to add a term to the coupon sum type, we could define a new "fat" fixed-income bond interface using the new sum type, and retroactively define how old fixed-income instances (trivially) implement the new interface. So even if we add a new term to the sum type (i.e., a new bond type), the existing bond instances on the ledger do not need to be upgraded.

But using the sum types (or more generally combiners) in the first place is a bit like building a DSL for a DSL, and not sure it is worth the hassle of maintaining/extending/upgrading combiners although it might be easier to digest for a user.