Skip to content

Commit 9e3bf00

Browse files
committed
Adding valuation over margin limit increments
1 parent 46f7005 commit 9e3bf00

File tree

5 files changed

+262
-92
lines changed

5 files changed

+262
-92
lines changed
Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
package net.finmath.smartcontract.simulation;
2+
3+
import java.io.Closeable;
4+
import java.io.IOException;
5+
import java.io.InputStream;
6+
import java.io.OutputStream;
7+
import java.nio.file.Files;
8+
import java.nio.file.Path;
9+
import java.util.LinkedHashMap;
10+
import java.util.List;
11+
import java.util.Objects;
12+
13+
import org.apache.poi.ss.usermodel.Cell;
14+
import org.apache.poi.ss.usermodel.CellStyle;
15+
import org.apache.poi.ss.usermodel.CellType;
16+
import org.apache.poi.ss.usermodel.DataFormat;
17+
import org.apache.poi.ss.usermodel.Row;
18+
import org.apache.poi.ss.usermodel.Sheet;
19+
import org.apache.poi.ss.usermodel.Workbook;
20+
import org.apache.poi.ss.usermodel.WorkbookFactory;
21+
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
22+
23+
public class ExcelTableWriter implements Closeable {
24+
25+
private final Path path;
26+
private final Workbook wb;
27+
28+
private final CellStyle numericStyle;
29+
30+
public ExcelTableWriter(Path path) throws IOException {
31+
this.path = path;
32+
33+
if (Files.exists(path)) {
34+
try (InputStream in = Files.newInputStream(path)) {
35+
this.wb = WorkbookFactory.create(in);
36+
}
37+
} else {
38+
this.wb = new XSSFWorkbook();
39+
}
40+
41+
DataFormat df = wb.createDataFormat();
42+
43+
numericStyle = wb.createCellStyle();
44+
numericStyle.setDataFormat(df.getFormat("0.###############"));
45+
}
46+
47+
48+
/**
49+
* Writes a "column table" to a sheet.
50+
*
51+
* @param sheetName sheet to write into
52+
* @param columns LinkedHashMap preserves column order
53+
* @param replaceSheet if true, deletes existing sheet with same name
54+
* @param autosize if true, autosize columns (can be slow on big sheets)
55+
*/
56+
public void writeTable(
57+
String sheetName,
58+
LinkedHashMap<String, ? extends List<?>> columns,
59+
boolean replaceSheet,
60+
boolean autosize
61+
) {
62+
Objects.requireNonNull(sheetName, "sheetName");
63+
Objects.requireNonNull(columns, "columns");
64+
65+
if (columns.isEmpty()) {
66+
throw new IllegalArgumentException("No columns provided.");
67+
}
68+
69+
// Determine row count (max length)
70+
int rowCount = columns.values().stream().mapToInt(List::size).max().orElse(0);
71+
72+
Sheet sheet = getOrCreateSheet(sheetName, replaceSheet);
73+
74+
// Header
75+
Row header = sheet.createRow(0);
76+
int colIdx = 0;
77+
for (String name : columns.keySet()) {
78+
Cell cell = header.createCell(colIdx++, CellType.STRING);
79+
cell.setCellValue(name);
80+
}
81+
82+
// Data
83+
for (int r = 0; r < rowCount; r++) {
84+
Row row = sheet.createRow(r + 1);
85+
86+
colIdx = 0;
87+
for (List<?> col : columns.values()) {
88+
Object value = (r < col.size()) ? col.get(r) : null;
89+
writeValue(row.createCell(colIdx++), value);
90+
}
91+
}
92+
93+
if (autosize) {
94+
for (int c = 0; c < columns.size(); c++) {
95+
sheet.autoSizeColumn(c);
96+
}
97+
}
98+
}
99+
100+
private Sheet getOrCreateSheet(String sheetName, boolean replaceSheet) {
101+
Sheet existing = wb.getSheet(sheetName);
102+
103+
if (existing != null && replaceSheet) {
104+
int idx = wb.getSheetIndex(existing);
105+
wb.removeSheetAt(idx);
106+
return wb.createSheet(sheetName);
107+
}
108+
109+
return existing != null ? existing : wb.createSheet(sheetName);
110+
}
111+
112+
private void writeValue(Cell cell, Object value) {
113+
if (value == null) {
114+
cell.setBlank();
115+
return;
116+
}
117+
118+
if (value instanceof Number n) {
119+
cell.setCellValue(n.doubleValue());
120+
cell.setCellStyle(numericStyle);
121+
return;
122+
}
123+
124+
// Fallback: string
125+
cell.setCellValue(String.valueOf(value));
126+
}
127+
128+
public void save() throws IOException {
129+
Files.createDirectories(path.toAbsolutePath().getParent());
130+
try (OutputStream out = Files.newOutputStream(path)) {
131+
wb.write(out);
132+
}
133+
}
134+
135+
@Override
136+
public void close() throws IOException {
137+
wb.close();
138+
}
139+
140+
}

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

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -45,15 +45,11 @@ public enum CURVE_NAME {
4545
ESTR,
4646
EURIBOR06M
4747
}
48-
49-
50-
48+
5149
private HashMap<CURVE_NAME, List<CalibrationDataItem>> fixings = new HashMap<>();
5250

