diff --git a/rosetta-source/src/main/rosetta/base-math-func.rosetta b/rosetta-source/src/main/rosetta/base-math-func.rosetta index 00dda044a8..188e29986b 100755 --- a/rosetta-source/src/main/rosetta/base-math-func.rosetta +++ b/rosetta-source/src/main/rosetta/base-math-func.rosetta @@ -133,6 +133,28 @@ func UpdateAmount: <"Updates an amount based on the given QuantityChangeDirectio Decrease then oldAmount - changeAmount, Replace then changeAmount +func UpdateDatedValues: <"Updates the amounts of the dated values based on the given QuantityChangeDirectionEnum. For all periods after the effective date of the change, if the direction is Increase, the old amount and change amount are summed, if the direction is Decrease, then the change amount is subtracted from the old amount, and if the direction is Replace then the change amount replaces the old amount."> + inputs: + datedValues DatedValue (0..*) + changeAmount number (0..1) + direction QuantityChangeDirectionEnum (1..1) + effectiveDate date (0..1) + output: + newdatedValues DatedValue (0..*) + + add newdatedValues: + datedValues + extract + DatedValue { + date: item -> date, + value: + if item -> date >= effectiveDate then ( + if direction = QuantityChangeDirectionEnum -> Increase then item -> value + changeAmount + else if direction = QuantityChangeDirectionEnum -> Decrease then item -> value - changeAmount + else if direction = QuantityChangeDirectionEnum -> Replace then changeAmount) + else item -> value + } + func FilterQuantity: <"Filter list of quantities based on unit type."> inputs: quantities Quantity (0..*) <"List of quantities to filter."> diff --git a/rosetta-source/src/main/rosetta/ingest-fpml-confirmation-workflowstep-func.rosetta b/rosetta-source/src/main/rosetta/ingest-fpml-confirmation-workflowstep-func.rosetta index dd769d4208..44b39b4806 100644 --- a/rosetta-source/src/main/rosetta/ingest-fpml-confirmation-workflowstep-func.rosetta +++ b/rosetta-source/src/main/rosetta/ingest-fpml-confirmation-workflowstep-func.rosetta @@ -222,13 +222,13 @@ func MapTerminationToPrimitiveInstruction: counterpartyList ) }, - quantityChange: termination -> tradeNotionalChangeModel -> tradeNotionalChangeModelSequence0 - extract - QuantityChangeInstruction { - change: MapPriceQuantity, - direction: if exists then Replace, - ... - }, + quantityChange: + if termination exists + then QuantityChangeInstruction { + change: MapPriceQuantity(termination), + direction: Replace, + ... + }, transfer: TransferInstruction { transferState: @@ -290,16 +290,17 @@ func MapTerminationToPrimitiveInstruction: func MapPriceQuantity: inputs: - f fpml.TradeNotionalChangeModelSequence0 (0..1) + f fpml.TradeNotionalChange (0..1) output: priceQuantityList PriceQuantity (0..*) add priceQuantityList: PriceQuantity { quantity: CreateQuantityWithLocation( - MapTradeNotionalChangeModelSequenceToNonNegativeQuantitySchedule(f), + MapTradeNotionalChangeModelSequenceToNonNegativeQuantitySchedule(f -> tradeNotionalChangeModel -> tradeNotionalChangeModelSequence0), CreateQuantityKey(empty, empty) ), + effectiveDate: MapAdjustedDateToAdjustableOrRelativeDate(f -> agreementAndEffectiveDatesModel -> effectiveDate -> date, empty), ... } diff --git a/rosetta-source/src/main/rosetta/product-common-settlement-func.rosetta b/rosetta-source/src/main/rosetta/product-common-settlement-func.rosetta index 2a93e3a0b0..cf8ec6e5b6 100644 --- a/rosetta-source/src/main/rosetta/product-common-settlement-func.rosetta +++ b/rosetta-source/src/main/rosetta/product-common-settlement-func.rosetta @@ -1,6 +1,7 @@ namespace cdm.product.common.settlement : <"Common product settlement concepts: cash vs physical, non-deliverable, money and cashflow, delivery vs payment."> version "${project.version}" +import cdm.base.datetime.* import cdm.base.math.* import cdm.observable.asset.* @@ -24,10 +25,11 @@ func UpdateAmountForEachMatchingQuantity: <"Updates any price or quantity from t direction ), quantity: priceQuantity -> quantity - extract - UpdateQuantityAmountForEachMatchingQuantity( + extract + UpdateQuantityAmountForEachMatchingQuantity( item, - change -> quantity, // FilterChangePriceQuantity(priceQuantity, change) -> quantity, + change, // FilterChangePriceQuantity(priceQuantity, change), + // PriceQuantity used as input to keep the quantity and effectiveDate linked direction ), observable: priceQuantity -> observable, @@ -76,20 +78,39 @@ func UpdateQuantityAmountForEachMatchingQuantity: <"Updates any quantity from th inputs: quantity NonNegativeQuantitySchedule (0..1) <"List of NonNegativeQuantitySchedule to update."> [metadata location] - change NonNegativeQuantitySchedule (0..*) <"List of new NonNegativeQuantitySchedule to use where the units match."> + change PriceQuantity (0..*) <"List of new PriceQuantity elements to be applied where units match. PriceQuantity is defined as input to ensure the quantity change remains associated with its corresponding effectiveDate."> direction QuantityChangeDirectionEnum (1..1) <"Enum specifying how the updated amounts should be applied, e.g., add, subtract or replace."> output: updatedQuantity NonNegativeQuantitySchedule (0..1) [metadata location] - alias changedAmount: - change - filter UnitEquals(item -> unit, quantity -> unit) + alias changeMatching: + SplitQuantityChange(change) + filter UnitEquals(item -> quantity only-element -> unit, quantity -> unit) then first - then extract UpdateAmount(quantity -> value, value, direction) + + alias changedAmount: + UpdateAmount( + quantity -> value, + changeMatching -> quantity only-element -> value, + direction + ) + + alias changeEffectiveDate: + AdjustableDateResolution(changeMatching -> effectiveDate -> adjustableDate) + // ResolveAdjustableDate(changeMatching -> effectiveDate) + // TODO uncomment usage once function is available + alias changedDatedValue: + UpdateDatedValues( + quantity -> datedValue, + changeMatching -> quantity only-element -> value, + direction, + changeEffectiveDate + ) set updatedQuantity: quantity set updatedQuantity -> value: changedAmount default quantity -> value + set updatedQuantity -> datedValue: changedDatedValue default quantity -> datedValue func PriceUnitEquals: <"Compares two PriceSchedule to check if all attributes match, except for the amount."> inputs: @@ -112,3 +133,22 @@ func PriceUnitEquals: <"Compares two PriceSchedule to check if all attributes ma set result: unitMatches and perUnitOfMatches and priceTypeMatches and priceExpressionMatches and arithmeticOperatorMatches + +func SplitQuantityChange: <"Splits a PriceQuantity list into separate elements, each containing a single quantity and its corresponding effective date, if multiple quantities exist."> + inputs: + changeList PriceQuantity (1..*) <"Original PriceQuantity list where each of them may contain multiple quantities."> + output: + splitChange PriceQuantity (1..*) <"New list of PriceQuantity where each of them contain a single quantity."> + + set splitChange: <"Iterates through the original PriceQuantity list and the quantity list."> + changeList + extract change [ + change -> quantity + extract quantity [ + PriceQuantity { + quantity: quantity, + effectiveDate: change -> effectiveDate, + ... + } + ] + ] then flatten \ No newline at end of file