// Reference pg. 253 - Hull - Options, Futures, and Other Derivatives 5th ed // Exercise 12.8 // Doesn't quite work. Need to deal with date conventions private void testEuropeanKnownValue() { // Testing dividend European option values with known value... using (SavedSettings backup = new SavedSettings()) { double tolerance = 1.0e-2; double expected = 3.67; DayCounter dc = new Actual360(); Date today = Date.Today; Settings.setEvaluationDate(today); SimpleQuote spot = new SimpleQuote(0.0); SimpleQuote qRate = new SimpleQuote(0.0); Handle <YieldTermStructure> qTS = new Handle <YieldTermStructure>(Utilities.flatRate(qRate, dc)); SimpleQuote rRate = new SimpleQuote(0.0); Handle <YieldTermStructure> rTS = new Handle <YieldTermStructure>(Utilities.flatRate(rRate, dc)); SimpleQuote vol = new SimpleQuote(0.0); Handle <BlackVolTermStructure> volTS = new Handle <BlackVolTermStructure>(Utilities.flatVol(vol, dc)); Date exDate = today + new Period(6, TimeUnit.Months); Exercise exercise = new EuropeanExercise(exDate); List <Date> dividendDates = new List <Date>(); List <double> dividends = new List <double>(); dividendDates.Add(today + new Period(2, TimeUnit.Months)); dividends.Add(0.50); dividendDates.Add(today + new Period(5, TimeUnit.Months)); dividends.Add(0.50); StrikedTypePayoff payoff = new PlainVanillaPayoff(Option.Type.Call, 40.0); BlackScholesMertonProcess stochProcess = new BlackScholesMertonProcess(new Handle <Quote>(spot), qTS, rTS, volTS); IPricingEngine engine = new AnalyticDividendEuropeanEngine(stochProcess); DividendVanillaOption option = new DividendVanillaOption(payoff, exercise, dividendDates, dividends); option.setPricingEngine(engine); double u = 40.0; double q = 0.0, r = 0.09; double v = 0.30; spot.setValue(u); qRate.setValue(q); rRate.setValue(r); vol.setValue(v); double calculated = option.NPV(); double error = Math.Abs(calculated - expected); if (error > tolerance) { REPORT_FAILURE("value start limit", payoff, exercise, u, q, r, today, v, expected, calculated, error, tolerance); } } }
public void testFdImpliedVol() { var settlementDate = new Date(26, 2, 2015); Settings.setEvaluationDate(settlementDate); var calendar = new TARGET(); var dayCounter = new Actual365Fixed(); const double volatility = 0.5; var underlyingQuote = new Handle <Quote>(new SimpleQuote(3227)); var flatTermStructure = new Handle <YieldTermStructure>(new FlatForward(settlementDate, 0.05, dayCounter)); var flatDividendYield = new Handle <YieldTermStructure>(new FlatForward(settlementDate, 0, dayCounter)); var flatVolatility = new Handle <BlackVolTermStructure>(new BlackConstantVol(settlementDate, calendar, volatility, dayCounter)); var process = new BlackScholesMertonProcess(underlyingQuote, flatDividendYield, flatTermStructure, flatVolatility); var exercise = new AmericanExercise(new Date(1, 12, 2015)); var pricingEngine = new FDDividendAmericanEngine(process); var payoff = new PlainVanillaPayoff(Option.Type.Put, 3200); var dividendDates = new[] { new Date(1, 3, 2015) }; var dividendAmounts = new[] { 10d }; var option = new DividendVanillaOption(payoff, exercise, dividendDates.ToList(), dividendAmounts.ToList()); option.setPricingEngine(pricingEngine); var npv = option.NPV(); var impliedVol = option.impliedVolatility(npv, process); const double tolerance = 3.0e-3; if (Math.Abs(impliedVol - volatility) > tolerance) { QAssert.Fail(string.Format("Implied volatility calculation failed. Expected {0}. Actual {1}", volatility, impliedVol)); } }
public void testFdmHestonEuropeanWithDividends() { //Testing FDM with European option with dividends in Heston model... using (SavedSettings backup = new SavedSettings()) { Handle <Quote> s0 = new Handle <Quote>(new SimpleQuote(100.0)); Handle <YieldTermStructure> rTS = new Handle <YieldTermStructure>(Utilities.flatRate(0.05, new Actual365Fixed())); Handle <YieldTermStructure> qTS = new Handle <YieldTermStructure>(Utilities.flatRate(0.0, new Actual365Fixed())); HestonProcess hestonProcess = new HestonProcess(rTS, qTS, s0, 0.04, 2.5, 0.04, 0.66, -0.8); Settings.Instance.setEvaluationDate(new Date(28, 3, 2004)); Date exerciseDate = new Date(28, 3, 2005); Exercise exercise = new AmericanExercise(exerciseDate); StrikedTypePayoff payoff = new PlainVanillaPayoff(Option.Type.Put, 100); List <double> dividends = new InitializedList <double>(1, 5); List <Date> dividendDates = new InitializedList <Date>(1, new Date(28, 9, 2004)); DividendVanillaOption option = new DividendVanillaOption(payoff, exercise, dividendDates, dividends); IPricingEngine engine = new FdHestonVanillaEngine(new HestonModel(hestonProcess), 50, 100, 50); option.setPricingEngine(engine); double tol = 0.01; double gammaTol = 0.001; double npvExpected = 7.365075; double deltaExpected = -0.396678; double gammaExpected = 0.027681; if (Math.Abs(option.NPV() - npvExpected) > tol) { QAssert.Fail("Failed to reproduce expected npv" + "\n calculated: " + option.NPV() + "\n expected: " + npvExpected + "\n tolerance: " + tol); } if (Math.Abs(option.delta() - deltaExpected) > tol) { QAssert.Fail("Failed to reproduce expected delta" + "\n calculated: " + option.delta() + "\n expected: " + deltaExpected + "\n tolerance: " + tol); } if (Math.Abs(option.gamma() - gammaExpected) > gammaTol) { QAssert.Fail("Failed to reproduce expected gamma" + "\n calculated: " + option.gamma() + "\n expected: " + gammaExpected + "\n tolerance: " + tol); } } }
public void testFDDividendAmericanEngine() { /* * Valuation date: 20 July 2018 * Maturity date: 17 Aug 2018 * Type: Call * Spot: 2900 * Strike: 2800 * Volatility: 20 % * Interest rate: 0 % * * Dividend(paid one day before expiry) * Date: 16 Aug 2018 * Value: 40 * * NPV = 124.37658 */ var result = 124.37658; var settlementDate = new Date(20, 7, 2018); Settings.setEvaluationDate(settlementDate); var calendar = new TARGET(); var dayCounter = new Actual365Fixed(); var spot = new Handle <Quote>(new SimpleQuote(2900)); var qRate = new Handle <Quote>(new SimpleQuote(0.0)); var rRate = new Handle <Quote>(new SimpleQuote(0.0)); var vol = new Handle <Quote>(new SimpleQuote(0.2)); var flatDividendYield = new Handle <YieldTermStructure>(new FlatForward(settlementDate, qRate, dayCounter)); var flatTermStructure = new Handle <YieldTermStructure>(new FlatForward(settlementDate, rRate, dayCounter)); var flatVolatility = new Handle <BlackVolTermStructure>(new BlackConstantVol(settlementDate, calendar, vol, dayCounter)); var process = new BlackScholesMertonProcess(spot, flatDividendYield, flatTermStructure, flatVolatility); var exercise = new AmericanExercise(new Date(17, 8, 2018)); var pricingEngine = new FDDividendAmericanEngine(process); var payoff = new PlainVanillaPayoff(Option.Type.Call, 2800); var dividendDates = new[] { new Date(16, 8, 2018) }; var dividendAmounts = new[] { 40d }; var option = new DividendVanillaOption(payoff, exercise, dividendDates.ToList(), dividendAmounts.ToList()); option.setPricingEngine(pricingEngine); var npv = option.NPV(); const double tolerance = 1.0e-5; if (Math.Abs(npv - result) > tolerance) { QAssert.Fail(string.Format("NPV calculation failed. Expected {0}. Actual {1}", result, npv)); } }
void testFdDegenerate <Engine>(Date today, Exercise exercise) where Engine : IFDEngine, new() { DayCounter dc = new Actual360(); SimpleQuote spot = new SimpleQuote(54.625); Handle <YieldTermStructure> rTS = new Handle <YieldTermStructure>(Utilities.flatRate(0.052706, dc)); Handle <YieldTermStructure> qTS = new Handle <YieldTermStructure>(Utilities.flatRate(0.0, dc)); Handle <BlackVolTermStructure> volTS = new Handle <BlackVolTermStructure>(Utilities.flatVol(0.282922, dc)); BlackScholesMertonProcess process = new BlackScholesMertonProcess(new Handle <Quote>(spot), qTS, rTS, volTS); int timeSteps = 300; int gridPoints = 300; IPricingEngine engine = new Engine().factory(process, timeSteps, gridPoints); StrikedTypePayoff payoff = new PlainVanillaPayoff(Option.Type.Call, 55.0); double tolerance = 3.0e-3; List <double> dividends = new List <double>(); List <Date> dividendDates = new List <Date>(); DividendVanillaOption option1 = new DividendVanillaOption(payoff, exercise, dividendDates, dividends); option1.setPricingEngine(engine); // FLOATING_POINT_EXCEPTION double refValue = option1.NPV(); for (int i = 0; i <= 6; i++) { dividends.Add(0.0); dividendDates.Add(today + i); DividendVanillaOption option = new DividendVanillaOption(payoff, exercise, dividendDates, dividends); option.setPricingEngine(engine); double value = option.NPV(); if (Math.Abs(refValue - value) > tolerance) { Assert.Fail("NPV changed by null dividend :\n" + " previous value: " + value + "\n" + " current value: " + refValue + "\n" + " change: " + (value - refValue)); } } }
private void Button_Click(object sender, RoutedEventArgs e) { Option.Type optionType; if (CallorPut.Text == "Call") { optionType = Option.Type.Call; } else { optionType = Option.Type.Put; } double underlyingPrice = Convert.ToDouble(Stockprice.Text); double strikePrice = Convert.ToDouble(Strikeprice.Text); double dividendYield = 0.0; double riskFreeRate = Convert.ToDouble(Intrate.Text); double volatility = Convert.ToDouble(Resultvol.Text) / 100; Date todaydate = Date.todaysDate(); string expd = Datepick.Text; Date maturityDate = new Date(); if (expd[1].ToString() is "/") { expd = '0' + expd; } if (expd[4].ToString() is "/") { expd = expd.Substring(0, 3) + '0' + expd.Substring(3); } maturityDate = DateParser.parseFormatted(expd, "%m/%d/%Y"); Settings.instance().setEvaluationDate(todaydate); Date settlementDate = new Date(); settlementDate = todaydate; QuantLib.Calendar calendar = new TARGET(); AmericanExercise americanExercise = new AmericanExercise(settlementDate, maturityDate); EuropeanExercise europeanExercise = new EuropeanExercise(maturityDate); DayCounter dayCounter = new Actual365Fixed(); YieldTermStructureHandle flatRateTSH = new YieldTermStructureHandle( new FlatForward(settlementDate, riskFreeRate, dayCounter)); YieldTermStructureHandle flatDividendTSH = new YieldTermStructureHandle( new FlatForward(settlementDate, dividendYield, dayCounter)); BlackVolTermStructureHandle flatVolTSH = new BlackVolTermStructureHandle( new BlackConstantVol(settlementDate, calendar, volatility, dayCounter)); QuoteHandle underlyingQuoteH = new QuoteHandle(new SimpleQuote(underlyingPrice)); BlackScholesMertonProcess stochasticProcess = new BlackScholesMertonProcess(underlyingQuoteH, flatDividendTSH, flatRateTSH, flatVolTSH); PlainVanillaPayoff payoff = new PlainVanillaPayoff(optionType, strikePrice); VanillaOption americanOption = new VanillaOption(payoff, americanExercise); VanillaOption americanOption2 = new VanillaOption(payoff, americanExercise); VanillaOption europeanOption = new VanillaOption(payoff, europeanExercise); //americanOption.setPricingEngine( // new BaroneAdesiWhaleyEngine(stochasticProcess)); //americanOption2.setPricingEngine( // new BinomialVanillaEngine(stochasticProcess, "coxrossrubinstein",1000)); europeanOption.setPricingEngine( new AnalyticEuropeanEngine(stochasticProcess)); //double opprice = Math.Round(americanOption2.NPV(),3); Date divdate1 = new Date(14, Month.December, 2019); DoubleVector divpay = new DoubleVector(); DateVector divDates = new DateVector(); //divpay.Add(.0001); //divDates.Add(divdate1); DividendVanillaOption americanOption1 = new DividendVanillaOption(payoff, americanExercise, divDates, divpay); FDDividendAmericanEngine engine = new FDDividendAmericanEngine(stochasticProcess); americanOption1.setPricingEngine(engine); double opprice4 = americanOption1.NPV(); //double vol1 = americanOption1.impliedVolatility(opprice4, stochasticProcess, .001); double delta1 = Math.Round(americanOption1.delta(), 2); double gamma1 = Math.Round(americanOption1.gamma(), 2); double theta1 = Math.Round(europeanOption.theta() / 365, 2); double vega1 = Math.Round(europeanOption.vega() / 100, 2); double oppricedisplay = Math.Round(opprice4, 3); Resultam.Text = oppricedisplay.ToString(); Resultam_Delta.Text = delta1.ToString(); Resultam_Gamma.Text = gamma1.ToString(); Resultam_Theta.Text = theta1.ToString(); Resultam_Vega.Text = vega1.ToString(); }
public void testFdEuropeanValues() { // Testing finite-difference dividend European option values... SavedSettings backup = new SavedSettings(); double tolerance = 1.0e-2; int gridPoints = 300; int timeSteps = 40; Option.Type[] types = { Option.Type.Call, Option.Type.Put }; double[] strikes = { 50.0, 99.5, 100.0, 100.5, 150.0 }; double[] underlyings = { 100.0 }; // Rate qRates[] = { 0.00, 0.10, 0.30 }; // Analytic dividend may not be handling q correctly double[] qRates = { 0.00 }; double[] rRates = { 0.01, 0.05, 0.15 }; int[] lengths = { 1, 2 }; double[] vols = { 0.05, 0.20, 0.40 }; DayCounter dc = new Actual360(); Date today = Date.Today; Settings.setEvaluationDate(today); SimpleQuote spot = new SimpleQuote(0.0); SimpleQuote qRate = new SimpleQuote(0.0); Handle <YieldTermStructure> qTS = new Handle <YieldTermStructure>(Utilities.flatRate(qRate, dc)); SimpleQuote rRate = new SimpleQuote(0.0); Handle <YieldTermStructure> rTS = new Handle <YieldTermStructure>(Utilities.flatRate(rRate, dc)); SimpleQuote vol = new SimpleQuote(0.0); Handle <BlackVolTermStructure> volTS = new Handle <BlackVolTermStructure>(Utilities.flatVol(vol, dc)); for (int i = 0; i < types.Length; i++) { for (int j = 0; j < strikes.Length; j++) { for (int k = 0; k < lengths.Length; k++) { Date exDate = today + new Period(lengths[k], TimeUnit.Years); Exercise exercise = new EuropeanExercise(exDate); List <Date> dividendDates = new List <Date>(); List <double> dividends = new List <double>(); for (Date d = today + new Period(3, TimeUnit.Months); d < exercise.lastDate(); d += new Period(6, TimeUnit.Months)) { dividendDates.Add(d); dividends.Add(5.0); } StrikedTypePayoff payoff = new PlainVanillaPayoff(types[i], strikes[j]); BlackScholesMertonProcess stochProcess = new BlackScholesMertonProcess(new Handle <Quote>(spot), qTS, rTS, volTS); IPricingEngine engine = new FDDividendEuropeanEngine(stochProcess, timeSteps, gridPoints); IPricingEngine ref_engine = new AnalyticDividendEuropeanEngine(stochProcess); DividendVanillaOption option = new DividendVanillaOption(payoff, exercise, dividendDates, dividends); option.setPricingEngine(engine); DividendVanillaOption ref_option = new DividendVanillaOption(payoff, exercise, dividendDates, dividends); ref_option.setPricingEngine(ref_engine); for (int l = 0; l < underlyings.Length; l++) { for (int m = 0; m < qRates.Length; m++) { for (int n = 0; n < rRates.Length; n++) { for (int p = 0; p < vols.Length; p++) { double u = underlyings[l]; double q = qRates[m], r = rRates[n]; double v = vols[p]; spot.setValue(u); qRate.setValue(q); rRate.setValue(r); vol.setValue(v); // FLOATING_POINT_EXCEPTION double calculated = option.NPV(); if (calculated > spot.value() * 1.0e-5) { double expected = ref_option.NPV(); double error = Math.Abs(calculated - expected); if (error > tolerance) { REPORT_FAILURE("value", payoff, exercise, u, q, r, today, v, expected, calculated, error, tolerance); } } } } } } } } } }
public void testEuropeanGreeks() { // Testing dividend European option greeks... SavedSettings backup = new SavedSettings(); Dictionary <string, double> calculated = new Dictionary <string, double>(), expected = new Dictionary <string, double>(), tolerance = new Dictionary <string, double>(); tolerance["delta"] = 1.0e-5; tolerance["gamma"] = 1.0e-5; tolerance["theta"] = 1.0e-5; tolerance["rho"] = 1.0e-5; tolerance["vega"] = 1.0e-5; Option.Type[] types = { Option.Type.Call, Option.Type.Put }; double[] strikes = { 50.0, 99.5, 100.0, 100.5, 150.0 }; double[] underlyings = { 100.0 }; double[] qRates = { 0.00, 0.10, 0.30 }; double[] rRates = { 0.01, 0.05, 0.15 }; int[] lengths = { 1, 2 }; double[] vols = { 0.05, 0.20, 0.40 }; DayCounter dc = new Actual360(); Date today = Date.Today; Settings.setEvaluationDate(today); SimpleQuote spot = new SimpleQuote(0.0); SimpleQuote qRate = new SimpleQuote(0.0); Handle <YieldTermStructure> qTS = new Handle <YieldTermStructure>(Utilities.flatRate(qRate, dc)); SimpleQuote rRate = new SimpleQuote(0.0); Handle <YieldTermStructure> rTS = new Handle <YieldTermStructure>(Utilities.flatRate(rRate, dc)); SimpleQuote vol = new SimpleQuote(0.0); Handle <BlackVolTermStructure> volTS = new Handle <BlackVolTermStructure>(Utilities.flatVol(vol, dc)); for (int i = 0; i < types.Length; i++) { for (int j = 0; j < strikes.Length; j++) { for (int k = 0; k < lengths.Length; k++) { Date exDate = today + new Period(lengths[k], TimeUnit.Years); Exercise exercise = new EuropeanExercise(exDate); List <Date> dividendDates = new List <Date>(); List <double> dividends = new List <double>(); for (Date d = today + new Period(3, TimeUnit.Months); d < exercise.lastDate(); d += new Period(6, TimeUnit.Months)) { dividendDates.Add(d); dividends.Add(5.0); } StrikedTypePayoff payoff = new PlainVanillaPayoff(types[i], strikes[j]); BlackScholesMertonProcess stochProcess = new BlackScholesMertonProcess(new Handle <Quote>(spot), qTS, rTS, volTS); IPricingEngine engine = new AnalyticDividendEuropeanEngine(stochProcess); DividendVanillaOption option = new DividendVanillaOption(payoff, exercise, dividendDates, dividends); option.setPricingEngine(engine); for (int l = 0; l < underlyings.Length; l++) { for (int m = 0; m < qRates.Length; m++) { for (int n = 0; n < rRates.Length; n++) { for (int p = 0; p < vols.Length; p++) { double u = underlyings[l]; double q = qRates[m], r = rRates[n]; double v = vols[p]; spot.setValue(u); qRate.setValue(q); rRate.setValue(r); vol.setValue(v); double value = option.NPV(); calculated["delta"] = option.delta(); calculated["gamma"] = option.gamma(); calculated["theta"] = option.theta(); calculated["rho"] = option.rho(); calculated["vega"] = option.vega(); if (value > spot.value() * 1.0e-5) { // perturb spot and get delta and gamma double du = u * 1.0e-4; spot.setValue(u + du); double value_p = option.NPV(), delta_p = option.delta(); spot.setValue(u - du); double value_m = option.NPV(), delta_m = option.delta(); spot.setValue(u); expected["delta"] = (value_p - value_m) / (2 * du); expected["gamma"] = (delta_p - delta_m) / (2 * du); // perturb risk-free rate and get rho double dr = r * 1.0e-4; rRate.setValue(r + dr); value_p = option.NPV(); rRate.setValue(r - dr); value_m = option.NPV(); rRate.setValue(r); expected["rho"] = (value_p - value_m) / (2 * dr); // perturb volatility and get vega double dv = v * 1.0e-4; vol.setValue(v + dv); value_p = option.NPV(); vol.setValue(v - dv); value_m = option.NPV(); vol.setValue(v); expected["vega"] = (value_p - value_m) / (2 * dv); // perturb date and get theta double dT = dc.yearFraction(today - 1, today + 1); Settings.setEvaluationDate(today - 1); value_m = option.NPV(); Settings.setEvaluationDate(today + 1); value_p = option.NPV(); Settings.setEvaluationDate(today); expected["theta"] = (value_p - value_m) / dT; // compare foreach (KeyValuePair <string, double> it in calculated) { string greek = it.Key; double expct = expected [greek], calcl = calculated[greek], tol = tolerance [greek]; double error = Utilities.relativeError(expct, calcl, u); if (error > tol) { REPORT_FAILURE(greek, payoff, exercise, u, q, r, today, v, expct, calcl, error, tol); } } } } } } } } } } }
void testFdGreeks <Engine>(Date today, Exercise exercise) where Engine : IFDEngine, new() { Dictionary <string, double> calculated = new Dictionary <string, double>(), expected = new Dictionary <string, double>(), tolerance = new Dictionary <string, double>(); tolerance.Add("delta", 5.0e-3); tolerance.Add("gamma", 7.0e-3); // tolerance["theta"] = 1.0e-2; Option.Type[] types = { Option.Type.Call, Option.Type.Put }; double[] strikes = { 50.0, 99.5, 100.0, 100.5, 150.0 }; double[] underlyings = { 100.0 }; double[] qRates = { 0.00, 0.10, 0.20 }; double[] rRates = { 0.01, 0.05, 0.15 }; double[] vols = { 0.05, 0.20, 0.50 }; DayCounter dc = new Actual360(); SimpleQuote spot = new SimpleQuote(0.0); SimpleQuote qRate = new SimpleQuote(0.0); Handle <YieldTermStructure> qTS = new Handle <YieldTermStructure>(Utilities.flatRate(qRate, dc)); SimpleQuote rRate = new SimpleQuote(0.0); Handle <YieldTermStructure> rTS = new Handle <YieldTermStructure>(Utilities.flatRate(rRate, dc)); SimpleQuote vol = new SimpleQuote(0.0); Handle <BlackVolTermStructure> volTS = new Handle <BlackVolTermStructure>(Utilities.flatVol(vol, dc)); for (int i = 0; i < types.Length; i++) { for (int j = 0; j < strikes.Length; j++) { List <Date> dividendDates = new List <Date>(); List <double> dividends = new List <double>(); for (Date d = today + new Period(3, TimeUnit.Months); d < exercise.lastDate(); d += new Period(6, TimeUnit.Months)) { dividendDates.Add(d); dividends.Add(5.0); } StrikedTypePayoff payoff = new PlainVanillaPayoff(types[i], strikes[j]); BlackScholesMertonProcess stochProcess = new BlackScholesMertonProcess(new Handle <Quote>(spot), qTS, rTS, volTS); IPricingEngine engine = new Engine().factory(stochProcess); DividendVanillaOption option = new DividendVanillaOption(payoff, exercise, dividendDates, dividends); option.setPricingEngine(engine); for (int l = 0; l < underlyings.Length; l++) { for (int m = 0; m < qRates.Length; m++) { for (int n = 0; n < rRates.Length; n++) { for (int p = 0; p < vols.Length; p++) { double u = underlyings[l]; double q = qRates[m], r = rRates[n]; double v = vols[p]; spot.setValue(u); qRate.setValue(q); rRate.setValue(r); vol.setValue(v); // FLOATING_POINT_EXCEPTION double value = option.NPV(); calculated["delta"] = option.delta(); calculated["gamma"] = option.gamma(); // calculated["theta"] = option.theta(); if (value > spot.value() * 1.0e-5) { // perturb spot and get delta and gamma double du = u * 1.0e-4; spot.setValue(u + du); double value_p = option.NPV(), delta_p = option.delta(); spot.setValue(u - du); double value_m = option.NPV(), delta_m = option.delta(); spot.setValue(u); expected["delta"] = (value_p - value_m) / (2 * du); expected["gamma"] = (delta_p - delta_m) / (2 * du); // perturb date and get theta /* * Time dT = dc.yearFraction(today-1, today+1); * Settings::instance().evaluationDate() = today-1; * value_m = option.NPV(); * Settings::instance().evaluationDate() = today+1; * value_p = option.NPV(); * Settings::instance().evaluationDate() = today; * expected["theta"] = (value_p - value_m)/dT; */ // compare foreach (string greek in calculated.Keys) { double expct = expected[greek], calcl = calculated[greek], tol = tolerance[greek]; double error = Utilities.relativeError(expct, calcl, u); if (error > tol) { REPORT_FAILURE(greek, payoff, exercise, u, q, r, today, v, expct, calcl, error, tol); } } } } } } } } } }
public void testEuropeanStartLimit() { // Testing dividend European option with a dividend on today's date... SavedSettings backup = new SavedSettings(); double tolerance = 1.0e-5; double dividendValue = 10.0; Option.Type[] types = { Option.Type.Call, Option.Type.Put }; double[] strikes = { 50.0, 99.5, 100.0, 100.5, 150.0 }; double[] underlyings = { 100.0 }; double[] qRates = { 0.00, 0.10, 0.30 }; double[] rRates = { 0.01, 0.05, 0.15 }; int[] lengths = { 1, 2 }; double[] vols = { 0.05, 0.20, 0.70 }; DayCounter dc = new Actual360(); Date today = Date.Today; Settings.setEvaluationDate(today); SimpleQuote spot = new SimpleQuote(0.0); SimpleQuote qRate = new SimpleQuote(0.0); Handle <YieldTermStructure> qTS = new Handle <YieldTermStructure>(Utilities.flatRate(qRate, dc)); SimpleQuote rRate = new SimpleQuote(0.0); Handle <YieldTermStructure> rTS = new Handle <YieldTermStructure>(Utilities.flatRate(rRate, dc)); SimpleQuote vol = new SimpleQuote(0.0); Handle <BlackVolTermStructure> volTS = new Handle <BlackVolTermStructure>(Utilities.flatVol(vol, dc)); for (int i = 0; i < types.Length; i++) { for (int j = 0; j < strikes.Length; j++) { for (int k = 0; k < lengths.Length; k++) { Date exDate = today + new Period(lengths[k], TimeUnit.Years); Exercise exercise = new EuropeanExercise(exDate); List <Date> dividendDates = new List <Date>(); List <double> dividends = new List <double>(); dividendDates.Add(today); dividends.Add(dividendValue); StrikedTypePayoff payoff = new PlainVanillaPayoff(types[i], strikes[j]); BlackScholesMertonProcess stochProcess = new BlackScholesMertonProcess(new Handle <Quote>(spot), qTS, rTS, volTS); IPricingEngine engine = new AnalyticDividendEuropeanEngine(stochProcess); IPricingEngine ref_engine = new AnalyticEuropeanEngine(stochProcess); DividendVanillaOption option = new DividendVanillaOption(payoff, exercise, dividendDates, dividends); option.setPricingEngine(engine); VanillaOption ref_option = new VanillaOption(payoff, exercise); ref_option.setPricingEngine(ref_engine); for (int l = 0; l < underlyings.Length; l++) { for (int m = 0; m < qRates.Length; m++) { for (int n = 0; n < rRates.Length; n++) { for (int p = 0; p < vols.Length; p++) { double u = underlyings[l]; double q = qRates[m], r = rRates[n]; double v = vols[p]; spot.setValue(u); qRate.setValue(q); rRate.setValue(r); vol.setValue(v); double calculated = option.NPV(); spot.setValue(u - dividendValue); double expected = ref_option.NPV(); double error = Math.Abs(calculated - expected); if (error > tolerance) { REPORT_FAILURE("value", payoff, exercise, u, q, r, today, v, expected, calculated, error, tolerance); } } } } } } } } }
internal static global::System.Runtime.InteropServices.HandleRef getCPtr(DividendVanillaOption obj) { return (obj == null) ? new global::System.Runtime.InteropServices.HandleRef(null, global::System.IntPtr.Zero) : obj.swigCPtr; }
internal static global::System.Runtime.InteropServices.HandleRef getCPtr(DividendVanillaOption obj) { return((obj == null) ? new global::System.Runtime.InteropServices.HandleRef(null, global::System.IntPtr.Zero) : obj.swigCPtr); }