/** * Copyright (C) 2014 - present by OpenGamma Inc. and the OpenGamma group of companies * * Please see distribution for license. */ package com.opengamma.analytics.financial.volatilityswap; import static org.testng.AssertJUnit.assertEquals; import static org.testng.AssertJUnit.assertTrue; import org.testng.annotations.Test; import com.opengamma.util.test.TestGroup; /** * */ @Test(groups = TestGroup.UNIT) public class CarrLeeNewlyIssuedSyntheticVolatilitySwapCalculatorTest { private final static CarrLeeNewlyIssuedSyntheticVolatilitySwapCalculator MODEL = new CarrLeeNewlyIssuedSyntheticVolatilitySwapCalculator(); private static final double EPS = 1.e-13; /** * */ @Test public void sampleData1Test() { final double timeToExpiry = 1.5; final double spot = 49.; // final double forward = 102.; // final double interestRate = Math.log(forward / spot) / timeToExpiry; final double interestRate = -0.05; final double dividend = -0.01; final double forward = spot * Math.exp((interestRate - dividend) * timeToExpiry); final double[] putStrikes = new double[] {30., 40. }; final double[] callStrikes = new double[] {50., 60., 70. }; final int nCalls = callStrikes.length; final int nPuts = putStrikes.length; final double[] callVols = new double[nCalls]; final double[] putVols = new double[nPuts]; for (int i = 0; i < nCalls; ++i) { callVols[i] = 0.5 - 0.005 * (callStrikes[i] - 50.); } for (int i = 0; i < nPuts; ++i) { putVols[i] = 0.5 - 0.005 * (putStrikes[i] - 50.); } final double strdVol = 0.5 - 0.005 * (forward - 50.); final VolatilitySwapCalculatorResult res = MODEL.evaluate(spot, putStrikes, callStrikes, timeToExpiry, interestRate, dividend, putVols, strdVol, callVols); final double ref = 57.538816886509770; assertEquals(ref, res.getFairValue(), ref * EPS); final double[] expPuts = new double[] {0.513350614584648, 0.308758357270425 }; final double[] putPrems = new double[] {4.90559632142506, 9.19600014626863 }; final double[] expCalls = new double[] {-0.154238701620069, -0.152104062947836, -0.116537598619695 }; final double[] callPrems = new double[] {10.4905519833061, 6.29326958461010, 3.23838983555186 }; final double expStrd = 2.217562648068431; final double strdPrem = 24.820912695461015; final double expWithoutCash = 57.446886504492230; final double cash = 0.091930382017545; for (int i = 0; i < nPuts; ++i) { assertEquals(putPrems[i], res.getPutPrices()[i], Math.max(Math.abs(putPrems[i]), 1.) * EPS); assertEquals(expPuts[i], res.getPutWeights()[i], Math.max(Math.abs(expPuts[i]), 1.) * EPS); } { assertEquals(expStrd, res.getStraddleWeight(), Math.max(Math.abs(expStrd), 1.) * EPS); assertEquals(strdPrem, res.getStraddlePrice(), Math.max(Math.abs(strdPrem), 1.) * EPS); } for (int i = 0; i < nCalls; ++i) { assertEquals(callPrems[i], res.getCallPrices()[i], Math.max(Math.abs(callPrems[i]), 1.) * EPS); assertEquals(expCalls[i], res.getCallWeights()[i], Math.max(Math.abs(expCalls[i]), 1.) * EPS); } assertEquals(cash, res.getCash(), Math.max(Math.abs(cash), 1.) * EPS); assertEquals(expWithoutCash, res.getOptionTotal(), Math.max(Math.abs(expWithoutCash), 1.) * EPS); } /** * */ @Test public void noModTest() { final double timeToExpiry = 1.; final double interestRate = 0.1; final double dividend = 0.04; final double forward = 45.; final double spot = forward * Math.exp(-(interestRate - dividend) * timeToExpiry); final double[] putStrikes = new double[] {30., 40. }; final double[] callStrikes = new double[] {50., 60., 70. }; final int nCalls = callStrikes.length; final int nPuts = putStrikes.length; final double[] callVols = new double[nCalls]; final double[] putVols = new double[nPuts]; for (int i = 0; i < nCalls; ++i) { callVols[i] = 0.5 - 0.005 * (callStrikes[i] - 50.); } for (int i = 0; i < nPuts; ++i) { putVols[i] = 0.5 - 0.005 * (putStrikes[i] - 50.); } final double strdVol = 0.5 - 0.005 * (forward - 50.); final VolatilitySwapCalculatorResult res = MODEL.evaluate(spot, putStrikes, callStrikes, timeToExpiry, interestRate, dividend, putVols, strdVol, callVols); final double ref = 48.733554853596400; assertEquals(ref, res.getFairValue(), ref * EPS); final double[] expPuts = new double[] {0.632296228517047, 0.380459348608907 }; final double[] putPrems = new double[] {2.89530163120534, 6.25593528240724 }; final double[] expCalls = new double[] {-0.257443117987717, -0.187547911423368, -0.143731501185040 }; final double[] callPrems = new double[] {6.40625025668058, 3.29997011943255, 1.36333840440528 }; final double expStrd = 2.785142527367778; final double strdPrem = 16.862334153913586; final double expWithoutCash = 48.710719107228470; final double cash = 0.022835746367929; for (int i = 0; i < nPuts; ++i) { assertEquals(putPrems[i], res.getPutPrices()[i], Math.max(Math.abs(putPrems[i]), 1.) * EPS); assertEquals(expPuts[i], res.getPutWeights()[i], Math.max(Math.abs(expPuts[i]), 1.) * EPS); } { assertEquals(expStrd, res.getStraddleWeight(), Math.max(Math.abs(expStrd), 1.) * EPS); assertEquals(strdPrem, res.getStraddlePrice(), Math.max(Math.abs(strdPrem), 1.) * EPS); } for (int i = 0; i < nCalls; ++i) { assertEquals(callPrems[i], res.getCallPrices()[i], Math.max(Math.abs(callPrems[i]), 1.) * EPS); assertEquals(expCalls[i], res.getCallWeights()[i], Math.max(Math.abs(expCalls[i]), 1.) * EPS); } assertEquals(cash, res.getCash(), Math.max(Math.abs(cash), 1.) * EPS); assertEquals(expWithoutCash, res.getOptionTotal(), Math.max(Math.abs(expWithoutCash), 1.) * EPS); } /** * */ @Test public void sampleData2Test() { final double timeToExpiry = 0.5; final double spot = 100.; // final double forward = 102.; // final double interestRate = Math.log(forward / spot) / timeToExpiry; final double interestRate = 0.04; final double forward = spot * Math.exp(interestRate * timeToExpiry); final double[] callStrikes = new double[] {105., 110., 115., 120., 125., 130. }; final double[] putStrikes = new double[] {60., 65., 70., 75., 80., 85., 90., 95., 100. }; final int nCalls = callStrikes.length; final int nPuts = putStrikes.length; final double[] callVols = new double[nCalls]; final double[] putVols = new double[nPuts]; for (int i = 0; i < nCalls; ++i) { callVols[i] = 0.2 - 0.002 * (callStrikes[i] - 100.); } for (int i = 0; i < nPuts; ++i) { putVols[i] = 0.2 - 0.002 * (putStrikes[i] - 100.); } final double strdVol = 0.2 - 0.002 * (forward - 100.); final VolatilitySwapCalculatorResult res = MODEL.evaluate(spot, putStrikes, callStrikes, timeToExpiry, interestRate, 0., putVols, strdVol, callVols); final double ref = 19.408; assertEquals(ref, res.getFairValue(), ref * 1.e-4); final double[] expPuts = new double[] {0.109, 0.094, 0.083, 0.073, 0.065, 0.059, 0.053, 0.048, 0.036 }; final double[] putPrems = new double[] {0.02, 0.05, 0.11, 0.25, 0.51, 0.97, 1.74, 2.92, 4.65 }; final double[] expCalls = new double[] {-0.040, -0.037, -0.035, -0.032, -0.030, -0.028 }; final double[] callPrems = new double[] {4.10, 2.26, 1.07, 0.42, 0.12, 0.03 }; final double expStrd = 1.737; final double strdPrem = 11.05; final double expWithoutCash = 19.412; final double cash = -0.004; for (int i = 0; i < nPuts; ++i) { assertEquals(putPrems[i], res.getPutPrices()[i], 1.e-2); assertEquals(expPuts[i], res.getPutWeights()[i], 1.e-3); } { assertEquals(expStrd, res.getStraddleWeight(), 1.e-3); assertEquals(strdPrem, res.getStraddlePrice(), 1.e-2); } for (int i = 0; i < nCalls; ++i) { assertEquals(callPrems[i], res.getCallPrices()[i], 1.e-2); assertEquals(expCalls[i], res.getCallWeights()[i], 1.e-3); } assertEquals(cash, res.getCash(), 5. * 1.e-4); assertEquals(expWithoutCash, res.getOptionTotal(), 5. * 1.e-4); } /** * */ @Test public void errorTest() { final double timeToExpiry = 1.2; final double spot = 45.; // final double forward = 102.; // final double interestRate = Math.log(forward / spot) / timeToExpiry; final double interestRate = 0.01; final double dividend = 0.005; final double forward = spot * Math.exp(interestRate * timeToExpiry); final double[] putStrikes = new double[] {35., 40., 45, }; final double[] callStrikes = new double[] {50., 55. }; final int nCalls = callStrikes.length; final int nPuts = putStrikes.length; final double[] callVols = new double[nCalls]; final double[] putVols = new double[nPuts]; for (int i = 0; i < nCalls; ++i) { callVols[i] = 0.5 - 0.005 * (callStrikes[i] - 50.); } for (int i = 0; i < nPuts; ++i) { putVols[i] = 0.5 - 0.005 * (putStrikes[i] - 50.); } final double strdVol = 0.5 - 0.005 * (forward - 50.); try { MODEL.evaluate(-spot, putStrikes, callStrikes, timeToExpiry, interestRate, dividend, putVols, strdVol, callVols); throw new RuntimeException(); } catch (Exception e) { assertTrue(e instanceof IllegalArgumentException); } try { MODEL.evaluate(spot, putStrikes, callStrikes, -timeToExpiry, interestRate, dividend, putVols, strdVol, callVols); throw new RuntimeException(); } catch (Exception e) { assertTrue(e instanceof IllegalArgumentException); } try { MODEL.evaluate(spot, putStrikes, callStrikes, timeToExpiry, interestRate, dividend, putVols, -strdVol, callVols); throw new RuntimeException(); } catch (Exception e) { assertTrue(e instanceof IllegalArgumentException); } try { MODEL.evaluate(spot, new double[] {40., 45, }, callStrikes, timeToExpiry, interestRate, dividend, putVols, strdVol, callVols); throw new RuntimeException(); } catch (Exception e) { assertTrue(e instanceof IllegalArgumentException); } try { MODEL.evaluate(spot, putStrikes, new double[] {35., 40., 45, }, timeToExpiry, interestRate, dividend, putVols, strdVol, callVols); throw new RuntimeException(); } catch (Exception e) { assertTrue(e instanceof IllegalArgumentException); } try { MODEL.evaluate(1., new double[] {-10., -5., 0, }, new double[] {5., 10. }, timeToExpiry, interestRate, dividend, putVols, strdVol, callVols); throw new RuntimeException(); } catch (Exception e) { assertTrue(e instanceof IllegalArgumentException); } try { MODEL.evaluate(spot, putStrikes, new double[] {-50., 55. }, timeToExpiry, interestRate, dividend, putVols, strdVol, callVols); throw new RuntimeException(); } catch (Exception e) { assertTrue(e instanceof IllegalArgumentException); } try { MODEL.evaluate(spot, putStrikes, callStrikes, timeToExpiry, interestRate, dividend, new double[] {0.5, -0.2, 0.3 }, strdVol, callVols); throw new RuntimeException(); } catch (Exception e) { assertTrue(e instanceof IllegalArgumentException); } try { MODEL.evaluate(spot, putStrikes, callStrikes, timeToExpiry, interestRate, dividend, putVols, strdVol, new double[] {-0.3, 0.5 }); throw new RuntimeException(); } catch (Exception e) { assertTrue(e instanceof IllegalArgumentException); } try { MODEL.evaluate(spot, new double[] {35., 40., 42. }, callStrikes, timeToExpiry, interestRate, dividend, putVols, strdVol, callVols); throw new RuntimeException(); } catch (Exception e) { assertTrue(e instanceof IllegalArgumentException); } try { MODEL.evaluate(spot, putStrikes, new double[] {53., 55. }, timeToExpiry, interestRate, dividend, putVols, strdVol, callVols); throw new RuntimeException(); } catch (Exception e) { assertTrue(e instanceof IllegalArgumentException); } try { MODEL.evaluate(spot + 5., putStrikes, callStrikes, timeToExpiry, interestRate, dividend, putVols, strdVol, callVols); throw new RuntimeException(); } catch (Exception e) { assertTrue(e instanceof IllegalArgumentException); } try { MODEL.evaluate(spot - 5., putStrikes, callStrikes, timeToExpiry, interestRate, dividend, putVols, strdVol, callVols); throw new RuntimeException(); } catch (Exception e) { assertTrue(e instanceof IllegalArgumentException); } } }