private void AsianOptionGreekCalc(String ValuationDate = "2015-03-19", Double vol = 0.28, Double spot = 1.0, Double strike = 1.03, string asianType = "ArithmeticAverage", Boolean isCall = true, Boolean isFixed = true, double expectedPv = 0.03368701153344, double expectedDelta = 0.431553260493781, double expectedGamma = 4319.00095926793, double expectedVega = 0.00146247323594882, double expectedRho = -1.62432084616776E-06, double expectedTheta = -0.000398443365606245 ) { var valuationDate = DateFromStr(ValuationDate); var maturityDate = new Term("176D").Next(valuationDate); var calendar = CalendarImpl.Get("chn"); var obsDates = new[] { new Date(2015, 4, 2), new Date(2015, 5, 4), new Date(2015, 6, 2), new Date(2015, 7, 2), new Date(2015, 8, 3), new Date(2015, 9, 2) }; #region comment //var fixings = File.ReadAllLines(@"./Data/HistoricalEquityPrices/hs300.csv") // .Select(x => // { // var splits = x.Split(','); // return Tuple.Create(new Date(DateTime.Parse(splits[0])), Double.Parse(splits[1])); // }).ToDictionary(x => x.Item1, x => x.Item2); //var initialSpot = fixings[startDate]; //fixings = fixings.Select(x => Tuple.Create(x.Key, x.Value / initialSpot)).Where(x => x.Item1 < startDate).ToDictionary(x => x.Item1, x => x.Item2); #endregion comment var option = new AsianOption( valuationDate, maturityDate, OptionExercise.European, isCall ? OptionType.Call : OptionType.Put, ToAsianType(asianType), isFixed ? StrikeStyle.Fixed:StrikeStyle.Floating, strike, InstrumentType.EquityIndex, calendar, new Act365(), CurrencyCode.CNY, CurrencyCode.CNY, new[] { maturityDate }, obsDates, new Dictionary <Date, double>() ); var market = TestMarket(referenceDate: ValuationDate, vol: vol, spot: spot); var analyticalEngine = new AnalyticalAsianOptionEngine(); var analyticalResult = analyticalEngine.Calculate(option, market, PricingRequest.All); //var engine = new GenericMonteCarloEngine(2, 30000); //var result = engine.Calculate(option, market, PricingRequest.All); //Console.WriteLine("Analytical: {0},{1},{2},{3},{4},{5}", analyticalResult.Pv, analyticalResult.Delta, analyticalResult.Gamma, analyticalResult.Vega, analyticalResult.Rho, analyticalResult.Theta); //Console.WriteLine("Monte Carlo: {0},{1},{2},{3},{4},{5}", result.Pv, result.Delta, result.Gamma, result.Vega, result.Rho, result.Theta); Assert.AreEqual(analyticalResult.Pv, expectedPv, 1e-1); Assert.AreEqual(analyticalResult.Delta, expectedDelta, 1e-1); Assert.AreEqual(analyticalResult.Gamma, expectedGamma, 1e4); Assert.AreEqual(analyticalResult.Vega, expectedVega, 1e-1); Assert.AreEqual(analyticalResult.Rho, expectedRho, 1e-1); Assert.AreEqual(analyticalResult.Theta, expectedTheta, 1e-1); }
private void AsianOptionGTJACalc(String ValuationDate = "2018-06-29", Double vol = 0.12, Double spot = 1820, Double strike = 1850, string asianType = "ArithmeticAverage", Boolean isCall = true, Boolean isFixed = true, double expectedPv = 0.03368701153344) { var valuationDate = DateFromStr(ValuationDate); var maturityDate = DateFromStr("2018-11-01"); var calendar = CalendarImpl.Get("chn"); var obsStartDate = DateFromStr("2018-10-01"); var obsDates = calendar.BizDaysBetweenDatesInclEndDay(obsStartDate, maturityDate).ToArray(); #region comment //var fixings = File.ReadAllLines(@"./Data/HistoricalEquityPrices/hs300.csv") // .Select(x => // { // var splits = x.Split(','); // return Tuple.Create(new Date(DateTime.Parse(splits[0])), Double.Parse(splits[1])); // }).ToDictionary(x => x.Item1, x => x.Item2); //var initialSpot = fixings[startDate]; //fixings = fixings.Select(x => Tuple.Create(x.Key, x.Value / initialSpot)).Where(x => x.Item1 < startDate).ToDictionary(x => x.Item1, x => x.Item2); #endregion comment var option = new AsianOption( valuationDate, maturityDate, OptionExercise.European, isCall ? OptionType.Call : OptionType.Put, ToAsianType(asianType), isFixed ? StrikeStyle.Fixed : StrikeStyle.Floating, strike, InstrumentType.CommodityFutures, calendar, new Act365(), CurrencyCode.CNY, CurrencyCode.CNY, new[] { maturityDate }, obsDates, new Dictionary <Date, double>(), notional: 30000 ); var market = TestMarket(referenceDate: ValuationDate, vol: vol, spot: spot); var analyticalEngine = new AnalyticalAsianOptionEngine(); var analyticalResult = analyticalEngine.Calculate(option, market, PricingRequest.All); //var engine = new GenericMonteCarloEngine(2, 30000); //var result = engine.Calculate(option, market, PricingRequest.All); //Console.WriteLine("Analytical: {0},{1},{2},{3},{4},{5}", analyticalResult.Pv, analyticalResult.Delta, analyticalResult.Gamma, analyticalResult.Vega, analyticalResult.Rho, analyticalResult.Theta); //Console.WriteLine("Monte Carlo: {0},{1},{2},{3},{4},{5}", result.Pv, result.Delta, result.Gamma, result.Vega, result.Rho, result.Theta); Assert.AreEqual(analyticalResult.Pv, expectedPv, 1e-1); }
private void AsianOptionGreekTest(double vol = 0.28, double spot = 1.0, double strike = 1.03, Boolean isCall = true, string asianType = "ArithmeticAverage", Boolean isFixed = true, string t0 = "2015-03-19", string t1 = "2015-03-20", 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 maturityDate = new Term("176D").Next(T0); var calendar = CalendarImpl.Get("chn"); var obsDates = new[] { new Date(2015, 4, 2), new Date(2015, 5, 4), new Date(2015, 6, 2), new Date(2015, 7, 2), new Date(2015, 8, 3), new Date(2015, 9, 2) }; var valuationDay = t0; var valuationDayNew = t1; var option = new AsianOption( T0, maturityDate, OptionExercise.European, isCall ? OptionType.Call : OptionType.Put, ToAsianType(asianType), isFixed ? StrikeStyle.Fixed : StrikeStyle.Floating, strike, InstrumentType.EquityIndex, calendar, new Act365(), CurrencyCode.CNY, CurrencyCode.CNY, new[] { maturityDate }, obsDates, new Dictionary <Date, double>() ); 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 AnalyticalAsianOptionEngine(); 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); }