Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 25 additions & 18 deletions rosetta-source/src/main/rosetta/event-common-func.rosetta
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,13 @@ func QuantityIncreased:

func QuantityDecreased:
inputs:
before TradeState (1..1)
instruction Instruction (1..1)
after TradeState (0..*)
output:
result boolean (1..1)

alias unitType: <"Unit Types of the instruction's quantities.">
instruction -> primitiveInstruction -> quantityChange -> change -> quantity -> unit

set result:
after
Expand All @@ -50,43 +53,45 @@ func QuantityDecreased:
CompareTradeLot(
item -> trade -> tradeLot only-element,
CompareOp -> LessThan,
before -> trade -> tradeLot only-element
) = True
and // check each after (item) is greater than zero
CompareTradeLotToAmount(
item -> trade -> tradeLot only-element,
CompareOp -> GreaterThan,
0.0
instruction -> before -> trade -> tradeLot only-element
) = True
and // Check that changed quantities have not decreased to zero
QuantityDecreasedToZero(instruction, after) = False
] all = True

func QuantityDecreasedToZero:
inputs:
before TradeState (0..*)
instruction Instruction (1..1)
after TradeState (0..*)
output:
result boolean (1..1)

alias unitTypes: <"Unit Types of the instruction's quantities.">
instruction -> primitiveInstruction -> quantityChange -> change -> quantity -> unit

set result:
CompareTradeLotToAmount(
before -> trade -> tradeLot only-element,
instruction -> before -> trade -> tradeLot only-element,
CompareOp -> GreaterThan,
0.0
0.0,
unitTypes
) = True
and CompareTradeStatesToAmount(after, CompareOp -> Equals, 0.0) = True
and CompareTradeStatesToAmount(after, CompareOp -> Equals, 0.0, unitTypes) = True

func CompareTradeStatesToAmount: <"For each TradeState, compare the Quantity amounts in each TradeState to the given amount (regardless of unit of amount), based on the CompareOp enum.">
func CompareTradeStatesToAmount: <"For each TradeState, compare the Quantity amounts in each TradeState to the given amount based on the CompareOp enum. If Unit Types are specified, only quantities with those units are compared. Otherwise, the comparison applies to all quantities, regardless of the unit type.">
inputs:
tradeStates TradeState (0..*) <"List of TradeState to be compared.">
op CompareOp (1..1) <"Comparison operation to use.">
amount number (1..1) <"Quantity amount to use.">
unitType UnitType (0..*) <"Unit Types to which condition should be applied.">

output:
result boolean (1..1)

set result:
set result: <"Result of applying the comparison. If Unit Types are provided, returns the result based only on quantities with those units; otherwise, returns the result for all quantities.">
tradeStates
extract [
CompareTradeLotToAmount(item -> trade -> tradeLot only-element, op, amount)
CompareTradeLotToAmount(item -> trade -> tradeLot only-element, op, amount, unitType)
] all = True

func TransfersForDate:
Expand Down Expand Up @@ -988,9 +993,11 @@ func Create_QuantityChange: <"A specification of the inputs, outputs and constra
set quantityChange -> trade -> ancillaryParty: trade -> ancillaryParty
set quantityChange -> trade -> adjustment: trade -> adjustment

set quantityChange -> state -> positionState:
if newTradeLots -> priceQuantity -> quantity -> value all = 0
then PositionStatusEnum -> Closed
set quantityChange -> state -> positionState: <"Set positionState to Closed if all quantities with the instruction’s unit have decreased to zero.">
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not convinced this is correct. For a stock loan against cash you would have 2 quantities, one holding the securities (unit = financialUnit -> Share) and one holding the cash (unit = currency). Both of these quantities would need to be set to zero in order to set the positionState to "Closed".
If the QuantityChange instruction only decreases one of these quantities to zero then this condition I think would still set the trade to Closed.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree. If we can have quantities with mixed types of units related to the actual quantities exchanged, then we'll need to rethink this logic.

This has been modelled from a Debt Option perspective, where we expect the trade to be closed even if the option entitlement quantity, which has a unit type of funancialUnit, is not reduced to zero, as this quantity is just a feature of the contract.

image

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah okay, what we may need to do then is check the product to determine what constitutes a Termination, or have separate functions to qualify termination for different product types. Either way it looks like it is not as straightforward as we'd hoped 🙁

newTradeLots -> priceQuantity -> quantity
filter instruction -> change -> quantity -> unit any = item -> unit
then if item -> value all = 0
then PositionStatusEnum -> Closed

func Create_TermsChange: <"A specification of the inputs, outputs and constraints when calculating the after tradeState based Terms Change Primitive Instruction.">
inputs:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -249,7 +249,7 @@ func Qualify_FullReturn: <"The qualification of a full return event from the fac
and businessEvent -> instruction -> primitiveInstruction -> quantityChange exists
or (businessEvent -> instruction -> primitiveInstruction -> quantityChange exists and transfer exists))
and QuantityDecreasedToZero(
businessEvent -> instruction -> before,
businessEvent -> instruction only-element,
businessEvent -> after
) = True
and businessEvent -> after -> state -> closedState -> state all = ClosedStateEnum -> Terminated
Expand Down Expand Up @@ -517,7 +517,7 @@ func Qualify_PartialNovation: <"The qualification of a novation event from the f
or // before trade counterparties match open after trade counterparties, and match trade identifiers, but with decreased quantity
(item -> trade -> counterparty -> partyReference = beforeTradeState -> trade -> counterparty -> partyReference
and item -> trade -> tradeIdentifier = beforeTradeState -> trade -> tradeIdentifier
and QuantityDecreased(beforeTradeState, [item]))
and QuantityDecreased(businessEvent -> instruction only-element, [item]))
] all = True

