public double protectionLeg(NodalCurve creditCurve) { double ht0 = creditCurve.yValue(proLegIntPoints[0]) * proLegIntPoints[0]; double rt0 = proYieldCurveRT[0]; double b0 = proDF[0] * Math.exp(-ht0); double pv = 0d; for (int i = 1; i < nProPoints; ++i) { double ht1 = creditCurve.yValue(proLegIntPoints[i]) * proLegIntPoints[i]; double rt1 = proYieldCurveRT[i]; double b1 = proDF[i] * Math.exp(-ht1); double dht = ht1 - ht0; double drt = rt1 - rt0; double dhrt = dht + drt; // this is equivalent to the ISDA code without explicitly calculating the time step - it also handles the limit double dPV; if (Math.abs(dhrt) < 1e-5) { dPV = dht * b0 * epsilon(-dhrt); } else { dPV = (b0 - b1) * dht / dhrt; } pv += dPV; ht0 = ht1; rt0 = rt1; b0 = b1; } pv *= lgdDF; // multiply by LGD and adjust to valuation date return pv; } }
/** * This is the Taylor expansion of the first derivative of $$\frac{\exp(x)-1}{x}$$. * * @param x the value * @return the result */ public static double epsilonP(double x) { if (Math.abs(x) > 1e-7) { return ((x - 1) * Math.expm1(x) + x) / x / x; } return taylor(x, COEFF2); }
if (formula == AccrualOnDefaultFormula.MARKIT_FIX) { if (Math.abs(dhrt) < SMALL) { double eps = epsilonP(-dhrt); tPv = dht * dt * b0 * eps; dhtBar[i - 1] = dt * b0 * eps; dhrtBar[i - 1] = -dht * dt * b0 * epsilonPP(-dhrt); bBar[i - 1] += dht * eps; } else { double t1 = t - effStart + omega; if (Math.abs(dhrt) < SMALL) { double eps = epsilon(-dhrt); double epsp = epsilonP(-dhrt); tPv = dht * b0 * (t0 * eps + dt * epsp); dhtBar[i - 1] = b0 * (t0 * eps + dt * epsp); dhrtBar[i - 1] = -dht * b0 * (t0 * epsp + dt * epsilonPP(-dhrt)); bBar[i - 1] += dht * (t0 * eps + dt * epsp); } else {
if (getAccrualOnDefaultFormula() == AccrualOnDefaultFormula.MARKIT_FIX) { if (Math.abs(dhrt) < 1e-5) { tPV = dht * dt * b0 * epsilonP(-dhrt); } else { tPV = dht * dt / dhrt * ((b0 - b1) / dhrt - b1); double t1 = t - accStart + getAccrualOnDefaultFormula().getOmega(); if (Math.abs(dhrt) < 1e-5) { tPV = dht * b0 * (t0 * epsilon(-dhrt) + dt * epsilonP(-dhrt)); } else { tPV = dht / dhrt * (t0 * b0 - t1 * b1 + dt / dhrt * (b0 - b1));
if (formula == AccrualOnDefaultFormula.MARKIT_FIX) { if (Math.abs(dhrt) < SMALL) { tPV = dht * dt * b0 * Epsilon.epsilonP(-dhrt); } else { tPV = dht * dt / dhrt * ((b0 - b1) / dhrt - b1); double t1 = t - effStart + omega; if (Math.abs(dhrt) < SMALL) { tPV = dht * b0 * (t0 * epsilon(-dhrt) + dt * Epsilon.epsilonP(-dhrt)); } else { tPV = dht / dhrt * (t0 * b0 - t1 * b1 + dt / dhrt * (b0 - b1));
/** * This is the Taylor expansion of $$\frac{\exp(x)-1}{x}$$ - note for $$|x| > 10^{-10}$$ the expansion is note used . * * @param x the value * @return the result */ public static double epsilon(double x) { if (Math.abs(x) > 1e-10) { return Math.expm1(x) / x; } return taylor(x, COEFF1); }
dPV = dht * b0 * epsilon(-dhrt); } else { dPV = (b0 - b1) * dht / dhrt;
/** * This is the Taylor expansion of the second derivative of $$\frac{\exp(x)-1}{x}$$. * * @param x the value * @return the result */ public static double epsilonPP(double x) { if (Math.abs(x) > 1e-5) { double x2 = x * x; double x3 = x * x2; return (Math.expm1(x) * (x2 - 2 * x + 2) + x2 - 2 * x) / x3; } return taylor(x, COEFF3); }
double dPv = 0d; if (Math.abs(dhrt[i - 1]) < SMALL) { double eps = epsilon(-dhrt[i - 1]); dPv = dht[i - 1] * b0 * eps; } else {