diff --git a/GOVERNANCE.md b/GOVERNANCE.md index e001f9d113..a5f1a2be78 100644 --- a/GOVERNANCE.md +++ b/GOVERNANCE.md @@ -8,8 +8,8 @@ Each Working Group may include the following roles. Additional roles may be adop * 1.1. Maintainer. “Maintainers” are responsible for organizing activities around developing, maintaining, and updating the specification(s) developed by the Working Group. Maintainers are also responsible for determining consensus and coordinating appeals. Each Working Group will designate one or more Maintainers for that Working Group. A Working Group may select a new or additional Maintainer(s) upon Approval of the Working Group Participants. -* 1.2. Editor. “Editors” are responsible for ensuring that the contents of the document accurately reflect the decisions that have been made by the group, and that the specification adheres to formatting and content guidelines. Each Working Group will designate an Editor for that Working Group. A Working Group may select a new Editor upon Approval of the Working Group Participants. - +* 1.2. Editor. “Editors” help to alleviate the workload of maintainers, key contributors are granted Editor status. As Editors, they have the authority to label Pull Requests and issues. Presently, individuals from TradeHeader, Fragmos Chain, and FT Advisory hold Editor status. If you are affiliated with these organizations and are not yet designated as an Editor, please reach out to the [CDM maintainers via email](https://lists.finos.org/g/cdm-maintainers). If you belong to a different organization and wish to become a contributor, you can submit a proposal to the maintainers outlining your request for Editor status. Upon review, further steps will be communicated to facilitate your inclusion as an Editor. + * 1.3. Participants. “Participants” are those that have made Contributions to the Working Group subject to the Community Specification License. Participants are automatically abiding by the IP policy of the standard by just participating in a meeting or by actively "enrolling" in the standard. * 1.4. Discussion Groups. The Working Group may form one or more "Discussion Groups" to organize collaboration around a particular aspect of a specification. Discussion Groups are for discussion only -- Approval of all portions of a specification is subject to the consensus-based decision making process. diff --git a/README.md b/README.md index 00cc5f895e..9b729ea0cb 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ +[![FINOS Hosted Platform - CDM Object Builder](https://img.shields.io/badge/FINOS%20Hosted%20Platform-CDM%20Object%20Builder-blue)](https://cdm-object-builder.finos.org/) [![FINOS - Incubating](https://cdn.jsdelivr.net/gh/finos/contrib-toolbox@master/images/badge-incubating.svg)](https://community.finos.org/docs/governance/Software-Projects/stages/incubating) - [![Codefresh build status]( https://g.codefresh.io/api/badges/pipeline/regnosysops/FINOS%2Fcommon-domain-model?type=cf-1)]( https://g.codefresh.io/public/accounts/regnosysops/pipelines/new/63ecb79bde06416b39d81e70) # Common Domain Model (CDM) diff --git a/RELEASE.md b/RELEASE.md index 6262fea071..f1b1c1e600 100644 --- a/RELEASE.md +++ b/RELEASE.md @@ -1,15 +1,21 @@ -# _Product Model - Bond Option and Forward Qualification_ +# _Product Model - Qualification of AssetClass_ _Background_ -A previous release introduced a regression in the qualification of Bond Forwards and Bond Options, that were no longer qualified due to an update in the `Qualify_AssetClass_InterestRate` function. This release addresses this issue. +Issue [#2863](https://github.com/finos/common-domain-model/issues/2863) was identified with the recent change to the qualification of `AssetClass` in PR [#2840](https://github.com/finos/common-domain-model/pull/2840). _What is being released?_ -- Reintroduced the capability to have a security with `securityType = SecurityTypeEnum -> Debt` as underlier of the option or forward in the `Qualify_AssetClass_InterestRate` function. +This release fixes the following functions to ensure an `else` clause is specified in all nested `if` statements. + +- `Qualify_AssetClass_InterestRate` +- `Qualify_AssetClass_Credit` +- `Qualify_AssetClass_ForeignExchange` +- `Qualify_AssetClass_Equity` +- `Qualify_AssetClass_Commodity` _Review directions_ -In Rosetta, select the Textual View and inspect the change identified above +In Rosetta, select the Textual Browser and inspect the changes identified above. -The changes can be reviewed in PR: [#2851](https://github.com/finos/common-domain-model/pull/2851) +The changes can be reviewed in PR: [#2864](https://github.com/finos/common-domain-model/pull/2864) diff --git a/rosetta-source/src/main/rosetta/mapping-fpml-confirmation-tradestate-synonym.rosetta b/rosetta-source/src/main/rosetta/mapping-fpml-confirmation-tradestate-synonym.rosetta index e49d53082f..ea891ef120 100644 --- a/rosetta-source/src/main/rosetta/mapping-fpml-confirmation-tradestate-synonym.rosetta +++ b/rosetta-source/src/main/rosetta/mapping-fpml-confirmation-tradestate-synonym.rosetta @@ -1712,15 +1712,15 @@ synonym source FpML_5_Confirmation_To_TradeState extends FpML [hint "bondOption"] [value "genericProduct"] + productTaxonomy - [hint "primaryAssetClass"] + [hint "primaryAssetClass"] [hint "secondaryAssetClass"] [hint "fra"] [hint "creditDefaultSwapOption"] [hint "bondOption"] [hint "commoditySwaption"] - [hint "genericProduct"] - [hint "productType"] - [value "commodityClassification"] + [hint "genericProduct"] + [hint "productType"] + [value "commodityClassification"] ProductTaxonomy: + primaryAssetClass @@ -2255,18 +2255,18 @@ synonym source FpML_5_Confirmation_To_TradeState extends FpML [value "features"] [hint "averagingMethod"] + observationTerms - [value "asian" path "features"] - [hint "pricingDates"] - [hint "calculationPeriodsSchedule"] - [value "equityValuation" path "equityExercise"] - + schedule - [value "schedule"] + [value "asian" path "features"] + [hint "pricingDates"] + [hint "calculationPeriodsSchedule"] + [value "equityValuation" path "equityExercise"] + + schedule + [value "schedule"] + delivery [value "ignore"] + strike - [value "strike"] - [hint "strikePricePerUnit"] - [hint "spotRate"] + [value "strike"] + [hint "strikePricePerUnit"] + [hint "spotRate"] + underlier [value "singleUnderlyer" path "underlyer" , "underlyer"] [hint "bond" , "equity" , "mortgage" , "convertibleBond" , "index"] @@ -2278,9 +2278,9 @@ synonym source FpML_5_Confirmation_To_TradeState extends FpML [hint "varianceSwapTransactionSupplement"] [hint "dividendSwapTransactionSupplement"] + optionType - [value "optionType"] - [set to OptionTypeEnum -> Straddle when "swaptionStraddle" = True] - + [value "optionType"] + [set to OptionTypeEnum -> Straddle when "swaptionStraddle" = True] + ExerciseTerms: + commencementDate [value "commencementDate" path "americanExercise"] @@ -2322,7 +2322,7 @@ synonym source FpML_5_Confirmation_To_TradeState extends FpML [value "expirationDates" path "europeanExercise"] // For FX Option [value "europeanExercise"] - [value "americanExercise"] + [value "americanExercise"] // [hint "americanExercise->expiryDate"] // [hint "expiryDate"] + expirationTime @@ -5363,6 +5363,8 @@ synonym source FpML_5_Confirmation_To_TradeState extends FpML [value "ZAR-CPIX"] BusinessCenterEnum: + + AEAB + [value "AEAB"] + AEAD [value "AEAD"] + AEDU @@ -5441,6 +5443,8 @@ synonym source FpML_5_Confirmation_To_TradeState extends FpML [value "CIAB"] + CLSA [value "CLSA"] + + CMYA + [value "CMYA"] + CNBE [value "CNBE"] + CNSH @@ -5449,6 +5453,8 @@ synonym source FpML_5_Confirmation_To_TradeState extends FpML [value "COBO"] + CRSJ [value "CRSJ"] + + CWWI + [value "CWWI"] + CYNI [value "CYNI"] + CZPR @@ -5475,6 +5481,8 @@ synonym source FpML_5_Confirmation_To_TradeState extends FpML [value "DOSD"] + DZAL [value "DZAL"] + + ECGU + [value "ECGU"] + EETA [value "EETA"] + EGCA @@ -5485,8 +5493,12 @@ synonym source FpML_5_Confirmation_To_TradeState extends FpML [value "ESBA"] + ESMA [value "ESMA"] + + ESSS + [value "ESSS"] + ETAA [value "ETAA"] + + EUR_ICESWAP + [value "EUR-ICESWAP"] + EUTA [value "EUTA"] + FIHE @@ -5497,14 +5509,24 @@ synonym source FpML_5_Confirmation_To_TradeState extends FpML [value "GBED"] + GBLO [value "GBLO"] + + GBP_ICESWAP + [value "GBP-ICESWAP"] + GETB [value "GETB"] + GGSP [value "GGSP"] + GHAC [value "GHAC"] + + GIGI + [value "GIGI"] + + GMBA + [value "GMBA"] + + GNCO + [value "GNCO"] + GRAT [value "GRAT"] + + GTGC + [value "GTGC"] + HKHK [value "HKHK"] + HNTE @@ -5519,8 +5541,12 @@ synonym source FpML_5_Confirmation_To_TradeState extends FpML [value "IEDU"] + ILJE [value "ILJE"] + + ILS_TELBOR + [value "ILS-TELBOR"] + ILTA [value "ILTA"] + + INAH + [value "INAH"] + INBA [value "INBA"] + INCH @@ -5533,6 +5559,8 @@ synonym source FpML_5_Confirmation_To_TradeState extends FpML [value "INMU"] + INND [value "INND"] + + IQBA + [value "IQBA"] + IRTE [value "IRTE"] + ISRE @@ -5561,6 +5589,8 @@ synonym source FpML_5_Confirmation_To_TradeState extends FpML [value "KYGE"] + KZAL [value "KZAL"] + + LAVI + [value "LAVI"] + LBBE [value "LBBE"] + LKCO @@ -5575,6 +5605,8 @@ synonym source FpML_5_Confirmation_To_TradeState extends FpML [value "MARA"] + MCMO [value "MCMO"] + + MNUB + [value "MNUB"] + MOMA [value "MOMA"] + MTVA @@ -5591,6 +5623,8 @@ synonym source FpML_5_Confirmation_To_TradeState extends FpML [value "MYKL"] + MYLA [value "MYLA"] + + MZMA + [value "MZMA"] + NAWI [value "NAWI"] + NGAB @@ -5653,6 +5687,8 @@ synonym source FpML_5_Confirmation_To_TradeState extends FpML [value "SILJ"] + SKBR [value "SKBR"] + + SLFR + [value "SLFR"] + SNDA [value "SNDA"] + SVSS @@ -5683,6 +5719,10 @@ synonym source FpML_5_Confirmation_To_TradeState extends FpML [value "USCH"] + USCR [value "USCR"] + + USD_ICESWAP + [value "USD-ICESWAP"] + + USD_MUNI + [value "USD-MUNI"] + USDC [value "USDC"] + USDN @@ -5709,10 +5749,14 @@ synonym source FpML_5_Confirmation_To_TradeState extends FpML [value "USSA"] + USSE [value "USSE"] + + USSF + [value "USSF"] + USWT [value "USWT"] + UYMO [value "UYMO"] + + UZTA + [value "UZTA"] + VECA [value "VECA"] + VGRT diff --git a/rosetta-source/src/main/rosetta/product-qualification-func.rosetta b/rosetta-source/src/main/rosetta/product-qualification-func.rosetta index b4dfd4bec3..cdbed7c87a 100644 --- a/rosetta-source/src/main/rosetta/product-qualification-func.rosetta +++ b/rosetta-source/src/main/rosetta/product-qualification-func.rosetta @@ -43,6 +43,7 @@ func Qualify_AssetClass_InterestRate: <"Qualifies a product as having the Asset or Qualify_AssetClass_InterestRate( optionUnderlier -> security -> economicTerms ) = True + else False ) ) or (economicTerms -> payout -> forwardPayout only exists @@ -67,15 +68,17 @@ func Qualify_AssetClass_Credit: <"Qualifies a product as having the Asset Class and if optionUnderlier exists then (optionUnderlier -> index -> productTaxonomy -> primaryAssetClass any = AssetClassEnum -> Credit or optionUnderlier -> security -> productTaxonomy -> primaryAssetClass any = AssetClassEnum -> Credit - or Qualify_AssetClass_Credit( optionUnderlier -> contractualProduct -> economicTerms ) + or Qualify_AssetClass_Credit( optionUnderlier -> contractualProduct -> economicTerms ) or Qualify_AssetClass_Credit( optionUnderlier -> security -> economicTerms ) - ) + ) + else False ) or (economicTerms -> payout -> forwardPayout only exists and if forwardUnderlier exists then (forwardUnderlier -> index -> productTaxonomy -> primaryAssetClass any = AssetClassEnum -> Credit or forwardUnderlier -> security -> productTaxonomy -> primaryAssetClass any = AssetClassEnum -> Credit) - + else False + ) func Qualify_AssetClass_ForeignExchange: <"Qualifies a product as having the Asset Class classification Foreign Exchange"> @@ -94,9 +97,11 @@ func Qualify_AssetClass_ForeignExchange: <"Qualifies a product as having the Ass or optionUnderlier -> index -> productTaxonomy -> primaryAssetClass any = AssetClassEnum -> ForeignExchange or optionUnderlier -> security -> productTaxonomy -> primaryAssetClass any = AssetClassEnum -> ForeignExchange or (if optionUnderlier exists - then Qualify_AssetClass_ForeignExchange(optionUnderlier -> contractualProduct -> economicTerms)) + then Qualify_AssetClass_ForeignExchange(optionUnderlier -> contractualProduct -> economicTerms) + else False) or (if optionUnderlier exists - then Qualify_AssetClass_ForeignExchange(optionUnderlier -> security -> economicTerms)) + then Qualify_AssetClass_ForeignExchange(optionUnderlier -> security -> economicTerms) + else False) or forwardUnderlier -> index -> productTaxonomy -> primaryAssetClass any = AssetClassEnum -> ForeignExchange or forwardUnderlier -> security -> productTaxonomy -> primaryAssetClass any = AssetClassEnum -> ForeignExchange @@ -124,12 +129,14 @@ func Qualify_AssetClass_Equity: then (Qualify_UnderlierProduct_Equity(optionUnderlier) = True or optionUnderlier -> index -> productTaxonomy -> primaryAssetClass any = AssetClassEnum -> Equity or optionUnderlier -> security -> productTaxonomy -> primaryAssetClass any = AssetClassEnum -> Equity) + else False ) or (economicTerms -> payout -> forwardPayout only exists and if forwardUnderlier exists then (Qualify_UnderlierProduct_Equity(forwardUnderlier) or forwardUnderlier -> index -> productTaxonomy -> primaryAssetClass any = AssetClassEnum -> Equity or forwardUnderlier -> security -> productTaxonomy -> primaryAssetClass any = AssetClassEnum -> Equity) + else False ) func Qualify_AssetClass_Commodity: <"Qualifies a product as having the Asset Class classification Commodity"> @@ -163,9 +170,10 @@ func Qualify_AssetClass_Commodity: <"Qualifies a product as having the Asset Cla or optionUnderlier -> index -> productTaxonomy -> primaryAssetClass any = AssetClassEnum -> Commodity or optionUnderlier -> security -> productTaxonomy -> primaryAssetClass any = AssetClassEnum -> Commodity ) + else False ) // CO Fwd - or ( ( (economicTerms -> payout -> forwardPayout, economicTerms -> payout -> fixedPricePayout) only exists + or ( ( (economicTerms -> payout -> forwardPayout, economicTerms -> payout -> fixedPricePayout) only exists or (economicTerms -> payout -> forwardPayout, economicTerms -> payout -> commodityPayout) only exists ) and (economicTerms -> payout -> forwardPayout -> underlier -> commodity exists @@ -1610,4 +1618,3 @@ func Qualify_Commodity_Forward: <"Qualifies a product as a Forward that will be and ( (economicTerms -> payout -> forwardPayout, economicTerms -> payout -> fixedPricePayout) only exists or // Fixed Price Forward (economicTerms -> payout -> forwardPayout, economicTerms -> payout -> commodityPayout) only exists) // Floating Price Forward - \ No newline at end of file diff --git a/rosetta-source/src/test/java/cdm/product/qualification/functions/Qualify_AssetClass_CreditTest.java b/rosetta-source/src/test/java/cdm/product/qualification/functions/Qualify_AssetClass_CreditTest.java new file mode 100644 index 0000000000..ad627cb00c --- /dev/null +++ b/rosetta-source/src/test/java/cdm/product/qualification/functions/Qualify_AssetClass_CreditTest.java @@ -0,0 +1,42 @@ +package cdm.product.qualification.functions; + +import cdm.event.common.TradeState; +import cdm.product.template.EconomicTerms; +import com.google.inject.Inject; +import org.isda.cdm.functions.AbstractFunctionTest; +import org.junit.jupiter.api.Test; +import util.ResourcesUtils; + +import java.io.IOException; + +import static org.junit.jupiter.api.Assertions.*; + +class Qualify_AssetClass_CreditTest extends AbstractFunctionTest { + + @Inject + Qualify_AssetClass_Credit qualifyAssetClassCredit; + + @Test + void shouldQualifyAsAssetClassCredit() throws IOException { + EconomicTerms economicTerms = getEconomicTerms("result-json-files/fpml-5-13/products/credit-derivatives/cdx-index-option.json"); + + Boolean result = qualifyAssetClassCredit.evaluate(economicTerms); + + assertTrue(result); + } + + @Test + void shouldNotQualifyAsAssetClassCredit() throws IOException { + EconomicTerms economicTerms = getEconomicTerms("result-json-files/fpml-5-13/products/fx-derivatives/fx-ex08-fx-swap.json"); + + Boolean result = qualifyAssetClassCredit.evaluate(economicTerms); + + assertFalse(result); + } + + private static EconomicTerms getEconomicTerms(String resourceName) throws IOException { + TradeState tradeState = ResourcesUtils.getObjectAndResolveReferences(TradeState.class, resourceName); + EconomicTerms economicTerms = tradeState.getTrade().getTradableProduct().getProduct().getContractualProduct().getEconomicTerms(); + return economicTerms; + } +} \ No newline at end of file diff --git a/rosetta-source/src/test/java/cdm/product/qualification/functions/Qualify_AssetClass_ForeignExchangeTest.java b/rosetta-source/src/test/java/cdm/product/qualification/functions/Qualify_AssetClass_ForeignExchangeTest.java new file mode 100644 index 0000000000..8b6e2dcb04 --- /dev/null +++ b/rosetta-source/src/test/java/cdm/product/qualification/functions/Qualify_AssetClass_ForeignExchangeTest.java @@ -0,0 +1,42 @@ +package cdm.product.qualification.functions; + +import cdm.event.common.TradeState; +import cdm.product.template.EconomicTerms; +import com.google.inject.Inject; +import org.isda.cdm.functions.AbstractFunctionTest; +import org.junit.jupiter.api.Test; +import util.ResourcesUtils; + +import java.io.IOException; + +import static org.junit.jupiter.api.Assertions.*; + +class Qualify_AssetClass_ForeignExchangeTest extends AbstractFunctionTest { + + @Inject + Qualify_AssetClass_ForeignExchange qualifyAssetClassForeignExchange; + + @Test + void shouldQualifyAsAssetClassForeignExchange() throws IOException { + EconomicTerms economicTerms = getEconomicTerms("result-json-files/fpml-5-13/products/fx-derivatives/fx-ex08-fx-swap.json"); + + Boolean result = qualifyAssetClassForeignExchange.evaluate(economicTerms); + + assertTrue(result); + } + + @Test + void shouldNotQualifyAsAssetClassForeignExchange() throws IOException { + EconomicTerms economicTerms = getEconomicTerms("result-json-files/fpml-5-13/products/credit-derivatives/cdx-index-option.json"); + + Boolean result = qualifyAssetClassForeignExchange.evaluate(economicTerms); + + assertFalse(result); + } + + private static EconomicTerms getEconomicTerms(String resourceName) throws IOException { + TradeState tradeState = ResourcesUtils.getObjectAndResolveReferences(TradeState.class, resourceName); + EconomicTerms economicTerms = tradeState.getTrade().getTradableProduct().getProduct().getContractualProduct().getEconomicTerms(); + return economicTerms; + } +} \ No newline at end of file