@Test public void greekTest() { final LatticeSpecification[] lattices = new LatticeSpecification[] { new CoxRossRubinsteinLatticeSpecification(), new JarrowRuddLatticeSpecification(), new TrigeorgisLatticeSpecification(), new JabbourKraminYoungLatticeSpecification(), new TianLatticeSpecification() }; final boolean[] tfSet = new boolean[] {true, false}; for (final LatticeSpecification lattice : lattices) { for (final boolean isCall : tfSet) { for (final double strike : STRIKES) { for (final double interest : INTERESTS) { for (final double vol : VOLS) { final int[] choicesSteps = new int[] {31, 112, 301}; for (final int nSteps : choicesSteps) { for (final double dividend : DIVIDENDS) { final OptionFunctionProvider1D function = new EuropeanVanillaOptionFunctionProvider(strike, TIME, nSteps, isCall); final GreekResultCollection resDiv = _model.getGreeks(lattice, function, SPOT, vol, interest, dividend); final double priceDiv = BlackScholesFormulaRepository.price( SPOT, strike, TIME, vol, interest, interest - dividend, isCall); final double refPriceDiv = Math.max(Math.abs(priceDiv), 1.) / Math.sqrt(nSteps); assertEquals(resDiv.get(Greek.FAIR_PRICE), priceDiv, refPriceDiv); final double deltaDiv = BlackScholesFormulaRepository.delta( SPOT, strike, TIME, vol, interest, interest - dividend, isCall); final double refDeltaDiv = Math.max(Math.abs(deltaDiv), 1.) / Math.sqrt(nSteps); assertEquals(resDiv.get(Greek.DELTA), deltaDiv, refDeltaDiv); final double gammaDiv = BlackScholesFormulaRepository.gamma( SPOT, strike, TIME, vol, interest, interest - dividend); final double refGammaDiv = Math.max(Math.abs(gammaDiv), 1.) / Math.sqrt(nSteps); assertEquals(resDiv.get(Greek.GAMMA), gammaDiv, refGammaDiv); final double thetaDiv = BlackScholesFormulaRepository.theta( SPOT, strike, TIME, vol, interest, interest - dividend, isCall); final double refThetaDiv = Math.max(Math.abs(thetaDiv), 1.) / Math.sqrt(nSteps); assertEquals(resDiv.get(Greek.THETA), thetaDiv, refThetaDiv); } } } } } } } }
@Test public void greekLeisenReimerTest() { final LatticeSpecification lattice = new LeisenReimerLatticeSpecification(); final boolean[] tfSet = new boolean[] {true, false}; for (final boolean isCall : tfSet) { for (final double strike : STRIKES) { for (final double interest : INTERESTS) { for (final double vol : VOLS) { final int[] choicesSteps = new int[] {31, 109, 301}; for (final int nSteps : choicesSteps) { for (final double dividend : DIVIDENDS) { final OptionFunctionProvider1D function = new EuropeanVanillaOptionFunctionProvider(strike, TIME, nSteps, isCall); final GreekResultCollection resDiv = _model.getGreeks(lattice, function, SPOT, vol, interest, dividend); final double priceDiv = BlackScholesFormulaRepository.price( SPOT, strike, TIME, vol, interest, interest - dividend, isCall); final double refPriceDiv = Math.max(Math.abs(priceDiv), 1.) / nSteps; assertEquals(resDiv.get(Greek.FAIR_PRICE), priceDiv, refPriceDiv); final double deltaDiv = BlackScholesFormulaRepository.delta( SPOT, strike, TIME, vol, interest, interest - dividend, isCall); final double refDeltaDiv = Math.max(Math.abs(deltaDiv), 1.) / nSteps; assertEquals(resDiv.get(Greek.DELTA), deltaDiv, refDeltaDiv); final double gammaDiv = BlackScholesFormulaRepository.gamma( SPOT, strike, TIME, vol, interest, interest - dividend); final double refGammaDiv = Math.max(Math.abs(gammaDiv), 1.) / nSteps; assertEquals(resDiv.get(Greek.GAMMA), gammaDiv, refGammaDiv); final double thetaDiv = BlackScholesFormulaRepository.theta( SPOT, strike, TIME, vol, interest, interest - dividend, isCall); final double refThetaDiv = Math.max(Math.abs(thetaDiv), 1.) / nSteps; assertEquals(resDiv.get(Greek.THETA), thetaDiv, refThetaDiv * 10.); } } } } } } }
/** The dividend is cash or proportional to asset price */ @Test public void greeksDiscreteDividendLatticeTest() { final LatticeSpecification[] lattices = new LatticeSpecification[] { new CoxRossRubinsteinLatticeSpecification(), new JarrowRuddLatticeSpecification(), new TrigeorgisLatticeSpecification(), new JabbourKraminYoungLatticeSpecification(), new TianLatticeSpecification(), new LeisenReimerLatticeSpecification() }; final double[] propDividends = new double[] {0.01, 0.01, 0.01}; final double[] cashDividends = new double[] {5., 10., 8.}; final double[] dividendTimes = new double[] {TIME / 420., TIME / 203., TIME / 2.}; final boolean[] tfSet = new boolean[] {true, false}; for (final LatticeSpecification lattice : lattices) { for (final boolean isCall : tfSet) { for (final double strike : STRIKES) { for (final double interest : INTERESTS) { for (final double vol : VOLS) { final int nSteps = 401; final double resSpot = SPOT * (1. - propDividends[0]) * (1. - propDividends[1]) * (1. - propDividends[2]); final double modSpot = SPOT - cashDividends[0] * Math.exp(-interest * dividendTimes[0]) - cashDividends[1] * Math.exp(-interest * dividendTimes[1]) - cashDividends[2] * Math.exp(-interest * dividendTimes[2]); final double exactPriceProp = BlackScholesFormulaRepository.price( resSpot, strike, TIME, vol, interest, interest, isCall); final double exactDeltaProp = BlackScholesFormulaRepository.delta( resSpot, strike, TIME, vol, interest, interest, isCall); final double exactGammaProp = BlackScholesFormulaRepository.gamma( resSpot, strike, TIME, vol, interest, interest); final double exactThetaProp = BlackScholesFormulaRepository.theta( resSpot, strike, TIME, vol, interest, interest, isCall); final double appPriceCash = BlackScholesFormulaRepository.price( modSpot, strike, TIME, vol, interest, interest, isCall); final double appDeltaCash = BlackScholesFormulaRepository.delta( modSpot, strike, TIME, vol, interest, interest, isCall); final double appGammaCash = BlackScholesFormulaRepository.gamma( modSpot, strike, TIME, vol, interest, interest); final double appThetaCash = BlackScholesFormulaRepository.theta( modSpot, strike, TIME, vol, interest, interest, isCall); final OptionFunctionProvider1D function = new EuropeanVanillaOptionFunctionProvider(strike, TIME, nSteps, isCall); final DividendFunctionProvider cashDividend = new CashDividendFunctionProvider(dividendTimes, cashDividends); final DividendFunctionProvider propDividend = new ProportionalDividendFunctionProvider(dividendTimes, propDividends); final GreekResultCollection resProp = _model.getGreeks(lattice, function, SPOT, vol, interest, propDividend); final GreekResultCollection resCash = _model.getGreeks(lattice, function, SPOT, vol, interest, cashDividend); assertEquals( resProp.get(Greek.FAIR_PRICE), exactPriceProp, Math.max(1., Math.abs(exactPriceProp)) * 1.e-2); assertEquals( resProp.get(Greek.DELTA), exactDeltaProp, Math.max(1., Math.abs(exactDeltaProp)) * 1.e-1); assertEquals( resProp.get(Greek.GAMMA), exactGammaProp, Math.max(1., Math.abs(exactGammaProp)) * 1.e-1); assertEquals( resProp.get(Greek.THETA), exactThetaProp, Math.max(1., Math.abs(exactThetaProp)) * 1.e-1); assertEquals( resCash.get(Greek.FAIR_PRICE), appPriceCash, Math.max(1., Math.abs(appPriceCash)) * 1.e-2); assertEquals( resCash.get(Greek.DELTA), appDeltaCash, Math.max(1., Math.abs(appDeltaCash)) * 1.e-1); assertEquals( resCash.get(Greek.GAMMA), appGammaCash, Math.max(1., Math.abs(appGammaCash)) * 1.e-1); assertEquals( resCash.get(Greek.THETA), appThetaCash, Math.max(1., Math.abs(appThetaCash))); if (lattice instanceof CoxRossRubinsteinLatticeSpecification || lattice instanceof JarrowRuddLatticeSpecification || lattice instanceof TrigeorgisLatticeSpecification || lattice instanceof TianLatticeSpecification) { final GreekResultCollection resPropTrinomial = _modelTrinomial.getGreeks(lattice, function, SPOT, vol, interest, propDividend); final GreekResultCollection resCashTrinomial = _modelTrinomial.getGreeks(lattice, function, SPOT, vol, interest, cashDividend); assertEquals( resPropTrinomial.get(Greek.FAIR_PRICE), resProp.get(Greek.FAIR_PRICE), Math.max(1., Math.abs(resProp.get(Greek.FAIR_PRICE))) * 1.e-2); assertEquals( resPropTrinomial.get(Greek.DELTA), resProp.get(Greek.DELTA), Math.max(1., Math.abs(resProp.get(Greek.DELTA))) * 1.e-2); assertEquals( resPropTrinomial.get(Greek.GAMMA), resProp.get(Greek.GAMMA), Math.max(1., Math.abs(resProp.get(Greek.GAMMA))) * 1.e-2); assertEquals( resPropTrinomial.get(Greek.THETA), resProp.get(Greek.THETA), Math.max(1., Math.abs(resProp.get(Greek.THETA))) * 1.e-1); assertEquals( resCashTrinomial.get(Greek.FAIR_PRICE), resCash.get(Greek.FAIR_PRICE), Math.max(1., Math.abs(resCash.get(Greek.FAIR_PRICE))) * 1.e-2); assertEquals( resCashTrinomial.get(Greek.DELTA), resCash.get(Greek.DELTA), Math.max(1., Math.abs(resCash.get(Greek.DELTA))) * 1.e-2); assertEquals( resCashTrinomial.get(Greek.GAMMA), resCash.get(Greek.GAMMA), Math.max(1., Math.abs(resCash.get(Greek.GAMMA))) * 1.e-2); assertEquals( resCashTrinomial.get(Greek.THETA), resCash.get(Greek.THETA), Math.max(1., Math.abs(resCash.get(Greek.THETA))) * 1.e-1); } } } } } } }