private void ResetStrikeOptionParityCalc(String ValuationDate = "2017-12-20", Double vol = 0.28, Double spot = 2.0, Double strike = 1.03, Boolean isCall = true, Boolean isPercentage = true) { var valuationDate = DateFromStr(ValuationDate); var strikefixingDate = valuationDate; var exerciseDate = new Term("176D").Next(valuationDate); var calendar = CalendarImpl.Get("chn"); var option1 = new ResetStrikeOption( valuationDate, exerciseDate, OptionExercise.European, isCall ? OptionType.Call : OptionType.Put, isPercentage ? ResetStrikeType.PercentagePayoff : ResetStrikeType.NormalPayoff, strike, InstrumentType.EquityIndex, calendar, new Act365(), CurrencyCode.CNY, CurrencyCode.CNY, new[] { exerciseDate }, new[] { exerciseDate }, strikefixingDate ); var option2 = new VanillaOption( valuationDate, exerciseDate, OptionExercise.European, isCall ? OptionType.Call : OptionType.Put, strike, InstrumentType.EquityIndex, calendar, new Act365(), CurrencyCode.CNY, CurrencyCode.CNY, new[] { exerciseDate }, new[] { exerciseDate } ); var market = TestMarket(referenceDate: ValuationDate, vol: vol, spot: spot); var engine = new AnalyticalResetStrikeOptionEngine(); var result = engine.Calculate(option1, market, PricingRequest.All); var engineVanilla = new AnalyticalVanillaEuropeanOptionEngine(); var resultVanilla = engineVanilla.Calculate(option2, market, PricingRequest.All); var result1 = (isPercentage) ? result.Pv * strike : result.Pv; Assert.AreEqual(result1, resultVanilla.Pv, 1e-8); }
private void ResetStrikeOptionGreekCalc(double expectedPv, double expectedDelta, double expectedGamma, double expectedVega, double expectedTheta, double expectedRho, String ValuationDate = "2017-12-20", Double vol = 0.28, Double spot = 1.0, Double strike = 1.03, Boolean isCall = true, Boolean isPercentage = true) { var valuationDate = DateFromStr(ValuationDate); var strikefixingDate = new Term("50D").Next(valuationDate); var exerciseDate = new Term("176D").Next(valuationDate); var calendar = CalendarImpl.Get("chn"); var option = new ResetStrikeOption( valuationDate, exerciseDate, OptionExercise.European, isCall ? OptionType.Call : OptionType.Put, isPercentage ? ResetStrikeType.PercentagePayoff : ResetStrikeType.NormalPayoff, strike, InstrumentType.EquityIndex, calendar, new Act365(), CurrencyCode.CNY, CurrencyCode.CNY, new[] { exerciseDate }, new[] { exerciseDate }, strikefixingDate ); var market = TestMarket(referenceDate: ValuationDate, vol: vol, spot: spot); var analyticalEngine = new AnalyticalResetStrikeOptionEngine(); var analyticalResult = analyticalEngine.Calculate(option, market, PricingRequest.All); Assert.AreEqual(expectedPv, analyticalResult.Pv, 1e-8); Assert.AreEqual(expectedDelta, analyticalResult.Delta, 1e-8); Assert.AreEqual(expectedGamma, analyticalResult.Gamma, 1e-8); Assert.AreEqual(expectedVega, analyticalResult.Vega, 1e-8); Assert.AreEqual(expectedTheta, analyticalResult.Theta, 1e-8); Assert.AreEqual(expectedRho, analyticalResult.Rho, 1e-8); }
private void ResetStrikeOptionPnLCalc(double vol = 0.28, double spot = 1.0, double strike = 1.03, Boolean isCall = true, Boolean isPercentage = true, string t0 = "2017-12-20", string t1 = "2017-12-21", double volMove = 0.10, double mktMove = 1e-4, double toleranceInPct = 2) { var T0 = DateFromStr(t0); var T1 = DateFromStr(t1); var spotNew = spot + spot * mktMove; var volNew = vol + volMove; var strikefixingDate = new Term("50D").Next(T0); var exerciseDate = new Term("176D").Next(T0); var calendar = CalendarImpl.Get("chn"); var valuationDay = t0; var valuationDayNew = t1; var option = new ResetStrikeOption( T0, exerciseDate, OptionExercise.European, isCall ? OptionType.Call : OptionType.Put, isPercentage ? ResetStrikeType.PercentagePayoff : ResetStrikeType.NormalPayoff, strike, InstrumentType.EquityIndex, calendar, new Act365(), CurrencyCode.CNY, CurrencyCode.CNY, new[] { exerciseDate }, new[] { exerciseDate }, strikefixingDate ); var market = TestMarket(referenceDate: t0, vol: vol, spot: spot); var marketNew = TestMarket(referenceDate: t1, vol: volNew, spot: spotNew); var marketPI = TestMarket(referenceDate: t0, vol: vol, spot: spotNew); var marketVI = TestMarket(referenceDate: t0, vol: volNew, spot: spot); var marketPVC = TestMarket(referenceDate: t0, vol: volNew, spot: spotNew); var engine = new AnalyticalResetStrikeOptionEngine(); var result = engine.Calculate(option, market, PricingRequest.All); var resultNew = engine.Calculate(option, marketNew, PricingRequest.All); var resultPI = engine.Calculate(option, marketPI, PricingRequest.All); var resultVI = engine.Calculate(option, marketVI, PricingRequest.All); var resultPVC = engine.Calculate(option, marketPVC, PricingRequest.All); var actualPL = resultNew.Pv - result.Pv; //price Impact //PI = PV(t-1, priceNew) - Pv(t-1) var basePv = result.Pv; var PI = resultPI.Pv - basePv; var thetapl = result.Theta * (T1 - T0); //vol impact //VI = PV(t-1. volNew) - Pv (t-1) var VI = resultVI.Pv - basePv; //price vol cross impact //PVC = PV(t-1. volNew, PriceNew) - Pv (t-1) - (PI+VI) var PVC = resultPVC.Pv - basePv - PI - VI; var newEstimate = PI + VI + PVC + thetapl; var newUnexplained = actualPL - newEstimate; //Time impact //TI = PV(t, all OldInfo) - Pv(t-1) //TODO: //Time/ price cross Impact //TPC = PV(t, priceNew) - pv(t-1) - (TI +PI) //Time/vol cross impact //TVC = PV(t, volNew) - pv(t-1) -(TI+VI) //TODO: //in case of big move ( vol and spot), we need high order risk to explain pnl //var diff = actualPL - esimstatedPL; //Assert.AreEqual(true, Math.Abs(diff / actualPL) * 100.0 < toleranceInPct); //pnl well explained in not too extreme moves Assert.AreEqual(true, Math.Abs(newUnexplained / actualPL) * 100.0 < toleranceInPct); }