@Test public void testNormal() { final ProbabilityDistribution<Double> highDOF = new StudentTDistribution(1000000, ENGINE); final ProbabilityDistribution<Double> normal = new NormalDistribution(0, 1, ENGINE); final double eps = 1e-4; double x; for (int i = 0; i < 100; i++) { x = RANDOM.nextDouble(); assertEquals(highDOF.getCDF(x), normal.getCDF(x), eps); assertEquals(highDOF.getPDF(x), normal.getPDF(x), eps); assertEquals(highDOF.getInverseCDF(x), normal.getInverseCDF(x), eps); } }
/** * Compute vega price of cash-or-nothing option * * @param spot The spot * @param strike The strike * @param timeToExpiry The time to expiry * @param lognormalVol The log-normal volatility * @param interestRate The interest rate * @param costOfCarry The cost-of-carry * @param isCall True for calls, false for puts * @return The option price */ public static double vega( final double spot, final double strike, final double timeToExpiry, final double lognormalVol, final double interestRate, final double costOfCarry, final boolean isCall) { ArgumentChecker.isTrue(spot > 0.0, "negative/NaN spot; have {}", spot); ArgumentChecker.isTrue(strike > 0.0, "negative/NaN strike; have {}", strike); ArgumentChecker.isTrue(timeToExpiry > 0.0, "negative/NaN timeToExpiry; have {}", timeToExpiry); ArgumentChecker.isTrue(lognormalVol > 0.0, "negative/NaN lognormalVol; have {}", lognormalVol); ArgumentChecker.isFalse(Double.isNaN(interestRate), "interestRate is NaN"); ArgumentChecker.isFalse(Double.isNaN(costOfCarry), "costOfCarry is NaN"); final double rootT = Math.sqrt(timeToExpiry); final double d = (Math.log(spot / strike) + (costOfCarry - 0.5 * lognormalVol * lognormalVol) * timeToExpiry) / lognormalVol / rootT; final double sign = isCall ? 1. : -1.; final double div = -(Math.log(spot / strike) + costOfCarry * timeToExpiry) / lognormalVol / lognormalVol / rootT - 0.5 * rootT; return sign * Math.exp(-interestRate * timeToExpiry) * NORMAL.getPDF(d) * div; }
/** * Compute driftless (forward) theta price of cash-or-nothing option * * @param forward The forward * @param strike The strike * @param timeToExpiry The time to expiry * @param lognormalVol The log-normal volatility * @param isCall True for calls, false for puts * @return The option price */ public static double driftlessTheta( final double forward, final double strike, final double timeToExpiry, final double lognormalVol, final boolean isCall) { ArgumentChecker.isTrue(forward > 0.0, "negative/NaN forward; have {}", forward); ArgumentChecker.isTrue(strike > 0.0, "negative/NaN strike; have {}", strike); ArgumentChecker.isTrue(timeToExpiry > 0.0, "negative/NaN timeToExpiry; have {}", timeToExpiry); ArgumentChecker.isTrue(lognormalVol > 0.0, "negative/NaN lognormalVol; have {}", lognormalVol); final double sigmaRootT = lognormalVol * Math.sqrt(timeToExpiry); final double d = Math.log(forward / strike) / sigmaRootT - 0.5 * sigmaRootT; final double sign = isCall ? 1. : -1.; final double div = 0.5 * (-Math.log(forward / strike) / Math.pow(timeToExpiry, 1.5) / lognormalVol - 0.5 * lognormalVol / Math.pow(timeToExpiry, 0.5)); return -sign * NORMAL.getPDF(d) * div; }