This exact source runs in TeaVM. Form changes update its Java literals and reset manual edits.
import com.nablatensor.engine.Nabla;
import com.nablatensor.quant.EquityMarket;
import com.nablatensor.quant.MonteCarlo;
import com.nablatensor.quant.Products;
import com.nablatensor.risk.NestedAggregation;
import com.nablatensor.risk.RiskClassEnum;
import com.nablatensor.risk.RiskFactor;
import com.nablatensor.risk.RiskMeasureEnum;
import com.nablatensor.risk.Sensitivities;
import java.util.HashSet;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
public final class IsdaSimmRiskStudio {
static final String[][] B = {
{
"USD", "EUR"
}, {
"1", "4"
}, {
"1", "2"
}, {
"1", "4"
}, {
"1", "5"
}, {
"USD", "EUR"
}
};
static final double[] DRW = {
.011, .008, .28, .22, .19, .075
}, VRW = {
.18, .64, .64, .28, .42, .3
}, RHO = {
.63, .42, .27, .16, .31, .5
}, GAMMA = {
.24, .21, .35, .15, .23, .5
}, DT = {
330, 12, 3, 8, 260, 2400
}, VT = {
130, 320, 85, 210, 74, 480
};
static final RiskClassEnum[] RC = {
RiskClassEnum.GIRR, RiskClassEnum.CSR_NON_SEC, RiskClassEnum.CSR_SEC, RiskClassEnum.EQUITY,
RiskClassEnum.COMMODITY, RiskClassEnum.FX
};
static final RiskMeasureEnum[] ME = {
RiskMeasureEnum.DELTA, RiskMeasureEnum.VEGA, RiskMeasureEnum.CURVATURE
};
public static void main(String[] z) {
String[] id = {
"IRS-USD-10Y", "XCCY-EURUSD-5Y", "CDS-IG-CPTY-5Y", "CDX-HY-INDEX-5Y", "EQ-CALL-SX5E-1Y", "EQ-PUT-SPX-1Y",
"COMDTY-WTI-SWAP-2Y"
}, cp = {
"CPTY-ALPHA", "CPTY-ALPHA", "CPTY-BRAVO", "CPTY-BRAVO", "CPTY-CHARLIE", "CPTY-CHARLIE", "CPTY-DELTA"
}, pc = {
"RATES_FX", "RATES_FX", "CREDIT", "CREDIT", "EQUITY", "EQUITY", "COMMODITY"
};
double[] notionals = {
120000000, 80000000, 50000000, 25000000, 15000000, 10000000, 30000000
};
int[] side = {
1, -1, 1, -1, -1, 1, 1
};
long paths = 200000L, seed = 42L;
Set<String> counterparties = new HashSet<>();
for (String c : cp) counterparties.add(c);
System.out.println("BOOK|" + id.length + "|" + counterparties.size());
int heavy = 0;
for (int t = 0; t < pc.length; t++) if (pc[t].equals("EQUITY")) {
heavy = t;
break;
}
double scale = side[heavy] * notionals[heavy] / 100.0 / 1.0e6;
EquityMarket market = EquityMarket.of()
.spot(100)
.strike(100)
.vol(.2)
.rate(.03)
.maturity(1)
.build();
double hd, hv, hir, hc;
try (MonteCarlo<EquityMarket> g = MonteCarlo.of(Products.europeanCall())
.market(market)
.steps(1)
.fp64()
.greeks()
.on("cpu")
.build(); MonteCarlo<EquityMarket> p = MonteCarlo.of(Products.europeanCall())
.market(market)
.steps(1)
.fp64()
.priceOnly()
.on("cpu")
.build()) {
Nabla.TypedValuation<EquityMarket> adj = g.run(paths, seed), base = p.run(paths, seed), up = p.run(EquityMarket.of()
.spot(130)
.strike(100)
.vol(.2)
.rate(.03)
.maturity(1)
.build(), paths, seed), down = p.run(EquityMarket.of()
.spot(70)
.strike(100)
.vol(.2)
.rate(.03)
.maturity(1)
.build(), paths, seed);
hd = side[heavy] * Math.abs(notionals[heavy]) / 100.0 / 1e6 * adj.greek(EquityMarket::spot);
hv = side[heavy] * Math.abs(notionals[heavy]) / 100.0 / 1e6 * adj.greek(EquityMarket::vol) * .01;
hir = side[heavy] * Math.abs(notionals[heavy]) / 100.0 / 1e6 * adj.greek(EquityMarket::rate) * .01;
double pb = side[heavy] * Math.abs(notionals[heavy]) / 100.0 / 1e6 * base.price(), pu = side[heavy] * Math.abs(notionals[heavy]) / 100.0 / 1e6 * up.price(),
pd = side[heavy] * Math.abs(notionals[heavy]) / 100.0 / 1e6 * down.price();
hc = -Math.min(pu - pb - 30 * hd, pd - pb + 30 * hd);
}
Sensitivities.Builder builder = Sensitivities.builder();
for (int t = 0; t < id.length; t++) {
double s = side[t] * notionals[t] / 1e6;
int fi = 0;
for (int c = 0; c < RC.length; c++) if (applies(pc[t], c)) for (String bucket : B[c]) {
double alt = ((fi++ + t) % 2 == 0) ? 1 : -.6;
String name = id[t] + "#" + bucket;
builder.add(factor(RC[c], RiskMeasureEnum.DELTA, bucket, name, 0), s * alt * .02);
builder.add(factor(RC[c], RiskMeasureEnum.VEGA, bucket, name, 1), Math.abs(s) * .004 * (1
+ .1 * t));
builder.add(factor(RC[c], RiskMeasureEnum.CURVATURE, bucket, name, 0), Math.abs(s) * alt * .0015);
}
}
builder.add(RiskFactor.equityDelta("4", id[heavy]), hd);
builder.add(factor(RiskClassEnum.EQUITY, RiskMeasureEnum.VEGA, "4", id[heavy], 1), hv);
builder.add(RiskFactor.equityDelta("4", id[heavy])
.asCurvature(), hc);
builder.add(RiskFactor.girrDelta("USD", 10.0), hir);
Sensitivities crif = builder.build();
double[][] result = new double[6][3];
for (int c = 0; c < 6; c++) for (int m = 0; m < 3; m++) result[c][m] = margin(crif, c, ME[m]);
for (int c = 0; c < 6; c++) System.out.println("CLASS|" + RC[c] + "|" + result[c][0] + "|" + result[c][1]
+ "|" + result[c][2]);
String[] products = {
"RATES_FX", "CREDIT", "EQUITY", "COMMODITY"
};
int[][] classes = {
{
0, 5
}, {
1, 2
}, {
3
}, {
4
}
};
double total = 0;
for (int p = 0; p < 4; p++) {
double[] sums = new double[3];
for (int m = 0; m < 3; m++) {
for (int x : classes[p]) {
sums[m] += result[x][m] * result[x][m];
for (int y : classes[p]) if (x != y) sums[m] += psi(x, y) * result[x][m] * result[y][m];
}
sums[m] = Math.sqrt(Math.max(0, sums[m]));
}
double pt = sums[0] + sums[1] + sums[2];
total += pt;
System.out.println("PRODUCT|" + products[p] + "|" + sums[0] + "|" + sums[1] + "|" + sums[2]
+ "|" + pt);
}
System.out.println("TOTAL|" + total);
}
static boolean applies(String p, int c) {
return p.equals("RATES_FX") ? (c == 0 || c == 5) : p.equals("CREDIT") ? (c == 1 || c == 2) : p.equals("EQUITY") ? c == 3 : c == 4;
}
static RiskFactor factor(RiskClassEnum c, RiskMeasureEnum m, String b, String n, double t) {
return RiskFactor.of()
.riskClass(c)
.measure(m)
.bucket(b)
.name(n)
.tenor(t)
.tenor2(0)
.build();
}
static int bi(int c, String b) {
for (int i = 0; i < B[c].length; i++) if (B[c][i].equals(b)) return i;
return 0;
}
static double margin(Sensitivities all, int c, RiskMeasureEnum m) {
Sensitivities x = all.ofClass(RC[c])
.ofMeasure(m);
if (x.isEmpty()) return 0;
if (m == RiskMeasureEnum.CURVATURE) return NestedAggregation.curvature((a, b) -> RHO[c], (a,
b) -> GAMMA[c])
.aggregate(x)
.total();
double threshold = m == RiskMeasureEnum.DELTA ? DT[c] : VT[c];
Map<String, Double> sums = new HashMap<>();
for (RiskFactor f : x.asMap()
.keySet()) sums.put(f.bucket(), sums.getOrDefault(f.bucket(), 0.0) + x.asMap()
.get(f));
NestedAggregation.ConcentrationFactor cr = (f, s) -> Math.max(1, Math.sqrt(Math.abs(sums.getOrDefault(f.bucket(),
0.0)) / threshold));
return NestedAggregation.delta(f -> m == RiskMeasureEnum.DELTA ? DRW[c] : VRW[c], (a, b) -> RHO[c],
(a, b) -> GAMMA[c])
.withConcentration(cr)
.aggregate(x)
.total();
}
static double psi(int a, int b) {
if (a == b) return 1;
if ((a == 0 && b == 5) || (a == 5 && b == 0)) return .28;
if ((a == 1 && b == 2) || (a == 2 && b == 1)) return .15;
return 0;
}
}