Skip to content

Commit

Permalink
Merge branch 'feature/leg_valuation_and_code_cleanup' into develop
Browse files Browse the repository at this point in the history
  • Loading branch information
cfries committed Nov 29, 2024
2 parents 29fe165 + 273965b commit 3e91acb
Show file tree
Hide file tree
Showing 49 changed files with 704 additions and 209 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@
import javafx.scene.layout.FlowPane;
import net.finmath.marketdata.products.Swap;
import net.finmath.plots.*;
import net.finmath.smartcontract.product.IRSwapGenerator;
import net.finmath.smartcontract.valuation.marketdata.curvecalibration.CalibrationDataset;
import net.finmath.smartcontract.valuation.marketdata.curvecalibration.CalibrationParserDataItems;
import net.finmath.smartcontract.valuation.oracle.SmartDerivativeContractSettlementOracle;
import net.finmath.smartcontract.valuation.oracle.interestrates.ValuationOraclePlainSwap;
import net.finmath.smartcontract.product.IRSwapGenerator;

import javax.swing.*;
import java.awt.*;
Expand All @@ -23,6 +23,7 @@
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
Expand Down Expand Up @@ -68,9 +69,9 @@ public static void main(final String[] args) throws Exception {
datapoint.getSpec().getProductName().equals("Swap-Rate") &&
datapoint.getSpec().getMaturity().equals("5Y")).mapToDouble(e -> e.getQuote()).findAny().getAsDouble();

final Swap swap = IRSwapGenerator.generateAnalyticSwapObject(productStartDate, maturityKey, fixRate, false, forwardCurveKey, discountCurveKey);
final Swap swap = IRSwapGenerator.generateAnalyticSwapObject(productStartDate, maturityKey, notional, fixRate, false, forwardCurveKey, discountCurveKey);

final ValuationOraclePlainSwap oracle = new ValuationOraclePlainSwap(swap, notional, scenarioList);
final ValuationOraclePlainSwap oracle = new ValuationOraclePlainSwap(Map.of("value",swap), scenarioList);
final SmartDerivativeContractSettlementOracle margin = new SmartDerivativeContractSettlementOracle(oracle);