5351
public InterestRateAnalyticCalibrator() {
5452
}
55-
56-
5753

5854
public AnalyticModel getCalibratedModel(LocalDate referenceDate, double[] discountCurveQuotes, double[] forwardCurveQuotes) throws CloneNotSupportedException, SolverException {
5955

@@ -246,7 +242,7 @@ private static CalibratedCurves.CalibrationSpec[] getCalibrationSpecsEur6M(Local
246242
specs[i] = new CalibratedCurves.CalibrationSpec("EUR-" + tenorLabel + maturities[i], "FRA", scheduleInterfaceFinal, FORWARD_EUR_6M, quotes[i], DISCOUNT_EUR_OIS, null, "", 0.0, null, FORWARD_EUR_6M, calibrationTime);
247243
}
248244
// 6M Swaps
249-
for (int i=8; i < quotes.length; i++) {
245+
for (int i=7; i < quotes.length; i++) {
250246
Schedule scheduleInterfaceRec = ScheduleGenerator.createScheduleFromConventions(referenceDate, 2, "0D", maturities[i], frequencyFloat[i], daycountConventionsFloat[i], "first", "modfollow", new BusinessdayCalendarExcludingTARGETHolidays(), -2, 0);
251247
Schedule scheduleInterfacePay = ScheduleGenerator.createScheduleFromConventions(referenceDate, 2, "0D", maturities[i], frequency[i], daycountConventions[i], "first", "modfollow", new BusinessdayCalendarExcludingTARGETHolidays(), -2, 0);
252248
double calibrationTime = scheduleInterfaceRec.getFixing(scheduleInterfaceRec.getNumberOfPeriods() - 1);

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ public MarketDataLoader(Path csvPath) {
1919
this.csvPath = csvPath;
2020
}
2121

22+
// Skips all entries that are not business dates
2223
public List<MarketDataSnapshot> load(BusinessdayCalendar businessdayCalendar) throws IOException {
2324
List<MarketDataSnapshot> snapshots = new ArrayList<>();
2425

@@ -52,6 +53,7 @@ public List<MarketDataSnapshot> load(BusinessdayCalendar businessdayCalendar) th
5253

5354
snapshots.add(new MarketDataSnapshot(date, quotes));
5455
}
56+
Collections.reverse(snapshots);
5557
}
5658

5759
return snapshots;

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

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package net.finmath.smartcontract.simulation;
22

33
import java.time.LocalDate;
4+
import java.util.Arrays;
45

56

67
public class MarketDataSnapshot {
@@ -21,13 +22,8 @@ public double[] getQuotes() {
2122
}
2223

2324
// Assumes the fixing is stored in the first entry of quotes
24-
// TODO google for optimization
2525
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;
26+
return Arrays.copyOfRange(this.quotes, 1, this.quotes.length);
3127
}
3228

3329
// Assumes the fixing is stored in the first entry of quotes

0 commit comments

Comments
 (0)