public static double Calculate(CalcMeasure Measure, DateTime settle, double price, Bond bondStatic, BondAnalytics.Country eCountry, DateTime asOfDate, List<DateTime> hols) { // byran lim config coded in symmetry.net. we use this until we have a centralised place for the curve static // different country has different setting of using forcast and discount curve bool bForecastCurve; switch (eCountry) { case BondAnalytics.Country.DE: bForecastCurve = false; break; default: bForecastCurve = true; break; } var fcstCfg = new SpreadTimeSeriesConfigs(eCountry.ToString(), bForecastCurve); int trial = 0; DiscountCurve forCurve = null; DiscountCurve disCurve = null; if (discountCurveCache.ContainsKey(fcstCfg.SymForecastCurveName)) { var forTup = discountCurveCache[fcstCfg.SymForecastCurveName].FirstOrDefault(i => i.Item1 == asOfDate); if (forTup != null) forCurve = forTup.Item2; } if (discountCurveCache.ContainsKey(fcstCfg.SymDiscountCurveName)) { var disTup = discountCurveCache[fcstCfg.SymDiscountCurveName].FirstOrDefault(i => i.Item1 == asOfDate); if (disTup != null) disCurve = disTup.Item2; } if (forCurve == null || disCurve == null) { while (trial < 3) { try { forCurve = SymmetryDataModel.GetDiscountCurve(fcstCfg.SymForecastCurveName, asOfDate); disCurve = SymmetryDataModel.GetDiscountCurve(fcstCfg.SymDiscountCurveName, asOfDate); trial = 5; break; } catch (Exception) { trial++; continue; } } if (forCurve != null && disCurve != null) { var forTup = new Tuple<DateTime, DiscountCurve>(asOfDate, forCurve); var disTup = new Tuple<DateTime, DiscountCurve>(asOfDate, disCurve); if (discountCurveCache.ContainsKey(fcstCfg.SymForecastCurveName)) discountCurveCache[fcstCfg.SymForecastCurveName].Add(forTup); else discountCurveCache[fcstCfg.SymForecastCurveName] = new[] {forTup}.ToList(); if (discountCurveCache.ContainsKey(fcstCfg.SymDiscountCurveName)) discountCurveCache[fcstCfg.SymDiscountCurveName].Add(disTup); else discountCurveCache[fcstCfg.SymDiscountCurveName] = new[] { disTup }.ToList(); } } if (forCurve == null || disCurve == null) return double.NaN; DateTime effectiveDate = bondStatic.EffectiveDate ?? DateTime.MinValue; DateTime maturity = bondStatic.Maturity ?? DateTime.MinValue; DateTime firstCpnDate = bondStatic.FirstCouponDate ?? DateTime.MinValue; double coupon = bondStatic.Coupon; long bondCpnFreq = fcstCfg.bndCouponFreq; bool bOIS = !fcstCfg.bForecastCurve; BondAnalytics.DayCountType dct = fcstCfg.dct; long swapFixedFreq = fcstCfg.swpfixfreq; long swapFloatFreq = fcstCfg.swpfloatfreq; return CalcMeasure(Measure, price, eCountry, settle, disCurve, forCurve, effectiveDate, maturity, firstCpnDate, coupon, bondCpnFreq, bOIS, dct, swapFixedFreq, swapFloatFreq, hols); }
public static double CalcMeasure(CalcMeasure Measure, double price, BondAnalytics.Country eCountry, //DateTime asof, DateTime settle, DiscountCurve discCurve, DiscountCurve fcstCurve, DateTime effectiveDate, DateTime maturity, DateTime firstCpnDate, double coupon, long bondCpnFreq, bool bOIS, BondAnalytics.DayCountType dct, long swapFixedFreq, long swapFloatFreq, List<DateTime> hols) //---------------------------------------------------------------------------------------- { double output = double.NaN; switch (Measure) { case Analytics.CalcMeasure.Price: { output = price; break; } case Analytics.CalcMeasure.Yield: { output = 10000.0*BondAnalytics.SolveYield(eCountry, settle, price, effectiveDate, firstCpnDate, maturity, coupon, bondCpnFreq)[0]; break; } case Analytics.CalcMeasure.TrueSpread: { DateTime[] dfDates = (bOIS ? discCurve.AsTuples().Select(x => x.Item1).ToArray() : fcstCurve.AsTuples().Select(x => x.Item1).ToArray()); double[] dfs = (bOIS ? discCurve.AsTuples().Select(x => x.Item2).ToArray() : fcstCurve.AsTuples().Select(x => x.Item2).ToArray()); // Check. Sometimes (holidays) the first date on the curve can be repeated, which will cause an exception in the pricer. if (dfDates[0] == dfDates[1]) { dfDates = dfDates.GetSubArray(1, dfDates.GetLength(0)).ToArray(); dfs = dfs.GetSubArray(1, dfs.GetLength(0)).ToArray(); } output = -10000.0*BondAnalytics.SolveZSpread(eCountry, settle, price, effectiveDate, firstCpnDate, maturity, coupon, bondCpnFreq, dfDates, dfs, hols); break; } case Analytics.CalcMeasure.MMS: { DateTime[] discDfDates = discCurve.AsTuples().Select(x => x.Item1).ToArray(); DateTime[] fcstDfDates = (bOIS ? discCurve.AsTuples().Select(x => x.Item1).ToArray() : fcstCurve.AsTuples().Select(x => x.Item1).ToArray()); double[] discDfs = discCurve.AsTuples().Select(x => x.Item2).ToArray(); double[] fcstDfs = (bOIS ? discCurve.AsTuples().Select(x => x.Item2).ToArray() : fcstCurve.AsTuples().Select(x => x.Item2).ToArray()); double mms = BondAnalytics.CalcMMS(settle, maturity, dct, swapFixedFreq, swapFloatFreq, discDfDates, discDfs, fcstDfDates, fcstDfs, hols, null, null, null, null, null, firstCpnDate, (bOIS ? 5 : 0)); output = 10000.0*mms; break; } case Analytics.CalcMeasure.Spread: { DateTime[] discDfDates = discCurve.AsTuples().Select(x => x.Item1).ToArray(); DateTime[] fcstDfDates = (bOIS ? discCurve.AsTuples().Select(x => x.Item1).ToArray() : fcstCurve.AsTuples().Select(x => x.Item1).ToArray()); double[] discDfs = discCurve.AsTuples().Select(x => x.Item2).ToArray(); double[] fcstDfs = (bOIS ? discCurve.AsTuples().Select(x => x.Item2).ToArray() : fcstCurve.AsTuples().Select(x => x.Item2).ToArray()); double mms = BondAnalytics.CalcMMS(settle, maturity, dct, swapFixedFreq, swapFloatFreq, discDfDates, discDfs, fcstDfDates, fcstDfs, hols, null, null, null, null, null, firstCpnDate, (bOIS ? 5 : 0)); double yield = BondAnalytics.SolveYield(eCountry, settle, price, effectiveDate, firstCpnDate, maturity, coupon, bondCpnFreq)[0]; output = 10000.0*(mms - yield); break; } } return output; }