final List<LocalDateTime> scenarioDates = scenarioList.stream().map(scenario -> scenario.getDate()).sorted().collect(Collectors.toList());
Expand All @@ -83,7 +84,7 @@ public static void main(final String[] args) throws Exception {
sdcVisual.updateWithValue(scenarioDates.get(0), marginBuffer, 0, null, 0);
Thread.sleep(1000);
for (int i = 0; i < scenarioDates.size(); i++) {
final double marginCall = i > 0 ? margin.getMargin(scenarioDates.get(i - 1), scenarioDates.get(i)) : 0.0;
final double marginCall = i > 0 ? margin.getMargin(scenarioDates.get(i - 1), scenarioDates.get(i)).get("value").doubleValue() : 0.0;
// double marginCall = i==0. ? oracle.getValue(scenarioDates.get(0)) : oracle.getValue(scenarioDates.get(i)) - oracle.getValue(scenarioDates.get(i-1));//90*(new Random()).nextDouble()-45;
System.out.println(i + "\t" + DateTimeFormatter.ofPattern("dd.MM.yyyy").format(scenarioDates.get(i)) + "\t" + marginCall);
marketValue += marginCall;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,12 @@
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.Arrays;
import java.util.Optional;

/**
* Scenario Generator provides static method for generating an analytic swap object
* Generates an interest rate swap. This is used for testing and visualization.
* Alternative way to generate the swap is via the parser.
*
* @author Peter Kohl-Landgraf
* @author Christian Fries
Expand All @@ -21,17 +23,31 @@ public class IRSwapGenerator {

private IRSwapGenerator(){}

public static Swap generateAnalyticSwapObject(final LocalDate startDate, final String maturityLabel, final double fixRate, final boolean isReceiveFix, final String forwardCurveName, final String discountCurveName) {
public static Swap generateAnalyticSwapObject(final LocalDate startDate, final String maturityLabel, final double notional, final double fixRate, final boolean isReceiveFix, final String forwardCurveName, final String discountCurveName) {

final String frequencyLabel = forwardCurveName.contains("3M") ? "quarterly" : forwardCurveName.contains("6M") ? "semiannual" : forwardCurveName.contains("1M") ? "monthly" : "annual";

// Schedules
final Schedule scheduleFloat = ScheduleGenerator.createScheduleFromConventions(startDate, 2, "0D", maturityLabel, frequencyLabel, "act/360", "first", "following", new BusinessdayCalendarExcludingTARGETHolidays(), 0, 0);
final Schedule scheduleFix = ScheduleGenerator.createScheduleFromConventions(startDate, 2, "0D", maturityLabel, "annual", "E30/360", "first", "following", new BusinessdayCalendarExcludingTARGETHolidays(), 0, 0);
final SwapLeg floatLeg = new SwapLeg(Optional.of(LocalDateTime.of(startDate, LocalTime.of(0, 0))), scheduleFloat, forwardCurveName, 0.0, discountCurveName);

// TODO Remove hardcoded effective date
// TODO Test effective date from parser
LocalDateTime cashFlowEffectiveDate = LocalDateTime.of(startDate, LocalTime.of(0, 0));
boolean isNotionalExchanged = false;

final double[] notionalsFloat = new double[scheduleFloat.getNumberOfPeriods()];
final double[] spreadsFloat = new double[scheduleFloat.getNumberOfPeriods()];
Arrays.fill(notionalsFloat, notional);
Arrays.fill(spreadsFloat, 0.0);
final SwapLeg floatLeg = new SwapLeg(Optional.of(cashFlowEffectiveDate), scheduleFloat, forwardCurveName, notionalsFloat, spreadsFloat, discountCurveName, isNotionalExchanged);

final double[] notionalsFix = new double[scheduleFix.getNumberOfPeriods()];
final double[] spreadsFix = new double[scheduleFix.getNumberOfPeriods()];
Arrays.fill(notionalsFix, notional);
Arrays.fill(spreadsFix, fixRate);
final SwapLeg fixLeg = new SwapLeg(Optional.of(LocalDateTime.of(startDate, LocalTime.of(0, 0))), scheduleFix, "", fixRate, discountCurveName);

return isReceiveFix ? new Swap(fixLeg, floatLeg) : new Swap(floatLeg, fixLeg);
}


}
Original file line number Diff line number Diff line change
Expand Up @@ -617,8 +617,8 @@ private AnalyticModel getAnalyticModel(String marketData, Schedule schedule, Str
List<CalibrationDataset> marketDataSets;
try {
marketDataSets = CalibrationParserDataItems.getScenariosFromJsonString(marketData);
} catch (IOException e) {
logger.error("Failed to load market data.");
} catch (IllegalArgumentException e) {
logger.error("Failed to load market data.", e);
throw e;
}
Validate.isTrue(marketDataSets.size() == 1, "Parameter marketData should be only a single market data set");
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
package net.finmath.smartcontract.product.xml;

import jakarta.xml.bind.*;
import jakarta.xml.bind.JAXBContext;
import jakarta.xml.bind.JAXBException;
import jakarta.xml.bind.Marshaller;
import jakarta.xml.bind.Unmarshaller;
import net.finmath.smartcontract.model.ExceptionId;
import net.finmath.smartcontract.model.SDCException;
import net.finmath.smartcontract.valuation.marketdata.curvecalibration.CalibrationDataItem;
import net.finmath.smartcontract.product.SmartDerivativeContractDescriptor;
import net.finmath.smartcontract.valuation.marketdata.curvecalibration.CalibrationDataItem;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Document;
Expand All @@ -13,7 +16,11 @@

import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import java.io.*;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.StringReader;
import java.io.StringWriter;
import java.math.BigDecimal;
import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.util.ArrayList;
Expand Down Expand Up @@ -106,7 +113,7 @@ public static SmartDerivativeContractDescriptor parse(String sdcxml) throws Pars
public static <T> T unmarshalXml(String xml, Class<T> t) {
try {
StringReader reader = new StringReader(xml);
JAXBContext jaxbContext = JAXBContext.newInstance(t);
JAXBContext jaxbContext = JAXBContext.newInstance(t, BigDecimal.class);
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
return (T) unmarshaller.unmarshal(reader);
} catch (JAXBException e) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package net.finmath.smartcontract.settlement;

import jakarta.xml.bind.annotation.adapters.XmlAdapter;

import java.math.BigDecimal;

public class BigDecimalAdapter extends XmlAdapter<String, BigDecimal> {

@Override
public String marshal(BigDecimal value) throws Exception
{
if (value!= null)
{
return value.toString();
}
return null;
}

@Override
public BigDecimal unmarshal(String s) throws Exception
{
return new BigDecimal(s);
}
}
56 changes: 27 additions & 29 deletions src/main/java/net/finmath/smartcontract/settlement/Settlement.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
package net.finmath.smartcontract.settlement;

import jakarta.xml.bind.annotation.*;
import jakarta.xml.bind.annotation.XmlElement;
import jakarta.xml.bind.annotation.XmlElementWrapper;
import jakarta.xml.bind.annotation.XmlRootElement;
import jakarta.xml.bind.annotation.XmlType;
import jakarta.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
import net.finmath.smartcontract.model.MarketDataList;

Expand All @@ -23,12 +26,9 @@
@XmlRootElement
@XmlType(propOrder = {"tradeId", "settlementType", "currency", "marginValue",
"marginLimits", "settlementTime", "settlementNPV", "settlementNPVPrevious",
"settlementTimeNext", "settlementNPVNext", "marketData"})
"settlementTimeNext", "settlementNPVNext", "marketData", "settlementInfos"})
public class Settlement {

public Settlement() {
}

public enum SettlementType {
INITIAL,
REGULAR,
Expand Down Expand Up @@ -62,9 +62,12 @@ public enum SettlementType {

private MarketDataList marketData;

// Custom additional information (e.g. risk figures or szenario values)
/// Custom additional information (e.g. risk figures or szenario values)
private List<SettlementInfo> settlementInfos;

//private Map<String, String> info;
/*
* Getter and setters
*/

public String getTradeId() {
return tradeId;
Expand Down Expand Up @@ -115,14 +118,6 @@ public void setSettlementTime(ZonedDateTime settlementTime) {
this.settlementTime = settlementTime;
}

public MarketDataList getMarketData() {
return marketData;
}

public void setMarketData(MarketDataList marketData) {
this.marketData = marketData;
}

public BigDecimal getSettlementNPV() {
return settlementNPV;
}
Expand All @@ -139,20 +134,6 @@ public void setSettlementNPVPrevious(BigDecimal settlementNPVPrevious) {
this.settlementNPVPrevious = settlementNPVPrevious;
}

public Settlement(String tradeId, SettlementType settlementType, String currency, BigDecimal marginValue, List<BigDecimal> marginLimits, ZonedDateTime settlementTime, MarketDataList marketData, BigDecimal settlementNPV, BigDecimal settlementNPVPrevious, ZonedDateTime settlementTimeNext, BigDecimal settlementNPVNext) {
this.tradeId = tradeId;
this.settlementType = settlementType;
this.currency = currency;
this.marginValue = marginValue;
this.marginLimits = marginLimits;
this.settlementTime = settlementTime;
this.marketData = marketData;
this.settlementNPV = settlementNPV;
this.settlementNPVPrevious = settlementNPVPrevious;
this.settlementTimeNext = settlementTimeNext;
this.settlementNPVNext = settlementNPVNext;
}

@XmlJavaTypeAdapter(ZonedDateTimeAdapter.class)
public ZonedDateTime getSettlementTimeNext() {
return settlementTimeNext;
Expand All @@ -169,5 +150,22 @@ public BigDecimal getSettlementNPVNext() {
public void setSettlementNPVNext(BigDecimal settlementNPVNext) {
this.settlementNPVNext = settlementNPVNext;
}
public MarketDataList getMarketData() {
return marketData;
}

public void setMarketData(MarketDataList marketData) {
this.marketData = marketData;
}

@XmlElementWrapper(name="settlementInfos")
@XmlElement(name = "settlementInfo")
public List<SettlementInfo> getSettlementInfos() {
return settlementInfos;
}

public void setSettlementInfos(List<SettlementInfo> settlementInfos) {
this.settlementInfos = settlementInfos;
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import java.time.ZonedDateTime;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Objects;

public class SettlementGenerator {
Expand Down Expand Up @@ -68,6 +69,11 @@ public SettlementGenerator settlementNPVNext(BigDecimal settlementNPVNext){
return this;
}

public SettlementGenerator settlementInfo(Map<String, BigDecimal> info){
settlement.setSettlementInfos(info.entrySet().stream().map(e -> new SettlementInfo(e.getKey(), e.getValue())).toList());
return this;
}

public Settlement buildObject(){
String settlementString = SDCXMLParser.marshalClassToXMLString(settlement);
if(allFieldsSet(settlement))
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package net.finmath.smartcontract.settlement;

import jakarta.xml.bind.annotation.XmlAttribute;
import jakarta.xml.bind.annotation.XmlRootElement;
import jakarta.xml.bind.annotation.XmlValue;
import jakarta.xml.bind.annotation.adapters.XmlJavaTypeAdapter;

import java.math.BigDecimal;

@XmlRootElement(name="settlementInfo")
public class SettlementInfo {

private String key;
private BigDecimal value;

public SettlementInfo() { }

public SettlementInfo(String key, BigDecimal value) {
this.key = key;
this.value = value;
}

@XmlAttribute
public String getKey() {
return key;
}

public void setKey(String key) {
this.key = key;
}

@XmlValue
@XmlJavaTypeAdapter(BigDecimalAdapter.class)
public BigDecimal getValue() {
return value;
}

public void setValue(BigDecimal value) {
this.value = value;
}
}
Loading

0 comments on commit 3e91acb

Please sign in to comment.