[TestMethod] //TODO: fix this one public void TestFdAmericanOptionEngine() { var startDate = new Date(2010, 08, 31); var endDate = new Date(2016, 08, 31); var calendar = CalendarImpl.Get("chn"); var option = new VanillaOption(startDate, endDate, OptionExercise.American, OptionType.Call, 3.53, InstrumentType.Stock, calendar, new Act365(), CurrencyCode.CNY, CurrencyCode.CNY, calendar.BizDaysBetweenDatesInclEndDay(startDate, endDate).ToArray(), null, 1.0 ); var engine = new FdAmericanOptionEngine(100); var result = engine.Calculate(option, TestMarket(), PricingRequest.All); Assert.AreEqual(result.Pv, 0.4459260143, 1e-8); Assert.AreEqual(result.Delta, 0.71918151, 1e-8); Assert.AreEqual(result.Gamma, 0.487730202, 1e-8); Assert.AreEqual(result.Vega, 0.0177395037, 1e-8); Assert.AreEqual(result.Theta, -0.00045427, 1e-8); }
private Bond ZheBaoBondPart() { var bond = new Bond( "010002", new Date(2017, 8, 17), new Date(2022, 8, 17), 100.0, CurrencyCode.CNY, new StepWiseCoupon(new Dictionary <Date, double> { { new Date(2017, 8, 17), 0.01 }, { new Date(2018, 8, 17), 0.01 }, { new Date(2019, 8, 17), 0.01 }, { new Date(2020, 8, 17), 0.01 }, { new Date(2021, 8, 17), 0.01 }, }, CalendarImpl.Get("chn_ib") ), CalendarImpl.Get("chn_ib"), Frequency.Annual, Stub.LongEnd, new Act365NoLeap(), new ModifiedAfb(), BusinessDayConvention.None, BusinessDayConvention.ModifiedFollowing, null, TradingMarket.ChinaExShg, redemption: new Qdp.Pricing.Library.Common.Utilities.Redemption(1.03, RedemptionType.SeparatePrincipal) ); return(bond); }
/// <summary> /// Return fixing curve by historicalIndexRates /// </summary> /// <param name="settlementDate"></param> /// <param name="historicalIndexRates"></param> /// <param name="floatingBondInfo"></param> /// <returns></returns> public static InstrumentCurveDefinition GetFixingCurve(string settlementDate, Dictionary <string, Dictionary <string, double> > historicalIndexRates, FloatingRateBondInfo floatingBondInfo) { var resetCalendar = CalendarImpl.Get(floatingBondInfo.Calendar); var index = floatingBondInfo.Index; var rates = historicalIndexRates[index]; var tradeId = floatingBondInfo.TradeId; var indexDate = new DayGap(floatingBondInfo.ResetToFixingGap).Get(resetCalendar, settlementDate.ToDate()); var fixingTuple = rates.TryGetValue(indexDate.ToString(), resetCalendar); var indexRate = rates.GetAverageIndex(fixingTuple.Item1, resetCalendar, floatingBondInfo.ResetAverageDays, floatingBondInfo.ResetRateDigits); string fixingCurveName = "FixingCurve_" + tradeId; var fixingRateDefinition = new[] { new RateMktData("1D", indexRate, index, "None", fixingCurveName), new RateMktData("50Y", indexRate, index, "None", fixingCurveName), }; var curveConvention = new CurveConvention("fixingCurveConvention_" + tradeId, "CNY", "ModifiedFollowing", "Chn_ib", index == null ? "Act365" : index.ToIndexType().DayCountEnum(), "Continuous", "ForwardFlat"); floatingBondInfo.ValuationParamters.FixingCurveName = fixingCurveName; AddTrades(new [] { floatingBondInfo }); return(new InstrumentCurveDefinition(fixingCurveName, curveConvention, fixingRateDefinition, "ForwardCurve")); }
private Bond TianJiBondPart() { var bond = new Bond( "010002", new Date(2015, 6, 8), new Date(2020, 6, 8), 100, CurrencyCode.CNY, new StepWiseCoupon(new Dictionary <Date, double> { { new Date(2015, 6, 8), 0.01 }, { new Date(2016, 6, 8), 0.01 }, { new Date(2017, 6, 8), 0.01 }, { new Date(2018, 6, 8), 0.01 }, { new Date(2019, 6, 8), 0.01 }, }, CalendarImpl.Get("chn_ib") ), CalendarImpl.Get("chn_ib"), Frequency.Annual, Stub.LongEnd, new Act365NoLeap(), new ModifiedAfb(), BusinessDayConvention.None, BusinessDayConvention.ModifiedFollowing, null, TradingMarket.ChinaExShg ); return(bond); }
private Bond HangXinBondPart() { var bond = new Bond( "010002", new Date(2015, 6, 12), new Date(2021, 6, 12), 100, CurrencyCode.CNY, new StepWiseCoupon(new Dictionary <Date, double> { { new Date(2015, 6, 12), 0.002 }, { new Date(2016, 6, 12), 0.005 }, { new Date(2017, 6, 12), 0.01 }, { new Date(2018, 6, 12), 0.015 }, { new Date(2019, 6, 12), 0.015 }, { new Date(2020, 6, 12), 0.016 }, }, CalendarImpl.Get("chn_ib") ), CalendarImpl.Get("chn_ib"), Frequency.Annual, Stub.LongEnd, new Act365NoLeap(), new ModifiedAfb(), BusinessDayConvention.None, BusinessDayConvention.ModifiedFollowing, null, TradingMarket.ChinaExShg, redemption: new Redemption(1.07, RedemptionType.SeparatePrincipalWithLastCoupon) ); return(bond); }
public void BasicBondTest() { var bond = new Bond( id: "bond", startDate: new Date(2016, 3, 15), maturityDate: new Date(2019, 3, 15), notional: 100.0, currency: CurrencyCode.CNY, coupon: new FixedCoupon(0.05), calendar: CalendarImpl.Get("chn"), paymentFreq: Frequency.SemiAnnual, stub: Stub.ShortEnd, accrualDayCount: new Act365(), paymentDayCount: new Act365(), accrualBizDayRule: BusinessDayConvention.ModifiedFollowing, paymentBizDayRule: BusinessDayConvention.ModifiedFollowing, settlementGap: new DayGap("+0D"), bondTradingMarket: TradingMarket.ChinaInterBank); var engine = new BondEngineCn(new BondYieldPricerCn()); var market = new MarketCondition( x => x.ValuationDate.Value = new Date(2018, 8, 1), x => x.MktQuote.Value = new Dictionary <string, Tuple <PriceQuoteType, double> > { { "bond", Tuple.Create(PriceQuoteType.Clean, 100.0) } } ); var result = engine.Calculate(bond, market, PricingRequest.Ytm); }
public Bond[] CreateBonds() { var bondPrices = new Dictionary <string, Tuple <PriceQuoteType, double> >(); var deliverableBonds = File.ReadAllLines(@"./Data/BondFuture/TF1509DeliverableBondInfo.txt") .Select(x => { var splits = x.Split(','); bondPrices[splits[0]] = Tuple.Create(PriceQuoteType.Dirty, Convert.ToDouble(splits[6])); return(new Bond( splits[0], new Date(DateTime.Parse(splits[4])), new Date(DateTime.Parse(splits[5])), 100.0, CurrencyCode.CNY, new FixedCoupon(Convert.ToDouble(splits[2])), CalendarImpl.Get("chn_ib"), Convert.ToInt32(splits[3]) == 1 ? Frequency.Annual : Frequency.SemiAnnual, Stub.LongEnd, new ActActIsma(), new ActAct(), BusinessDayConvention.None, BusinessDayConvention.ModifiedFollowing, new DayGap("0D"), TradingMarket.ChinaInterBank )); }).ToArray(); return(deliverableBonds); }
private static Bond GeliBondPart(String cbTicker) { var bond = new Bond( cbTicker, new Date(2014, 12, 25), new Date(2019, 12, 25), 100, CurrencyCode.CNY, new StepWiseCoupon(new Dictionary <Date, double> { { new Date(2014, 12, 25), 0.006 }, { new Date(2015, 12, 25), 0.008 }, { new Date(2016, 12, 25), 0.01 }, { new Date(2017, 12, 25), 0.015 }, { new Date(2018, 12, 25), 0.02 } }, CalendarImpl.Get("chn_ib") ), CalendarImpl.Get("chn_ib"), Frequency.Annual, Stub.LongEnd, new Act365NoLeap(), new ModifiedAfb(), BusinessDayConvention.None, BusinessDayConvention.ModifiedFollowing, null, TradingMarket.ChinaExShg, redemption: new Redemption(1.06, RedemptionType.SeparatePrincipalWithLastCoupon) ); return(bond); }
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); }
//[TestMethod] public void AsianArithmeticOptionTest() { var valuationDate = DateFromStr("2018-03-14"); var maturityDate = new Term("176D").Next(valuationDate); var calendar = CalendarImpl.Get("chn"); //var obsDates = new[] { new Date(2018, 3, 14), 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) }; }
public void TestNumberOfBizDates() { var cny = CalendarImpl.Get("chn"); var start = new Date(2018, 4, 26); // 2 days var end = new Date(2018, 5, 4); //3 days var numDays = cny.NumberBizDaysBetweenDate(start, end, true); Assert.AreEqual(4, numDays); }
public void TestTfDeliverableBondCf() { var startDates = new[] { new Date(2016, 04, 06), new Date(2016, 04, 06), new Date(2016, 04, 06), }; var maturityDates = new[] { new Date(2016, 06, 15), new Date(2016, 09, 14), new Date(2016, 12, 13), }; var files = new[] { "QbTF1606CfTest.txt", "QbTF1609CfTest.txt", "QbTF1612CfTest.txt" }; var futuresNames = new[] { "TF1606", "TF1609", "TF1612" }; for (var k = 0; k < startDates.Length; ++k) { var bondPrices = new Dictionary <string, double>(); var targetConversionFactors = new List <double>(); var bonds = File.ReadAllLines(@"./Data/BondFuture/" + files[k]) .Select(x => { var splits = x.Split(','); var startDate = new Date(DateTime.Parse(splits[3])); var maturityDate = new Date(DateTime.Parse(splits[4])); var rate = Convert.ToDouble(splits[1]); var frequency = splits[2] == "Annual" ? Frequency.Annual : Frequency.SemiAnnual; targetConversionFactors.Add(Convert.ToDouble(splits[5])); bondPrices[splits[0]] = Convert.ToDouble(splits[6]); return(new Bond( splits[0], startDate, maturityDate, 100.0, CurrencyCode.CNY, new FixedCoupon(rate), CalendarImpl.Get("chn_ib"), frequency, Stub.LongEnd, new Act365(), new Act365(), BusinessDayConvention.None, BusinessDayConvention.ModifiedFollowing, null, TradingMarket.ChinaInterBank)); }).ToArray(); var bondfuture = new BondFutures( futuresNames[k], startDates[k], maturityDates[k], maturityDates[k], CalendarImpl.Get("chn"), bonds, new Act365() ); var market = new BondFutureTests().TestMarket("2016-04-06"); for (var i = 0; i < bonds.Length; ++i) { Assert.AreEqual(bondfuture.GetConversionFactor(bonds[i], market), targetConversionFactors[i]); } } }
private void CommodityLookbackVanillaComparison(String ValuationDate = "2015-03-19", Double vol = 0.28, Double spot = 240, Double strike = 240, Boolean isCall = true, Boolean isFixed = true) { 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) }; var option = new LookbackOption( valuationDate, maturityDate, OptionExercise.European, isCall ? OptionType.Call : OptionType.Put, isFixed ? StrikeStyle.Fixed : StrikeStyle.Floating, strike, InstrumentType.EquityIndex, calendar, new Act365(), CurrencyCode.CNY, CurrencyCode.CNY, new[] { maturityDate }, obsDates, new Dictionary <Date, double>(), notional: 1 ); var vanilla = new VanillaOption( valuationDate, maturityDate, OptionExercise.European, isCall ? OptionType.Call : OptionType.Put, strike, InstrumentType.EquityIndex, calendar, new Act365(), CurrencyCode.CNY, CurrencyCode.CNY, new[] { maturityDate }, obsDates, notional: 1 ); var market1 = TestMarket(referenceDate: ValuationDate, vol: vol, spot: spot); var market2 = TestMarket(referenceDate: ValuationDate, vol: vol * 0.8, spot: spot); var analyticalEngine = new AnalyticalLookbackOptionEngine(); var vanillaEngine = new AnalyticalVanillaEuropeanOptionEngine(); var analyticalResult = analyticalEngine.Calculate(option, market1, PricingRequest.All); var vanillaResult = vanillaEngine.Calculate(vanilla, market1, PricingRequest.All); var volResult = analyticalEngine.Calculate(option, market2, PricingRequest.All); //Floating Lookback Option >= ATM vanilla //High volatility Floating >= Low volatility Floating Assert.AreEqual(analyticalResult.Pv >= vanillaResult.Pv, true); Assert.AreEqual(analyticalResult.Pv >= volResult.Pv, true); }
private void TradeVolLinearInterpCalc(double expectedValue, Date valuationDate, double tradeOpenVol, double tradeCloseVol, DayCountMode dayCountMode) { var startDate = new Date(2018, 3, 21); var maturityDate = new Date(2018, 5, 21); var numOfSmoothingDays = 30; var calendar = CalendarImpl.Get("chn"); double vol = AnalyticalOptionTradeVolInterp.tradeVolLinearInterp(valuationDate, tradeOpenVol, tradeCloseVol, startDate, maturityDate, numOfSmoothingDays, dayCountMode, calendar); Assert.AreEqual(expectedValue, vol, 1e-10); }
public void CommodityBinaryEuropeanOptionTest() { var goldOption = new BinaryOption( new Date(2015, 03, 20), new Date(2015, 06, 16), OptionExercise.European, OptionType.Put, 231.733, InstrumentType.Futures, BinaryOptionPayoffType.CashOrNothing, 10.0, CalendarImpl.Get("chn"), new Act365(), CurrencyCode.CNY, CurrencyCode.CNY, new[] { new Date(2015, 06, 16) }, new[] { new Date(2015, 06, 16) }, 5.5 ); var market = GetMarket(); IMarketCondition marketCondition = new MarketCondition( x => x.ValuationDate.Value = market.ReferenceDate, x => x.DiscountCurve.Value = market.GetData <CurveData>("Fr007").YieldCurve, x => x.DividendCurves.Value = new Dictionary <string, IYieldCurve> { { "", market.GetData <CurveData>("Fr007").YieldCurve } }, x => x.SpotPrices.Value = new Dictionary <string, double> { { "", 240.6 } }, x => x.VolSurfaces.Value = new Dictionary <string, IVolSurface> { { "", market.GetData <VolSurfMktData>("goldVolSurf").ToImpliedVolSurface(market.ReferenceDate) } } ); var engine = new AnalyticalBinaryEuropeanOptionEngine(); var result = engine.Calculate(goldOption, marketCondition, PricingRequest.All); Assert.AreEqual(0.615985804, result.Pv, 1e-8); Assert.AreEqual(-0.409184000310747, result.Delta, 1e-8); Assert.AreEqual(0.239395655872165, result.Gamma, 1e-8); Assert.AreEqual(0.265082040475919, result.Vega, 1e-8); Assert.AreEqual(-8.43816170E-07, result.Rho, 1e-8); var engine2 = new AnalyticalBinaryEuropeanOptionReplicationEngine(2.0, BinaryOptionReplicationStrategy.Up); result = engine2.Calculate(goldOption, marketCondition, PricingRequest.All); Assert.AreEqual(1.25655313, result.Pv, 1e-8); Assert.AreEqual(-0.745647330608376, result.Delta, 1e-8); Assert.AreEqual(0.377738685022888, result.Gamma, 1e-8); Assert.AreEqual(0.417379971819684, result.Vega, 1e-8); Assert.AreEqual(-1.72130447839702E-06, result.Rho, 1e-8); }
public void TestQbTfDeliverableBondYield() { var files = new[] { "QbTF1606CfTest.txt", "QbTF1609CfTest.txt", "QbTF1612CfTest.txt" }; for (var k = 0; k < files.Length; ++k) { var bondPrices = new Dictionary <string, Tuple <PriceQuoteType, double> >(); var targetYtm = new List <double>(); var targetAi = new List <double>(); var bonds = File.ReadAllLines(@"./Data/BondFuture/" + files[k]) .Select(x => { var splits = x.Split(','); var startDate = new Date(DateTime.Parse(splits[3])); var maturityDate = new Date(DateTime.Parse(splits[4])); var rate = Convert.ToDouble(splits[1]); var frequency = splits[2] == "Annual" ? Frequency.Annual : Frequency.SemiAnnual; targetYtm.Add(Convert.ToDouble(splits[8])); targetAi.Add(Convert.ToDouble(splits[6]) - Convert.ToDouble(splits[7])); bondPrices[splits[0]] = Tuple.Create(PriceQuoteType.Dirty, Convert.ToDouble(splits[6])); return(new Bond( splits[0], startDate, maturityDate, 100.0, CurrencyCode.CNY, new FixedCoupon(rate), CalendarImpl.Get("chn_ib"), frequency, Stub.LongEnd, new ActActIsma(), new ActActIsma(), BusinessDayConvention.None, BusinessDayConvention.None, null, TradingMarket.ChinaInterBank)); }).ToArray(); var market = new BondFutureTests().TestMarket("2016-04-06", bondPrices); var engine = new BondEngine(); for (var i = 0; i < bonds.Length; ++i) { var result = engine.Calculate(bonds[i], market, PricingRequest.Ytm | PricingRequest.Ai); Assert.AreEqual(Math.Round(result.Ai, 4), targetAi[i], 1e-5); Assert.AreEqual(Math.Round(result.Ytm, 6), targetYtm[i], 1e-7); } } }
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 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 TradeVolLinearInterpSlopeCalc(double tradeOpenVol, double tradeCloseVol, DayCountMode dayCountMode = DayCountMode.TradingDay) { var startDate = new Date(2018, 3, 21); var maturityDate = new Date(2018, 5, 21); var valuationDate = new Date[] { new Date(2018, 3, 22), new Date(2018, 3, 23), new Date(2018, 3, 26) }; var numOfSmoothingDays = 30; var calendar = CalendarImpl.Get("chn"); double vol1 = AnalyticalOptionTradeVolInterp.tradeVolLinearInterp(valuationDate[0], tradeOpenVol, tradeCloseVol, startDate, maturityDate, numOfSmoothingDays, dayCountMode, calendar); double vol2 = AnalyticalOptionTradeVolInterp.tradeVolLinearInterp(valuationDate[1], tradeOpenVol, tradeCloseVol, startDate, maturityDate, numOfSmoothingDays, dayCountMode, calendar); double vol3 = AnalyticalOptionTradeVolInterp.tradeVolLinearInterp(valuationDate[2], tradeOpenVol, tradeCloseVol, startDate, maturityDate, numOfSmoothingDays, dayCountMode, calendar); Assert.AreEqual(vol2 - vol1, vol3 - vol2, 1e-10); }
private void SpreadOptionBjerksundCalc(string spreadType = "TwoAssetsSpread", Boolean isCall = true, string ValuationDate = "2017-12-26", double vol1 = 0.28, double spot1 = 1.0, double vol2 = 0.30, double spot2 = 2.0, double vol3 = 0.28, double spot3 = 1.0, double vol4 = 0.28, double spot4 = 1.0, double strike = 1.03, double tol = 1e-8) { var valuationDate = DateFromStr(ValuationDate); var maturityDate = new Term("176D").Next(valuationDate); var calendar = CalendarImpl.Get("chn"); var asset1 = "asset1"; var asset2 = "asset2"; var asset3 = "asset3"; var asset4 = "asset4"; var option = new SpreadOption( startDate: valuationDate, maturityDate: maturityDate, exercise: OptionExercise.European, optionType: (isCall) ? OptionType.Call : OptionType.Put, spreadType: ToSpreadType(spreadType), strike: strike, weights: new double[] { 1.0, 1.0, 1.0, 1.0 }, underlyingInstrumentType: InstrumentType.EquityIndex, calendar: calendar, dayCount: new Act365(), payoffCcy: CurrencyCode.CNY, settlementCcy: CurrencyCode.CNY, exerciseDates: new[] { maturityDate }, observationDates: new[] { maturityDate }, underlyingTickers: new[] { asset1, asset2, asset3, asset4 } ) { UnderlyingTickers = new string[] { asset1, asset2, asset3, asset4 } }; var market = TestMarket(referenceDate: ValuationDate, vol1: vol1, vol2: vol2, vol3: vol3, vol4: vol4, spot1: spot1, spot2: spot2, spot3: spot3, spot4: spot4, asset1: asset1, asset2: asset2, asset3: asset3, asset4: asset4); var analyticalEngine = new AnalyticalSpreadOptionBjerksundEngine(); var analyticalResult = analyticalEngine.Calculate(option, market, PricingRequest.All); var Engine = new AnalyticalSpreadOptionKirkEngine(); var Result = Engine.Calculate(option, market, PricingRequest.All); Assert.AreEqual(analyticalResult.Pv, Result.Pv, tol); }
private void SpreadOptionGreekCalc(double ExpectedPv, string spreadType = "TwoAssetsSpread", string ValuationDate = "2017-12-26") { var valuationDate = DateFromStr(ValuationDate); var maturityDate = new Term("176D").Next(valuationDate); var calendar = CalendarImpl.Get("chn"); var asset1 = "asset1"; var asset2 = "asset2"; var asset3 = "asset3"; var asset4 = "asset4"; var option = new SpreadOption( startDate: valuationDate, maturityDate: maturityDate, exercise: OptionExercise.European, optionType: OptionType.Call, spreadType: ToSpreadType(spreadType), strike: 1.03, weights: new double[] { 1.0, 1.0, 1.0, 1.0 }, underlyingInstrumentType: InstrumentType.EquityIndex, calendar: calendar, dayCount: new Act365(), payoffCcy: CurrencyCode.CNY, settlementCcy: CurrencyCode.CNY, exerciseDates: new[] { maturityDate }, observationDates: new[] { maturityDate }, underlyingTickers: new[] { asset1, asset2, asset3, asset4 } ) { UnderlyingTickers = new string[] { asset1, asset2, asset3, asset4 } }; var market = TestMarket(referenceDate: ValuationDate, asset1: asset1, asset2: asset2, asset3: asset3, asset4: asset4); //var analyticalEngine = new AnalyticalSpreadOptionEngine(); //var analyticalResult = analyticalEngine.Calculate(option, market, PricingRequest.All); var Engine = new AnalyticalSpreadOptionKirkEngine(); var Result = Engine.Calculate(option, market, PricingRequest.All); //Assert.AreEqual(ExpectedPv, analyticalResult.Pv, 1e-8); Assert.AreEqual(ExpectedPv, Result.Pv, 1e-8); }
private void CommodityLookbackOptionGreekCalc(String ValuationDate = "2015-03-19", Double vol = 0.28, Double spot = 240, Double strike = 240, 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) }; var option = new LookbackOption( valuationDate, maturityDate, OptionExercise.European, isCall ? OptionType.Call : OptionType.Put, isFixed ? StrikeStyle.Fixed : StrikeStyle.Floating, strike, InstrumentType.EquityIndex, calendar, new Act365(), CurrencyCode.CNY, CurrencyCode.CNY, new[] { maturityDate }, obsDates, new Dictionary <Date, double>(), notional: 1 ); var market = TestMarket(referenceDate: ValuationDate, vol: vol, spot: spot); var analyticalEngine = new AnalyticalLookbackOptionEngine(); 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(expectedRho, analyticalResult.Rho, 1e-8); Assert.AreEqual(expectedTheta, analyticalResult.Theta, 1e-8); }
public void Fr007CurveConstructionTest() { var historiclIndexRates = HistoricalDataLoadHelper.HistoricalIndexRates; var fr007CurveName = "Swap_Fr007"; var fr007CurveConvention = new CurveConvention("fr007CurveConvention", "CNY", "ModifiedFollowing", "Chn_ib", "Act365", "Continuous", "CubicHermiteMonotic"); var rateDefinition = new[] { new RateMktData("1D", 0.0431, "Fr007", "Deposit", fr007CurveName), new RateMktData("7D", 0.053, "Fr007", "Deposit", fr007CurveName), new RateMktData("3M", 0.0494, "Fr007", "InterestRateSwap", fr007CurveName), new RateMktData("6M", 0.0493, "Fr007", "InterestRateSwap", fr007CurveName), }; var curveDefinition = new[] { new InstrumentCurveDefinition(fr007CurveName, fr007CurveConvention, rateDefinition, "SpotCurve") }; var marketInfo = new MarketInfo("tmpMarket", "2014-02-10", curveDefinition, historiclIndexRates); var temp = CalendarImpl.Get("chn_ib"); QdpMarket market = null; var time1 = DateTime.Now; for (var i = 0; i <= 10; ++i) { var result = MarketFunctions.BuildMarket(marketInfo, out market); } var time2 = DateTime.Now; Console.WriteLine("{0}ms", (time2 - time1).TotalMilliseconds); var fr007Curve = market.GetData <CurveData>(fr007CurveName).YieldCurve; Assert.AreEqual(fr007Curve.KeyPoints[0].Item2, 0.0430974555290732, 1e-4); // use IrsFloatingLegPvReal Assert.AreEqual(fr007Curve.KeyPoints[3].Item2, 0.048992349561639, 1e-4); // use IrsFloatingLegPvReal }
public static Date GetFxSpotDate(Date startDate, DayGap settlement, CurrencyCode fgnCcy, CurrencyCode domCcy, ICalendar fgnCalendar, ICalendar domCalendar) { //中国外汇交易中心产品指引(外汇市场)V1.8 58页 var foreignSpotDate = settlement.Get(fgnCalendar, startDate); var domesticSpotDate = settlement.Get(domCalendar, startDate); var usdCalendar = CalendarImpl.Get(Calendar.Usd); if (fgnCcy == CurrencyCode.USD) { if (!usdCalendar.IsHoliday(domesticSpotDate)) { return(domesticSpotDate); } } if (domCcy == CurrencyCode.USD) { if (!usdCalendar.IsHoliday(foreignSpotDate)) { return(foreignSpotDate); } } var guessSettlementDate = foreignSpotDate > domesticSpotDate ? foreignSpotDate : domesticSpotDate; if (usdCalendar.IsHoliday(guessSettlementDate) || fgnCalendar.IsHoliday(guessSettlementDate) || domCalendar.IsHoliday(guessSettlementDate)) { //find next biz day for foreign currency and domestic currency while (fgnCalendar.IsHoliday(guessSettlementDate) || domCalendar.IsHoliday(guessSettlementDate)) { guessSettlementDate = new Term("1D").Next(guessSettlementDate); } return(guessSettlementDate); } return(guessSettlementDate); }
public void TestAsianOptionPvAgainistHaugerExcel() { var startDate = new Date(2015, 03, 19); var maturityDate = new Term("183D").Next(startDate); var calendar = CalendarImpl.Get("chn"); var oneWeek = new Term("7D"); var dates = new List <Date>() { new Date(2015, 03, 20) }; for (int i = 1; i < 27; i++) { dates.Add(oneWeek.Next(dates[i - 1])); } var option = new AsianOption( startDate, maturityDate, OptionExercise.European, OptionType.Call, AsianType.DiscreteArithmeticAverage, StrikeStyle.Fixed, 100, InstrumentType.EquityIndex, calendar, new Act365(), CurrencyCode.CNY, CurrencyCode.CNY, new[] { maturityDate }, dates.ToArray(), new Dictionary <Date, double>() ); var market = TestMarket2(); var analyticalEngine = new AnalyticalAsianOptionEngineLegacy(); var result = analyticalEngine.Calculate(option, market, PricingRequest.All); Console.WriteLine("{0},{1},{2},{3},{4}", result.Pv, result.Delta, result.Gamma, result.Vega, result.Rho); //Note: originally was 1.9622573116 Assert.AreEqual(2.91746104388858, result.Pv, 1e-8); }
private VanillaOption CreateOption(Double strike, Date expiry, Date firstConversionDate, Boolean American = true) { var americanNoticeDates = CalendarImpl.Get("chn").BizDaysBetweenDates(new Date(2015, 06, 30), new Date(2019, 12, 25)).ToArray(); var exerciseStyle = American ? OptionExercise.American : OptionExercise.European; var noticeDates = American ? americanNoticeDates : new Date[] { expiry }; return(new VanillaOption(firstConversionDate, expiry, exerciseStyle, OptionType.Call, strike, InstrumentType.Stock, CalendarImpl.Get("chn"), new Act365(), CurrencyCode.CNY, CurrencyCode.CNY, noticeDates, noticeDates )); }
public void TestCallableBond() { var bond = new Bond( "010001", new Date(2012, 05, 03), new Date(2017, 05, 03), 100, CurrencyCode.CNY, new FixedCoupon(0.068), CalendarImpl.Get("chn_ib"), Frequency.Annual, Stub.LongEnd, new ActActIsma(), new ActAct(), BusinessDayConvention.None, BusinessDayConvention.ModifiedFollowing, null, TradingMarket.ChinaInterBank ); var option = new VanillaOption(new Date(2012, 05, 03), new Date(2017, 05, 03), OptionExercise.European, OptionType.Put, 106.8, InstrumentType.Bond, CalendarImpl.Get("chn_ib"), new Act365(), CurrencyCode.CNY, CurrencyCode.CNY, new[] { new Date(2015, 05, 03) }, new[] { new Date(2015, 05, 03) } ); var callableBond = new CallableBond(bond, new[] { option }, new[] { PriceQuoteType.Dirty }); var market = TestMarket(); var engine = new CallableBondEngine <HullWhite>(new HullWhite(0.1, 0.01), true, 40); var result = engine.Calculate(callableBond, market, PricingRequest.All); Assert.AreEqual(107.0198942139, result.Pv, 1e-8); }
private void RainbowOptionGreekCalc(double ExpectedPv, string rainbowType = "Max", string ValuationDate = "2017-12-18", double vol = 0.28, double spot = 1.0, double volNew = 0.30, double spotNew = 2.0, double strike1 = 1.03, double strike2 = 1.05, Boolean isCall = true) { var valuationDate = DateFromStr(ValuationDate); var maturityDate = new Term("176D").Next(valuationDate); var calendar = CalendarImpl.Get("chn"); var asset1 = "asset1"; var asset2 = "asset2"; var option = new RainbowOption( startDate: valuationDate, maturityDate: maturityDate, exercise: OptionExercise.European, optionType: isCall ? OptionType.Call : OptionType.Put, rainbowType: ToRainbowType(rainbowType), strikes: new double[] { strike1, strike2 }, cashAmount: 1.0, underlyingInstrumentType: InstrumentType.EquityIndex, calendar: calendar, dayCount: new Act365(), payoffCcy: CurrencyCode.CNY, settlementCcy: CurrencyCode.CNY, exerciseDates: new[] { maturityDate }, observationDates: new[] { maturityDate }, underlyingTickers: new[] { asset1, asset2 } ) { UnderlyingTickers = new string[] { asset1, asset2 } }; var market = TestMarket(referenceDate: ValuationDate, vol: vol, volNew: volNew, spot: spot, spotNew: spotNew, asset1: asset1, asset2: asset2); var analyticalEngine = new AnalyticalRainbowOptionEngine(); var analyticalResult = analyticalEngine.Calculate(option, market, PricingRequest.All); Assert.AreEqual(ExpectedPv, analyticalResult.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); }
public void TestVanillaEuropeanCallMc() { var startDate = new Date(2014, 03, 18); var maturityDate = new Date(2015, 03, 18); var market = TestMarket(); var call = new VanillaOption(startDate, maturityDate, OptionExercise.European, OptionType.Call, 1.0, InstrumentType.Stock, CalendarImpl.Get("chn"), new Act365(), CurrencyCode.CNY, CurrencyCode.CNY, new[] { maturityDate }, new[] { maturityDate }); var mcengine = new GenericMonteCarloEngine(2, 200000); var result = mcengine.Calculate(call, market, PricingRequest.All); var analyticalResult = new AnalyticalVanillaEuropeanOptionEngine().Calculate(call, market, PricingRequest.All); Console.WriteLine("{0},{1}", analyticalResult.Pv, result.Pv); Console.WriteLine("{0},{1}", analyticalResult.Delta, result.Delta); Console.WriteLine("{0},{1}", analyticalResult.Gamma, result.Gamma); Console.WriteLine("{0},{1}", analyticalResult.Vega, result.Vega); Console.WriteLine("{0},{1}", analyticalResult.Rho, result.Rho); Console.WriteLine("{0},{1}", analyticalResult.Theta, result.Theta); Assert.AreEqual(analyticalResult.Pv, result.Pv, 0.002); Assert.AreEqual(analyticalResult.Delta, result.Delta, 0.02); Assert.AreEqual(analyticalResult.Gamma, result.Gamma, 0.05); Assert.AreEqual(analyticalResult.Theta, result.Theta, 1e-5); Assert.AreEqual(analyticalResult.Rho, result.Rho, 1e-6); Assert.AreEqual(analyticalResult.Vega, result.Vega, 1e-4); }