From 138ba151dcfb73fb346b359254482dc6e8080317 Mon Sep 17 00:00:00 2001 From: Julius Lauterbach Date: Tue, 17 Sep 2024 15:30:31 +0200 Subject: [PATCH 01/51] SDC-633, fix for SDC product xml parsing. This way its more adaptable when DataDocument is formatted with namespace tags --- .../net/finmath/smartcontract/product/xml/SDCXMLParser.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/net/finmath/smartcontract/product/xml/SDCXMLParser.java b/src/main/java/net/finmath/smartcontract/product/xml/SDCXMLParser.java index f8d2e581..de2e0f79 100644 --- a/src/main/java/net/finmath/smartcontract/product/xml/SDCXMLParser.java +++ b/src/main/java/net/finmath/smartcontract/product/xml/SDCXMLParser.java @@ -89,7 +89,7 @@ public static SmartDerivativeContractDescriptor parse(String sdcxml) throws Pars .getElementsByTagName("underlying") .item(0) .getFirstChild(); - if (!underlying.getNodeName().equals("dataDocument")) { + if (!underlying.getNodeName().contains("dataDocument")) { underlying = underlying.getNextSibling(); } Swap swap = (Swap) sdc.getUnderlyings().getUnderlying().getDataDocument().getTrade().get(0).getProduct().getValue(); From 0175319315e662e4452bcfa68149c66b28daf244 Mon Sep 17 00:00:00 2001 From: Julius Lauterbach Date: Tue, 17 Sep 2024 15:31:39 +0200 Subject: [PATCH 02/51] SDC-633, adding the missing schema location for SDC xml --- .../net/finmath/smartcontract/product/xml/SDCXMLParser.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/java/net/finmath/smartcontract/product/xml/SDCXMLParser.java b/src/main/java/net/finmath/smartcontract/product/xml/SDCXMLParser.java index de2e0f79..02a648f6 100644 --- a/src/main/java/net/finmath/smartcontract/product/xml/SDCXMLParser.java +++ b/src/main/java/net/finmath/smartcontract/product/xml/SDCXMLParser.java @@ -116,6 +116,8 @@ public static String marshalClassToXMLString(T t) { try { JAXBContext jaxbContextSettlement = JAXBContext.newInstance(t.getClass()); Marshaller jaxbMarshaller = jaxbContextSettlement.createMarshaller(); + if (t instanceof Smartderivativecontract) + jaxbMarshaller.setProperty(Marshaller.JAXB_SCHEMA_LOCATION, "uri:sdc smartderivativecontract.xsd"); StringWriter writer = new StringWriter(); jaxbMarshaller.marshal(t, writer); return writer.toString(); From b8f3bcc3e0244cb797999fdabcd1388e1bb378ed Mon Sep 17 00:00:00 2001 From: Julius Lauterbach Date: Wed, 18 Sep 2024 12:29:34 +0200 Subject: [PATCH 03/51] SDC-633, added new SDCtoXML method with text replacements --- .../product/xml/SDCXMLParser.java | 187 +++++++++--------- 1 file changed, 98 insertions(+), 89 deletions(-) diff --git a/src/main/java/net/finmath/smartcontract/product/xml/SDCXMLParser.java b/src/main/java/net/finmath/smartcontract/product/xml/SDCXMLParser.java index 02a648f6..5e00c552 100644 --- a/src/main/java/net/finmath/smartcontract/product/xml/SDCXMLParser.java +++ b/src/main/java/net/finmath/smartcontract/product/xml/SDCXMLParser.java @@ -28,102 +28,111 @@ */ public class SDCXMLParser { - private static final Logger logger = LoggerFactory.getLogger(SDCXMLParser.class); + private static final Logger logger = LoggerFactory.getLogger(SDCXMLParser.class); - private SDCXMLParser() { - } + private SDCXMLParser() { + } - public static SmartDerivativeContractDescriptor parse(String sdcxml) throws ParserConfigurationException, IOException, SAXException { + public static SmartDerivativeContractDescriptor parse(String sdcxml) throws ParserConfigurationException, IOException, SAXException { - Smartderivativecontract sdc = unmarshalXml(sdcxml, Smartderivativecontract.class); + Smartderivativecontract sdc = unmarshalXml(sdcxml, Smartderivativecontract.class); - LocalDateTime settlementDateInitial = LocalDateTime.parse(sdc.getSettlement().settlementDateInitial.trim()); + LocalDateTime settlementDateInitial = LocalDateTime.parse(sdc.getSettlement().settlementDateInitial.trim()); - String uniqueTradeIdentifier = sdc.getUniqueTradeIdentifier().trim(); - String dltAddress = sdc.getDltAddress() == null ? "" : sdc.getDltAddress().trim(); - String dltTradeId = sdc.getDltTradeId() == null ? "" : sdc.getDltTradeId().trim(); + String uniqueTradeIdentifier = sdc.getUniqueTradeIdentifier().trim(); + String dltAddress = sdc.getDltAddress() == null ? "" : sdc.getDltAddress().trim(); + String dltTradeId = sdc.getDltTradeId() == null ? "" : sdc.getDltTradeId().trim(); /* Market Data */ - List marketdataItems = new ArrayList<>(); - for(Smartderivativecontract.Settlement.Marketdata.Marketdataitems.Item item : sdc.getSettlement().getMarketdata().getMarketdataitems().getItem()){ - String symbol = item.getSymbol().get(0).trim(); - String curve = item.getCurve().get(0).trim(); - String type = item.getType().get(0).trim(); - String tenor = item.getTenor().get(0).trim(); - CalibrationDataItem.Spec spec = new CalibrationDataItem.Spec(symbol, curve, type, tenor); - marketdataItems.add(spec); - } - - /* - * Counterparties - */ - List parties = new ArrayList<>(); - Map marginAccountInitialByPartyID = new HashMap<>(); - Map penaltyFeeInitialByPartyID = new HashMap<>(); - - for(Smartderivativecontract.Parties.Party p : sdc.getParties().getParty()){ - SmartDerivativeContractDescriptor.Party party = new SmartDerivativeContractDescriptor.Party( - p.getId().trim(), - p.getName().trim(), - null, - p.getAddress().trim() - ); - parties.add(party); - marginAccountInitialByPartyID.put(party.getId(), p.getMarginAccount().getValue()); - penaltyFeeInitialByPartyID.put(party.getId(), p.getPenaltyFee().getValue()); - } - - // Receiver party ID - String receiverPartyID = sdc.getReceiverPartyID().trim(); - - // TODO The parser needs to check that the field receiverPartyID of the SDC matched the field in the FPML - - // TODO Support multiple underlyings - - Document document = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(new ByteArrayInputStream(sdcxml.getBytes(StandardCharsets.UTF_8))); - document.getDocumentElement().normalize(); - - Node underlying = document - .getElementsByTagName("underlying") - .item(0) - .getFirstChild(); - if (!underlying.getNodeName().contains("dataDocument")) { - underlying = underlying.getNextSibling(); - } - Swap swap = (Swap) sdc.getUnderlyings().getUnderlying().getDataDocument().getTrade().get(0).getProduct().getValue(); - String currency = swap.getSwapStream().get(0).getCalculationPeriodAmount().getCalculation().getNotionalSchedule().getNotionalStepSchedule().getCurrency().getValue().trim(); - - String marketDataProvider = sdc.getSettlement().getMarketdata().getProvider().trim(); - - return new SmartDerivativeContractDescriptor(dltTradeId, dltAddress, uniqueTradeIdentifier, settlementDateInitial, parties, marginAccountInitialByPartyID, penaltyFeeInitialByPartyID, receiverPartyID, underlying, marketdataItems, currency, marketDataProvider); - } - - public static T unmarshalXml(String xml, Class t) { - try { - StringReader reader = new StringReader(xml); - JAXBContext jaxbContext = JAXBContext.newInstance(t); - Unmarshaller unmarshaller = jaxbContext.createUnmarshaller(); - return (T) unmarshaller.unmarshal(reader); - } catch (JAXBException e) { - logger.error("unmarshalXml: jaxb error, ", e); - throw new SDCException(ExceptionId.SDC_JAXB_ERROR, e.getMessage(), 400); - } - } - - public static String marshalClassToXMLString(T t) { - try { - JAXBContext jaxbContextSettlement = JAXBContext.newInstance(t.getClass()); - Marshaller jaxbMarshaller = jaxbContextSettlement.createMarshaller(); - if (t instanceof Smartderivativecontract) - jaxbMarshaller.setProperty(Marshaller.JAXB_SCHEMA_LOCATION, "uri:sdc smartderivativecontract.xsd"); - StringWriter writer = new StringWriter(); - jaxbMarshaller.marshal(t, writer); - return writer.toString(); - } catch (JAXBException e) { - logger.error("marshalClassToXMLString: jaxb error, ", e); - throw new SDCException(ExceptionId.SDC_JAXB_ERROR, e.getMessage(), 400); - } - } + List marketdataItems = new ArrayList<>(); + for (Smartderivativecontract.Settlement.Marketdata.Marketdataitems.Item item : sdc.getSettlement().getMarketdata().getMarketdataitems().getItem()) { + String symbol = item.getSymbol().get(0).trim(); + String curve = item.getCurve().get(0).trim(); + String type = item.getType().get(0).trim(); + String tenor = item.getTenor().get(0).trim(); + CalibrationDataItem.Spec spec = new CalibrationDataItem.Spec(symbol, curve, type, tenor); + marketdataItems.add(spec); + } + + /* + * Counterparties + */ + List parties = new ArrayList<>(); + Map marginAccountInitialByPartyID = new HashMap<>(); + Map penaltyFeeInitialByPartyID = new HashMap<>(); + + for (Smartderivativecontract.Parties.Party p : sdc.getParties().getParty()) { + SmartDerivativeContractDescriptor.Party party = new SmartDerivativeContractDescriptor.Party( + p.getId().trim(), + p.getName().trim(), + null, + p.getAddress().trim() + ); + parties.add(party); + marginAccountInitialByPartyID.put(party.getId(), p.getMarginAccount().getValue()); + penaltyFeeInitialByPartyID.put(party.getId(), p.getPenaltyFee().getValue()); + } + + // Receiver party ID + String receiverPartyID = sdc.getReceiverPartyID().trim(); + + // TODO The parser needs to check that the field receiverPartyID of the SDC matched the field in the FPML + + // TODO Support multiple underlyings + + Document document = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(new ByteArrayInputStream(sdcxml.getBytes(StandardCharsets.UTF_8))); + document.getDocumentElement().normalize(); + + Node underlying = document + .getElementsByTagName("underlying") + .item(0) + .getFirstChild(); + if (!underlying.getNodeName().contains("dataDocument")) { + underlying = underlying.getNextSibling(); + } + Swap swap = (Swap) sdc.getUnderlyings().getUnderlying().getDataDocument().getTrade().get(0).getProduct().getValue(); + String currency = swap.getSwapStream().get(0).getCalculationPeriodAmount().getCalculation().getNotionalSchedule().getNotionalStepSchedule().getCurrency().getValue().trim(); + + String marketDataProvider = sdc.getSettlement().getMarketdata().getProvider().trim(); + + return new SmartDerivativeContractDescriptor(dltTradeId, dltAddress, uniqueTradeIdentifier, settlementDateInitial, parties, marginAccountInitialByPartyID, penaltyFeeInitialByPartyID, receiverPartyID, underlying, marketdataItems, currency, marketDataProvider); + } + + public static T unmarshalXml(String xml, Class t) { + try { + StringReader reader = new StringReader(xml); + JAXBContext jaxbContext = JAXBContext.newInstance(t); + Unmarshaller unmarshaller = jaxbContext.createUnmarshaller(); + return (T) unmarshaller.unmarshal(reader); + } catch (JAXBException e) { + logger.error("unmarshalXml: jaxb error, ", e); + throw new SDCException(ExceptionId.SDC_JAXB_ERROR, e.getMessage(), 400); + } + } + + public static String marshalClassToXMLString(T t) { + try { + JAXBContext jaxbContextSettlement = JAXBContext.newInstance(t.getClass()); + Marshaller jaxbMarshaller = jaxbContextSettlement.createMarshaller(); + if (t instanceof Smartderivativecontract) + jaxbMarshaller.setProperty(Marshaller.JAXB_SCHEMA_LOCATION, "uri:sdc smartderivativecontract.xsd"); + StringWriter writer = new StringWriter(); + jaxbMarshaller.marshal(t, writer); + return writer.toString(); + } catch (JAXBException e) { + logger.error("marshalClassToXMLString: jaxb error, ", e); + throw new SDCException(ExceptionId.SDC_JAXB_ERROR, e.getMessage(), 400); + } + } + + public static String marshalSDCToXMLString(Smartderivativecontract smartderivativecontract) { + //TODO took over an old implementation + // add tests to make sure that the format we are expecting to replace exists and only exists once. + // add test to make sure format is parseable after marshalling + return marshalClassToXMLString(smartderivativecontract) + .replaceAll("", "") + .replaceAll("fpml:", ""); + } } From ac9eb17872ef7ef83f2b5fe9f8352965037d90e5 Mon Sep 17 00:00:00 2001 From: Julius Lauterbach Date: Wed, 18 Sep 2024 13:11:45 +0200 Subject: [PATCH 04/51] SDC-633, added doc comments to the parser methods, added detailed test to SDCXMLParserTest --- .../product/xml/SDCXMLParser.java | 15 ++++++++-- .../product/xml/SDCXMLParserTest.java | 29 +++++++++++++++++++ 2 files changed, 41 insertions(+), 3 deletions(-) diff --git a/src/main/java/net/finmath/smartcontract/product/xml/SDCXMLParser.java b/src/main/java/net/finmath/smartcontract/product/xml/SDCXMLParser.java index 5e00c552..92fe8f0a 100644 --- a/src/main/java/net/finmath/smartcontract/product/xml/SDCXMLParser.java +++ b/src/main/java/net/finmath/smartcontract/product/xml/SDCXMLParser.java @@ -112,6 +112,12 @@ public static T unmarshalXml(String xml, Class t) { } } + /** + * Generic object-to-XML-string converter for all annotated classes + * @param t object to be converted to an XML string + * @return XML formatted String + * @param generic Type, which has the correct XML bind annotations + */ public static String marshalClassToXMLString(T t) { try { JAXBContext jaxbContextSettlement = JAXBContext.newInstance(t.getClass()); @@ -127,10 +133,13 @@ public static String marshalClassToXMLString(T t) { } } + /** + * this version of an SDC-object-to-XML-string conversion includes text replacements to get rid of XML namespace tags like "fpml:dataDocument" + * @param smartderivativecontract SDC product data object which will be transformed into an XML string + * @return formatted xml string + */ public static String marshalSDCToXMLString(Smartderivativecontract smartderivativecontract) { - //TODO took over an old implementation - // add tests to make sure that the format we are expecting to replace exists and only exists once. - // add test to make sure format is parseable after marshalling + //TODO took over an old implementation, please review return marshalClassToXMLString(smartderivativecontract) .replaceAll("", "") .replaceAll("fpml:", ""); diff --git a/src/test/java/net/finmath/smartcontract/product/xml/SDCXMLParserTest.java b/src/test/java/net/finmath/smartcontract/product/xml/SDCXMLParserTest.java index a9d3045c..f17b9b8d 100644 --- a/src/test/java/net/finmath/smartcontract/product/xml/SDCXMLParserTest.java +++ b/src/test/java/net/finmath/smartcontract/product/xml/SDCXMLParserTest.java @@ -9,6 +9,7 @@ import net.finmath.smartcontract.settlement.Settlement; import net.finmath.smartcontract.valuation.client.ValuationClient; import net.finmath.smartcontract.valuation.marketdata.data.MarketDataPoint; +import org.apache.commons.lang3.StringUtils; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import org.w3c.dom.Node; @@ -115,4 +116,32 @@ void marshalClassToXMLString() { Assertions.assertTrue(xmlString.contains("")); } + @Test + void marshalSDCToXMLString() throws IOException, ParserConfigurationException, SAXException { + //given + String fpml = new String(SDCXMLParserTest.class.getClassLoader().getResourceAsStream("net.finmath.smartcontract.product.xml/smartderivativecontract.xml").readAllBytes(), StandardCharsets.UTF_8); + Smartderivativecontract sdc = SDCXMLParser.unmarshalXml(fpml, Smartderivativecontract.class); + + //when + String xmlString = SDCXMLParser.marshalSDCToXMLString(sdc); + String xmlStringNameSpaceTags = SDCXMLParser.marshalClassToXMLString(sdc); + SmartDerivativeContractDescriptor sdcDescriptor = SDCXMLParser.parse(xmlString); + + //then + //xml based + Assertions.assertTrue(xmlStringNameSpaceTags.contains("")); + Assertions.assertEquals(1, StringUtils.countMatches(xmlStringNameSpaceTags,"")); + Assertions.assertFalse(xmlString.contains("")); + Assertions.assertTrue(xmlString.contains("")); + Assertions.assertTrue(xmlStringNameSpaceTags.contains(" Date: Thu, 26 Sep 2024 11:27:47 +0200 Subject: [PATCH 05/51] SDC-626, added new models for regularSettlements, reduced logging in MarketDataGeneratorWebsocket --- .../generators/MarketDataGeneratorWebsocket.java | 7 ++----- src/main/resources/api.yml | 4 ++++ .../openapi-schemas/RegularSettlementRequest.yml | 9 +++++++++ .../openapi-schemas/RegularSettlementResult.yml | 16 ++++++++++++++++ 4 files changed, 31 insertions(+), 5 deletions(-) create mode 100644 src/main/resources/schemas/openapi-schemas/RegularSettlementRequest.yml create mode 100644 src/main/resources/schemas/openapi-schemas/RegularSettlementResult.yml diff --git a/src/main/java/net/finmath/smartcontract/valuation/marketdata/generators/MarketDataGeneratorWebsocket.java b/src/main/java/net/finmath/smartcontract/valuation/marketdata/generators/MarketDataGeneratorWebsocket.java index 49036edd..8a140757 100644 --- a/src/main/java/net/finmath/smartcontract/valuation/marketdata/generators/MarketDataGeneratorWebsocket.java +++ b/src/main/java/net/finmath/smartcontract/valuation/marketdata/generators/MarketDataGeneratorWebsocket.java @@ -103,7 +103,7 @@ public void writeDataset(String importDir, MarketDataList s, boolean isOvernight @Override public void onTextMessage(WebSocket websocket, String message) throws Exception { - logger.info("message: {}", message); + logger.debug("message: {}", message); JsonNode responseJson = null; if (!message.isEmpty()) { @@ -146,17 +146,14 @@ public void onTextMessage(WebSocket websocket, String message) throws Exception } - if (this.allQuotesRetrieved()) { logger.info("all quotes retrieved"); - logger.info(marketDataList.toString()); + logger.debug(marketDataList.toString()); this.publishSubject.onNext(marketDataList); //this.sink.tryEmitNext(marketDataList); this.reset(); requestSent = false; } - - } private void reset() { diff --git a/src/main/resources/api.yml b/src/main/resources/api.yml index 0cb03b65..b358ab77 100644 --- a/src/main/resources/api.yml +++ b/src/main/resources/api.yml @@ -510,6 +510,8 @@ components: $ref: "schemas/openapi-schemas/ValueResult.yml" MarginResult: $ref: "schemas/openapi-schemas/MarginResult.yml" + RegularSettlementResult: + $ref: "schemas/openapi-schemas/RegularSettlementResult.yml" Error: $ref: "schemas/openapi-schemas/Error.yml" PlainSwapOperationResponse: @@ -518,6 +520,8 @@ components: $ref: "schemas/openapi-schemas/ValueRequest.yml" MarginRequest: $ref: "schemas/openapi-schemas/MarginRequest.yml" + RegularSettlementRequest: + $ref: "schemas/openapi-schemas/RegularSettlementRequest.yml" PlainSwapOperationRequest: $ref: "schemas/openapi-schemas/PlainSwapOperationRequest.yml" CashflowPeriod: diff --git a/src/main/resources/schemas/openapi-schemas/RegularSettlementRequest.yml b/src/main/resources/schemas/openapi-schemas/RegularSettlementRequest.yml new file mode 100644 index 00000000..d2424f82 --- /dev/null +++ b/src/main/resources/schemas/openapi-schemas/RegularSettlementRequest.yml @@ -0,0 +1,9 @@ +type: object +required: + - settlementLast + - tradeData +properties: + settlementLast: + type: string + tradeData: + type: string \ No newline at end of file diff --git a/src/main/resources/schemas/openapi-schemas/RegularSettlementResult.yml b/src/main/resources/schemas/openapi-schemas/RegularSettlementResult.yml new file mode 100644 index 00000000..b6af1e9f --- /dev/null +++ b/src/main/resources/schemas/openapi-schemas/RegularSettlementResult.yml @@ -0,0 +1,16 @@ +type: object +required: + - marginValue + - currency + - valuationDate + - generatedRegularSettlement +properties: + marginValue: + type: integer + format: int64 + currency: + type: string + valuationDate: + type: string + generatedRegularSettlement: + type: string \ No newline at end of file From 2e353ace96e9c51eb39a335a650110eeb439c762 Mon Sep 17 00:00:00 2001 From: Julius Lauterbach Date: Thu, 26 Sep 2024 11:29:21 +0200 Subject: [PATCH 06/51] SDC-626, mark writeDataSet as deprecated as it is not used anymore --- .../marketdata/generators/MarketDataGeneratorWebsocket.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/net/finmath/smartcontract/valuation/marketdata/generators/MarketDataGeneratorWebsocket.java b/src/main/java/net/finmath/smartcontract/valuation/marketdata/generators/MarketDataGeneratorWebsocket.java index 8a140757..315f0774 100644 --- a/src/main/java/net/finmath/smartcontract/valuation/marketdata/generators/MarketDataGeneratorWebsocket.java +++ b/src/main/java/net/finmath/smartcontract/valuation/marketdata/generators/MarketDataGeneratorWebsocket.java @@ -91,6 +91,7 @@ public void closeStreamsAndLogoff(WebSocket webSocket) { } + @Deprecated(forRemoval = true) public void writeDataset(String importDir, MarketDataList s, boolean isOvernightFixing) throws IOException { throw new RuntimeException("Not implemented"); /*String json = s.serializeToJson(); From 94888f1af5f3e8bd43ebd6c5a2da8ac19d76cb98 Mon Sep 17 00:00:00 2001 From: Julius Lauterbach Date: Thu, 26 Sep 2024 11:55:15 +0200 Subject: [PATCH 07/51] SDC-626, new config for marketdata provider --- src/main/resources/application.yml | 12 ++ .../service/config/RefinitivConfigTest.java | 136 ++++++++++++++++++ 2 files changed, 148 insertions(+) create mode 100644 src/test/java/net/finmath/smartcontract/valuation/service/config/RefinitivConfigTest.java diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index fcccd070..394ae5f8 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -52,3 +52,15 @@ storage: marketDataProviderConnectionPropertiesFile: '/config/market_data_connect.properties' databaseConnectionPropertiesFile: '/config/database_connect.properties' +refinitiv: + user: ${REFINITIV_USER} + password: ${REFINITIV_PASSWORD} + client-id: ${REFINITIV_CLIENT_ID} + host-name: ${REFINITIV_HOST_NAME} + port: 443 + auth-url: "https://api.refinitiv.com:443/auth/oauth2/v1/token" + use-proxy: "FALSE" + proxy-host: "" + proxy-port: 9400 + proxy-user: "" + proxy-password: "" \ No newline at end of file diff --git a/src/test/java/net/finmath/smartcontract/valuation/service/config/RefinitivConfigTest.java b/src/test/java/net/finmath/smartcontract/valuation/service/config/RefinitivConfigTest.java new file mode 100644 index 00000000..8c332dd5 --- /dev/null +++ b/src/test/java/net/finmath/smartcontract/valuation/service/config/RefinitivConfigTest.java @@ -0,0 +1,136 @@ +package net.finmath.smartcontract.valuation.service.config; + +import static org.junit.jupiter.api.Assertions.*; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +class RefinitivConfigTest { + private RefinitivConfig connectionDetails; + + @BeforeEach + public void setUp() { + connectionDetails = new RefinitivConfig(); + } + + @Test + void testGetUser() { + assertNull(connectionDetails.getUser()); + } + + @Test + void testSetUser() { + connectionDetails.setUser("testUser"); + assertEquals("testUser", connectionDetails.getUser()); + } + + @Test + void testGetPassword() { + assertNull(connectionDetails.getPassword()); + } + + @Test + void testSetPassword() { + connectionDetails.setPassword("testPassword"); + assertEquals("testPassword", connectionDetails.getPassword()); + } + + @Test + void testGetClientId() { + assertNull(connectionDetails.getClientId()); + } + + @Test + void testSetClientId() { + connectionDetails.setClientId("client123"); + assertEquals("client123", connectionDetails.getClientId()); + } + + @Test + void testGetHostName() { + assertNull(connectionDetails.getHostName()); + } + + @Test + void testSetHostName() { + connectionDetails.setHostName("localhost"); + assertEquals("localhost", connectionDetails.getHostName()); + } + + @Test + void testGetPort() { + assertEquals(0, connectionDetails.getPort()); + } + + @Test + void testSetPort() { + connectionDetails.setPort(8080); + assertEquals(8080, connectionDetails.getPort()); + } + + @Test + void testGetAuthUrl() { + assertNull(connectionDetails.getAuthUrl()); + } + + @Test + void testSetAuthUrl() { + connectionDetails.setAuthUrl("http://auth.example.com"); + assertEquals("http://auth.example.com", connectionDetails.getAuthUrl()); + } + + @Test + void testGetUseProxy() { + assertNull(connectionDetails.getUseProxy()); + } + + @Test + void testSetUseProxy() { + connectionDetails.setUseProxy("true"); + assertEquals("true", connectionDetails.getUseProxy()); + } + + @Test + void testGetProxyHost() { + assertNull(connectionDetails.getProxyHost()); + } + + @Test + void testSetProxyHost() { + connectionDetails.setProxyHost("proxy.example.com"); + assertEquals("proxy.example.com", connectionDetails.getProxyHost()); + } + + @Test + void testGetProxyPort() { + assertEquals(0, connectionDetails.getProxyPort()); + } + + @Test + void testSetProxyPort() { + connectionDetails.setProxyPort(8081); + assertEquals(8081, connectionDetails.getProxyPort()); + } + + @Test + void testGetProxyUser() { + assertNull(connectionDetails.getProxyUser()); + } + + @Test + void testSetProxyUser() { + connectionDetails.setProxyUser("proxyUser"); + assertEquals("proxyUser", connectionDetails.getProxyUser()); + } + + @Test + void testGetProxyPassword() { + assertNull(connectionDetails.getProxyPassword()); + } + + @Test + void testSetProxyPassword() { + connectionDetails.setProxyPassword("proxyPassword"); + assertEquals("proxyPassword", connectionDetails.getProxyPassword()); + } +} \ No newline at end of file From 0267bf87379a983114c80c948819c2f54cec3bf8 Mon Sep 17 00:00:00 2001 From: Julius Lauterbach Date: Thu, 26 Sep 2024 11:56:06 +0200 Subject: [PATCH 08/51] SDC-626, new config for marketdata provider --- .../service/config/RefinitivConfig.java | 109 ++++++++++++++++++ 1 file changed, 109 insertions(+) create mode 100644 src/main/java/net/finmath/smartcontract/valuation/service/config/RefinitivConfig.java diff --git a/src/main/java/net/finmath/smartcontract/valuation/service/config/RefinitivConfig.java b/src/main/java/net/finmath/smartcontract/valuation/service/config/RefinitivConfig.java new file mode 100644 index 00000000..c2ce6143 --- /dev/null +++ b/src/main/java/net/finmath/smartcontract/valuation/service/config/RefinitivConfig.java @@ -0,0 +1,109 @@ +package net.finmath.smartcontract.valuation.service.config; + +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Configuration; + + +@Configuration +@ConfigurationProperties(prefix = "refinitiv") +public class RefinitivConfig { + private String user; + private String password; + private String clientId; + private String hostName; + private int port; + private String authUrl; + private String useProxy; + private String proxyHost; + private int proxyPort; + private String proxyUser; + private String proxyPassword; + + public String getUser() { + return user; + } + + public void setUser(String user) { + this.user = user; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + public String getClientId() { + return clientId; + } + + public void setClientId(String clientId) { + this.clientId = clientId; + } + + public String getHostName() { + return hostName; + } + + public void setHostName(String hostName) { + this.hostName = hostName; + } + + public int getPort() { + return port; + } + + public void setPort(int port) { + this.port = port; + } + + public String getAuthUrl() { + return authUrl; + } + + public void setAuthUrl(String authUrl) { + this.authUrl = authUrl; + } + + public String getUseProxy() { + return useProxy; + } + + public void setUseProxy(String useProxy) { + this.useProxy = useProxy; + } + + public String getProxyHost() { + return proxyHost; + } + + public void setProxyHost(String proxyHost) { + this.proxyHost = proxyHost; + } + + public int getProxyPort() { + return proxyPort; + } + + public void setProxyPort(int proxyPort) { + this.proxyPort = proxyPort; + } + + public String getProxyUser() { + return proxyUser; + } + + public void setProxyUser(String proxyUser) { + this.proxyUser = proxyUser; + } + + public String getProxyPassword() { + return proxyPassword; + } + + public void setProxyPassword(String proxyPassword) { + this.proxyPassword = proxyPassword; + } +} From 6cb76f5643d46e167d2adc3838f89d10f317629b Mon Sep 17 00:00:00 2001 From: Julius Lauterbach Date: Thu, 26 Sep 2024 14:47:31 +0200 Subject: [PATCH 09/51] SDC-626, new generate-regular-settlement endpoint, new ExceptionId, new config for valuation --- .../smartcontract/model/ExceptionId.java | 1 + .../settlement/ZonedDateTimeAdapter.java | 2 - .../service/config/ValuationConfig.java | 37 +++++ .../controllers/SettlementController.java | 23 +++ .../service/utils/SDCAbstractRounding.java | 77 ++++++++++ .../valuation/service/utils/SDCRounding.java | 19 +++ .../service/utils/SettlementService.java | 142 ++++++++++++++++++ src/main/resources/api.yml | 24 +++ src/main/resources/application.yml | 4 + .../RegularSettlementResult.yml | 3 +- 10 files changed, 328 insertions(+), 4 deletions(-) create mode 100644 src/main/java/net/finmath/smartcontract/valuation/service/config/ValuationConfig.java create mode 100644 src/main/java/net/finmath/smartcontract/valuation/service/controllers/SettlementController.java create mode 100644 src/main/java/net/finmath/smartcontract/valuation/service/utils/SDCAbstractRounding.java create mode 100644 src/main/java/net/finmath/smartcontract/valuation/service/utils/SDCRounding.java create mode 100644 src/main/java/net/finmath/smartcontract/valuation/service/utils/SettlementService.java diff --git a/src/main/java/net/finmath/smartcontract/model/ExceptionId.java b/src/main/java/net/finmath/smartcontract/model/ExceptionId.java index 8314f611..c130da58 100644 --- a/src/main/java/net/finmath/smartcontract/model/ExceptionId.java +++ b/src/main/java/net/finmath/smartcontract/model/ExceptionId.java @@ -12,6 +12,7 @@ public enum ExceptionId { SDC_JAXB_ERROR, SDC_INVALID_TRADE_DATA, SDC_MARGIN_CALCULATION_ERROR, + SDC_VALUE_CALCULATION_ERROR, SDC_CALIBRATION_ERROR, SDC_CERTIFICATE_ERROR, SDC_FABRIC_GETALLPAYMENTS_ERROR, diff --git a/src/main/java/net/finmath/smartcontract/settlement/ZonedDateTimeAdapter.java b/src/main/java/net/finmath/smartcontract/settlement/ZonedDateTimeAdapter.java index 007476ef..50416cf1 100644 --- a/src/main/java/net/finmath/smartcontract/settlement/ZonedDateTimeAdapter.java +++ b/src/main/java/net/finmath/smartcontract/settlement/ZonedDateTimeAdapter.java @@ -2,7 +2,6 @@ import jakarta.xml.bind.annotation.adapters.XmlAdapter; -import java.text.ParseException; import java.time.LocalDateTime; import java.time.ZoneId; import java.time.ZonedDateTime; @@ -19,7 +18,6 @@ public String marshal(ZonedDateTime v) { public ZonedDateTime unmarshal(String str) { DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd-HHmmss"); LocalDateTime ldt = LocalDateTime.parse(str, formatter); - //return ZonedDateTime.parse(str, formatter); return ZonedDateTime.of(ldt, ZoneId.systemDefault()); } } \ No newline at end of file diff --git a/src/main/java/net/finmath/smartcontract/valuation/service/config/ValuationConfig.java b/src/main/java/net/finmath/smartcontract/valuation/service/config/ValuationConfig.java new file mode 100644 index 00000000..ce9d3608 --- /dev/null +++ b/src/main/java/net/finmath/smartcontract/valuation/service/config/ValuationConfig.java @@ -0,0 +1,37 @@ +package net.finmath.smartcontract.valuation.service.config; + +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Configuration; + + +@Configuration +@ConfigurationProperties(prefix = "valuation") +public class ValuationConfig { + private boolean liveMarketData; + private String settlementCurrency; + private String liveMarketDataProvider; + + public boolean isLiveMarketData() { + return liveMarketData; + } + + public void setLiveMarketData(boolean liveMarketData) { + this.liveMarketData = liveMarketData; + } + + public String getSettlementCurrency() { + return settlementCurrency; + } + + public void setSettlementCurrency(String settlementCurrency) { + this.settlementCurrency = settlementCurrency; + } + + public String getLiveMarketDataProvider() { + return liveMarketDataProvider; + } + + public void setLiveMarketDataProvider(String liveMarketDataProvider) { + this.liveMarketDataProvider = liveMarketDataProvider; + } +} diff --git a/src/main/java/net/finmath/smartcontract/valuation/service/controllers/SettlementController.java b/src/main/java/net/finmath/smartcontract/valuation/service/controllers/SettlementController.java new file mode 100644 index 00000000..5ee3181d --- /dev/null +++ b/src/main/java/net/finmath/smartcontract/valuation/service/controllers/SettlementController.java @@ -0,0 +1,23 @@ +package net.finmath.smartcontract.valuation.service.controllers; + +import net.finmath.smartcontract.api.SettlementApi; +import net.finmath.smartcontract.model.RegularSettlementRequest; +import net.finmath.smartcontract.model.RegularSettlementResult; +import net.finmath.smartcontract.valuation.service.utils.SettlementService; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.RestController; + +@RestController +public class SettlementController implements SettlementApi { + + private final SettlementService settlementService; + + public SettlementController(SettlementService settlementService) {this.settlementService = settlementService;} + + @Override + public ResponseEntity generateRegularSettlementResult(RegularSettlementRequest regularSettlementRequest) { + RegularSettlementResult regularSettlementResult = settlementService.generateRegularSettlementResult(regularSettlementRequest); + return ResponseEntity.ok(regularSettlementResult); + } + +} diff --git a/src/main/java/net/finmath/smartcontract/valuation/service/utils/SDCAbstractRounding.java b/src/main/java/net/finmath/smartcontract/valuation/service/utils/SDCAbstractRounding.java new file mode 100644 index 00000000..266f13b7 --- /dev/null +++ b/src/main/java/net/finmath/smartcontract/valuation/service/utils/SDCAbstractRounding.java @@ -0,0 +1,77 @@ +/** + * SDC Project + * + * @author Dietmar Schnabel + * + * This class implements some number rounding according to business conventions. + * + */ + package net.finmath.smartcontract.valuation.service.utils; + +import java.math.BigDecimal; +import java.math.RoundingMode; + +/** + * The Class SDCAbstractRounding + *

+ * Contains general rounding methods, as well as converting to strings. + */ +public abstract class SDCAbstractRounding { + + protected int scale; + protected RoundingMode roundingMode; + + private BigDecimal round(double variable) { + String s = Double.toString(variable); + return new BigDecimal(s).setScale(scale, roundingMode); + } + + /** + * Round double. + * + * @param variable the double var + * @return the rounded double + */ + public double roundDouble(double variable) { + return round(variable).doubleValue(); + } + + private String getAsIntString(BigDecimal variable) { + String margin = variable.toString(); + return margin.replace(".",""); + } + + /** + * Returns an integer value, the double left shifted + * + * @param variable the double var + * @return the double as integer string + */ + public String getRoundedValueAsIntegerString(double variable) { + BigDecimal x = round(variable); + return getAsIntString(x); + } + + /** + * Gets the double from the left shifted integer String + * + * @param s the integer string + * @return the double + */ + public double getDoubleFromIntegerString(String s) { + String sf = null; + + if (s.length()==1) { + sf = "0.0" + s; //TODO introduce scale + } else if (s.length()==2) { + sf = "0." + s; + } else { + int i1 = s.length() - scale -1; + int i2 = s.length() -1; + sf = s.substring(0,i1+1) + "." + s.substring(i1+1,i2+1); + } + + double x = Double.parseDouble(sf); + return roundDouble(x); + } +} diff --git a/src/main/java/net/finmath/smartcontract/valuation/service/utils/SDCRounding.java b/src/main/java/net/finmath/smartcontract/valuation/service/utils/SDCRounding.java new file mode 100644 index 00000000..ec368895 --- /dev/null +++ b/src/main/java/net/finmath/smartcontract/valuation/service/utils/SDCRounding.java @@ -0,0 +1,19 @@ +package net.finmath.smartcontract.valuation.service.utils; + +import java.math.RoundingMode; +/** + * The Class SDCRounding. + *

+ * Concrete implementation of the SDCAbstractRounding class. + * Will be currency dependent. + * */ +public class SDCRounding extends SDCAbstractRounding { + + private SDCRounding() { } + + public SDCRounding(int sc, RoundingMode rc) { + scale = sc; + roundingMode = rc; + } + +} diff --git a/src/main/java/net/finmath/smartcontract/valuation/service/utils/SettlementService.java b/src/main/java/net/finmath/smartcontract/valuation/service/utils/SettlementService.java new file mode 100644 index 00000000..ff07bcf2 --- /dev/null +++ b/src/main/java/net/finmath/smartcontract/valuation/service/utils/SettlementService.java @@ -0,0 +1,142 @@ +package net.finmath.smartcontract.valuation.service.utils; + +import net.finmath.smartcontract.model.*; +import net.finmath.smartcontract.product.SmartDerivativeContractDescriptor; +import net.finmath.smartcontract.product.xml.SDCXMLParser; +import net.finmath.smartcontract.settlement.Settlement; +import net.finmath.smartcontract.settlement.SettlementGenerator; +import net.finmath.smartcontract.valuation.implementation.MarginCalculator; +import net.finmath.smartcontract.valuation.marketdata.generators.MarketDataGeneratorLauncher; +import net.finmath.smartcontract.valuation.marketdata.generators.MarketDataGeneratorScenarioList; +import net.finmath.smartcontract.valuation.service.config.RefinitivConfig; +import net.finmath.smartcontract.valuation.service.config.ValuationConfig; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Service; +import org.xml.sax.SAXException; + +import javax.xml.parsers.ParserConfigurationException; +import java.io.IOException; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.time.ZonedDateTime; +import java.time.format.DateTimeFormatter; +import java.util.Properties; +import java.util.concurrent.atomic.AtomicReference; + +@Service +public class SettlementService { + private static final Logger logger = LoggerFactory.getLogger(SettlementService.class); + + private final MarginCalculator marginCalculator = new MarginCalculator(); + + private final RefinitivConfig refinitivConfig; + private final ValuationConfig valuationConfig; + + public SettlementService(RefinitivConfig refinitivConfig, ValuationConfig valuationConfig) { + this.refinitivConfig = refinitivConfig; + this.valuationConfig = valuationConfig; + } + + public RegularSettlementResult generateRegularSettlementResult(RegularSettlementRequest regularSettlementRequest) { + + SmartDerivativeContractDescriptor sdc = parseProductData(regularSettlementRequest); + MarketDataList newMarketDataList = retrieveMarketData(sdc); + String newMarketDataString = SDCXMLParser.marshalClassToXMLString(newMarketDataList); + Settlement settlementLast = SDCXMLParser.unmarshalXml(regularSettlementRequest.getSettlementLast(), Settlement.class); + String marketDataLastString = SDCXMLParser.marshalClassToXMLString(settlementLast.getMarketData()); + + ZonedDateTime settlementTimeNext = ZonedDateTime.now().plusDays(1); + + ValueResult settlementValueNext = getValuationValueAtTime( + newMarketDataString, regularSettlementRequest.getTradeData(), settlementTimeNext.toLocalDateTime()); + + BigDecimal margin = getMargin(marketDataLastString, newMarketDataString, regularSettlementRequest.getTradeData()); + + Settlement newSettlement = new SettlementGenerator() + .generateRegularSettlementXml( + newMarketDataString, + sdc, + margin) + .marginLimits(settlementLast.getMarginLimits()) + .settlementValue(getValue(newMarketDataString, regularSettlementRequest.getTradeData())) + .settlementValuePrevious(settlementLast.getSettlementValue()) + .settlementTimeNext(settlementTimeNext) + .settlementValueNext(settlementValueNext.getValue()) + .buildObject(); + + return new RegularSettlementResult() + .generatedRegularSettlement(SDCXMLParser.marshalClassToXMLString(newSettlement)) + .currency(valuationConfig.getSettlementCurrency()) + .marginValue(margin) + .valuationDate(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMdd-HHmmss"))); + } + + private static SmartDerivativeContractDescriptor parseProductData(RegularSettlementRequest regularSettlementRequest) { + try { + return SDCXMLParser.parse(regularSettlementRequest.getTradeData()); + } catch (ParserConfigurationException | IOException | SAXException e) { + logger.error("error parsing product data ", e); + throw new SDCException(ExceptionId.SDC_XML_PARSE_ERROR, "product data format incorrect, could not parse xml", 400); + } + } + + private MarketDataList retrieveMarketData(SmartDerivativeContractDescriptor sdc) { + AtomicReference marketDataList = new AtomicReference<>(new MarketDataList()); + + if (sdc.getMarketDataProvider().equals(valuationConfig.getLiveMarketDataProvider()) && valuationConfig.isLiveMarketData()) { + marketDataList.set(MarketDataGeneratorLauncher.instantiateMarketDataGeneratorWebsocket(initConnectionProperties(), sdc)); + } else { + //includes provider internal or no liveMarketData activated + final io.reactivex.rxjava3.functions.Consumer marketDataWriter = marketDataList::set; + MarketDataGeneratorScenarioList marketDataServiceScenarioList = new MarketDataGeneratorScenarioList(); + marketDataServiceScenarioList.asObservable().subscribe(marketDataWriter, //onNext + throwable -> logger.error("unable to generate marketData from files ", throwable), //onError + () -> logger.info("on complete, simulated marketData generated from files")); //onComplete + } + return marketDataList.get(); + } + + private Properties initConnectionProperties() { + Properties connectionProperties = new Properties(); + connectionProperties.put("USER", refinitivConfig.getUser()); + connectionProperties.put("PASSWORD", refinitivConfig.getPassword()); + connectionProperties.put("CLIENTID", refinitivConfig.getClientId()); + connectionProperties.put("HOSTNAME", refinitivConfig.getHostName()); + connectionProperties.put("PORT", refinitivConfig.getPort()); + connectionProperties.put("AUTHURL", refinitivConfig.getAuthUrl()); + connectionProperties.put("USEPROXY", refinitivConfig.getUseProxy()); + connectionProperties.put("PROXYHOST", refinitivConfig.getProxyHost()); + connectionProperties.put("PROXYPORT", refinitivConfig.getProxyPort()); + connectionProperties.put("PROXYUSER", refinitivConfig.getProxyUser()); + connectionProperties.put("PROXYPASS", refinitivConfig.getProxyPassword()); + + return connectionProperties; + } + + private ValueResult getValuationValueAtTime(String marketData, String tradeData, LocalDateTime valuationDate){ + try { + return marginCalculator.getValueAtEvaluationTime(marketData, tradeData, valuationDate); + } catch (Exception e) { + logger.error("unable to get valueAtTime for market data ", e); + throw new SDCException(ExceptionId.SDC_VALUE_CALCULATION_ERROR, "error in MarginCalculator getValueAtTime"); } + } + + private BigDecimal getValue(String marketData, String tradeData){ + try { + return marginCalculator.getValue(marketData, tradeData).getValue(); + } catch (Exception e) { + logger.error("unable to get value for market data ", e); + throw new SDCException(ExceptionId.SDC_VALUE_CALCULATION_ERROR, "error in MarginCalculator getValue"); + } + } + + private BigDecimal getMargin(String marketDataStart, String marketDataEnd, String tradeData){ + try { + return marginCalculator.getValue(marketDataStart, marketDataEnd, tradeData).getValue(); + } catch (Exception e) { + logger.error("unable to get margin for market data ", e); + throw new SDCException(ExceptionId.SDC_VALUE_CALCULATION_ERROR, "error in MarginCalculator getMargin"); + } + } +} diff --git a/src/main/resources/api.yml b/src/main/resources/api.yml index b358ab77..325ceecc 100644 --- a/src/main/resources/api.yml +++ b/src/main/resources/api.yml @@ -504,6 +504,30 @@ paths: schema: $ref: "#/components/schemas/Error" + + /settlement/generate-regular-settlement: + post: + summary: generate a regular settlement xml based on given settlement and product xml + operationId: generateRegularSettlementResult + requestBody: + content: + application/json: + schema: + $ref: "#/components/schemas/RegularSettlementRequest" + responses: + "200": + description: regular settlement xml was created + content: + application/json: + schema: + $ref: "#/components/schemas/RegularSettlementResult" + default: + description: unexpected error + content: + application/json: + schema: + $ref: "#/components/schemas/Error" + components: schemas: ValueResult: diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 394ae5f8..62ea7c4f 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -52,6 +52,10 @@ storage: marketDataProviderConnectionPropertiesFile: '/config/market_data_connect.properties' databaseConnectionPropertiesFile: '/config/database_connect.properties' +valuation: + live-marketdata: false + settlement-currency: "EUR" + refinitiv: user: ${REFINITIV_USER} password: ${REFINITIV_PASSWORD} diff --git a/src/main/resources/schemas/openapi-schemas/RegularSettlementResult.yml b/src/main/resources/schemas/openapi-schemas/RegularSettlementResult.yml index b6af1e9f..eda885a2 100644 --- a/src/main/resources/schemas/openapi-schemas/RegularSettlementResult.yml +++ b/src/main/resources/schemas/openapi-schemas/RegularSettlementResult.yml @@ -6,8 +6,7 @@ required: - generatedRegularSettlement properties: marginValue: - type: integer - format: int64 + type: number currency: type: string valuationDate: From 558f0ef9c657d729f60fe2eb6456a9680bd6471a Mon Sep 17 00:00:00 2001 From: Julius Lauterbach Date: Thu, 26 Sep 2024 16:54:40 +0200 Subject: [PATCH 10/51] SDC-626, new endpoint yml and models --- src/main/resources/api.yml | 26 +++++++++++++++++++ .../InitialSettlementRequest.yml | 6 +++++ .../InitialSettlementResult.yml | 15 +++++++++++ 3 files changed, 47 insertions(+) create mode 100644 src/main/resources/schemas/openapi-schemas/InitialSettlementRequest.yml create mode 100644 src/main/resources/schemas/openapi-schemas/InitialSettlementResult.yml diff --git a/src/main/resources/api.yml b/src/main/resources/api.yml index 325ceecc..a13c7821 100644 --- a/src/main/resources/api.yml +++ b/src/main/resources/api.yml @@ -528,6 +528,28 @@ paths: schema: $ref: "#/components/schemas/Error" + /settlement/generate-initial-settlement: + post: + summary: generate an initial settlement xml based on given product xml + operationId: generateInitialSettlementResult + requestBody: + content: + application/json: + schema: + $ref: "#/components/schemas/InitialSettlementRequest" + responses: + "200": + description: initial settlement xml was created + content: + application/json: + schema: + $ref: "#/components/schemas/InitialSettlementResult" + default: + description: unexpected error + content: + application/json: + schema: + $ref: "#/components/schemas/Error" components: schemas: ValueResult: @@ -536,6 +558,8 @@ components: $ref: "schemas/openapi-schemas/MarginResult.yml" RegularSettlementResult: $ref: "schemas/openapi-schemas/RegularSettlementResult.yml" + InitialSettlementResult: + $ref: "schemas/openapi-schemas/InitialSettlementResult.yml" Error: $ref: "schemas/openapi-schemas/Error.yml" PlainSwapOperationResponse: @@ -546,6 +570,8 @@ components: $ref: "schemas/openapi-schemas/MarginRequest.yml" RegularSettlementRequest: $ref: "schemas/openapi-schemas/RegularSettlementRequest.yml" + InitialSettlementRequest: + $ref: "schemas/openapi-schemas/InitialSettlementRequest.yml" PlainSwapOperationRequest: $ref: "schemas/openapi-schemas/PlainSwapOperationRequest.yml" CashflowPeriod: diff --git a/src/main/resources/schemas/openapi-schemas/InitialSettlementRequest.yml b/src/main/resources/schemas/openapi-schemas/InitialSettlementRequest.yml new file mode 100644 index 00000000..e2f28376 --- /dev/null +++ b/src/main/resources/schemas/openapi-schemas/InitialSettlementRequest.yml @@ -0,0 +1,6 @@ +type: object +required: + - tradeData +properties: + tradeData: + type: string \ No newline at end of file diff --git a/src/main/resources/schemas/openapi-schemas/InitialSettlementResult.yml b/src/main/resources/schemas/openapi-schemas/InitialSettlementResult.yml new file mode 100644 index 00000000..62bb74a8 --- /dev/null +++ b/src/main/resources/schemas/openapi-schemas/InitialSettlementResult.yml @@ -0,0 +1,15 @@ +type: object +required: + - marginValue + - currency + - valuationDate + - generatedInitialSettlement +properties: + marginValue: + type: number + currency: + type: string + valuationDate: + type: string + generatedInitialSettlement: + type: string \ No newline at end of file From 34c7423c4de7479d81479dc5d7d65685e3bf804f Mon Sep 17 00:00:00 2001 From: Julius Lauterbach Date: Thu, 26 Sep 2024 16:56:17 +0200 Subject: [PATCH 11/51] SDC-626, new endpoint for initial settlement generation, new ExceptionId --- .../smartcontract/model/ExceptionId.java | 1 + .../controllers/SettlementController.java | 7 +++ .../service/utils/SettlementService.java | 46 ++++++++++++++++--- 3 files changed, 48 insertions(+), 6 deletions(-) diff --git a/src/main/java/net/finmath/smartcontract/model/ExceptionId.java b/src/main/java/net/finmath/smartcontract/model/ExceptionId.java index c130da58..8c68533f 100644 --- a/src/main/java/net/finmath/smartcontract/model/ExceptionId.java +++ b/src/main/java/net/finmath/smartcontract/model/ExceptionId.java @@ -13,6 +13,7 @@ public enum ExceptionId { SDC_INVALID_TRADE_DATA, SDC_MARGIN_CALCULATION_ERROR, SDC_VALUE_CALCULATION_ERROR, + SDC_VALUATION_HTTP_ERROR, SDC_CALIBRATION_ERROR, SDC_CERTIFICATE_ERROR, SDC_FABRIC_GETALLPAYMENTS_ERROR, diff --git a/src/main/java/net/finmath/smartcontract/valuation/service/controllers/SettlementController.java b/src/main/java/net/finmath/smartcontract/valuation/service/controllers/SettlementController.java index 5ee3181d..219ac72d 100644 --- a/src/main/java/net/finmath/smartcontract/valuation/service/controllers/SettlementController.java +++ b/src/main/java/net/finmath/smartcontract/valuation/service/controllers/SettlementController.java @@ -1,6 +1,8 @@ package net.finmath.smartcontract.valuation.service.controllers; import net.finmath.smartcontract.api.SettlementApi; +import net.finmath.smartcontract.model.InitialSettlementRequest; +import net.finmath.smartcontract.model.InitialSettlementResult; import net.finmath.smartcontract.model.RegularSettlementRequest; import net.finmath.smartcontract.model.RegularSettlementResult; import net.finmath.smartcontract.valuation.service.utils.SettlementService; @@ -20,4 +22,9 @@ public ResponseEntity generateRegularSettlementResult(R return ResponseEntity.ok(regularSettlementResult); } + @Override + public ResponseEntity generateInitialSettlementResult(InitialSettlementRequest initialSettlementRequest) { + InitialSettlementResult initialSettlementResult = settlementService.generateInitialSettlementResult(initialSettlementRequest); + return ResponseEntity.ok(initialSettlementResult); + } } diff --git a/src/main/java/net/finmath/smartcontract/valuation/service/utils/SettlementService.java b/src/main/java/net/finmath/smartcontract/valuation/service/utils/SettlementService.java index ff07bcf2..811c6499 100644 --- a/src/main/java/net/finmath/smartcontract/valuation/service/utils/SettlementService.java +++ b/src/main/java/net/finmath/smartcontract/valuation/service/utils/SettlementService.java @@ -21,6 +21,8 @@ import java.time.LocalDateTime; import java.time.ZonedDateTime; import java.time.format.DateTimeFormatter; +import java.util.ArrayList; +import java.util.List; import java.util.Properties; import java.util.concurrent.atomic.AtomicReference; @@ -40,7 +42,7 @@ public SettlementService(RefinitivConfig refinitivConfig, ValuationConfig valuat public RegularSettlementResult generateRegularSettlementResult(RegularSettlementRequest regularSettlementRequest) { - SmartDerivativeContractDescriptor sdc = parseProductData(regularSettlementRequest); + SmartDerivativeContractDescriptor sdc = parseProductData(regularSettlementRequest.getTradeData()); MarketDataList newMarketDataList = retrieveMarketData(sdc); String newMarketDataString = SDCXMLParser.marshalClassToXMLString(newMarketDataList); Settlement settlementLast = SDCXMLParser.unmarshalXml(regularSettlementRequest.getSettlementLast(), Settlement.class); @@ -53,7 +55,7 @@ public RegularSettlementResult generateRegularSettlementResult(RegularSettlement BigDecimal margin = getMargin(marketDataLastString, newMarketDataString, regularSettlementRequest.getTradeData()); - Settlement newSettlement = new SettlementGenerator() + String newSettlement = new SettlementGenerator() .generateRegularSettlementXml( newMarketDataString, sdc, @@ -63,18 +65,50 @@ public RegularSettlementResult generateRegularSettlementResult(RegularSettlement .settlementValuePrevious(settlementLast.getSettlementValue()) .settlementTimeNext(settlementTimeNext) .settlementValueNext(settlementValueNext.getValue()) - .buildObject(); + .build(); return new RegularSettlementResult() - .generatedRegularSettlement(SDCXMLParser.marshalClassToXMLString(newSettlement)) + .generatedRegularSettlement(newSettlement) .currency(valuationConfig.getSettlementCurrency()) .marginValue(margin) .valuationDate(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMdd-HHmmss"))); } - private static SmartDerivativeContractDescriptor parseProductData(RegularSettlementRequest regularSettlementRequest) { + public InitialSettlementResult generateInitialSettlementResult(InitialSettlementRequest initialSettlementRequest) { + + SmartDerivativeContractDescriptor sdc = parseProductData(initialSettlementRequest.getTradeData()); + MarketDataList newMarketDataList = retrieveMarketData(sdc); + String newMarketDataString = SDCXMLParser.marshalClassToXMLString(newMarketDataList); + + ZonedDateTime settlementTimeNext = ZonedDateTime.now().plusDays(1); + + ValueResult settlementValueNext = getValuationValueAtTime( + newMarketDataString, initialSettlementRequest.getTradeData(), settlementTimeNext.toLocalDateTime()); + + List marginLimits = new ArrayList<>(); + sdc.getCounterparties().forEach(party -> marginLimits.add(BigDecimal.valueOf(sdc.getMarginAccount(party.getId())))); + + String newSettlement = new SettlementGenerator() + .generateInitialSettlementXml(newMarketDataString, sdc) + .marginLimits(marginLimits) + .settlementValue(getValue(newMarketDataString, initialSettlementRequest.getTradeData())) + //.settlementValuePrevious(BigDecimal.ZERO) + .settlementTimeNext(settlementTimeNext) + .settlementValueNext(settlementValueNext.getValue()) + .build(); + + return new InitialSettlementResult() + .generatedInitialSettlement(newSettlement) + .currency(valuationConfig.getSettlementCurrency()) + .marginValue(BigDecimal.ZERO) + .valuationDate(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMdd-HHmmss"))); + } + + + + private static SmartDerivativeContractDescriptor parseProductData(String tradeData) { try { - return SDCXMLParser.parse(regularSettlementRequest.getTradeData()); + return SDCXMLParser.parse(tradeData); } catch (ParserConfigurationException | IOException | SAXException e) { logger.error("error parsing product data ", e); throw new SDCException(ExceptionId.SDC_XML_PARSE_ERROR, "product data format incorrect, could not parse xml", 400); From ed38fc435355edf3545d9b6e3b6721ad74504358 Mon Sep 17 00:00:00 2001 From: Julius Lauterbach Date: Thu, 26 Sep 2024 17:28:28 +0200 Subject: [PATCH 12/51] SDC-626, new SettlementControllerTest, increased logging for SettlementController --- .../controllers/SettlementController.java | 5 + .../controllers/SettlementControllerTest.java | 94 +++++++++++++++++++ 2 files changed, 99 insertions(+) create mode 100644 src/test/java/net/finmath/smartcontract/valuation/service/controllers/SettlementControllerTest.java diff --git a/src/main/java/net/finmath/smartcontract/valuation/service/controllers/SettlementController.java b/src/main/java/net/finmath/smartcontract/valuation/service/controllers/SettlementController.java index 219ac72d..b618e07f 100644 --- a/src/main/java/net/finmath/smartcontract/valuation/service/controllers/SettlementController.java +++ b/src/main/java/net/finmath/smartcontract/valuation/service/controllers/SettlementController.java @@ -6,24 +6,29 @@ import net.finmath.smartcontract.model.RegularSettlementRequest; import net.finmath.smartcontract.model.RegularSettlementResult; import net.finmath.smartcontract.valuation.service.utils.SettlementService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.RestController; @RestController public class SettlementController implements SettlementApi { + private static final Logger logger = LoggerFactory.getLogger(SettlementController.class); private final SettlementService settlementService; public SettlementController(SettlementService settlementService) {this.settlementService = settlementService;} @Override public ResponseEntity generateRegularSettlementResult(RegularSettlementRequest regularSettlementRequest) { + logger.info("Generating regular settlement result, generateRegularSettlementResult"); RegularSettlementResult regularSettlementResult = settlementService.generateRegularSettlementResult(regularSettlementRequest); return ResponseEntity.ok(regularSettlementResult); } @Override public ResponseEntity generateInitialSettlementResult(InitialSettlementRequest initialSettlementRequest) { + logger.info("Generating initial settlement result, generateInitialSettlementResult"); InitialSettlementResult initialSettlementResult = settlementService.generateInitialSettlementResult(initialSettlementRequest); return ResponseEntity.ok(initialSettlementResult); } diff --git a/src/test/java/net/finmath/smartcontract/valuation/service/controllers/SettlementControllerTest.java b/src/test/java/net/finmath/smartcontract/valuation/service/controllers/SettlementControllerTest.java new file mode 100644 index 00000000..f2a18333 --- /dev/null +++ b/src/test/java/net/finmath/smartcontract/valuation/service/controllers/SettlementControllerTest.java @@ -0,0 +1,94 @@ +package net.finmath.smartcontract.valuation.service.controllers; + +import com.google.gson.Gson; +import net.finmath.smartcontract.model.InitialSettlementRequest; +import net.finmath.smartcontract.model.InitialSettlementResult; +import net.finmath.smartcontract.model.RegularSettlementRequest; +import net.finmath.smartcontract.model.RegularSettlementResult; +import net.finmath.smartcontract.valuation.service.Application; +import net.finmath.smartcontract.valuation.service.config.BasicAuthWebSecurityConfiguration; +import net.finmath.smartcontract.valuation.service.config.MockUserAuthConfig; +import net.finmath.smartcontract.valuation.service.utils.SettlementService; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestInstance; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.http.MediaType; +import org.springframework.security.test.context.support.WithUserDetails; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit.jupiter.SpringExtension; +import org.springframework.test.web.servlet.MockMvc; + +import static org.hamcrest.Matchers.containsString; +import static org.mockito.Mockito.when; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +@ExtendWith(SpringExtension.class) +@SpringBootTest(classes = {SettlementController.class, Application.class}, + webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT +) +@AutoConfigureMockMvc +@ContextConfiguration(classes = {BasicAuthWebSecurityConfiguration.class, Application.class, MockUserAuthConfig.class}) +@TestInstance(TestInstance.Lifecycle.PER_CLASS) +class SettlementControllerTest { + + @Autowired + private MockMvc mockMvc; + + @MockBean + private SettlementService settlementService; + + @Test + @WithUserDetails("user1") + void generateRegularSettlementResult() throws Exception { + String mockSettlement = "testSettlement"; + + RegularSettlementRequest request = new RegularSettlementRequest() + .settlementLast("settle") + .tradeData("tradeData"); + Gson gson = new Gson(); + String jsonRequest = gson.toJson(request); + RegularSettlementResult result = new RegularSettlementResult().generatedRegularSettlement(mockSettlement); + + when(this.settlementService.generateRegularSettlementResult(request)).thenReturn(result); + + this.mockMvc + .perform( + post("/settlement/generate-regular-settlement") + .contentType(MediaType.APPLICATION_JSON) + .accept(MediaType.APPLICATION_JSON) + .content(jsonRequest) + ) + .andExpect(status().isOk()) + .andExpect(content().string(containsString(mockSettlement))); + } + + @Test + @WithUserDetails("user1") + void generateInitialSettlementResult() throws Exception { + String mockSettlement = "testSettlement"; + + InitialSettlementRequest request = new InitialSettlementRequest() + .tradeData("tradeData"); + Gson gson = new Gson(); + String jsonRequest = gson.toJson(request); + InitialSettlementResult result = new InitialSettlementResult().generatedInitialSettlement(mockSettlement); + + when(this.settlementService.generateInitialSettlementResult(request)).thenReturn(result); + + this.mockMvc + .perform( + post("/settlement/generate-initial-settlement") + .contentType(MediaType.APPLICATION_JSON) + .accept(MediaType.APPLICATION_JSON) + .content(jsonRequest) + ) + .andExpect(status().isOk()) + .andExpect(content().string(containsString(mockSettlement))); + } +} \ No newline at end of file From e2b122ce2c8a1b617153e62e419c98f426b705d4 Mon Sep 17 00:00:00 2001 From: Julius Lauterbach Date: Thu, 26 Sep 2024 17:51:48 +0200 Subject: [PATCH 13/51] SDC-626, added gson to pom --- pom.xml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/pom.xml b/pom.xml index c8907869..5f3c801c 100644 --- a/pom.xml +++ b/pom.xml @@ -322,6 +322,12 @@ slf4j-api 2.0.7 + + + com.google.code.gson + gson + 2.11.0 + From a46a9e130694f76f7b4382f82ecf3e3225932864 Mon Sep 17 00:00:00 2001 From: Julius Lauterbach Date: Thu, 26 Sep 2024 18:08:47 +0200 Subject: [PATCH 14/51] SDC-626, added try catch and exception if refinitiv properties not set --- .../service/utils/SettlementService.java | 43 +++++++++++-------- .../service/utils/SettlementServiceTest.java | 40 +++++++++++++++++ 2 files changed, 64 insertions(+), 19 deletions(-) create mode 100644 src/test/java/net/finmath/smartcontract/valuation/service/utils/SettlementServiceTest.java diff --git a/src/main/java/net/finmath/smartcontract/valuation/service/utils/SettlementService.java b/src/main/java/net/finmath/smartcontract/valuation/service/utils/SettlementService.java index 811c6499..73ef443f 100644 --- a/src/main/java/net/finmath/smartcontract/valuation/service/utils/SettlementService.java +++ b/src/main/java/net/finmath/smartcontract/valuation/service/utils/SettlementService.java @@ -105,7 +105,6 @@ public InitialSettlementResult generateInitialSettlementResult(InitialSettlement } - private static SmartDerivativeContractDescriptor parseProductData(String tradeData) { try { return SDCXMLParser.parse(tradeData); @@ -132,31 +131,37 @@ private MarketDataList retrieveMarketData(SmartDerivativeContractDescriptor sdc) } private Properties initConnectionProperties() { - Properties connectionProperties = new Properties(); - connectionProperties.put("USER", refinitivConfig.getUser()); - connectionProperties.put("PASSWORD", refinitivConfig.getPassword()); - connectionProperties.put("CLIENTID", refinitivConfig.getClientId()); - connectionProperties.put("HOSTNAME", refinitivConfig.getHostName()); - connectionProperties.put("PORT", refinitivConfig.getPort()); - connectionProperties.put("AUTHURL", refinitivConfig.getAuthUrl()); - connectionProperties.put("USEPROXY", refinitivConfig.getUseProxy()); - connectionProperties.put("PROXYHOST", refinitivConfig.getProxyHost()); - connectionProperties.put("PROXYPORT", refinitivConfig.getProxyPort()); - connectionProperties.put("PROXYUSER", refinitivConfig.getProxyUser()); - connectionProperties.put("PROXYPASS", refinitivConfig.getProxyPassword()); - - return connectionProperties; + try { + Properties connectionProperties = new Properties(); + connectionProperties.put("USER", refinitivConfig.getUser()); + connectionProperties.put("PASSWORD", refinitivConfig.getPassword()); + connectionProperties.put("CLIENTID", refinitivConfig.getClientId()); + connectionProperties.put("HOSTNAME", refinitivConfig.getHostName()); + connectionProperties.put("PORT", refinitivConfig.getPort()); + connectionProperties.put("AUTHURL", refinitivConfig.getAuthUrl()); + connectionProperties.put("USEPROXY", refinitivConfig.getUseProxy()); + connectionProperties.put("PROXYHOST", refinitivConfig.getProxyHost()); + connectionProperties.put("PROXYPORT", refinitivConfig.getProxyPort()); + connectionProperties.put("PROXYUSER", refinitivConfig.getProxyUser()); + connectionProperties.put("PROXYPASS", refinitivConfig.getProxyPassword()); + + return connectionProperties; + } catch (NullPointerException e) { + logger.error("refinitiv connection properties not set", e); + throw new SDCException(ExceptionId.SDC_NO_DATA_FOUND, "missing connection properties", 400); + } } - private ValueResult getValuationValueAtTime(String marketData, String tradeData, LocalDateTime valuationDate){ + private ValueResult getValuationValueAtTime(String marketData, String tradeData, LocalDateTime valuationDate) { try { return marginCalculator.getValueAtEvaluationTime(marketData, tradeData, valuationDate); } catch (Exception e) { logger.error("unable to get valueAtTime for market data ", e); - throw new SDCException(ExceptionId.SDC_VALUE_CALCULATION_ERROR, "error in MarginCalculator getValueAtTime"); } + throw new SDCException(ExceptionId.SDC_VALUE_CALCULATION_ERROR, "error in MarginCalculator getValueAtTime"); + } } - private BigDecimal getValue(String marketData, String tradeData){ + private BigDecimal getValue(String marketData, String tradeData) { try { return marginCalculator.getValue(marketData, tradeData).getValue(); } catch (Exception e) { @@ -165,7 +170,7 @@ private BigDecimal getValue(String marketData, String tradeData){ } } - private BigDecimal getMargin(String marketDataStart, String marketDataEnd, String tradeData){ + private BigDecimal getMargin(String marketDataStart, String marketDataEnd, String tradeData) { try { return marginCalculator.getValue(marketDataStart, marketDataEnd, tradeData).getValue(); } catch (Exception e) { diff --git a/src/test/java/net/finmath/smartcontract/valuation/service/utils/SettlementServiceTest.java b/src/test/java/net/finmath/smartcontract/valuation/service/utils/SettlementServiceTest.java new file mode 100644 index 00000000..c0ee8425 --- /dev/null +++ b/src/test/java/net/finmath/smartcontract/valuation/service/utils/SettlementServiceTest.java @@ -0,0 +1,40 @@ +package net.finmath.smartcontract.valuation.service.utils; + +import net.finmath.smartcontract.model.InitialSettlementRequest; +import net.finmath.smartcontract.model.SDCException; +import net.finmath.smartcontract.valuation.service.config.ValuationConfig; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.junit.jupiter.MockitoExtension; + +import java.io.IOException; +import java.io.InputStream; + +import static org.junit.jupiter.api.Assertions.*; + +@ExtendWith(MockitoExtension.class) +class SettlementServiceTest { + + @InjectMocks + private SettlementService serviceUnderTest; + + @Mock + private ValuationConfig valuationConfig; + + @Test + void generateInitialSettlement_Exception_missingRefinitvConfig() throws IOException { + InputStream inputStream = SettlementServiceTest.class.getClassLoader().getResourceAsStream("net.finmath.smartcontract.product.xml/smartderivativecontract_with_rics.xml"); + String productXml = new String(inputStream.readAllBytes()); + + InitialSettlementRequest initialSettlementRequest = new InitialSettlementRequest().tradeData(productXml); + + Mockito.when(valuationConfig.getLiveMarketDataProvider()).thenReturn("refinitiv"); + Mockito.when(valuationConfig.isLiveMarketData()).thenReturn(true); + + assertThrows(SDCException.class, () -> serviceUnderTest.generateInitialSettlementResult(initialSettlementRequest)); + } + +} \ No newline at end of file From 073b6ac030139ea4eaf5bc5c1e0a7ab3c1729976 Mon Sep 17 00:00:00 2001 From: Julius Lauterbach Date: Fri, 27 Sep 2024 17:03:34 +0200 Subject: [PATCH 15/51] SDC-626, new static html page, small change in SettlementService --- .../service/utils/SettlementService.java | 3 +- .../static/generate-initial-settlement.html | 133 ++++++++++++++++++ 2 files changed, 135 insertions(+), 1 deletion(-) create mode 100644 src/main/resources/static/generate-initial-settlement.html diff --git a/src/main/java/net/finmath/smartcontract/valuation/service/utils/SettlementService.java b/src/main/java/net/finmath/smartcontract/valuation/service/utils/SettlementService.java index 73ef443f..99d47fcd 100644 --- a/src/main/java/net/finmath/smartcontract/valuation/service/utils/SettlementService.java +++ b/src/main/java/net/finmath/smartcontract/valuation/service/utils/SettlementService.java @@ -34,10 +34,12 @@ public class SettlementService { private final RefinitivConfig refinitivConfig; private final ValuationConfig valuationConfig; + private final MarketDataGeneratorScenarioList marketDataServiceScenarioList; public SettlementService(RefinitivConfig refinitivConfig, ValuationConfig valuationConfig) { this.refinitivConfig = refinitivConfig; this.valuationConfig = valuationConfig; + this.marketDataServiceScenarioList = new MarketDataGeneratorScenarioList(); } public RegularSettlementResult generateRegularSettlementResult(RegularSettlementRequest regularSettlementRequest) { @@ -122,7 +124,6 @@ private MarketDataList retrieveMarketData(SmartDerivativeContractDescriptor sdc) } else { //includes provider internal or no liveMarketData activated final io.reactivex.rxjava3.functions.Consumer marketDataWriter = marketDataList::set; - MarketDataGeneratorScenarioList marketDataServiceScenarioList = new MarketDataGeneratorScenarioList(); marketDataServiceScenarioList.asObservable().subscribe(marketDataWriter, //onNext throwable -> logger.error("unable to generate marketData from files ", throwable), //onError () -> logger.info("on complete, simulated marketData generated from files")); //onComplete diff --git a/src/main/resources/static/generate-initial-settlement.html b/src/main/resources/static/generate-initial-settlement.html new file mode 100644 index 00000000..2d6e1d5e --- /dev/null +++ b/src/main/resources/static/generate-initial-settlement.html @@ -0,0 +1,133 @@ + + + + + + + + + + + +

+

finmath Valuation Oracle: Margin Calculator

+ +

+ Perform a valuation of the settlement (margin) based on product data and two market data sets. +

+ +
+
+ + +
+ + + + + + + + + \ No newline at end of file From 4f6af002d618250d3674bc86074ee1c2e14d2f82 Mon Sep 17 00:00:00 2001 From: Julius Lauterbach Date: Fri, 27 Sep 2024 17:35:52 +0200 Subject: [PATCH 16/51] SDC-626, added new initial settlement page to index.html --- src/main/resources/static/index.html | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/main/resources/static/index.html b/src/main/resources/static/index.html index 2b7c7124..94ae8913 100644 --- a/src/main/resources/static/index.html +++ b/src/main/resources/static/index.html @@ -45,6 +45,16 @@

Product XML Check

+
+
+

Generate Initial Settlement XML

+

+ generate an initial settlement XML based on product data +

+ +
+
+