/*
Copyright (C) 2008 Richard Gomes
This source code is release under the BSD License.
This file is part of JQuantLib, a free-software/open-source library
for financial quantitative analysts and developers - http://jquantlib.org/
JQuantLib is free software: you can redistribute it and/or modify it
under the terms of the JQuantLib license. You should have received a
copy of the license along with this program; if not, please email
. The license is also available online at
.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the license for more details.
JQuantLib is based on QuantLib. http://quantlib.org/
When applicable, the original copyright notice follows this notice.
*/
package org.jquantlib.testsuite.instruments;
import static org.junit.Assert.fail;
import org.jquantlib.QL;
import org.jquantlib.Settings;
import org.jquantlib.daycounters.Actual360;
import org.jquantlib.daycounters.DayCounter;
import org.jquantlib.exercise.EuropeanExercise;
import org.jquantlib.exercise.Exercise;
import org.jquantlib.instruments.BarrierOption;
import org.jquantlib.instruments.BarrierType;
import org.jquantlib.instruments.Option;
import org.jquantlib.instruments.PlainVanillaPayoff;
import org.jquantlib.instruments.StrikedTypePayoff;
import org.jquantlib.pricingengines.PricingEngine;
import org.jquantlib.pricingengines.barrier.AnalyticBarrierEngine;
import org.jquantlib.processes.BlackScholesMertonProcess;
import org.jquantlib.quotes.Handle;
import org.jquantlib.quotes.Quote;
import org.jquantlib.quotes.SimpleQuote;
import org.jquantlib.termstructures.BlackVolTermStructure;
import org.jquantlib.termstructures.YieldTermStructure;
import org.jquantlib.testsuite.util.Utilities;
import org.jquantlib.time.Date;
import org.junit.Test;
public class BarrierOptionTest {
public BarrierOptionTest() {
QL.info("::::: "+this.getClass().getSimpleName()+" :::::");
}
@Test
public void testHaugValues() {
QL.info("Testing barrier options against Haug's values...");
final NewBarrierOptionData values[] = {
//
// The data below are from "Option pricing formulas", E.G. Haug, McGraw-Hill 1998 pag. 72
//
// barrierType, barrier, rebate, type, strike, s, q, r, t, v, result, tol
new NewBarrierOptionData( BarrierType.DownOut, 95.0, 3.0, Option.Type.Call, 90, 100.0, 0.04, 0.08, 0.50, 0.25, 9.0246, 1.0e-4),
new NewBarrierOptionData( BarrierType.DownOut, 95.0, 3.0, Option.Type.Call, 100, 100.0, 0.04, 0.08, 0.50, 0.25, 6.7924, 1.0e-4),
new NewBarrierOptionData( BarrierType.DownOut, 95.0, 3.0, Option.Type.Call, 110, 100.0, 0.04, 0.08, 0.50, 0.25, 4.8759, 1.0e-4),
new NewBarrierOptionData( BarrierType.DownOut, 100.0, 3.0, Option.Type.Call, 90, 100.0, 0.04, 0.08, 0.50, 0.25, 3.0000, 1.0e-4),
new NewBarrierOptionData( BarrierType.DownOut, 100.0, 3.0, Option.Type.Call, 100, 100.0, 0.04, 0.08, 0.50, 0.25, 3.0000, 1.0e-4),
new NewBarrierOptionData( BarrierType.DownOut, 100.0, 3.0, Option.Type.Call, 110, 100.0, 0.04, 0.08, 0.50, 0.25, 3.0000, 1.0e-4),
new NewBarrierOptionData( BarrierType.UpOut, 105.0, 3.0, Option.Type.Call, 90, 100.0, 0.04, 0.08, 0.50, 0.25, 2.6789, 1.0e-4),
new NewBarrierOptionData( BarrierType.UpOut, 105.0, 3.0, Option.Type.Call, 100, 100.0, 0.04, 0.08, 0.50, 0.25, 2.3580, 1.0e-4),
new NewBarrierOptionData( BarrierType.UpOut, 105.0, 3.0, Option.Type.Call, 110, 100.0, 0.04, 0.08, 0.50, 0.25, 2.3453, 1.0e-4),
new NewBarrierOptionData( BarrierType.DownIn, 95.0, 3.0, Option.Type.Call, 90, 100.0, 0.04, 0.08, 0.50, 0.25, 7.7627, 1.0e-4),
new NewBarrierOptionData( BarrierType.DownIn, 95.0, 3.0, Option.Type.Call, 100, 100.0, 0.04, 0.08, 0.50, 0.25, 4.0109, 1.0e-4),
new NewBarrierOptionData( BarrierType.DownIn, 95.0, 3.0, Option.Type.Call, 110, 100.0, 0.04, 0.08, 0.50, 0.25, 2.0576, 1.0e-4),
new NewBarrierOptionData( BarrierType.DownIn, 100.0, 3.0, Option.Type.Call, 90, 100.0, 0.04, 0.08, 0.50, 0.25, 13.8333, 1.0e-4),
new NewBarrierOptionData( BarrierType.DownIn, 100.0, 3.0, Option.Type.Call, 100, 100.0, 0.04, 0.08, 0.50, 0.25, 7.8494, 1.0e-4),
new NewBarrierOptionData( BarrierType.DownIn, 100.0, 3.0, Option.Type.Call, 110, 100.0, 0.04, 0.08, 0.50, 0.25, 3.9795, 1.0e-4),
new NewBarrierOptionData( BarrierType.UpIn, 105.0, 3.0, Option.Type.Call, 90, 100.0, 0.04, 0.08, 0.50, 0.25, 14.1112, 1.0e-4),
new NewBarrierOptionData( BarrierType.UpIn, 105.0, 3.0, Option.Type.Call, 100, 100.0, 0.04, 0.08, 0.50, 0.25, 8.4482, 1.0e-4),
new NewBarrierOptionData( BarrierType.UpIn, 105.0, 3.0, Option.Type.Call, 110, 100.0, 0.04, 0.08, 0.50, 0.25, 4.5910, 1.0e-4),
new NewBarrierOptionData( BarrierType.DownOut, 95.0, 3.0, Option.Type.Call, 90, 100.0, 0.04, 0.08, 0.50, 0.30, 8.8334, 1.0e-4),
new NewBarrierOptionData( BarrierType.DownOut, 95.0, 3.0, Option.Type.Call, 100, 100.0, 0.04, 0.08, 0.50, 0.30, 7.0285, 1.0e-4),
new NewBarrierOptionData( BarrierType.DownOut, 95.0, 3.0, Option.Type.Call, 110, 100.0, 0.04, 0.08, 0.50, 0.30, 5.4137, 1.0e-4),
new NewBarrierOptionData( BarrierType.DownOut, 100.0, 3.0, Option.Type.Call, 90, 100.0, 0.04, 0.08, 0.50, 0.30, 3.0000, 1.0e-4),
new NewBarrierOptionData( BarrierType.DownOut, 100.0, 3.0, Option.Type.Call, 100, 100.0, 0.04, 0.08, 0.50, 0.30, 3.0000, 1.0e-4),
new NewBarrierOptionData( BarrierType.DownOut, 100.0, 3.0, Option.Type.Call, 110, 100.0, 0.04, 0.08, 0.50, 0.30, 3.0000, 1.0e-4),
new NewBarrierOptionData( BarrierType.UpOut, 105.0, 3.0, Option.Type.Call, 90, 100.0, 0.04, 0.08, 0.50, 0.30, 2.6341, 1.0e-4),
new NewBarrierOptionData( BarrierType.UpOut, 105.0, 3.0, Option.Type.Call, 100, 100.0, 0.04, 0.08, 0.50, 0.30, 2.4389, 1.0e-4),
new NewBarrierOptionData( BarrierType.UpOut, 105.0, 3.0, Option.Type.Call, 110, 100.0, 0.04, 0.08, 0.50, 0.30, 2.4315, 1.0e-4),
new NewBarrierOptionData( BarrierType.DownIn, 95.0, 3.0, Option.Type.Call, 90, 100.0, 0.04, 0.08, 0.50, 0.30, 9.0093, 1.0e-4),
new NewBarrierOptionData( BarrierType.DownIn, 95.0, 3.0, Option.Type.Call, 100, 100.0, 0.04, 0.08, 0.50, 0.30, 5.1370, 1.0e-4),
new NewBarrierOptionData( BarrierType.DownIn, 95.0, 3.0, Option.Type.Call, 110, 100.0, 0.04, 0.08, 0.50, 0.30, 2.8517, 1.0e-4),
new NewBarrierOptionData( BarrierType.DownIn, 100.0, 3.0, Option.Type.Call, 90, 100.0, 0.04, 0.08, 0.50, 0.30, 14.8816, 1.0e-4),
new NewBarrierOptionData( BarrierType.DownIn, 100.0, 3.0, Option.Type.Call, 100, 100.0, 0.04, 0.08, 0.50, 0.30, 9.2045, 1.0e-4),
new NewBarrierOptionData( BarrierType.DownIn, 100.0, 3.0, Option.Type.Call, 110, 100.0, 0.04, 0.08, 0.50, 0.30, 5.3043, 1.0e-4),
new NewBarrierOptionData( BarrierType.UpIn, 105.0, 3.0, Option.Type.Call, 90, 100.0, 0.04, 0.08, 0.50, 0.30, 15.2098, 1.0e-4),
new NewBarrierOptionData( BarrierType.UpIn, 105.0, 3.0, Option.Type.Call, 100, 100.0, 0.04, 0.08, 0.50, 0.30, 9.7278, 1.0e-4),
new NewBarrierOptionData( BarrierType.UpIn, 105.0, 3.0, Option.Type.Call, 110, 100.0, 0.04, 0.08, 0.50, 0.30, 5.8350, 1.0e-4),
new NewBarrierOptionData( BarrierType.DownOut, 95.0, 3.0, Option.Type.Put, 90, 100.0, 0.04, 0.08, 0.50, 0.25, 2.2798, 1.0e-4 ),
new NewBarrierOptionData( BarrierType.DownOut, 95.0, 3.0, Option.Type.Put, 100, 100.0, 0.04, 0.08, 0.50, 0.25, 2.2947, 1.0e-4 ),
new NewBarrierOptionData( BarrierType.DownOut, 95.0, 3.0, Option.Type.Put, 110, 100.0, 0.04, 0.08, 0.50, 0.25, 2.6252, 1.0e-4 ),
new NewBarrierOptionData( BarrierType.DownOut, 100.0, 3.0, Option.Type.Put, 90, 100.0, 0.04, 0.08, 0.50, 0.25, 3.0000, 1.0e-4 ),
new NewBarrierOptionData( BarrierType.DownOut, 100.0, 3.0, Option.Type.Put, 100, 100.0, 0.04, 0.08, 0.50, 0.25, 3.0000, 1.0e-4 ),
new NewBarrierOptionData( BarrierType.DownOut, 100.0, 3.0, Option.Type.Put, 110, 100.0, 0.04, 0.08, 0.50, 0.25, 3.0000, 1.0e-4 ),
new NewBarrierOptionData( BarrierType.UpOut, 105.0, 3.0, Option.Type.Put, 90, 100.0, 0.04, 0.08, 0.50, 0.25, 3.7760, 1.0e-4 ),
new NewBarrierOptionData( BarrierType.UpOut, 105.0, 3.0, Option.Type.Put, 100, 100.0, 0.04, 0.08, 0.50, 0.25, 5.4932, 1.0e-4 ),
new NewBarrierOptionData( BarrierType.UpOut, 105.0, 3.0, Option.Type.Put, 110, 100.0, 0.04, 0.08, 0.50, 0.25, 7.5187, 1.0e-4 ),
new NewBarrierOptionData( BarrierType.DownIn, 95.0, 3.0, Option.Type.Put, 90, 100.0, 0.04, 0.08, 0.50, 0.25, 2.9586, 1.0e-4 ),
new NewBarrierOptionData( BarrierType.DownIn, 95.0, 3.0, Option.Type.Put, 100, 100.0, 0.04, 0.08, 0.50, 0.25, 6.5677, 1.0e-4 ),
new NewBarrierOptionData( BarrierType.DownIn, 95.0, 3.0, Option.Type.Put, 110, 100.0, 0.04, 0.08, 0.50, 0.25, 11.9752, 1.0e-4 ),
new NewBarrierOptionData( BarrierType.DownIn, 100.0, 3.0, Option.Type.Put, 90, 100.0, 0.04, 0.08, 0.50, 0.25, 2.2845, 1.0e-4 ),
new NewBarrierOptionData( BarrierType.DownIn, 100.0, 3.0, Option.Type.Put, 100, 100.0, 0.04, 0.08, 0.50, 0.25, 5.9085, 1.0e-4 ),
new NewBarrierOptionData( BarrierType.DownIn, 100.0, 3.0, Option.Type.Put, 110, 100.0, 0.04, 0.08, 0.50, 0.25, 11.6465, 1.0e-4 ),
new NewBarrierOptionData( BarrierType.UpIn, 105.0, 3.0, Option.Type.Put, 90, 100.0, 0.04, 0.08, 0.50, 0.25, 1.4653, 1.0e-4 ),
new NewBarrierOptionData( BarrierType.UpIn, 105.0, 3.0, Option.Type.Put, 100, 100.0, 0.04, 0.08, 0.50, 0.25, 3.3721, 1.0e-4 ),
new NewBarrierOptionData( BarrierType.UpIn, 105.0, 3.0, Option.Type.Put, 110, 100.0, 0.04, 0.08, 0.50, 0.25, 7.0846, 1.0e-4 ),
new NewBarrierOptionData( BarrierType.DownOut, 95.0, 3.0, Option.Type.Put, 90, 100.0, 0.04, 0.08, 0.50, 0.30, 2.4170, 1.0e-4 ),
new NewBarrierOptionData( BarrierType.DownOut, 95.0, 3.0, Option.Type.Put, 100, 100.0, 0.04, 0.08, 0.50, 0.30, 2.4258, 1.0e-4 ),
new NewBarrierOptionData( BarrierType.DownOut, 95.0, 3.0, Option.Type.Put, 110, 100.0, 0.04, 0.08, 0.50, 0.30, 2.6246, 1.0e-4 ),
new NewBarrierOptionData( BarrierType.DownOut, 100.0, 3.0, Option.Type.Put, 90, 100.0, 0.04, 0.08, 0.50, 0.30, 3.0000, 1.0e-4 ),
new NewBarrierOptionData( BarrierType.DownOut, 100.0, 3.0, Option.Type.Put, 100, 100.0, 0.04, 0.08, 0.50, 0.30, 3.0000, 1.0e-4 ),
new NewBarrierOptionData( BarrierType.DownOut, 100.0, 3.0, Option.Type.Put, 110, 100.0, 0.04, 0.08, 0.50, 0.30, 3.0000, 1.0e-4 ),
new NewBarrierOptionData( BarrierType.UpOut, 105.0, 3.0, Option.Type.Put, 90, 100.0, 0.04, 0.08, 0.50, 0.30, 4.2293, 1.0e-4 ),
new NewBarrierOptionData( BarrierType.UpOut, 105.0, 3.0, Option.Type.Put, 100, 100.0, 0.04, 0.08, 0.50, 0.30, 5.8032, 1.0e-4 ),
new NewBarrierOptionData( BarrierType.UpOut, 105.0, 3.0, Option.Type.Put, 110, 100.0, 0.04, 0.08, 0.50, 0.30, 7.5649, 1.0e-4 ),
new NewBarrierOptionData( BarrierType.DownIn, 95.0, 3.0, Option.Type.Put, 90, 100.0, 0.04, 0.08, 0.50, 0.30, 3.8769, 1.0e-4 ),
new NewBarrierOptionData( BarrierType.DownIn, 95.0, 3.0, Option.Type.Put, 100, 100.0, 0.04, 0.08, 0.50, 0.30, 7.7989, 1.0e-4 ),
new NewBarrierOptionData( BarrierType.DownIn, 95.0, 3.0, Option.Type.Put, 110, 100.0, 0.04, 0.08, 0.50, 0.30, 13.3078, 1.0e-4 ),
new NewBarrierOptionData( BarrierType.DownIn, 100.0, 3.0, Option.Type.Put, 90, 100.0, 0.04, 0.08, 0.50, 0.30, 3.3328, 1.0e-4 ),
new NewBarrierOptionData( BarrierType.DownIn, 100.0, 3.0, Option.Type.Put, 100, 100.0, 0.04, 0.08, 0.50, 0.30, 7.2636, 1.0e-4 ),
new NewBarrierOptionData( BarrierType.DownIn, 100.0, 3.0, Option.Type.Put, 110, 100.0, 0.04, 0.08, 0.50, 0.30, 12.9713, 1.0e-4 ),
new NewBarrierOptionData( BarrierType.UpIn, 105.0, 3.0, Option.Type.Put, 90, 100.0, 0.04, 0.08, 0.50, 0.30, 2.0658, 1.0e-4 ),
new NewBarrierOptionData( BarrierType.UpIn, 105.0, 3.0, Option.Type.Put, 100, 100.0, 0.04, 0.08, 0.50, 0.30, 4.4226, 1.0e-4 ),
new NewBarrierOptionData( BarrierType.UpIn, 105.0, 3.0, Option.Type.Put, 110, 100.0, 0.04, 0.08, 0.50, 0.30, 8.3686, 1.0e-4 ),
//
// Data from "Going to Extreme: Correcting Simulation Bias in Exotic Option Valuation"
// D.R. Beaglehole, P.H. Dybvig and G. Zhou
// Financial Analysts Journal; Jan / Feb 1997; 53, 1
//
// barrierType, barrier, rebate, type, strike, s, q, r, t, v, result, tol
//---- new NewBarrierOptionData( BarrierType.DownOut, 45.0, 0.0, Option.Type.PUT, 50, 50.0,-0.05, 0.10, 0.25, 0.50, 4.032, 1.0e-3 ),
//---- new NewBarrierOptionData( BarrierType.DownOut, 45.0, 0.0, Option.Type.PUT, 50, 50.0,-0.05, 0.10, 1.00, 0.50, 5.477, 1.0e-3 )
};
final DayCounter dc = new Actual360();
final Date today = Date.todaysDate();
new Settings().setEvaluationDate(today);
final SimpleQuote spot = new SimpleQuote(0.0);
final SimpleQuote qRate = new SimpleQuote(0.0);
final YieldTermStructure qTS = Utilities.flatRate(today, qRate, dc);
final SimpleQuote rRate = new SimpleQuote(0.0);
final YieldTermStructure rTS = Utilities.flatRate(today, rRate, dc);
final SimpleQuote vol = new SimpleQuote(0.0);
final BlackVolTermStructure volTS = Utilities.flatVol(today, vol, dc);
for (final NewBarrierOptionData value : values) {
final Date exDate = today.add( timeToDays(value.t) );
final Exercise exercise = new EuropeanExercise(exDate);
spot.setValue(value.s);
qRate.setValue(value.q);
rRate.setValue(value.r);
vol.setValue(value.v);
final StrikedTypePayoff payoff = new PlainVanillaPayoff(value.type, value.strike);
final BlackScholesMertonProcess stochProcess = new BlackScholesMertonProcess(
new Handle(spot),
new Handle(qTS),
new Handle(rTS),
new Handle(volTS));
final PricingEngine engine = new AnalyticBarrierEngine(stochProcess);
final BarrierOption barrierOption = new BarrierOption(value.barrierType, value.barrier, value.rebate, payoff, exercise);
barrierOption.setPricingEngine(engine);
final double calculated = barrierOption.NPV();
final double expected = value.result;
final double error = Math.abs(calculated-expected);
if (error>value.tol) {
REPORT_FAILURE("value", value.barrierType, value.barrier,
value.rebate, payoff, exercise, value.s,
value.q, value.r, today, value.v,
expected, calculated, error, value.tol);
}
}
}
@Test
public void testBabsiriValues() {
QL.info("Testing barrier options against Babsiri's values...");
/**
* Data from
* "Simulating Path-Dependent Options: A New Approach"
* - M. El Babsiri and G. Noel
* Journal of Derivatives; Winter 1998; 6, 2
*/
final BarrierOptionData values[] = {
new BarrierOptionData( BarrierType.DownIn, 0.10, 100, 90, 0.07187, 0.0),
new BarrierOptionData( BarrierType.DownIn, 0.15, 100, 90, 0.60638, 0.0),
new BarrierOptionData( BarrierType.DownIn, 0.20, 100, 90, 1.64005, 0.0),
new BarrierOptionData( BarrierType.DownIn, 0.25, 100, 90, 2.98495, 0.0),
new BarrierOptionData( BarrierType.DownIn, 0.30, 100, 90, 4.50952, 0.0),
new BarrierOptionData( BarrierType.UpIn, 0.10, 100, 110, 4.79148, 0.0),
new BarrierOptionData( BarrierType.UpIn, 0.15, 100, 110, 7.08268, 0.0 ),
new BarrierOptionData( BarrierType.UpIn, 0.20, 100, 110, 9.11008, 0.0 ),
new BarrierOptionData( BarrierType.UpIn, 0.25, 100, 110, 11.06148, 0.0 ),
new BarrierOptionData( BarrierType.UpIn, 0.30, 100, 110, 12.98351, 0.0 )
};
final double underlyingPrice = 100.0;
final double rebate = 0.0;
final double r = 0.05;
final double q = 0.02;
final DayCounter dc = new Actual360();
final Date today = Date.todaysDate();
new Settings().setEvaluationDate(today);
final Quote underlying = new SimpleQuote(underlyingPrice);
final Quote qH_SME = new SimpleQuote(q);
final YieldTermStructure qTS = Utilities.flatRate(today, qH_SME, dc);
final Quote rH_SME = new SimpleQuote(r);
final YieldTermStructure rTS = Utilities.flatRate(today, rH_SME, dc);
final SimpleQuote volatility = new SimpleQuote(0.10);
final BlackVolTermStructure volTS = Utilities.flatVol(today, volatility, dc);
final Date exDate = today.add(360);
final Exercise exercise = new EuropeanExercise(exDate);
for (final BarrierOptionData value : values) {
volatility.setValue(value.volatility);
final StrikedTypePayoff callPayoff = new PlainVanillaPayoff(Option.Type.Call, value.strike);
final BlackScholesMertonProcess stochProcess = new BlackScholesMertonProcess(
new Handle(underlying),
new Handle(qTS),
new Handle(rTS),
new Handle(volTS));
final PricingEngine engine = new AnalyticBarrierEngine(stochProcess);
final BarrierOption barrierCallOption = new BarrierOption(value.barrierType, value.barrier, rebate, callPayoff, exercise);
barrierCallOption.setPricingEngine(engine);
final double calculated = barrierCallOption.NPV();
final double expected = value.callValue;
final double error = Math.abs(calculated - expected);
final double maxErrorAllowed = 1.0e-3;
if (error > maxErrorAllowed) {
REPORT_FAILURE("value", value.barrierType, value.barrier, rebate, callPayoff, exercise, underlyingPrice, q,
r, today, value.volatility, expected, calculated, error, maxErrorAllowed);
}
}
}
@Test
public void testBeagleholeValues() {
QL.info("Testing barrier options against Beaglehole's values...");
/**
* Data from
* "Going to Extreme: Correcting Simulation Bias in Exotic Option Valuation"
* - D.R. Beaglehole, P.H. Dybvig and G. Zhou
* Financial Analysts Journal; Jan / Feb 1997; 53, 1
*/
final BarrierOptionData values[] = {
new BarrierOptionData(BarrierType.DownOut, 0.50, 50, 45, 5.477, 0.0)
};
final double underlyingPrice = 50.0;
final double rebate = 0.0;
final double r = Math.log(1.1);
final double q = 0.00;
final DayCounter dc = new Actual360();
final Date today = Date.todaysDate();
new Settings().setEvaluationDate(today);
final Quote underlying = new SimpleQuote(underlyingPrice);
final Quote qH_SME = new SimpleQuote(q);
final YieldTermStructure qTS = Utilities.flatRate(today, qH_SME, dc);
final Quote rH_SME = new SimpleQuote(r);
final YieldTermStructure rTS = Utilities.flatRate(today, rH_SME, dc);
final SimpleQuote volatility = new SimpleQuote(0.10);
final BlackVolTermStructure volTS = Utilities.flatVol(today, volatility, dc);
final Date exDate = today.add(360);
final Exercise exercise = new EuropeanExercise(exDate);
for (final BarrierOptionData value : values) {
volatility.setValue(value.volatility);
final StrikedTypePayoff callPayoff = new PlainVanillaPayoff(Option.Type.Call, value.strike);
final BlackScholesMertonProcess stochProcess = new BlackScholesMertonProcess(
new Handle(underlying),
new Handle(qTS),
new Handle(rTS),
new Handle(volTS));
final PricingEngine engine = new AnalyticBarrierEngine(stochProcess);
final BarrierOption barrierCallOption = new BarrierOption(value.barrierType, value.barrier, rebate, callPayoff, exercise);
barrierCallOption.setPricingEngine(engine);
final double calculated = barrierCallOption.NPV();
final double expected = value.callValue;
final double error = Math.abs(calculated - expected);
final double maxErrorAllowed = 1.0e-3;
if (error > maxErrorAllowed) {
REPORT_FAILURE("value", value.barrierType, value.barrier, rebate, callPayoff, exercise, underlyingPrice, q,
r, today, value.volatility, expected, calculated, error, maxErrorAllowed);
}
}
//TODO: MC Barrier engine not implemented yet.
/*
final double maxMcRelativeErrorAllowed = 0.01;
final int timeSteps = 1;
final boolean brownianBridge = true;
final boolean antitheticVariate = false;
final boolean controlVariate = false;
final int requiredSamples = 131071; //2^17-1
final double requiredTolerance;
final int maxSamples = 1048575; // 2^20-1
final boolean isBiased = false;
final double seed = 10;
boost::shared_ptr mcEngine(
new MCBarrierEngine(timeSteps, brownianBridge,
antitheticVariate, controlVariate,
requiredSamples, requiredTolerance,
maxSamples, isBiased, seed));
barrierCallOption.setPricingEngine(mcEngine);
calculated = barrierCallOption.NPV();
error = std::fabs(calculated-expected)/expected;
if (error>maxMcRelativeErrorAllowed) {
REPORT_FAILURE("value", values[i].type, values[i].barrier,
rebate, callPayoff, exercise, underlyingPrice,
q, r, today, values[i].volatility,
expected, calculated, error,
maxMcRelativeErrorAllowed);
}
*/
}
// http://bugs.jquantlib.org/view.php?id=459
//
// void BarrierOptionTest::testPerturbative() {
// BOOST_MESSAGE("Testing perturbative engine for barrier options...");
//
// Real S = 100.0;
// Real rebate = 0.0;
// Rate r = 0.03;
// Rate q = 0.02;
//
// DayCounter dc = Actual360();
// Date today = Date::todaysDate();
//
// ---- This is future Java code, to be inserted when this code were translated
//FIXME: http://bugs.jquantlib.org/view.php?id=460
//new Settings().setEvaluationDate(today);
//
// boost::shared_ptr underlying(new SimpleQuote(S));
// boost::shared_ptr qTS = flatRate(today, q, dc);
// boost::shared_ptr rTS = flatRate(today, r, dc);
//
// std::vector dates(2);
// std::vector vols(2);
//
// dates[0] = today + 90; vols[0] = 0.105;
// dates[1] = today + 180; vols[1] = 0.11;
//
// boost::shared_ptr volTS(
// new BlackVarianceCurve(today, dates, vols, dc));
//
// boost::shared_ptr stochProcess(
// new BlackScholesMertonProcess(Handle(underlying),
// Handle(qTS),
// Handle(rTS),
// Handle(volTS)));
//
// Real strike = 101.0;
// Real barrier = 101.0;
// Date exDate = today+180;
//
// boost::shared_ptr exercise(new EuropeanExercise(exDate));
// boost::shared_ptr payoff(
// new PlainVanillaPayoff(Option::Put, strike));
//
// BarrierOption option(Barrier::UpOut, barrier, rebate, payoff, exercise);
//
// Natural order = 0;
// bool zeroGamma = false;
// boost::shared_ptr engine(
// new PerturbativeBarrierOptionEngine(stochProcess, order, zeroGamma));
//
// option.setPricingEngine(engine);
//
// Real calculated = option.NPV();
// Real expected = 0.897365;
// Real tolerance = 1.0e-6;
// if (std::fabs(calculated-expected) > tolerance) {
// BOOST_ERROR("Failed to reproduce expected value"
// << "\n calculated: " << std::setprecision(5) << calculated
// << "\n expected: " << std::setprecision(5) << expected);
// }
//
// order = 1;
// engine = boost::shared_ptr(
// new PerturbativeBarrierOptionEngine(stochProcess, order, zeroGamma));
//
// option.setPricingEngine(engine);
//
// calculated = option.NPV();
// expected = 0.894374;
// if (std::fabs(calculated-expected) > tolerance) {
// BOOST_ERROR("Failed to reproduce expected value"
// << "\n calculated: " << std::setprecision(5) << calculated
// << "\n expected: " << std::setprecision(5) << expected);
// }
//
// order = 2;
// engine = boost::shared_ptr(
// new PerturbativeBarrierOptionEngine(stochProcess, order, zeroGamma));
//
// option.setPricingEngine(engine);
//
// calculated = option.NPV();
// expected = 0.894375;
// if (std::fabs(calculated-expected) > tolerance) {
// BOOST_ERROR("Failed to reproduce expected value"
// << "\n calculated: " << std::setprecision(5) << calculated
// << "\n expected: " << std::setprecision(5) << expected);
// }
// }
private int timeToDays(/*@Time*/ final double t) {
return (int) (t*360+0.5);
}
private void REPORT_FAILURE(final String greekName, final BarrierType barrierType,
final double barrier, final double rebate, final StrikedTypePayoff payoff,
final Exercise exercise, final double s, final double q, final double r, final Date today,
final double v, final double expected, final double calculated,
final double error, final double tolerance) {
fail("\n" + barrierType + " " + exercise
+ payoff.optionType() + " option with "
+ payoff.getClass().getSimpleName() + " payoff:\n"
+ " underlying value: " + s + "\n"
+ " strike: " + payoff.strike() + "\n"
+ " barrier: " + barrier + "\n"
+ " rebate: " + rebate + "\n"
+ " dividend yield: " + q + "\n"
+ " risk-free rate: " + r + "\n"
+ " reference date: " + today + "\n"
+ " maturity: " + exercise.lastDate() + "\n"
+ " volatility: " + v + "\n\n"
+ " expected " + greekName + ": " + expected + "\n"
+ " calculated " + greekName + ": " + calculated + "\n"
+ " error: " + error + "\n"
+ " tolerance: " + tolerance);
}
private static class NewBarrierOptionData {
private final BarrierType barrierType;
private final double barrier;
private final double rebate;
private final Option.Type type;
private final double strike;
private final double s; // spot
private final double q; // dividend
private final double r; // risk-free rate
private final double t; // time to maturity
private final double v; // volatility
private final double result; // result
private final double tol; // tolerance
public NewBarrierOptionData(
final BarrierType barrierType,
final double barrier,
final double rebate,
final Option.Type type,
final double strike,
final double s, // spot
final double q, // dividend
final double r, // risk-free rate
final double t, // time to maturity
final double v, // volatility
final double result, // result
final double tol // tolerance
) {
this.barrierType = barrierType;
this.barrier = barrier;
this.rebate = rebate;
this.type = type;
this.strike = strike;
this.s = s;
this.q = q;
this.r = r;
this.t = t;
this.v = v;
this.result = result;
this.tol = tol;
}
}
private static class BarrierOptionData {
private final BarrierType barrierType;
private final double volatility;
private final double strike;
private final double barrier;
private final double callValue;
private final double putValue;
public BarrierOptionData(
final BarrierType barrierType,
final double volatility,
final double strike,
final double barrier,
final double callValue,
final double putValue) {
this.barrierType = barrierType;
this.volatility = volatility;
this.strike = strike;
this.barrier = barrier;
this.callValue = callValue;
this.putValue = putValue;
}
}
}
Ads help maintain this website.