Skip to content

Commit 46f7005

Browse files
Revising calibration and historical simulation
1 parent 4d19338 commit 46f7005

File tree

4 files changed

+138
-150
lines changed

4 files changed

+138
-150
lines changed

src/main/java/net/finmath/smartcontract/simulation/InterestRateAnalyticCalibration.java renamed to src/main/java/net/finmath/smartcontract/simulation/InterestRateAnalyticCalibrator.java

Lines changed: 47 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import java.util.ArrayList;
55
import java.util.Arrays;
66
import java.util.Comparator;
7+
import java.util.HashMap;
78
import java.util.List;
89
import java.util.stream.IntStream;
910
import java.util.stream.Stream;
@@ -32,20 +33,28 @@
3233
import net.finmath.time.daycount.DayCountConvention_ACT_360;
3334

3435

35-
public class InterestRateAnalyticCalibration {
36+
public class InterestRateAnalyticCalibrator {
3637

3738
public static String DISCOUNT_EUR_OIS = "discount-EUR-OIS";
3839
public static String FORWARD_EUR_6M = "forward-EUR-6M";
3940
private static String FORWARD_EUR_OIS = "forward-EUR-OIS";
4041
private static String FIXED_EUR_6M = "fixed-EUR-6M";
4142

42-
private List<CalibrationDataItem> fixings;
43-
44-
public InterestRateAnalyticCalibration() {
45-
this.fixings = new ArrayList<>();
43+
44+
public enum CURVE_NAME {
45+
ESTR,
46+
EURIBOR06M
4647
}
4748

4849

50+
51+
private HashMap<CURVE_NAME, List<CalibrationDataItem>> fixings = new HashMap<>();
52+
53+
public InterestRateAnalyticCalibrator() {
54+
}
55+
56+
57+
4958
public AnalyticModel getCalibratedModel(LocalDate referenceDate, double[] discountCurveQuotes, double[] forwardCurveQuotes) throws CloneNotSupportedException, SolverException {
5059

5160
final AnalyticModelFromCurvesAndVols model = new AnalyticModelFromCurvesAndVols(new Curve[] { getDiscountCurveEurOIS(referenceDate), getForwardCurveEurOIS(referenceDate), getForwardCurveEur6M(referenceDate)});
@@ -58,19 +67,37 @@ public AnalyticModel getCalibratedModel(LocalDate referenceDate, double[] discou
5867
return calibratedCurves.getModel();
5968
}
6069

70+
71+
public void addFixingItem(CURVE_NAME curveName, LocalDate fixingDate, Double fixing) {
72+
switch(curveName) {
73+
case ESTR:
74+
this.fixings.computeIfAbsent(curveName, k -> new ArrayList<>()).add(createFixingItemEurOIS(fixingDate, fixing));
75+
break;
76+
case EURIBOR06M:
77+
this.fixings.computeIfAbsent(curveName, k -> new ArrayList<>()).add(createFixingItemEur6M(fixingDate, fixing));
78+
break;
79+
}
80+
}
81+
6182

62-
public void addFixingItem(CalibrationDataItem fixingItem) {
63-
this.fixings.add(fixingItem);
83+
private CalibrationDataItem createFixingItemEur6M(LocalDate fixingDate, Double fixing) {
84+
CalibrationDataItem.Spec spec = new CalibrationDataItem.Spec("EURIBOR06M", "Euribor6M", "FIXING", "6M");
85+
CalibrationDataItem item = new CalibrationDataItem(spec, fixing, fixingDate.atStartOfDay());
86+
return item;
6487
}
6588

89+
private CalibrationDataItem createFixingItemEurOIS(LocalDate fixingDate, Double fixing) {
90+
CalibrationDataItem.Spec spec = new CalibrationDataItem.Spec("IREURDRFO_N", "ESTR", "FIXING", "1D");
91+
CalibrationDataItem item = new CalibrationDataItem(spec, fixing, fixingDate.atStartOfDay());
92+
return item;
93+
}
6694

6795
private DiscountCurveInterpolation getDiscountCurveEurOIS(LocalDate referenceDate) {
6896
ArrayList<Double> fixingValuesList = new ArrayList<>();
6997
ArrayList<Double> fixingTimesList = new ArrayList<>();
7098
ArrayList<Double> dfList = new ArrayList<>();
7199
ArrayList<Double> dfTimesList = new ArrayList<>();
72-
fixings.stream().filter(x -> x.getCurveName().equals("ESTR"))
73-
.sorted(Comparator.comparing(CalibrationDataItem::getDate).reversed())
100+
this.fixings.getOrDefault(CURVE_NAME.ESTR, new ArrayList<>()).stream().sorted(Comparator.comparing(CalibrationDataItem::getDate).reversed())
74101
.forEach(x -> {
75102
double time = FloatingpointDate.getFloatingPointDateFromDate(
76103
referenceDate,
@@ -116,7 +143,7 @@ private ForwardCurve getForwardCurveEurOIS(LocalDate referenceDate) {
116143
}
117144

118145
private ForwardCurve getForwardCurveEur6M(LocalDate referenceDate) {
119-
double[] fixingTimes = fixings.stream().filter(x -> x.getCurveName().equals("Euribor6M")).map(x -> x.getDate())
146+
double[] fixingTimes = this.fixings.getOrDefault(CURVE_NAME.EURIBOR06M, new ArrayList<>()).stream().map(x -> x.getDate())
120147
.map(x -> FloatingpointDate.getFloatingPointDateFromDate(referenceDate, x))
121148
.mapToDouble(Double::doubleValue).sorted().toArray();
122149
if (fixingTimes.length == 0) { //if there are no fixings return empty curve
@@ -131,7 +158,7 @@ private ForwardCurve getForwardCurveEur6M(LocalDate referenceDate) {
131158
ForwardCurveInterpolation.InterpolationEntityForward.FORWARD,
132159
DISCOUNT_EUR_OIS);
133160
}
134-
double[] fixingValues = fixings.stream().filter(x -> x.getCurveName().equals("Euribor6M"))
161+
double[] fixingValues = this.fixings.getOrDefault(CURVE_NAME.EURIBOR06M, new ArrayList<>()).stream()
135162
.sorted(Comparator.comparing(CalibrationDataItem::getDate)).map(CalibrationDataItem::getQuote)
136163
.mapToDouble(Double::doubleValue).toArray();
137164
ForwardCurve fixedPart = ForwardCurveInterpolation.createForwardCurveFromForwards(FIXED_EUR_6M,
@@ -165,6 +192,10 @@ private static CalibratedCurves.CalibrationSpec[] getCalibrationSpecsEurOIS(Loca
165192
final String[] maturities = { "1D", "7D", "14D", "21D", "1M", "2M", "3M", "4M", "5M", "6M", "7M", "8M", "9M", "10M", "11M", "1Y", "15M", "18M", "21M", "2Y", "3Y", "4Y", "5Y", "6Y", "7Y", "8Y", "9Y", "10Y", "12Y", "15Y", "20Y", "25Y", "30Y"};
166193
final String[] frequency = { "tenor", "annual", "annual", "annual", "annual", "annual", "annual", "annual", "annual", "annual", "annual", "annual", "annual", "annual", "annual", "annual", "annual", "annual", "annual", "annual", "annual", "annual", "annual", "annual", "annual", "annual", "annual", "annual", "annual", "annual", "annual", "annual", "annual"};
167194

195+
if (quotes.length != maturities.length) {
196+
throw new IllegalArgumentException("Size of provided quotes does not match the number of EUR-OIS bootstrapp instruments");
197+
}
198+
168199
CalibratedCurves.CalibrationSpec[] specs = new CalibratedCurves.CalibrationSpec[maturities.length];
169200
BusinessdayCalendar calendar = new BusinessdayCalendarExcludingTARGETHolidays();
170201
// The first product is an overnight cash deposit, followed by 32 swaps
@@ -190,10 +221,14 @@ private static CalibratedCurves.CalibrationSpec[] getCalibrationSpecsEur6M(Local
190221
final String[] daycountConventionsFloat = { "", "", "", "", "", "", "", "ACT/360", "ACT/360", "ACT/360", "ACT/360", "ACT/360", "ACT/360", "ACT/360", "ACT/360", "ACT/360", "ACT/360", "ACT/360", "ACT/360", "ACT/360", "ACT/360"};
191222
final String[] daycountConventions = { "ACT/360", "ACT/360", "ACT/360", "ACT/360", "ACT/360", "ACT/360", "ACT/360", "E30/360", "E30/360", "E30/360", "E30/360", "E30/360", "E30/360", "E30/360", "E30/360", "E30/360", "E30/360", "E30/360", "E30/360", "E30/360", "E30/360"};
192223

224+
if (quotes.length != maturities.length) {
225+
throw new IllegalArgumentException("Size of provided quotes does not match the number of EUR-6M bootstrapp instruments");
226+
}
227+
193228
CalibratedCurves.CalibrationSpec[] specs = new CalibratedCurves.CalibrationSpec[maturities.length];
194229
BusinessdayCalendar calendar = new BusinessdayCalendarExcludingTARGETHolidays();
195230
// The first 7 product are FRAs, followed by 14 swaps
196-
for (int i=0; i < 8; i++) {
231+
for (int i=0; i < 7; i++) {
197232
int nMonthMaturity = Integer.parseInt(maturities[i].replace("M", ""));
198233
int nMonthOffset = nMonthMaturity - Integer.parseInt(tenorLabel.replace("M", ""));
199234
String startOffsetLabel = nMonthOffset + "M";

src/main/java/net/finmath/smartcontract/simulation/MarketDataLoader.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
import java.time.format.DateTimeFormatter;
99
import java.util.*;
1010

11+
import net.finmath.time.businessdaycalendar.BusinessdayCalendar;
12+
1113
public class MarketDataLoader {
1214

1315
private final Path csvPath;
@@ -17,7 +19,7 @@ public MarketDataLoader(Path csvPath) {
1719
this.csvPath = csvPath;
1820
}
1921

20-
public List<MarketDataSnapshot> load() throws IOException {
22+
public List<MarketDataSnapshot> load(BusinessdayCalendar businessdayCalendar) throws IOException {
2123
List<MarketDataSnapshot> snapshots = new ArrayList<>();
2224

2325
try (BufferedReader reader = Files.newBufferedReader(csvPath)) {
@@ -41,8 +43,9 @@ public List<MarketDataSnapshot> load() throws IOException {
4143
}
4244

4345
LocalDate date = LocalDate.parse(fields[0], dateFormatter);
46+
if(!businessdayCalendar.isBusinessday(date)) continue;
47+
4448
double[] quotes = new double[fields.length - 1];
45-
4649
for (int i = 1; i < fields.length; i++) {
4750
quotes[i-1] = Double.parseDouble(fields[i]) / 100.0;
4851
}

src/main/java/net/finmath/smartcontract/simulation/MarketDataSnapshot.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,21 @@ public LocalDate getValuationDate() {
1919
public double[] getQuotes() {
2020
return quotes;
2121
}
22+
23+
// Assumes the fixing is stored in the first entry of quotes
24+
// TODO google for optimization
25+
public double[] getQuotesWithoutFixing() {
26+
double[] quotesWithoutFixing = new double[this.quotes.length - 1];
27+
for (int i = 1; i < quotes.length; i++) {
28+
quotesWithoutFixing[i - 1] = this.quotes[i];
29+
}
30+
return quotesWithoutFixing;
31+
}
32+
33+
// Assumes the fixing is stored in the first entry of quotes
34+
public double getFixing() {
35+
return this.quotes[0];
36+
}
2237
}
2338

2439

0 commit comments

Comments
 (0)