func Qualify_PartialTermination: <"The qualification of a partial termination event from the fact that (i) the intent is Partial Termination when specified, (ii) the associated primitives are the quantityChange and the cash transfer, the (iii) the quantity associated with the contract decreases, and (iv) there is an actual remaining quantity.">
Expand All @@ -537,7 +537,7 @@ func Qualify_PartialTermination: <"The qualification of a partial termination ev
businessEvent -> intent is absent
and (primitiveInstruction -> quantityChange only exists
or (primitiveInstruction -> quantityChange, primitiveInstruction -> transfer) only exists)
and (QuantityDecreased(businessEvent -> instruction -> before only-element, businessEvent -> after) = True)
and (QuantityDecreased(businessEvent -> instruction only-element, businessEvent -> after) = True)
and businessEvent -> after -> state -> closedState is absent

func Qualify_PortfolioRebalancing: <"The qualification of a portfolio rebalancing event from the fact that (i) the intent is PortfolioRebalancing, and (ii) the execution primitive exists">
Expand Down Expand Up @@ -574,7 +574,7 @@ func Qualify_Reallocation: <"The qualification of a reallocation event from the
or // before trade counterparties match open after trade counterparties, and match trade identifiers, but with decreased quantity
(item -> trade -> counterparty -> partyReference = beforeTradeState -> trade -> counterparty -> partyReference
and item -> trade -> tradeIdentifier = beforeTradeState -> trade -> tradeIdentifier
and QuantityDecreased(beforeTradeState, [item]))
and QuantityDecreased(businessEvent -> instruction only-element, [item]))
] all = True

func Qualify_Renegotiation: <"The qualification of a renegotiation event from the fact that (i) the intent is Renegotiation when specified, and (ii) the associated primitives instructions are the TermsChange, QuantityChange and the cash transfer.">
Expand All @@ -593,7 +593,7 @@ func Qualify_Renegotiation: <"The qualification of a renegotiation event from th
and (businessEvent -> instruction
extract
(primitiveInstruction -> termsChange only exists or (primitiveInstruction -> termsChange, primitiveInstruction -> quantityChange) only exists)) all = True
and (QuantityDecreasedToZero(businessEvent -> instruction -> before, businessEvent -> after) = False)
and (QuantityDecreasedToZero(businessEvent -> instruction only-element, businessEvent -> after) = False)
and businessEvent -> after -> state -> closedState is absent

func Qualify_Reprice: <"This qualification function is used to qualify repricing of a contractual product with an interest rate payout and assetPayout.">
Expand Down Expand Up @@ -654,7 +654,7 @@ func Qualify_Repurchase: <"The qualification of a repurchase event from the fact
extract
(primitiveInstruction -> quantityChange, primitiveInstruction -> transfer) only exists)
and QuantityDecreasedToZero(
businessEvent -> instruction -> before,
businessEvent -> instruction only-element,
businessEvent -> after
) = True
and businessEvent -> after -> state -> closedState -> state all = ClosedStateEnum -> Terminated
Expand Down Expand Up @@ -853,7 +853,7 @@ func Qualify_Termination: <"The qualification of a termination event from the fa
businessEvent -> intent is absent
and (primitiveInstruction -> quantityChange only exists
or (primitiveInstruction -> quantityChange, primitiveInstruction -> transfer) only exists)
and (QuantityDecreasedToZero(businessEvent -> instruction -> before, businessEvent -> after) = True)
and (QuantityDecreasedToZero(businessEvent -> instruction only-element, businessEvent -> after) = True)
and (businessEvent -> after -> state -> closedState -> state all = ClosedStateEnum -> Terminated)

func Qualify_ValuationUpdate: <"The qualification of a valuation update from the fact that the only component is a valuation.">
Expand Down
12 changes: 8 additions & 4 deletions rosetta-source/src/main/rosetta/product-template-func.rosetta
Original file line number Diff line number Diff line change
Expand Up @@ -77,19 +77,23 @@ func CompareTradeLot: <"Compare the Quantity in TradeLot 1 to the Quantity (with
},
unitOfAmount
)
] all = True
] any = True //the comparison succeeds if at least one quantity meets the condition

func CompareTradeLotToAmount: <"Compare the Quantity amount in TradeLot to the given amount (regardless of unit of amount), based on the CompareOp enum.">
func CompareTradeLotToAmount: <"Compare the Quantity amount in TradeLot to the given amount, based on the CompareOp enum. If Unit Types are specified, only quantities with those units are compared. Otherwise, the comparison applies to all quantities, regardless of the unit type">
inputs:
tradeLot TradeLot (1..1)
op CompareOp (1..1)
amount number (1..1)
unitTypes UnitType (0..*) <"Unit Types to which comparison should be applied.">
output:
result boolean (1..1)

set result:
tradeLot -> priceQuantity -> quantity
tradeLot -> priceQuantity -> quantity
filter item -> value exists
then (if unitTypes exists
then filter unitTypes any = item -> unit
else item)
then extract [ CompareNumbers(item -> value, op, amount) ]
all = True

Expand Down
Loading