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 void ClnTest() { var valueDate = new Date(2015, 06, 1); var market = new MarketCondition(x => x.ValuationDate.Value = valueDate); var fixings = File.ReadAllLines(@"./Data/HistoricalEquityPrices/hsgy.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 cln = new ConstantLeveragedNote(new Date(2015, 5, 28), new Date(2018, 10, 29), 1000, 3.0, 0.055, fixings, new Dictionary <Date, double>() { { new Date(2015, 05, 28), 0.8002 }, { new Date(2015, 06, 01), 0.8 } } ); var engine = new ConstantLeveragedNoteEngine(); var result = engine.Calculate(cln, market, PricingRequest.All); Assert.AreEqual(result.Pv / cln.Notional, 1.022959, 1e-6); }
public double ImpliedVolFromPremium(double targetPremium, VanillaOption option, MarketCondition market) { var timeIncrement = AnalyticalOptionPricerUtil.optionTimeToMaturityIncrement(option); var calculator = ConfigureCalculator(option, market, timeIncrement: timeIncrement); return(calculator.SolveVol(targetPremium)); }
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 TestSwapCurveRepricing() { var ReferenceDate = "2017-11-15"; const string t0MarketName = "Market2017-11-15"; var curveName = "Fr007SwapCurve"; //Calibrate curve var curveDefinitions = GetTestIrsCurveDefinition(curveName); var t0MarketInfo = new MarketInfo(t0MarketName) { ReferenceDate = ReferenceDate, YieldCurveDefinitions = curveDefinitions.ToArray(), HistoricalIndexRates = HistoricalDataLoadHelper.HistoricalIndexRates }; XlManager.LoadMarket(t0MarketInfo); var market = XlManager.GetXlMarket(t0MarketName).QdpMarket; var tCurves = XlManager.GetXlMarket(t0MarketName).MarketInfo.YieldCurveDefinitions.Select(x => x.Name) .Select(x => market.GetData <CurveData>(x).YieldCurve).ToDictionary(x => x.Name, x => x); var curve = tCurves.First().Value; var inputInstruments = curve.MarketInstruments; inputInstruments.Select(p => p.TargetValue); //Repricing curve building instruments //Repricing threshold var threshold = 1e-7; var expected = inputInstruments.Select(p => p.TargetValue).ToArray(); var actual = new double[inputInstruments.Length]; var marketCondition = new MarketCondition( x => x.ValuationDate.Value = market.ReferenceDate, x => x.DiscountCurve.Value = market.GetData <CurveData>(curveName).YieldCurve, x => x.FixingCurve.Value = market.GetData <CurveData>(curveName).YieldCurve, x => x.RiskfreeCurve.Value = market.GetData <CurveData>(curveName).YieldCurve, x => x.HistoricalIndexRates.Value = new Dictionary <IndexType, SortedDictionary <Date, double> >() ); for (int i = 0; i < inputInstruments.Length; i++) { actual[i] = inputInstruments[i].Instrument.ModelValue(marketCondition, MktInstrumentCalibMethod.Default); } var diffReport = expected.Zip(actual, (first, second) => Tuple.Create <double, double, double, bool>(first, second, first - second, Math.Abs(first - second) > threshold)); foreach (Tuple <double, double, double, bool> diffLine in diffReport) { Console.WriteLine($"Repricing diff : {diffLine}"); } var breaches = diffReport.Where(x => x.Item4 == true).Count(); Assert.AreEqual(true, breaches == 0); }
public void DlnTest() { var valueDate = new Date(2015, 06, 16); var market = new MarketCondition(x => x.ValuationDate.Value = valueDate); 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 dln = new DynamicLeveragedNote(new Date(2015, 1, 5), new Date(2018, 10, 29), 1000, 2.0, 1.75, 2.25, 0.05, 0.004, fixings ); var engine = new DynamicLeveragedNoteEngine(); var result = engine.Calculate(dln, market, PricingRequest.All); Assert.AreEqual(result.Pv / dln.Notional, 1.793219889635, 1e-10); Assert.AreEqual(result.Delta / dln.Notional, 3.695695861697, 1e-10); var dln2 = new DynamicLeveragedNote(new Date(2015, 1, 5), new Date(2018, 10, 29), 1000, 1.0, 0.75, 1.25, 0.05, 0.004, fixings ); result = engine.Calculate(dln2, market, PricingRequest.All); Assert.AreEqual(result.Pv / dln2.Notional, 1.39084563124, 1e-10); Assert.AreEqual(result.Delta / dln2.Notional, 1.39084563124, 1e-10); }
//Takes too long time //[TestMethod] public void CommodityBinaryEuropeanOptionMcTest() { 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) }, 1.0 ); var market = GetMarket(); var volsurf = market.GetData <VolSurfMktData>("goldVolSurf").ToImpliedVolSurface(market.ReferenceDate); var yc = market.GetData <CurveData>("Fr007").YieldCurve; IMarketCondition marketCondition = new MarketCondition( x => x.ValuationDate.Value = market.ReferenceDate, x => x.DiscountCurve.Value = yc, x => x.DividendCurves.Value = new Dictionary <string, IYieldCurve> { { "", yc } }, x => x.SpotPrices.Value = new Dictionary <string, double> { { "", 240.6 } }, x => x.VolSurfaces.Value = new Dictionary <string, IVolSurface> { { "", volsurf } } ); // set first point on dividend curve to 0 //MC pricing var dc = ZeroRateCurve(marketCondition.DividendCurves.Value.Values.First()); marketCondition = marketCondition.UpdateCondition(new UpdateMktConditionPack <Dictionary <string, IYieldCurve> >(x => x.DividendCurves, new Dictionary <string, IYieldCurve> { { "", dc } })); var engine = new GenericMonteCarloEngine(2, 500000); var result = engine.Calculate(goldOption, marketCondition, PricingRequest.All); //analytical pricing var analyticalResult = new AnalyticalBinaryEuropeanOptionEngine().Calculate(goldOption, marketCondition, PricingRequest.All); Console.WriteLine("Pv:{0},{1}", analyticalResult.Pv, result.Pv); Console.WriteLine("Delta: {0},{1}", analyticalResult.Delta, result.Delta); Console.WriteLine("Gamma: {0},{1}", analyticalResult.Gamma, result.Gamma); Console.WriteLine("Vega: {0},{1}", analyticalResult.Vega, result.Vega); Console.WriteLine("Rho: {0},{1}", analyticalResult.Rho, result.Rho); //TODO binary option monte carlo rho Console.WriteLine("Theta: {0},{1}", analyticalResult.Theta, result.Theta); //Assert.AreEqual(analyticalResult.Pv, result.Pv, 0.02); //Assert.AreEqual(analyticalResult.Delta, result.Delta, 0.02); //Assert.AreEqual(analyticalResult.Gamma, result.Gamma, 0.05); //Assert.AreEqual(analyticalResult.Vega, result.Vega, 1e-2); //Assert.AreEqual(analyticalResult.Rho, result.Rho, 1e-6); //Assert.AreEqual(analyticalResult.Theta, result.Theta, 1e-5); }
public void CommodityBinaryOptionGreekTest(double vol, double spot, double strike, Boolean isCall = true, Boolean isCashOrNothing = true, string t0 = "2017-12-01", string t1 = "2017-12-02", 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 expiry = new Date(2017, 12, 17); var valuationDay = t0; var valuationDayNew = t1; var option = new BinaryOption( T0, expiry, OptionExercise.European, isCall ? OptionType.Call : OptionType.Put, strike, InstrumentType.CommodityFutures, isCashOrNothing ? BinaryOptionPayoffType.CashOrNothing : BinaryOptionPayoffType.AssetOrNothing, 2, CalendarImpl.Get("chn"), new Act365(), CurrencyCode.CNY, CurrencyCode.CNY, new[] { expiry }, new[] { expiry }, notional: 1 ); var curveName = "Fr007"; var volName = "volSurf"; var diviCurveName = "diviCurve"; var market = GetMarketJinTao(valuationDay, rate: 0.04, vol: vol, dividendRate: 0, curveName: curveName, volName: volName, diviCurveName: diviCurveName); IMarketCondition marketCondition = new MarketCondition( x => x.ValuationDate.Value = market.ReferenceDate, x => x.DiscountCurve.Value = market.GetData <CurveData>(curveName).YieldCurve, x => x.DividendCurves.Value = new Dictionary <string, IYieldCurve> { { "", market.GetData <CurveData>(diviCurveName).YieldCurve } }, x => x.SpotPrices.Value = new Dictionary <string, double> { { "", spot } }, x => x.VolSurfaces.Value = new Dictionary <string, IVolSurface> { { "", market.GetData <VolSurfMktData>(volName).ToImpliedVolSurface(market.ReferenceDate) } } ); var marketNew = GetMarketJinTao(valuationDayNew, rate: 0.04, vol: volNew, dividendRate: 0, curveName: curveName, volName: volName, diviCurveName: diviCurveName); IMarketCondition marketConditionNew = new MarketCondition( x => x.ValuationDate.Value = marketNew.ReferenceDate, x => x.DiscountCurve.Value = marketNew.GetData <CurveData>(curveName).YieldCurve, x => x.DividendCurves.Value = new Dictionary <string, IYieldCurve> { { "", marketNew.GetData <CurveData>(diviCurveName).YieldCurve } }, x => x.SpotPrices.Value = new Dictionary <string, double> { { "", spotNew } }, x => x.VolSurfaces.Value = new Dictionary <string, IVolSurface> { { "", marketNew.GetData <VolSurfMktData>(volName).ToImpliedVolSurface(market.ReferenceDate) } } ); IMarketCondition marketConditionPI = new MarketCondition( x => x.ValuationDate.Value = market.ReferenceDate, x => x.DiscountCurve.Value = market.GetData <CurveData>(curveName).YieldCurve, x => x.DividendCurves.Value = new Dictionary <string, IYieldCurve> { { "", market.GetData <CurveData>(diviCurveName).YieldCurve } }, x => x.SpotPrices.Value = new Dictionary <string, double> { { "", spotNew } }, x => x.VolSurfaces.Value = new Dictionary <string, IVolSurface> { { "", market.GetData <VolSurfMktData>(volName).ToImpliedVolSurface(market.ReferenceDate) } } ); var marketVI = GetMarketJinTao(valuationDay, rate: 0.04, vol: volNew, dividendRate: 0, curveName: curveName, volName: volName, diviCurveName: diviCurveName); IMarketCondition marketConditionVI = new MarketCondition( x => x.ValuationDate.Value = marketVI.ReferenceDate, x => x.DiscountCurve.Value = marketVI.GetData <CurveData>(curveName).YieldCurve, x => x.DividendCurves.Value = new Dictionary <string, IYieldCurve> { { "", marketVI.GetData <CurveData>(diviCurveName).YieldCurve } }, x => x.SpotPrices.Value = new Dictionary <string, double> { { "", spot } }, x => x.VolSurfaces.Value = new Dictionary <string, IVolSurface> { { "", marketVI.GetData <VolSurfMktData>(volName).ToImpliedVolSurface(market.ReferenceDate) } } ); var marketPVC = GetMarketJinTao(valuationDay, rate: 0.04, vol: volNew, dividendRate: 0, curveName: curveName, volName: volName, diviCurveName: diviCurveName); IMarketCondition marketConditionPVC = new MarketCondition( x => x.ValuationDate.Value = marketPVC.ReferenceDate, x => x.DiscountCurve.Value = marketPVC.GetData <CurveData>(curveName).YieldCurve, x => x.DividendCurves.Value = new Dictionary <string, IYieldCurve> { { "", marketPVC.GetData <CurveData>(diviCurveName).YieldCurve } }, x => x.SpotPrices.Value = new Dictionary <string, double> { { "", spotNew } }, x => x.VolSurfaces.Value = new Dictionary <string, IVolSurface> { { "", marketPVC.GetData <VolSurfMktData>(volName).ToImpliedVolSurface(market.ReferenceDate) } } ); var engine = new AnalyticalBinaryEuropeanOptionEngine(); var result = engine.Calculate(option, marketCondition, PricingRequest.All); var resultNew = engine.Calculate(option, marketConditionNew, PricingRequest.All); var resultPI = engine.Calculate(option, marketConditionPI, PricingRequest.All); var resultVI = engine.Calculate(option, marketConditionVI, PricingRequest.All); var resultPVC = engine.Calculate(option, marketConditionPVC, 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); var engine2 = new AnalyticalBinaryEuropeanOptionReplicationEngine(2.0, BinaryOptionReplicationStrategy.Up); var result2 = engine2.Calculate(option, marketCondition, PricingRequest.All); var resultNew2 = engine2.Calculate(option, marketConditionNew, PricingRequest.All); var resultPI2 = engine2.Calculate(option, marketConditionPI, PricingRequest.All); var resultVI2 = engine2.Calculate(option, marketConditionVI, PricingRequest.All); var resultPVC2 = engine2.Calculate(option, marketConditionPVC, PricingRequest.All); var actualPL2 = resultNew2.Pv - result2.Pv; //price Impact //PI = PV(t-1, priceNew) - Pv(t-1) var basePv2 = result2.Pv; var PI2 = resultPI2.Pv - basePv2; var thetapl2 = result2.Theta * (T1 - T0); //vol impact //VI = PV(t-1. volNew) - Pv (t-1) var VI2 = resultVI2.Pv - basePv2; //price vol cross impact //PVC = PV(t-1. volNew, PriceNew) - Pv (t-1) - (PI+VI) var PVC2 = resultPVC2.Pv - basePv2 - PI2 - VI2; var newEstimate2 = PI2 + VI2 + PVC2 + thetapl2; var newUnexplained2 = actualPL2 - newEstimate2; Assert.AreEqual(true, Math.Abs(newUnexplained2 / actualPL2) * 100.0 < toleranceInPct); }
public void CommodityBinaryAmericanOptionTest() { var strike = 3100.0; var spot = 2900; var expiry = new Date(2018, 04, 16); var valuationDay = "2018-03-28"; var option = new BinaryOption( new Date(2018, 03, 28), expiry, OptionExercise.European, OptionType.Call, strike, InstrumentType.CommodityFutures, BinaryOptionPayoffType.CashOrNothing, 2, CalendarImpl.Get("chn"), new Act365(), CurrencyCode.CNY, CurrencyCode.CNY, new[] { expiry }, new[] { expiry }, notional: 1000 ); var option2 = new BinaryOption( new Date(2018, 03, 28), expiry, OptionExercise.European, OptionType.Call, strike, InstrumentType.CommodityFutures, BinaryOptionPayoffType.CashOrNothing, 2, CalendarImpl.Get("chn"), new Act365(), CurrencyCode.CNY, CurrencyCode.CNY, new[] { expiry }, new[] { expiry }, notional: 1000, binaryRebateType: BinaryRebateType.AtEnd ); var curveName = "Fr007"; var volName = "volSurf"; var diviCurveName = "diviCurve"; var market = GetMarketJinTao(valuationDay, rate: 0.05, vol: 0.3, dividendRate: 0, curveName: curveName, volName: volName, diviCurveName: diviCurveName); var volsurf = market.GetData <VolSurfMktData>(volName).ToImpliedVolSurface(market.ReferenceDate); IMarketCondition marketCondition = new MarketCondition( x => x.ValuationDate.Value = market.ReferenceDate, x => x.DiscountCurve.Value = market.GetData <CurveData>(curveName).YieldCurve, x => x.DividendCurves.Value = new Dictionary <string, IYieldCurve> { { "", market.GetData <CurveData>(diviCurveName).YieldCurve } }, x => x.SpotPrices.Value = new Dictionary <string, double> { { "", spot } }, x => x.VolSurfaces.Value = new Dictionary <string, IVolSurface> { { "", volsurf } } ); var engine = new AnalyticalBinaryAmericanOptionEngine(); var result = engine.Calculate(option, marketCondition, PricingRequest.All); var result3 = engine.Calculate(option2, marketCondition, PricingRequest.All); Assert.AreEqual(result.Pv != result3.Pv, true); Assert.AreEqual(637.071254168821, result.Pv, 1e-8); Assert.AreEqual(4.94251151619665, result.Delta, 1e-8); Assert.AreEqual(0.0237525887314405, result.Gamma, 1e-8); Assert.AreEqual(31.1432441274033, result.Vega, 1e-8); Assert.AreEqual(-25.2234472794418, result.Theta, 1e-8); Assert.AreEqual(-0.00171280700558327, result.Rho, 1e-8); var engine2 = new AnalyticalBinaryEuropeanOptionEngine(); var result2 = engine2.Calculate(option, marketCondition, PricingRequest.All); Assert.AreEqual(result.Pv >= result2.Pv, true); Assert.AreEqual(result.Delta >= result2.Delta, true); Assert.AreEqual(result.Gamma >= result2.Gamma, true); Assert.AreEqual(result.Vega >= result2.Vega, true); Assert.AreEqual(Math.Abs(result.Theta) >= Math.Abs(result2.Theta), true); }
public void BondForwardTest() { var bond = new Bond( "010000", new Date(2013, 2, 25), new Date(2015, 2, 25), 100, CurrencyCode.CNY, new FixedCoupon(0.0375), CalendarImpl.Get("chn_ib"), Frequency.SemiAnnual, Stub.LongEnd, new ActActIsma(), new Act365(), BusinessDayConvention.None, BusinessDayConvention.None, null, TradingMarket.ChinaInterBank ); var bondForward = new Forward <Bond>( new Date(2013, 5, 28), new Date(2013, 8, 28), 100.0, 98.57947065, bond, CurrencyCode.CNY ); var referenceDate = new Date(2013, 8, 23); var yieldCurve = new YieldCurve( "中债国债收收益率曲线", referenceDate, new[] { Tuple.Create((ITerm) new Term("1D"), 0.035), Tuple.Create((ITerm) new Term("1Y"), 0.035) }, BusinessDayConvention.ModifiedFollowing, new Act365(), CalendarImpl.Get("chn_ib"), CurrencyCode.CNY, Compound.Simple, Interpolation.CubicHermiteMonotic, YieldCurveTrait.SpotCurve ); var market = new MarketCondition ( x => x.ValuationDate.Value = referenceDate, x => x.MktQuote.Value = new Dictionary <string, Tuple <PriceQuoteType, double> > { { "010000", Tuple.Create(PriceQuoteType.Dirty, 99.71798177) } }, x => x.DiscountCurve.Value = yieldCurve, x => x.FixingCurve.Value = yieldCurve, x => x.RiskfreeCurve.Value = yieldCurve, x => x.UnderlyingDiscountCurve.Value = yieldCurve, x => x.HistoricalIndexRates.Value = new Dictionary <IndexType, SortedDictionary <Date, double> >() ); var bondengine = new BondEngine(); var zeroSpread = bondengine.Calculate(bond, market, PricingRequest.ZeroSpread).ZeroSpread; var engine = new ForwardEngine <Bond>(); var result = engine.Calculate(bondForward, market, PricingRequest.Pv); Assert.AreEqual(-0.68888788, result.Pv, 1e-8); }
public static object BondEngineCalc(string bondId, string calcDate, PriceQuoteType priceQuote, double quote, PricingRequest request, FixedRateBondInfo fixedBond = null) { var bond = fixedBond ?? XlManager.GetTrade(bondId); if (bond == null) { return(string.Format("Cannot find bond {0}.", bondId)); } var vf = new BondVf((BondInfoBase)bond); var bondInstrument = vf.GenerateInstrument(); var valueDate = calcDate.ToDate(); var fixingCurve = new YieldCurve( "中债国债收收益率曲线", valueDate, new[] { new Tuple <Date, double>(valueDate, 0.0), new Tuple <Date, double>(new Term("10Y").Next(valueDate), 0.0) }, BusinessDayConvention.ModifiedFollowing, new Act365(), CalendarImpl.Get("Chn_ib"), CurrencyCode.CNY, Compound.Continuous, Interpolation.ForwardFlat, YieldCurveTrait.ForwardCurve ); var market = new MarketCondition( x => x.ValuationDate.Value = valueDate, x => x.FixingCurve.Value = fixingCurve, x => x.MktQuote.Value = new Dictionary <string, Tuple <PriceQuoteType, double> > { { bondId, Tuple.Create(priceQuote, quote) } }, x => x.HistoricalIndexRates.Value = HistoricalIndexRates ); if (bond is FloatingRateBondInfo) { var fixingTuple = bondInstrument.Coupon.GetPrimeCoupon(HistoricalIndexRates, fixingCurve, valueDate); var keyTenors = new string[fixingCurve.GetKeyTenors().Length]; fixingCurve.GetKeyTenors().CopyTo(keyTenors, 0); for (var i = 0; i < keyTenors.Length; ++i) { market = (MarketCondition)market.UpdateCondition(new UpdateMktConditionPack <IYieldCurve>(x => x.FixingCurve, market.FixingCurve.Value.BumpKeyRate(i, fixingTuple.Item2))); } if (request.Equals(PricingRequest.None)) { return(fixingTuple); } } var engine = vf.GenerateEngine(); var result = engine.Calculate(bondInstrument, market, request); if (!result.Succeeded) { return(string.Format("Failed to Calculate bond {0}:{1}", bondId, result.ErrorMessage)); } return(result); }
public void BasicVanillaOptionTest() { var startDate = new Date(2014, 03, 18); var maturityDate = new Date(2015, 03, 18); var valueDate = new Date(2014, 03, 18); #region Prepare Market // build discount curve and dividend curve var fr007CurveName = "Fr007"; var fr007RateDefinition = new[] { new RateMktData("1D", 0.06, "Spot", "None", fr007CurveName), new RateMktData("5Y", 0.06, "Spot", "None", fr007CurveName), }; var dividendCurveName = "Dividend"; var dividendRateDefinition = new[] { new RateMktData("1D", 0.03, "Spot", "None", dividendCurveName), new RateMktData("5Y", 0.03, "Spot", "None", dividendCurveName), }; var discountCurve = new YieldCurve( name: fr007CurveName, referenceDate: valueDate, keyPoints: fr007RateDefinition.Select(x => Tuple.Create((ITerm) new Term(x.Tenor), x.Rate)).ToArray(), bda: BusinessDayConvention.ModifiedFollowing, dayCount: new Act365(), calendar: CalendarImpl.Get("Chn"), currency: CurrencyCode.CNY, compound: Compound.Continuous, interpolation: Interpolation.CubicHermiteMonotic, trait: YieldCurveTrait.SpotCurve); var dividendCurve = new YieldCurve( name: dividendCurveName, referenceDate: valueDate, keyPoints: dividendRateDefinition.Select(x => Tuple.Create((ITerm) new Term(x.Tenor), x.Rate)).ToArray(), bda: BusinessDayConvention.ModifiedFollowing, dayCount: new Act365(), calendar: CalendarImpl.Get("Chn"), currency: CurrencyCode.CNY, compound: Compound.Continuous, interpolation: Interpolation.CubicHermiteMonotic, trait: YieldCurveTrait.SpotCurve); // build vol surface var volSurfData = new VolSurfMktData("VolSurf", 0.25); var volSurface = volSurfData.ToImpliedVolSurface( valuationDate: valueDate, dc: "Act365"); // construct market var market = new MarketCondition( x => x.ValuationDate.Value = valueDate, x => x.DiscountCurve.Value = discountCurve, x => x.DividendCurves.Value = new Dictionary <string, IYieldCurve> { { "", dividendCurve } }, x => x.VolSurfaces.Value = new Dictionary <string, IVolSurface> { { "", volSurface } }, x => x.SpotPrices.Value = new Dictionary <string, double> { { "", 1.0 } } ); #endregion // construct a put option var put = new VanillaOption(startDate, maturityDate, OptionExercise.European, OptionType.Put, 1.0, InstrumentType.Stock, CalendarImpl.Get("chn"), new Act365(), CurrencyCode.CNY, CurrencyCode.CNY, new[] { maturityDate }, new[] { maturityDate }); var engine = new AnalyticalVanillaEuropeanOptionEngine(); var result = engine.Calculate(put, market, PricingRequest.All); }
public void MoneynessDeltaTest() { var startDate = new Date(2018, 03, 02); var maturityDate = new Date(2018, 04, 27); var call = new VanillaOption(startDate, maturityDate, OptionExercise.American, OptionType.Call, 1.05, InstrumentType.Stock, CalendarImpl.Get("chn"), new Act365(), CurrencyCode.CNY, CurrencyCode.CNY, new[] { maturityDate }, new[] { maturityDate }, 12, null, null, 0, true, 8000); #region construct market var historiclIndexRates = HistoricalDataLoadHelper.HistoricalIndexRates; var curveConvention = new CurveConvention("fr007CurveConvention", "CNY", "ModifiedFollowing", "Chn", "Act365", "Continuous", "CubicHermiteMonotic"); var fr007CurveName = "Fr007"; var fr007RateDefinition = new[] { new RateMktData("1D", 0.05, "Spot", "None", fr007CurveName), new RateMktData("5Y", 0.05, "Spot", "None", fr007CurveName), }; var dividendCurveName = "Dividend"; var dividendRateDefinition = new[] { new RateMktData("1D", 0, "Spot", "None", dividendCurveName), new RateMktData("5Y", 0, "Spot", "None", dividendCurveName), }; var curveDefinition = new[] { new InstrumentCurveDefinition(fr007CurveName, curveConvention, fr007RateDefinition, "SpotCurve"), new InstrumentCurveDefinition(dividendCurveName, curveConvention, dividendRateDefinition, "SpotCurve"), }; var volSurf = new[] { new VolSurfMktData("VolSurf", 0.3), }; var marketInfo = new MarketInfo("tmpMarket", "2018-03-02", curveDefinition, historiclIndexRates, null, null, volSurf); QdpMarket qdpMarket; MarketFunctions.BuildMarket(marketInfo, out qdpMarket); var valuationDate = new Date(2018, 3, 2); //flat vol surface var surface1 = qdpMarket.GetData <VolSurfMktData>("VolSurf").ToImpliedVolSurface(valuationDate); // market with flat vol surface var market = new MarketCondition( x => x.ValuationDate.Value = valuationDate, x => x.DiscountCurve.Value = qdpMarket.GetData <CurveData>("Fr007").YieldCurve, x => x.DividendCurves.Value = new Dictionary <string, IYieldCurve> { { "", qdpMarket.GetData <CurveData>("Dividend").YieldCurve } }, x => x.VolSurfaces.Value = new Dictionary <string, IVolSurface> { { "", surface1 } }, x => x.SpotPrices.Value = new Dictionary <string, double> { { "", 8000 } } ); //a real vol surface, same as stock 600000 of 2018-03-02 in OTC system var maturities = new Date[] { (new Term("1W")).Next(startDate), (new Term("2W")).Next(startDate), (new Term("1M")).Next(startDate) }; var strikes = new double[] { 0.9, 0.95, 1.0, 1.05, 1.1 }; var vols = new double[3, 5]; for (var i = 0; i < vols.GetLength(0); ++i) { for (var j = 0; j < vols.GetLength(1); ++j) { vols[i, j] = 0.3; } } vols[2, 2] = 0.4; var surface2 = new ImpliedVolSurface(valuationDate, maturities, strikes, vols, Interpolation2D.BiLinear); // market with flat vol surface var market2 = new MarketCondition( x => x.ValuationDate.Value = valuationDate, x => x.DiscountCurve.Value = qdpMarket.GetData <CurveData>("Fr007").YieldCurve, x => x.DividendCurves.Value = new Dictionary <string, IYieldCurve> { { "", qdpMarket.GetData <CurveData>("Dividend").YieldCurve } }, x => x.VolSurfaces.Value = new Dictionary <string, IVolSurface> { { "", surface2 } }, x => x.SpotPrices.Value = new Dictionary <string, double> { { "", 8000 } } ); #endregion var engine = new AnalyticalVanillaEuropeanOptionEngine(); //result of a flat vol surface of 0.3, which is the same as pricing result in OTC-926 var result = engine.Calculate(call, market, PricingRequest.All); //result of real vol surface, which is the same as scenario analysis in OTC-926 var result2 = engine.Calculate(call, market2, PricingRequest.All); }
/// <summary> /// for Option version only /// </summary> /// <param name="prebuiltMarket"></param> /// <param name="curveDate"></param> /// <param name="curveDefinition"></param> /// <returns></returns> public static YieldCurve BuildYieldCurve(PrebuiltQdpMarket prebuiltMarket, Date curveDate, InstrumentCurveDefinition curveDefinition) { IMarketCondition baseMarket; baseMarket = new MarketCondition(x => x.ValuationDate.Value = prebuiltMarket.ReferenceDate, x => x.HistoricalIndexRates.Value = prebuiltMarket.HistoricalIndexRates); YieldCurve instrumentCurve = null; if (curveDefinition.RateDefinitions.All( x => x.InstrumentType.ToInstrumentType() == InstrumentType.Dummy || x.InstrumentType.ToInstrumentType() == InstrumentType.None)) { if (curveDefinition.RateDefinitions.All(x => x.IsTerm())) { instrumentCurve = new YieldCurve( curveDefinition.Name, curveDate, curveDefinition.RateDefinitions.Select(x => Tuple.Create((ITerm) new Term(x.Tenor), x.Rate)).ToArray(), curveDefinition.CurveConvention.BusinessDayConvention.ToBda(), curveDefinition.CurveConvention.DayCount.ToDayCountImpl(), curveDefinition.CurveConvention.Calendar.ToCalendarImpl(), curveDefinition.CurveConvention.Currency.ToCurrencyCode(), curveDefinition.CurveConvention.Compound.ToCompound(), curveDefinition.CurveConvention.Interpolation.ToInterpolation(), curveDefinition.Trait.ToYieldCurveTrait(), null, null, null, null, curveDefinition ); } else { instrumentCurve = new YieldCurve( curveDefinition.Name, curveDate, curveDefinition.RateDefinitions.Select(x => Tuple.Create(new Date(DateTime.Parse(x.Tenor)), x.Rate)).ToArray(), curveDefinition.CurveConvention.BusinessDayConvention.ToBda(), curveDefinition.CurveConvention.DayCount.ToDayCountImpl(), curveDefinition.CurveConvention.Calendar.ToCalendarImpl(), curveDefinition.CurveConvention.Currency.ToCurrencyCode(), curveDefinition.CurveConvention.Compound.ToCompound(), curveDefinition.CurveConvention.Interpolation.ToInterpolation(), curveDefinition.Trait.ToYieldCurveTrait(), null, null, null, null, curveDefinition ); } } else { var mktInstruments = new List <MarketInstrument>(); foreach (var rateDefinition in curveDefinition.RateDefinitions) { MktInstrumentCalibMethod calibrationMethod; if (rateDefinition.InstrumentType.ToInstrumentType() == InstrumentType.InterestRateSwap) { var swap = CurveBuildHelper.CreateIrsInstrument(curveDate, rateDefinition, out calibrationMethod); mktInstruments.Add(new MarketInstrument(swap, rateDefinition.Rate, calibrationMethod)); } else if (rateDefinition.InstrumentType.ToInstrumentType() == InstrumentType.Deposit || rateDefinition.InstrumentType.ToInstrumentType() == InstrumentType.Repo || rateDefinition.InstrumentType.ToInstrumentType() == InstrumentType.Ibor) { var deposit = CurveBuildHelper.CreateDepositInstrument(curveDate, rateDefinition, out calibrationMethod); mktInstruments.Add(new MarketInstrument(deposit, rateDefinition.Rate, calibrationMethod)); } else if (rateDefinition.InstrumentType.ToInstrumentType() == InstrumentType.Dummy || rateDefinition.InstrumentType.ToInstrumentType() == InstrumentType.None) { var dummy = CurveBuildHelper.CreateDummyInstrument(curveDate, rateDefinition); mktInstruments.Add(new MarketInstrument(dummy, rateDefinition.Rate, MktInstrumentCalibMethod.Default)); } else if (rateDefinition.InstrumentType.ToInstrumentType() == InstrumentType.CreditDefaultSwap) { var cds = CurveBuildHelper.CreateCreditDefaultSwap(curveDate, rateDefinition); mktInstruments.Add(new MarketInstrument(cds, rateDefinition.Rate, MktInstrumentCalibMethod.Default)); } else if (rateDefinition.InstrumentType.ToInstrumentType() == InstrumentType.CommodityForward) { mktInstruments.Add(new MarketInstrument(CurveBuildHelper.CreateCommodityForward(curveDate, rateDefinition), rateDefinition.Rate, MktInstrumentCalibMethod.Default)); } else if (rateDefinition.InstrumentType.ToInstrumentType() == InstrumentType.CommoditySpot) { //baseMarket = baseMarket.UpdateCondition(new UpdateMktConditionPack<double>(x => x.SpotPrice, rateDefinition.Rate)); } else if (rateDefinition.InstrumentType.ToInstrumentType() == InstrumentType.FxSpot) { } else { throw new PricingLibraryException("Unrecognized product type in calibrating curve."); } } var isSpcCurve = curveDefinition.RateDefinitions.All(x => x.IndexType != null && x.IndexType.ToIndexType() == IndexType.Spc); var isConvenicenYield = curveDefinition.RateDefinitions.All(x => x.IndexType != null && x.IndexType.ToIndexType() == IndexType.ConvenienceYield); //Expression<Func<IMarketCondition, object>>[] expression = null; //if (isSpcCurve) expression = new Expression<Func<IMarketCondition, object>>[] { x => x.SurvivalProbabilityCurve }; //if (isConvenicenYield) expression = new Expression<Func<IMarketCondition, object>>[] { x => x.DividendCurve }; instrumentCurve = new YieldCurve( curveDefinition.Name, curveDate, mktInstruments.ToArray(), curveDefinition.CurveConvention.BusinessDayConvention.ToBda(), curveDefinition.CurveConvention.DayCount.ToDayCountImpl(), curveDefinition.CurveConvention.Calendar.ToCalendarImpl(), curveDefinition.CurveConvention.Currency.ToCurrencyCode(), curveDefinition.CurveConvention.Compound.ToCompound(), curveDefinition.CurveConvention.Interpolation.ToInterpolation(), curveDefinition.Trait.ToYieldCurveTrait(), baseMarket, null, null, null, null, curveDefinition); } return(instrumentCurve); }
/// <summary> /// Calibrate implied bs vol from spot premium of an european option /// </summary> /// <param name="premium"></param> /// <param name="isCall"></param> /// <param name="strike"></param> /// <param name="spot"></param> /// <param name="rate"></param> /// <param name="expiryDateStr"></param> /// <param name="valuationDateStr"></param> /// <param name="underlyingInstrumentType"></param> /// <param name="calendarStr"></param> /// <param name="dayCountStr"></param> /// <param name="commodityFuturesPreciseTimeMode"></param> /// <param name="hasNightMarket"></param> /// <returns>if succeed then return implied vol, if falied then return error message</returns> public static double xl_ImpliedVolFromPremium(double premium, bool isCall, double strike, double spot, double rate, string expiryDateStr, string valuationDateStr, string underlyingInstrumentType, string calendarStr, string dayCountStr, bool commodityFuturesPreciseTimeMode = false, bool hasNightMarket = false) { var bsEngine = new AnalyticalVanillaEuropeanOptionEngine(); var expiryDate = expiryDateStr.ToDate(); var valuationDate = valuationDateStr.ToDate(); var instrumentType = underlyingInstrumentType.ToInstrumentType(); var calendar = calendarStr.ToCalendarImpl(); var dayCount = dayCountStr.ToDayCountImpl(); var trade = new VanillaOption( valuationDate, expiryDate, OptionExercise.European, isCall ? OptionType.Call : OptionType.Put, strike, instrumentType, calendar, dayCount, CurrencyCode.CNY, CurrencyCode.CNY, new[] { expiryDate }, new[] { expiryDate }, notional: 1, hasNightMarket: hasNightMarket, commodityFuturesPreciseTimeMode: commodityFuturesPreciseTimeMode ); var curve = new YieldCurve( "riskFreeRate", valuationDate, new[] { Tuple.Create((ITerm) new Term("1D"), rate), Tuple.Create((ITerm) new Term("1Y"), rate) }, BusinessDayConvention.ModifiedFollowing, dayCount, calendar, CurrencyCode.CNY, Compound.Continuous, Interpolation.CubicHermiteMonotic, YieldCurveTrait.SpotCurve ); var volSurf = new VolSurfMktData("VolSurf", 0.1).ToImpliedVolSurface(valuationDate); var market = new MarketCondition( x => x.ValuationDate.Value = valuationDate, x => x.DiscountCurve.Value = curve, x => x.DividendCurves.Value = new Dictionary <string, IYieldCurve> { { "", curve } }, //not used by futures option x => x.FixingCurve.Value = curve, x => x.RiskfreeCurve.Value = curve, x => x.SpotPrices.Value = new Dictionary <string, double> { { "", spot } }, x => x.VolSurfaces.Value = new Dictionary <string, IVolSurface> { { "", volSurf } }); //not used by this calibration return(bsEngine.ImpliedVolFromPremium(targetPremium: premium, option: trade, market: market)); }
public void CommodityJinTaoBinaryEuropeanOptionTest() { var strike = 3100.0; var spot = 2900; var expiry = new Date(2017, 12, 17); var valuationDay = "2017-12-01"; var option = new BinaryOption( new Date(2017, 12, 1), expiry, OptionExercise.European, OptionType.Call, strike, InstrumentType.CommodityFutures, BinaryOptionPayoffType.CashOrNothing, 2, CalendarImpl.Get("chn"), new Act365(), CurrencyCode.CNY, CurrencyCode.CNY, new[] { expiry }, new[] { expiry }, notional: 1 ); var optionInfo = new BinaryOptionInfo( tradeId: "", valuationParameter: new OptionValuationParameters("Fr007", "diviCurve", "volSurf", "000300.SH"), underlyingTicker: "000300.SH", strike: strike, underlyingInstrumentType: "CommodityFutures", optionType: "Call", notional: 1, startDate: "2017-12-01", exerciseDates: "2017-12-17" ) { CashOrNothingAmount = 2, BinaryOptionPayoffType = "CashOrNothing", BinaryOptionReplicationStrategy = "Down", ReplicationShiftSize = 2, }; var curveName = "Fr007"; var volName = "volSurf"; var diviCurveName = "diviCurve"; var market = GetMarketJinTao(valuationDay, rate: 0.04, vol: 0.4, dividendRate: 0, curveName: curveName, volName: volName, diviCurveName: diviCurveName, spot: spot); var volsurf = market.GetData <VolSurfMktData>(volName).ToImpliedVolSurface(market.ReferenceDate); IMarketCondition marketCondition = new MarketCondition( x => x.ValuationDate.Value = market.ReferenceDate, x => x.DiscountCurve.Value = market.GetData <CurveData>(curveName).YieldCurve, x => x.DividendCurves.Value = new Dictionary <string, IYieldCurve> { { "", market.GetData <CurveData>(diviCurveName).YieldCurve } }, x => x.SpotPrices.Value = new Dictionary <string, double> { { "", spot } }, x => x.VolSurfaces.Value = new Dictionary <string, IVolSurface> { { "", volsurf } } ); var engine = new AnalyticalBinaryEuropeanOptionEngine(); var result = engine.Calculate(option, marketCondition, PricingRequest.All); Assert.AreEqual(0.401208951727572, result.Pv, 1e-8); Assert.AreEqual(0.00230806033816866, result.Delta, 1e-8); Assert.AreEqual(7.16979364767667E-06, result.Gamma, 1e-8); Assert.AreEqual(0.0105751548032081, result.Vega, 1e-8); Assert.AreEqual(-0.0149236357909549, result.Theta, 1e-8); Assert.AreEqual(-1.75872031726865E-06, result.Rho, 1e-8); var engine2 = new AnalyticalBinaryEuropeanOptionReplicationEngine(2.0, BinaryOptionReplicationStrategy.Down); var result2 = engine2.Calculate(option, marketCondition, PricingRequest.All); Assert.AreEqual(0.403373182249897, result2.Pv, 1e-7); Assert.AreEqual(0.00231550673674974, result2.Delta, 1e-7); Assert.AreEqual(7.16340764483903E-06, result2.Gamma, 1e-7); Assert.AreEqual(0.0105550810113932, result2.Vega, 1e-7); Assert.AreEqual(-0.0149004654797067, result2.Theta, 1e-7); Assert.AreEqual(-1.74927811613657E-06, result2.Rho, 1e-7); var vfResult = new BinaryOptionVf(optionInfo).ValueTrade(market, PricingRequest.Pv); Assert.AreEqual(vfResult.Pv, result2.Pv, 1e-7); Assert.AreEqual(result2.Pv > result.Pv, true); }
public void testBondCurve1() { var bondIds = new[] { "1", "2", "3", "4", "5" }; var maturitys = new[] { "2017-10-28", "2018-10-28", "2019-10-28", "2020-10-28", "2021-10-28" }; var coupons = new[] { 0.0367, 0.0378, 0.04, 0.039, 0.041 }; var yields = new[] { 0.04, 0.041, 0.0415, 0.0425, 0.044 }; var bondInfos = bondIds.Select((x, i) => new FixedRateBondInfo(bondIds[i]) { StartDate = "2016-10-28", MaturityDate = maturitys[i], Notional = 100.0, Currency = "CNY", FixedCoupon = coupons[i], Calendar = "chn_ib", PaymentFreq = "SemiAnnual", PaymentStub = "LongEnd", AccrualDC = "ActActIsma", DayCount = "ActActIsma", AccrualBD = "None", PaymentBD = "None", TradingMarket = "ChinaInterBank", Settlement = "+0D", ValuationParamters = new SimpleCfValuationParameters("Fr007", null, "Fr007") } ).ToArray(); var bonds = bondInfos.Select(x => new BondVf(x).GenerateInstrument()).ToArray(); var marketInstrumetns = bonds.Select((x, i) => new MarketInstrument(bonds[i], yields[i], MktInstrumentCalibMethod.Default)).ToArray(); var referenceDate = new Date(2017, 03, 23); var yieldCurve = new YieldCurve( "中债国债收收益率曲线", referenceDate, marketInstrumetns.ToArray(), BusinessDayConvention.ModifiedFollowing, new Act365(), CalendarImpl.Get("chn_ib"), CurrencyCode.CNY, Compound.Continuous, Interpolation.ExponentialSpline, YieldCurveTrait.DiscountCurve, null, null, null, maturitys.Select(x => x.ToDate()).ToArray()); var term = new Term("1D"); var targetSpotRates = new[] { 0.0395360864, 0.0405725835, 0.0410856649, 0.0420840373, 0.0436655798, }; Console.WriteLine("Fitting error is {0}", yieldCurve.fittingError); for (var i = 0; i < yieldCurve.KeyPoints.Length; ++i) { Console.WriteLine("{0},{1},{2},{3}", yieldCurve.KeyPoints[i].Item1, yieldCurve.GetDf(yieldCurve.KeyPoints[i].Item1), yieldCurve.GetSpotRate(yieldCurve.KeyPoints[i].Item1), yieldCurve.ZeroRate(referenceDate, yieldCurve.KeyPoints[i].Item1)); if (i > 3) { Assert.AreEqual(yieldCurve.GetSpotRate(yieldCurve.KeyPoints[i].Item1), targetSpotRates[i - 4], 1e-10); } } Console.WriteLine(); var baseMarket = new MarketCondition( x => x.ValuationDate.Value = referenceDate, x => x.DiscountCurve.Value = null, x => x.FixingCurve.Value = null, x => x.HistoricalIndexRates.Value = new Dictionary <IndexType, SortedDictionary <Date, double> >() ); var bondCfs = marketInstrumetns.Select(x => (x.Instrument as Bond).GetCashflows(baseMarket, true)).ToList(); var bondPricer = new BondYieldPricer(); for (var i = 0; i < bondCfs.Count; ++i) { var pv = bondCfs[i].Select(cf => cf.PaymentAmount * yieldCurve.GetDf(referenceDate, cf.PaymentDate)).Sum(); var x = marketInstrumetns[i].Instrument as Bond; var mktPrice = bondPricer.FullPriceFromYield(bondCfs[i], x.PaymentDayCount, x.PaymentFreq, x.StartDate, referenceDate, marketInstrumetns[i].TargetValue, x.BondTradeingMarket, x.IrregularPayment); Console.WriteLine("{0},{1},{2}", pv, mktPrice, pv - mktPrice); } }
private GuidObject CurveBuiltFromDependents(DependentObject fatherNode, DependentObject[] childrenNodes) { IMarketCondition baseMarket; if (childrenNodes.Any(x => x is InstrumentCurveObject)) { var baseCurve = (CurveData)childrenNodes.First().Value; baseMarket = new MarketCondition(x => x.ValuationDate.Value = Market.ReferenceDate, x => x.HistoricalIndexRates.Value = Market.HistoricalIndexRates, x => x.DiscountCurve.Value = baseCurve.YieldCurve, x => x.FixingCurve.Value = baseCurve.YieldCurve, x => x.FgnDiscountCurve.Value = baseCurve.YieldCurve); } else { baseMarket = new MarketCondition(x => x.ValuationDate.Value = Market.ReferenceDate, x => x.HistoricalIndexRates.Value = Market.HistoricalIndexRates); } var rateDefinitions = childrenNodes.Where(x => x.Value is RateMktData).Select(x => (RateMktData)x.Value).ToArray(); var fxSpotDefinition = rateDefinitions.Where(x => x.InstrumentType.ToInstrumentType() == InstrumentType.FxSpot).ToArray(); if (fxSpotDefinition.Count() > 1) { throw new PricingBaseException("A yield curve cannot have more than 2 fx rates against its base curve's currency"); } if (fxSpotDefinition.Any()) { baseMarket = baseMarket.UpdateCondition( new UpdateMktConditionPack <FxSpot[]>(x => x.FxSpots, new[] { CreateFxSpot(fxSpotDefinition[0]) })); } var curveConvention = childrenNodes.Last().Value as CurveConvention; if (curveConvention == null) { Logger.ErrorFormat("Curve conventions are missing!"); return(null); } var isRegridded = rateDefinitions.All(x => x.IndexType != null && x.IndexType.ToIndexType() == IndexType.Regridded); if (isRegridded) { var yieldCurve = baseMarket.DiscountCurve.Value; var tempRateDefinitions = new List <RateMktData>(); foreach (var tenor in Definition.RegriddedTenors) { var date = new Term(tenor).Next(yieldCurve.ReferenceDate); if (date > yieldCurve.KeyPoints.Last().Item1) { date = yieldCurve.KeyPoints.Last().Item1; } tempRateDefinitions.Add(new RateMktData(date.ToString(), GetParRate(date, yieldCurve), "SwapParRate", "InterestRateSwap", Definition.Name)); } rateDefinitions = tempRateDefinitions.ToArray(); } YieldCurve instrumentCurve; //This branch is for bond pnl calculation if (rateDefinitions.All( x => x.InstrumentType.ToInstrumentType() == InstrumentType.Dummy || x.InstrumentType.ToInstrumentType() == InstrumentType.None)) { if (rateDefinitions.All(x => x.IsTerm())) { instrumentCurve = new YieldCurve( Definition.Name, Market.ReferenceDate, rateDefinitions.Select(x => Tuple.Create((ITerm) new Term(x.Tenor), x.Rate)).ToArray(), curveConvention.BusinessDayConvention.ToBda(), curveConvention.DayCount.ToDayCountImpl(), curveConvention.Calendar.ToCalendarImpl(), curveConvention.Currency.ToCurrencyCode(), curveConvention.Compound.ToCompound(), curveConvention.Interpolation.ToInterpolation(), Definition.Trait.ToYieldCurveTrait(), baseMarket ); } else { instrumentCurve = new YieldCurve( Definition.Name, Market.ReferenceDate, rateDefinitions.Select(x => Tuple.Create(new Date(DateTime.Parse(x.Tenor)), x.Rate)).ToArray(), curveConvention.BusinessDayConvention.ToBda(), curveConvention.DayCount.ToDayCountImpl(), curveConvention.Calendar.ToCalendarImpl(), curveConvention.Currency.ToCurrencyCode(), curveConvention.Compound.ToCompound(), curveConvention.Interpolation.ToInterpolation(), Definition.Trait.ToYieldCurveTrait(), baseMarket ); } } else { var mktInstruments = new List <MarketInstrument>(); foreach (var rateDefinition in rateDefinitions) { MktInstrumentCalibMethod calibrationMethod; var instType = rateDefinition.InstrumentType.ToInstrumentType(); switch (instType) { case InstrumentType.InterestRateSwap: var swap = CreateIrsInstrument(rateDefinition, out calibrationMethod); mktInstruments.Add(new MarketInstrument(swap, rateDefinition.Rate, calibrationMethod)); break; case InstrumentType.Deposit: case InstrumentType.Repo: case InstrumentType.Ibor: var deposit = CreateDepositInstrument(rateDefinition, out calibrationMethod); mktInstruments.Add(new MarketInstrument(deposit, rateDefinition.Rate, calibrationMethod)); break; case InstrumentType.Dummy: case InstrumentType.None: var dummy = CreateDummyInstrument(rateDefinition); mktInstruments.Add(new MarketInstrument(dummy, rateDefinition.Rate, MktInstrumentCalibMethod.Default)); break; case InstrumentType.CreditDefaultSwap: var cds = CreateCreditDefaultSwap(rateDefinition); mktInstruments.Add(new MarketInstrument(cds, rateDefinition.Rate, MktInstrumentCalibMethod.Default)); break; case InstrumentType.CommodityForward: mktInstruments.Add(new MarketInstrument(CreateCommodityForward(rateDefinition), rateDefinition.Rate, MktInstrumentCalibMethod.Default)); break; case InstrumentType.CommoditySpot: //baseMarket = baseMarket.UpdateCondition(new UpdateMktConditionPack<double>(x => x.SpotPrices, rateDefinition.Rate)); baseMarket = baseMarket.UpdateCondition(new UpdateMktConditionPack <Dictionary <string, double> >(x => x.SpotPrices, new Dictionary <string, double> { { "", rateDefinition.Rate } })); break; case InstrumentType.FxSpot: break; default: throw new PricingLibraryException("Unrecognized product type in calibrating curve."); } #region legacy code // if (rateDefinition.InstrumentType.ToInstrumentType() == InstrumentType.InterestRateSwap) //{ // var swap = CreateIrsInstrument(rateDefinition, out calibrationMethod); // mktInstruments.Add(new MarketInstrument(swap, rateDefinition.Rate, calibrationMethod)); //} //else if ( instType == InstrumentType.Deposit // || rateDefinition.InstrumentType.ToInstrumentType() == InstrumentType.Repo // || rateDefinition.InstrumentType.ToInstrumentType() == InstrumentType.Ibor) //{ // var deposit = CreateDepositInstrument(rateDefinition, out calibrationMethod); // mktInstruments.Add(new MarketInstrument(deposit, rateDefinition.Rate, calibrationMethod)); //} //else if (rateDefinition.InstrumentType.ToInstrumentType() == InstrumentType.Dummy || // rateDefinition.InstrumentType.ToInstrumentType() == InstrumentType.None) //{ // var dummy = CreateDummyInstrument(rateDefinition); // mktInstruments.Add(new MarketInstrument(dummy, rateDefinition.Rate, MktInstrumentCalibMethod.Default)); //} //else if (rateDefinition.InstrumentType.ToInstrumentType() == InstrumentType.CreditDefaultSwap) //{ // var cds = CreateCreditDefaultSwap(rateDefinition); // mktInstruments.Add(new MarketInstrument(cds, rateDefinition.Rate, MktInstrumentCalibMethod.Default)); //} //else if (rateDefinition.InstrumentType.ToInstrumentType() == InstrumentType.CommodityForward) //{ // mktInstruments.Add(new MarketInstrument(CreateCommodityForward(rateDefinition), rateDefinition.Rate, MktInstrumentCalibMethod.Default)); //} //else if (rateDefinition.InstrumentType.ToInstrumentType() == InstrumentType.CommoditySpot) //{ // //baseMarket = baseMarket.UpdateCondition(new UpdateMktConditionPack<double>(x => x.SpotPrices, rateDefinition.Rate)); // baseMarket = baseMarket.UpdateCondition(new UpdateMktConditionPack<Dictionary<string, double>>(x => x.SpotPrices, new Dictionary<string, double> { {"", rateDefinition.Rate } })); // } //else if (rateDefinition.InstrumentType.ToInstrumentType() == InstrumentType.FxSpot) //{ //} //else //{ // throw new PricingLibraryException("Unrecognized product type in calibrating curve."); //} #endregion legacy code } var isSpcCurve = rateDefinitions.All(x => x.IndexType != null && x.IndexType.ToIndexType() == IndexType.Spc); var isConvenicenYield = rateDefinitions.All(x => x.IndexType != null && x.IndexType.ToIndexType() == IndexType.ConvenienceYield); Expression <Func <IMarketCondition, object> >[] expression = null; if (isSpcCurve) { expression = new Expression <Func <IMarketCondition, object> >[] { x => x.SurvivalProbabilityCurve } } ; if (isConvenicenYield) { expression = new Expression <Func <IMarketCondition, object> >[] { x => x.DividendCurves } } ; instrumentCurve = new YieldCurve( Definition.Name, Market.ReferenceDate, mktInstruments.ToArray(), curveConvention.BusinessDayConvention.ToBda(), curveConvention.DayCount.ToDayCountImpl(), curveConvention.Calendar.ToCalendarImpl(), curveConvention.Currency.ToCurrencyCode(), curveConvention.Compound.ToCompound(), curveConvention.Interpolation.ToInterpolation(), Definition.Trait.ToYieldCurveTrait(), baseMarket, expression, null ); } return(new CurveData(instrumentCurve)); }