public void testLiborFixing() { // "Testing use of today's LIBOR fixings in swap curve..."); CommonVars vars = new CommonVars(); var swapHelpers = new InitializedList <RateHelper>(); IborIndex euribor6m = new Euribor6M(); for (int i = 0; i < vars.swaps; i++) { Handle <Quote> r = new Handle <Quote>(vars.rates[i + vars.deposits]); swapHelpers.Add(new SwapRateHelper(r, new Period(vars.swapData[i].n, vars.swapData[i].units), vars.calendar, vars.fixedLegFrequency, vars.fixedLegConvention, vars.fixedLegDayCounter, euribor6m)); } vars.termStructure = new PiecewiseYieldCurve <Discount, LogLinear>(vars.settlement, swapHelpers, new Actual360()); Handle <YieldTermStructure> curveHandle = new Handle <YieldTermStructure>(vars.termStructure); IborIndex index = new Euribor6M(curveHandle); for (int i = 0; i < vars.swaps; i++) { Period tenor = new Period(vars.swapData[i].n, vars.swapData[i].units); VanillaSwap swap = new MakeVanillaSwap(tenor, index, 0.0) .withEffectiveDate(vars.settlement) .withFixedLegDayCount(vars.fixedLegDayCounter) .withFixedLegTenor(new Period(vars.fixedLegFrequency)) .withFixedLegConvention(vars.fixedLegConvention) .withFixedLegTerminationDateConvention(vars.fixedLegConvention) .value(); double expectedRate = vars.swapData[i].rate / 100, estimatedRate = swap.fairRate(); double tolerance = 1.0e-9; if (Math.Abs(expectedRate - estimatedRate) > tolerance) { QAssert.Fail("before LIBOR fixing:\n" + vars.swapData[i].n + " year(s) swap:\n" + " estimated rate: " + (estimatedRate) + "\n" + " expected rate: " + (expectedRate)); } } Flag f = new Flag(); vars.termStructure.registerWith(f.update); f.lower(); index.addFixing(vars.today, 0.0425); if (!f.isUp()) { QAssert.Fail("Observer was not notified of rate fixing"); } for (int i = 0; i < vars.swaps; i++) { Period tenor = new Period(vars.swapData[i].n, vars.swapData[i].units); VanillaSwap swap = new MakeVanillaSwap(tenor, index, 0.0) .withEffectiveDate(vars.settlement) .withFixedLegDayCount(vars.fixedLegDayCounter) .withFixedLegTenor(new Period(vars.fixedLegFrequency)) .withFixedLegConvention(vars.fixedLegConvention) .withFixedLegTerminationDateConvention(vars.fixedLegConvention) .value(); double expectedRate = vars.swapData[i].rate / 100, estimatedRate = swap.fairRate(); double tolerance = 1.0e-9; if (Math.Abs(expectedRate - estimatedRate) > tolerance) { QAssert.Fail("after LIBOR fixing:\n" + vars.swapData[i].n + " year(s) swap:\n" + " estimated rate: " + (estimatedRate) + "\n" + " expected rate: " + (expectedRate)); } } }
static void Main(string[] args) { DateTime timer = DateTime.Now; //////////////// DATES ////////////////////////////////////////////// Calendar calendar = new TARGET(); Date todaysDate = new Date(15, Month.January, 2017); Date settlementDate = new Date(todaysDate); Settings.setEvaluationDate(todaysDate); DayCounter dayCounter = new Actual365Fixed(); //////////////// MARKET ////////////////////////////////////////////// // Spot double underlying = 1.0; Handle <Quote> underlyingH = new Handle <Quote>(new SimpleQuote(underlying)); // Curves double riskFreeRate = 0.01; double dividendYield = 0.035; double cstVol = 0.2; double hazardRate = 0.02; Handle <YieldTermStructure> flatTermStructure = new Handle <YieldTermStructure>(new FlatForward(settlementDate, riskFreeRate, dayCounter)); Handle <YieldTermStructure> flatDividendTS = new Handle <YieldTermStructure>(new FlatForward(settlementDate, dividendYield, dayCounter)); Handle <BlackVolTermStructure> mySurfaceH = new Handle <BlackVolTermStructure>(new BlackConstantVol(settlementDate, calendar, cstVol, dayCounter)); Handle <DefaultProbabilityTermStructure> defaultTSH = new Handle <DefaultProbabilityTermStructure>(new FlatHazardRate(settlementDate, hazardRate, dayCounter)); // Process GeneralizedBlackScholesProcessTolerance bsmProcess = new GeneralizedBlackScholesProcessTolerance(underlyingH, flatDividendTS, flatTermStructure, mySurfaceH); //////////////// INSTRUMENT ////////////////////////////////////////////// List <Date> fixings = new InitializedList <Date>(); for (int i = 1; i <= 8; i++) { fixings.Add(settlementDate + new Period(i * 3, TimeUnit.Months)); } double couponBond = 0.0525; double couponBinary = 0.077; double barrierlvl = 0.7; double strike = 1.0; double recovery = 0.4; double absoluteTolerance = 0.0001; GenericScriptRepack repack = new GenericScriptRepack(fixings, couponBond, couponBinary, barrierlvl, strike, recovery); IPricingEngine mcengine = new MakeMCGenericScriptInstrument <PseudoRandom>(bsmProcess) .withAbsoluteTolerance(absoluteTolerance) .withStepsPerYear(52) .withSeed(50) .withCredit(defaultTSH) .value(); repack.setPricingEngine(mcengine); Console.WriteLine("Repack pricing = {0:0.0000}", repack.NPV()); repack.inspout(5, true); //////////////// END TEST ////////////////////////////////////////////// Console.WriteLine(); Console.WriteLine(" \nRun completed in {0}", DateTime.Now - timer); Console.WriteLine(); Console.Write("Press any key to continue ..."); Console.ReadKey(); }
public override void calculate() { /* this engine cannot really check for the averageType==Geometric since it can be used as control variate for the Arithmetic version QL_REQUIRE(arguments_.averageType == Average::Geometric, "not a geometric average option"); */ if(!(arguments_.exercise.type() == Exercise.Type.European)) throw new ApplicationException("not an European Option"); double runningLog; int pastFixings; if (arguments_.averageType == Average.Type.Geometric) { if(!(arguments_.runningAccumulator>0.0)) throw new ApplicationException("positive running product required: " + arguments_.runningAccumulator + " not allowed"); runningLog = Math.Log(arguments_.runningAccumulator.GetValueOrDefault()); pastFixings = arguments_.pastFixings.GetValueOrDefault(); } else { // it is being used as control variate runningLog = 1.0; pastFixings = 0; } PlainVanillaPayoff payoff = (PlainVanillaPayoff)(arguments_.payoff); if (payoff == null) throw new ApplicationException("non-plain payoff given"); Date referenceDate = process_.riskFreeRate().link.referenceDate(); DayCounter rfdc = process_.riskFreeRate().link.dayCounter(); DayCounter divdc = process_.dividendYield().link.dayCounter(); DayCounter voldc = process_.blackVolatility().link.dayCounter(); List<double> fixingTimes = new InitializedList<double>(arguments_.fixingDates.Count()); int i; for (i=0; i<arguments_.fixingDates.Count(); i++) { if (arguments_.fixingDates[i]>=referenceDate) { double t = voldc.yearFraction(referenceDate, arguments_.fixingDates[i]); fixingTimes.Add(t); } } int remainingFixings = fixingTimes.Count(); int numberOfFixings = pastFixings + remainingFixings; double N = numberOfFixings; double pastWeight = pastFixings/N; double futureWeight = 1.0-pastWeight; /*double timeSum = std::accumulate(fixingTimes.begin(), fixingTimes.end(), 0.0);*/ double timeSum = 0; fixingTimes.ForEach((ii, vv) => timeSum += fixingTimes[ii]); double vola = process_.blackVolatility().link.blackVol( arguments_.exercise.lastDate(), payoff.strike()); double temp = 0.0; for (i=pastFixings+1; i<numberOfFixings; i++) temp += fixingTimes[i-pastFixings-1]*(N-i); double variance = vola*vola /N/N * (timeSum+ 2.0*temp); double dsigG_dsig = Math.Sqrt((timeSum + 2.0*temp))/N; double sigG = vola * dsigG_dsig; double dmuG_dsig = -(vola * timeSum)/N; Date exDate = arguments_.exercise.lastDate(); double dividendRate = process_.dividendYield().link. zeroRate(exDate, divdc, Compounding.Continuous, Frequency.NoFrequency).rate(); double riskFreeRate = process_.riskFreeRate().link. zeroRate(exDate, rfdc, Compounding.Continuous, Frequency.NoFrequency).rate(); double nu = riskFreeRate - dividendRate - 0.5*vola*vola; double s = process_.stateVariable().link.value(); if(!(s > 0.0)) throw new ApplicationException("positive underlying value required"); int M = (pastFixings == 0 ? 1 : pastFixings); double muG = pastWeight * runningLog/M + futureWeight * Math.Log(s) + nu*timeSum/N; double forwardPrice = Math.Exp(muG + variance / 2.0); double riskFreeDiscount = process_.riskFreeRate().link.discount( arguments_.exercise.lastDate()); BlackCalculator black = new BlackCalculator(payoff, forwardPrice, Math.Sqrt(variance), riskFreeDiscount); results_.value = black.value(); results_.delta = futureWeight*black.delta(forwardPrice)*forwardPrice/s; results_.gamma = forwardPrice*futureWeight/(s*s) *( black.gamma(forwardPrice)*futureWeight*forwardPrice - pastWeight*black.delta(forwardPrice) ); double Nx_1, nx_1; CumulativeNormalDistribution CND = new CumulativeNormalDistribution(); NormalDistribution ND = new NormalDistribution(); if (sigG > Const.QL_Epsilon) { double x_1 = (muG-Math.Log(payoff.strike())+variance)/sigG; Nx_1 = CND.value(x_1); nx_1 = ND.value( x_1); } else { Nx_1 = (muG > Math.Log(payoff.strike()) ? 1.0 : 0.0); nx_1 = 0.0; } results_.vega = forwardPrice * riskFreeDiscount * ( (dmuG_dsig + sigG * dsigG_dsig)*Nx_1 + nx_1*dsigG_dsig ); if (payoff.optionType() == Option.Type.Put) results_.vega -= riskFreeDiscount * forwardPrice * (dmuG_dsig + sigG * dsigG_dsig); double tRho = rfdc.yearFraction(process_.riskFreeRate().link.referenceDate(), arguments_.exercise.lastDate()); results_.rho = black.rho(tRho)*timeSum/(N*tRho) - (tRho-timeSum/N)*results_.value; double tDiv = divdc.yearFraction( process_.dividendYield().link.referenceDate(), arguments_.exercise.lastDate()); results_.dividendRho = black.dividendRho(tDiv)*timeSum /(N*tDiv); results_.strikeSensitivity = black.strikeSensitivity(); results_.theta = Utils.blackScholesTheta(process_, results_.value.GetValueOrDefault(), results_.delta.GetValueOrDefault(), results_.gamma.GetValueOrDefault()); }
public void testPastFixings() { //BOOST_MESSAGE("Testing use of past fixings in Asian options..."); DayCounter dc = new Actual360(); Date today = Date.Today ; SimpleQuote spot = new SimpleQuote(100.0); SimpleQuote qRate = new SimpleQuote(0.03); YieldTermStructure qTS = Utilities.flatRate(today, qRate, dc); SimpleQuote rRate = new SimpleQuote(0.06); YieldTermStructure rTS = Utilities.flatRate(today, rRate, dc); SimpleQuote vol = new SimpleQuote(0.20); BlackVolTermStructure volTS = Utilities.flatVol(today, vol, dc); StrikedTypePayoff payoff = new PlainVanillaPayoff(Option.Type.Put, 100.0); Exercise exercise = new EuropeanExercise(today + new Period(1,TimeUnit.Years)); BlackScholesMertonProcess stochProcess = new BlackScholesMertonProcess(new Handle<Quote>(spot), new Handle<YieldTermStructure>(qTS), new Handle<YieldTermStructure>(rTS), new Handle<BlackVolTermStructure>(volTS)); // MC arithmetic average-price double runningSum = 0.0; int pastFixings = 0; List<Date> fixingDates1 = new InitializedList<Date>(); for (int i=0; i<=12; ++i) fixingDates1.Add(today + new Period(i,TimeUnit.Months)); DiscreteAveragingAsianOption option1 = new DiscreteAveragingAsianOption(Average.Type.Arithmetic, runningSum, pastFixings, fixingDates1, payoff, exercise); pastFixings = 2; runningSum = pastFixings * spot.value() * 0.8; List<Date> fixingDates2 = new InitializedList<Date>(); for (int i=-2; i<=12; ++i) fixingDates2.Add(today + new Period(i,TimeUnit.Months)); DiscreteAveragingAsianOption option2 = new DiscreteAveragingAsianOption(Average.Type.Arithmetic, runningSum, pastFixings, fixingDates2, payoff, exercise); IPricingEngine engine = new MakeMCDiscreteArithmeticAPEngine<LowDiscrepancy,Statistics>(stochProcess) .withStepsPerYear(1) .withSamples(2047) .value() ; option1.setPricingEngine(engine); option2.setPricingEngine(engine); double price1 = option1.NPV(); double price2 = option2.NPV(); if (Utils.close(price1, price2)) { Assert.Fail( "past fixings had no effect on arithmetic average-price option" + "\n without fixings: " + price1 + "\n with fixings: " + price2); } // MC arithmetic average-strike engine = new MakeMCDiscreteArithmeticASEngine<LowDiscrepancy,Statistics>(stochProcess) .withSamples(2047) .value(); option1.setPricingEngine(engine); option2.setPricingEngine(engine); price1 = option1.NPV(); price2 = option2.NPV(); if (Utils.close(price1, price2)) { Assert.Fail( "past fixings had no effect on arithmetic average-strike option" + "\n without fixings: " + price1 + "\n with fixings: " + price2); } // analytic geometric average-price double runningProduct = 1.0; pastFixings = 0; DiscreteAveragingAsianOption option3 = new DiscreteAveragingAsianOption(Average.Type.Geometric, runningProduct, pastFixings, fixingDates1, payoff, exercise); pastFixings = 2; runningProduct = spot.value() * spot.value(); DiscreteAveragingAsianOption option4 = new DiscreteAveragingAsianOption(Average.Type.Geometric, runningProduct, pastFixings, fixingDates2, payoff, exercise); engine = new AnalyticDiscreteGeometricAveragePriceAsianEngine(stochProcess); option3.setPricingEngine(engine); option4.setPricingEngine(engine); double price3 = option3.NPV(); double price4 = option4.NPV(); if (Utils.close(price3, price4)) { Assert.Fail( "past fixings had no effect on geometric average-price option" + "\n without fixings: " + price3 + "\n with fixings: " + price4); } // MC geometric average-price engine = new MakeMCDiscreteGeometricAPEngine<LowDiscrepancy,Statistics>(stochProcess) .withStepsPerYear(1) .withSamples(2047) .value(); option3.setPricingEngine(engine); option4.setPricingEngine(engine); price3 = option3.NPV(); price4 = option4.NPV(); if (Utils.close(price3, price4)) { Assert.Fail( "past fixings had no effect on geometric average-price option" + "\n without fixings: " + price3 + "\n with fixings: " + price4); } }
static void Main(string[] args) { DateTime timer = DateTime.Now; //////////////// DATES ////////////////////////////////////////////// Calendar calendar = new TARGET(); Date todaysDate = new Date(15, Month.January, 2017); Date settlementDate = new Date(todaysDate); Settings.setEvaluationDate(todaysDate); DayCounter dayCounter = new Actual365Fixed(); //////////////// MARKET ////////////////////////////////////////////// // Spot double underlying = 4468.17; Handle <Quote> underlyingH = new Handle <Quote>(new SimpleQuote(underlying)); // riskfree double riskFreeRate = 0.035; Handle <YieldTermStructure> flatTermStructure = new Handle <YieldTermStructure>(new FlatForward(settlementDate, riskFreeRate, dayCounter)); // dividend double dividendYield = 0.0; double fixedDiv = 5.0; Handle <YieldTermStructure> flatDividendTS = new Handle <YieldTermStructure>(new FlatForward(settlementDate, dividendYield, dayCounter)); Handle <YieldTermStructure> FixedDivTermStructure = new Handle <YieldTermStructure>(new FixedForward(settlementDate, fixedDiv, underlying, dayCounter)); // vol surface Date StartDateVol = settlementDate + new Period(1, TimeUnit.Months); List <int> maturityInDays = new InitializedList <int>() { 0, 13, 41, 90, 165, 256, 345, 524, 703 }; List <Date> datesVol = new InitializedList <Date>(); for (int d = 1; d < maturityInDays.Count; d++) { datesVol.Add(calendar.advance(settlementDate, new Period(maturityInDays[d], TimeUnit.Days))); } List <double> strikes = new InitializedList <double>() { 3400, 3600, 3800, 4000, 4200, 4400, 4500, 4600, 4800, 5000, 5200, 5400, 5600 }; Matrix blackVolMatrix = new Matrix(maturityInDays.Count - 1, strikes.Count, 0.2); var vols = new InitializedList <double>() { 0.6625, 0.4875, 0.4204, 0.3667, 0.3431, 0.3267, 0.3121, 0.3121, 0.6007, 0.4543, 0.3967, 0.3511, 0.3279, 0.3154, 0.2984, 0.2921, 0.5084, 0.4221, 0.3718, 0.3327, 0.3155, 0.3027, 0.2919, 0.2889, 0.4541, 0.3869, 0.3492, 0.3149, 0.2963, 0.2926, 0.2819, 0.2800, 0.4060, 0.3607, 0.3330, 0.2999, 0.2887, 0.2811, 0.2751, 0.2775, 0.3726, 0.3396, 0.3108, 0.2781, 0.2788, 0.2722, 0.2661, 0.2686, 0.3550, 0.3277, 0.3012, 0.2781, 0.2781, 0.2661, 0.2661, 0.2681, 0.3428, 0.3209, 0.2958, 0.2740, 0.2688, 0.2627, 0.2580, 0.2620, 0.3302, 0.3062, 0.2799, 0.2631, 0.2573, 0.2533, 0.2504, 0.2544, 0.3343, 0.2959, 0.2705, 0.2540, 0.2504, 0.2464, 0.2448, 0.2462, 0.3460, 0.2845, 0.2624, 0.2463, 0.2425, 0.2385, 0.2373, 0.2422, 0.3857, 0.2860, 0.2578, 0.2399, 0.2357, 0.2327, 0.2312, 0.2351, 0.3976, 0.2860, 0.2607, 0.2356, 0.2297, 0.2268, 0.2241, 0.2320 }; for (int i = 0; i < vols.Count; i++) { int testraw = (int)(i % (datesVol.Count)); int testcol = (int)(i / (datesVol.Count)); blackVolMatrix[testraw, testcol] = vols[i]; } BlackVarianceSurface mySurface = new BlackVarianceSurface(settlementDate, calendar, datesVol, strikes, Matrix.transpose(blackVolMatrix), dayCounter); Handle <BlackVolTermStructure> mySurfaceH = new Handle <BlackVolTermStructure>(mySurface); //////////////// CALIBRATION ////////////////////////////////////////////// Period helperPeriod = new Period(); //helpers List <CalibrationHelper> calibrationHelpers = new List <CalibrationHelper>(); for (int k = 0; k < strikes.Count; k++) { for (int d = 0; d < datesVol.Count; d++) { helperPeriod = new Period(datesVol[d] - settlementDate, TimeUnit.Days); calibrationHelpers.Add(new HestonModelHelper(helperPeriod, calendar, underlying, strikes[k], new Handle <Quote>(new SimpleQuote(blackVolMatrix[d, k])), flatTermStructure, flatDividendTS, CalibrationHelper.CalibrationErrorType.ImpliedVolError)); } } // starting data double v0 = 0.1; double kappa = 1.0; double theta = 0.1; double sigma = 0.5; double rho = -0.5; // model HestonProcess hestonProcess = new HestonProcess(flatTermStructure, flatDividendTS, underlyingH, v0, kappa, theta, sigma, rho); HestonModel hestonmodel = new HestonModel(hestonProcess); AnalyticHestonEngine analyticHestonEngine = new AnalyticHestonEngine(hestonmodel); foreach (HestonModelHelper hmh in calibrationHelpers) { hmh.setPricingEngine(analyticHestonEngine); } // optimization double tolerance = 1.0e-8; LevenbergMarquardt optimizationmethod = new LevenbergMarquardt(tolerance, tolerance, tolerance); hestonmodel.calibrate(calibrationHelpers, optimizationmethod, new EndCriteria(400, 40, tolerance, tolerance, tolerance)); double error = 0.0; List <double> errorList = new InitializedList <double>(); //////////////// CALIBRATION RESULTS ////////////////////////////////////////////// Console.WriteLine("Calbration :"); Console.WriteLine("-----------"); foreach (HestonModelHelper hmh in calibrationHelpers) { error += Math.Abs(hmh.calibrationError()); errorList.Add(Math.Abs(hmh.calibrationError())); } Vector hestonParameters = hestonmodel.parameters(); Console.WriteLine("v0 = {0:0.00%}", hestonParameters[4]); Console.WriteLine("kappa = {0:0.00%}", hestonParameters[1]); Console.WriteLine("theta = {0:0.00%}", hestonParameters[0]); Console.WriteLine("sigma = {0:0.00%}", hestonParameters[2]); Console.WriteLine("rho = {0:0.00%}", hestonParameters[3]); Console.WriteLine(); Console.WriteLine("Total error = {0:0.0000}", error); Console.WriteLine("Mean error = {0:0.0000%}", error / (errorList.Count - 1)); Console.WriteLine(); int StepsPerYear = 52; double absoluteTolerance = 80.0; ulong mcSeed = 42; // MC Heston process HestonProcess calibratedHestonProcess = new HestonProcess(flatTermStructure, flatDividendTS, underlyingH, hestonParameters[4], hestonParameters[1], hestonParameters[0], hestonParameters[2], hestonParameters[3]); // BS process GeneralizedBlackScholesProcessTolerance bsmProcess = new GeneralizedBlackScholesProcessTolerance(underlyingH, FixedDivTermStructure, flatTermStructure, mySurfaceH); //////////////// ENGINES ///////////////////////////////////////////////// IPricingEngine mcHestonEngine = new MakeMCEuropeanHestonEngine <PseudoRandom, Statistics>(calibratedHestonProcess) .withStepsPerYear(StepsPerYear) .withAbsoluteTolerance(absoluteTolerance) .withSeed(mcSeed) .getAsPricingEngine(); double absoluteTolerance2 = 1.0; IPricingEngine mcGenHestonEngineTestbs = new MakeMCGenericScriptInstrument <PseudoRandom>(bsmProcess) .withStepsPerYear(StepsPerYear) .withAbsoluteTolerance(absoluteTolerance2) .withSeed(mcSeed) .value(); IPricingEngine mcGenHestonEngineTestbs2 = new MakeMCGenericScriptInstrument <PseudoRandom>(calibratedHestonProcess) .withStepsPerYear(StepsPerYear) .withAbsoluteTolerance(absoluteTolerance2) .withSeed(mcSeed) .value(); //////////////// PRICING ////////////////////////////////////////////// Console.WriteLine("Pricing Vanilla:"); Console.WriteLine("---------------"); Date maturity = new Date(17, Month.May, 2019); Exercise europeanExercise = new EuropeanExercise(maturity); Option.Type type = Option.Type.Call; double strike = underlying; StrikedTypePayoff payoff = new PlainVanillaPayoff(type, strike); VanillaOption europeanOption = new VanillaOption(payoff, europeanExercise); // heston europeanOption.setPricingEngine(analyticHestonEngine); Console.Write("Heston pricing = {0:0.0000}", europeanOption.NPV()); Console.WriteLine(" -> {0:0.0000%}", europeanOption.NPV() / underlying); // Mc heston europeanOption.setPricingEngine(mcHestonEngine); Console.Write("HestMC pricing = {0:0.0000}", europeanOption.NPV()); Console.Write(" -> {0:0.0000%}", europeanOption.NPV() / underlying); Console.WriteLine(" tolerance {0:0.0} / {1:0.00%}", absoluteTolerance, absoluteTolerance / underlying); // analytic bs europeanOption.setPricingEngine(new AnalyticEuropeanEngine(bsmProcess)); Console.Write("BS pricing = {0:0.0000}", europeanOption.NPV()); Console.WriteLine(" -> {0:0.0000%}", europeanOption.NPV() / underlying); Console.WriteLine(); //////////////// AUTOCALL HESTON ////////////////////////////////////////////// List <Date> fixingdates = new InitializedList <Date>(); double coupon = 0.05; double barrierlvl = 0.6; for (int i = 1; i <= 4; i++) { fixingdates.Add(settlementDate + new Period(i, TimeUnit.Years)); } ScriptGenericAutocall myGenericAutocallHTTEst = new ScriptGenericAutocall(fixingdates, coupon, barrierlvl, underlying); myGenericAutocallHTTEst.setPricingEngine(mcGenHestonEngineTestbs); Console.WriteLine("Pricing Autocall BS :"); Console.WriteLine("---------------------"); Console.WriteLine("test = {0:0.0000}", myGenericAutocallHTTEst.NPV()); Console.WriteLine("Err = {0:0.0000%}", myGenericAutocallHTTEst.errorEstimate() / myGenericAutocallHTTEst.NPV()); Console.WriteLine("Samples = {0}", myGenericAutocallHTTEst.samples()); Console.Write("\n"); for (int i = 0; i < 4; i++) { Console.WriteLine("ProbaCall {1} = {0:0.0000%}", myGenericAutocallHTTEst.inspout("ProbaCall " + i), i + 1); } Console.WriteLine("ProbaMid = {0:0.0000%}", myGenericAutocallHTTEst.inspout("ProbaMid")); Console.WriteLine("probaDown = {0:0.0000%}", myGenericAutocallHTTEst.inspout("ProbaDown")); Console.WriteLine("test = {0:0.0000%}", myGenericAutocallHTTEst.inspout("ProbaDown")); Console.WriteLine("AvgDown/Proba = {0:0.0000%}", myGenericAutocallHTTEst.inspout("AvgDown") / myGenericAutocallHTTEst.inspout("ProbaDown")); Console.Write("\n"); myGenericAutocallHTTEst.setPricingEngine(mcGenHestonEngineTestbs2); Console.WriteLine("Pricing Autocall Heston:"); Console.WriteLine("------------------------"); Console.WriteLine("test = {0:0.0000}", myGenericAutocallHTTEst.NPV()); Console.WriteLine("Err = {0:0.0000%}", myGenericAutocallHTTEst.errorEstimate() / myGenericAutocallHTTEst.NPV()); Console.WriteLine("Samples = {0}", myGenericAutocallHTTEst.samples()); Console.Write("\n"); for (int i = 0; i < 4; i++) { Console.WriteLine("ProbaCall {1} = {0:0.0000%}", myGenericAutocallHTTEst.inspout("ProbaCall " + i), i + 1); } Console.WriteLine("ProbaMid = {0:0.0000%}", myGenericAutocallHTTEst.inspout("ProbaMid")); Console.WriteLine("probaDown = {0:0.0000%}", myGenericAutocallHTTEst.inspout("ProbaDown")); Console.WriteLine("test = {0:0.0000%}", myGenericAutocallHTTEst.inspout("ProbaDown")); Console.WriteLine("AvgDown/Proba = {0:0.0000%}", myGenericAutocallHTTEst.inspout("AvgDown") / myGenericAutocallHTTEst.inspout("ProbaDown")); Console.Write("\n"); //////////////// END TEST ////////////////////////////////////////////// Console.WriteLine(); Console.WriteLine(" \nRun completed in {0}", DateTime.Now - timer); Console.WriteLine(); Console.Write("Press any key to continue ..."); Console.ReadKey(); }
static void Main(string[] args) { DateTime timer = DateTime.Now; //////////////// DATES ////////////////////////////////////////////// Calendar calendar = new TARGET(); Date todaysDate = new Date(15, Month.January, 2017); Date settlementDate = new Date(todaysDate); Settings.setEvaluationDate(todaysDate); DayCounter dayCounter = new Actual365Fixed(); //////////////// MARKET ////////////////////////////////////////////// // Spot double underlying = 100; Handle <Quote> underlyingH = new Handle <Quote>(new SimpleQuote(underlying)); // riskfree double riskFreeRate = 0.01; Handle <YieldTermStructure> flatTermStructure = new Handle <YieldTermStructure>(new FlatForward(settlementDate, riskFreeRate, dayCounter)); // dividend double dividendYield = 0.035; double fixedDiv = 5.0; Handle <YieldTermStructure> flatDividendTS = new Handle <YieldTermStructure>(new FlatForward(settlementDate, dividendYield, dayCounter)); Handle <YieldTermStructure> FixedDivTermStructure = new Handle <YieldTermStructure>(new FixedForward(settlementDate, fixedDiv, underlying, dayCounter)); // flatvol double volatility = 0.20; Handle <BlackVolTermStructure> flatVolTS = new Handle <BlackVolTermStructure>(new BlackConstantVol(settlementDate, calendar, volatility, dayCounter)); Console.WriteLine("Underlying price = " + underlying); Console.WriteLine("Risk-free interest rate = {0:0.00%}", riskFreeRate); Console.WriteLine("Dividend yield = {0:0.00%}", dividendYield); Console.WriteLine("Flat Volatility = {0:0.00%}", volatility); Console.Write("\n"); // volSurface List <Date> datesVol = new InitializedList <Date>(); List <double> strikesVol = new InitializedList <double>(); double spotATP = 100; Date StartDateVol = settlementDate + new Period(1, TimeUnit.Months); Matrix blackVolMatrix = new Matrix(5, 5, 0.2); List <double> timesVol = new InitializedList <double>(); for (int i = 0; i < blackVolMatrix.rows(); i++) { timesVol.Add(i + 1); } for (int j = 0; j < blackVolMatrix.columns(); j++) { datesVol.Add(StartDateVol + new Period(j, TimeUnit.Years)); for (int i = 0; i < blackVolMatrix.rows(); i++) { blackVolMatrix[i, j] = 0.2 + Math.Pow(2.5, (i)) / 100; } } for (int j = 0; j < blackVolMatrix.columns(); j++) { strikesVol.Add(spotATP * (1 - (double)((int)(blackVolMatrix.rows() / 2)) / 10) + spotATP * 0.1 * j); } BlackVarianceSurface mySurface = new BlackVarianceSurface(settlementDate, calendar, datesVol, strikesVol, blackVolMatrix, dayCounter); Handle <BlackVolTermStructure> mySurfaceH = new Handle <BlackVolTermStructure>(mySurface); // process GeneralizedBlackScholesProcessTolerance bsmProcessVolSurface = new GeneralizedBlackScholesProcessTolerance(underlyingH, FixedDivTermStructure, flatTermStructure, mySurfaceH); GeneralizedBlackScholesProcessTolerance bsmProcess = new GeneralizedBlackScholesProcessTolerance(underlyingH, flatDividendTS, flatTermStructure, flatVolTS); //////////////// INSTRUMENT ////////////////////////////////////////////// double tolerance = 0.2; List <Date> fixingdates = new InitializedList <Date>(); double coupon = 0.05; double barrierlvl = 0.6; for (int i = 1; i <= 4; i++) { fixingdates.Add(settlementDate + new Period(i, TimeUnit.Years)); } GenericAutocall myGenericAutocall = new GenericAutocall(fixingdates, coupon, barrierlvl, underlying); IPricingEngine mcengine = new MakeMGenericInstrument <PseudoRandom>(bsmProcessVolSurface) .withAbsoluteTolerance(tolerance) .withStepsPerYear(52) .withSeed(50) .value(); myGenericAutocall.setPricingEngine(mcengine); //////////////// Printing Results ////////////////////////////////////////////// Console.WriteLine("NPV Generic Autocall = {0:0.0000}", myGenericAutocall.NPV()); Console.WriteLine("Err = {0:0.0000%}", myGenericAutocall.errorEstimate() / myGenericAutocall.NPV()); Console.WriteLine("Samples = {0}", myGenericAutocall.samples()); Console.Write("\n"); for (int i = 0; i < 4; i++) { Console.WriteLine("ProbaCall {1} = {0:0.0000%}", myGenericAutocall.inspout("ProbaCall " + i), i + 1); } Console.WriteLine("ProbaMid = {0:0.0000%}", myGenericAutocall.inspout("ProbaMid")); Console.WriteLine("probaDown = {0:0.0000%}", myGenericAutocall.inspout("ProbaDown")); Console.WriteLine("AvgDown/Proba = {0:0.0000%}", myGenericAutocall.inspout("AvgDown") / myGenericAutocall.inspout("ProbaDown")); Console.Write("\n"); Console.WriteLine("Test - NoValue = {0:0.0000%}", myGenericAutocall.inspout("NoValue")); // inspout() function Console.Write("\n"); myGenericAutocall.inspout(); Console.Write("\n"); myGenericAutocall.inspout(2, true); // End test Console.WriteLine(" \nRun completed in {0}", DateTime.Now - timer); Console.WriteLine(); Console.Write("Press any key to continue ..."); Console.ReadKey(); }