//---------------------------------------------------------------------------------------- public static BondStatic GetBondStatic(string bondID) //---------------------------------------------------------------------------------------- { Log_.InfoFormat("Getting bond static for {0}", bondID); if (bondStaticCache.ContainsKey(bondID)) return bondStaticCache[bondID]; BondStatic instrumentStatic = new BondStatic(); int MAX_RETRIES = 5; int retries = 0; for (retries = 0; retries < MAX_RETRIES; ++retries) { try { var moniker = new Moniker { Close = Moniker.sStatic, Source = Moniker.sOfficial, Date = null, Name = bondID.Trim(), Type = "bondstatic" }; var symmetryServiceClient = GetSymmetryServiceClient(); var resultObj = symmetryServiceClient.GetSingleObject(moniker.ToString()); instrumentStatic = resultObj.Xml.DeserializeObject<BondStatic>(); break; } catch (Exception e) { Log_.WarnFormat("Attempt" + retries.ToString() + " - Error in setting static for " +bondID + ": " + e.Message); Thread.Sleep(200); // Wait for 2 seconds first before trying again } } if (retries == MAX_RETRIES) { throw new TimeoutException("Max retries reach " + MAX_RETRIES + ". Giving up on pulling bond static"); } // Set cache bondStaticCache[bondID] = instrumentStatic; return instrumentStatic; }
private BondSpreadResult BondSpreadResult(BondAnalytics.Country eCountry, DateTime settleDate, double optStartDate, double optFirstCpnDate, long Freq, Dictionary<DateTime, double> liborInterestCurveDict, Dictionary<DateTime, double> oisInterestCurveDict, double cleanPrice, BondStatic bondStatic) { try { if (liborInterestCurveDict == null || oisInterestCurveDict == null) return null; var yield = BondAnalytics.SolveYield(eCountry, settleDate, cleanPrice, DateTime.MinValue, DateTime.MinValue, DateTime.FromOADate(bondStatic.Maturity), bondStatic.Coupon, Freq)[0]; var loas = BondAnalytics.SolveZSpread(eCountry, settleDate, cleanPrice, (optStartDate == 0.0 ? DateTime.MinValue : DateTime.FromOADate(optStartDate)), (optFirstCpnDate == 0.0 ? DateTime.MinValue : DateTime.FromOADate(optFirstCpnDate)), DateTime.FromOADate(bondStatic.Maturity), bondStatic.Coupon, Freq, liborInterestCurveDict.Keys.ToArray(), liborInterestCurveDict.Values.ToArray(), new List<DateTime>()); var oisoas = BondAnalytics.SolveZSpread(eCountry, settleDate, cleanPrice, (optStartDate == 0.0 ? DateTime.MinValue : DateTime.FromOADate(optStartDate)), (optFirstCpnDate == 0.0 ? DateTime.MinValue : DateTime.FromOADate(optFirstCpnDate)), DateTime.FromOADate(bondStatic.Maturity), bondStatic.Coupon, Freq, oisInterestCurveDict.Keys.ToArray(), oisInterestCurveDict.Values.ToArray(), new List<DateTime>()); if (loas == -1.0) loas = double.NaN; if (oisoas == -1.0) oisoas = double.NaN; // Forward var frontDate = forwardBuilder.GetFrontDateForBond(DateTime.FromOADate(bondStatic.Maturity)); var fwdPriceFrontResult = forwardBuilder.ComputeBondForwardPrice(bondStatic.MLP, cleanPrice, DateTime.FromOADate(bondStatic.IssueDate), DateTime.FromOADate(bondStatic.Maturity), bondStatic.Coupon, true); var fwdPriceFront = fwdPriceFrontResult.Item1; double fwdLoasFront=Double.NaN; double fwdOisoasFront=Double.NaN; double fwdOisoasBack = Double.NaN; double fwdLoasBack = Double.NaN; if (fwdPriceFront != 0.0) { fwdLoasFront = BondAnalytics.SolveZSpread(eCountry, frontDate, fwdPriceFront, (optStartDate == 0.0 ? DateTime.MinValue : DateTime.FromOADate(optStartDate)), (optFirstCpnDate == 0.0 ? DateTime.MinValue : DateTime.FromOADate(optFirstCpnDate)), DateTime.FromOADate(bondStatic.Maturity), bondStatic.Coupon, Freq, liborInterestCurveDict.Keys.ToArray(), liborInterestCurveDict.Values.ToArray(), new List<DateTime>()); fwdOisoasFront = BondAnalytics.SolveZSpread(eCountry, frontDate, fwdPriceFront, (optStartDate == 0.0 ? DateTime.MinValue : DateTime.FromOADate(optStartDate)), (optFirstCpnDate == 0.0 ? DateTime.MinValue : DateTime.FromOADate(optFirstCpnDate)), DateTime.FromOADate(bondStatic.Maturity), bondStatic.Coupon, Freq, oisInterestCurveDict.Keys.ToArray(), oisInterestCurveDict.Values.ToArray(), new List<DateTime>()); if (fwdLoasFront == -1.0) fwdLoasFront = double.NaN; if (fwdOisoasFront == -1.0) fwdOisoasFront = double.NaN; } var backDate = forwardBuilder.GetBackDateForBond(DateTime.FromOADate(bondStatic.Maturity)); var fwdPriceBackResult = forwardBuilder.ComputeBondForwardPrice(bondStatic.MLP, cleanPrice, DateTime.FromOADate(bondStatic.IssueDate), DateTime.FromOADate(bondStatic.Maturity), bondStatic.Coupon, false); var fwdPriceBack = fwdPriceBackResult.Item1; if (fwdPriceBack != 0.0) { fwdLoasBack = BondAnalytics.SolveZSpread(eCountry, backDate, fwdPriceBack, (optStartDate == 0.0 ? DateTime.MinValue : DateTime.FromOADate(optStartDate)), (optFirstCpnDate == 0.0 ? DateTime.MinValue : DateTime.FromOADate(optFirstCpnDate)), DateTime.FromOADate(bondStatic.Maturity), bondStatic.Coupon, Freq, liborInterestCurveDict.Keys.ToArray(), liborInterestCurveDict.Values.ToArray(), new List<DateTime>()); fwdOisoasBack = BondAnalytics.SolveZSpread(eCountry, backDate, fwdPriceBack, (optStartDate == 0.0 ? DateTime.MinValue : DateTime.FromOADate(optStartDate)), (optFirstCpnDate == 0.0 ? DateTime.MinValue : DateTime.FromOADate(optFirstCpnDate)), DateTime.FromOADate(bondStatic.Maturity), bondStatic.Coupon, Freq, oisInterestCurveDict.Keys.ToArray(), oisInterestCurveDict.Values.ToArray(), new List<DateTime>()); if (fwdLoasBack == -1.0) fwdLoasBack = double.NaN; if (fwdOisoasBack == -1.0) fwdOisoasBack = double.NaN; } // forward price would not be 0.0, we change it to NaN..... if (fwdPriceFront == 0.0) fwdPriceFront = double.NaN; if (fwdPriceBack == 0.0) fwdPriceBack = double.NaN; // find out if the bond is a ctd bond Future ctdFuture = null; var ctdreuters = FutureCache.Where(f => f.CTDReuters != null).ToArray(); if (ctdreuters.Any()) { if (ctdreuters.Select(f => f.CTDReuters.TrimEnd('=')).Contains(bondStatic.CUSIP)) { ctdFuture = ctdreuters.First(f => f.CTDReuters.TrimEnd('=') == bondStatic.CUSIP); } } return new BondSpreadResult { Ticker = bondStatic.MLP, Cusip = bondStatic.CUSIP, ISIN = bondStatic.ISIN, Coupon = bondStatic.Coupon, IssueDate = DateTime.FromOADate(bondStatic.IssueDate), Maturity = DateTime.FromOADate(bondStatic.Maturity), LOAS = -1*loas*10000, OISOAS = -1*oisoas*10000, Price = cleanPrice, Yield = yield, ForwardPriceFront = fwdPriceFront, FwdLOASFront = -1*fwdLoasFront*10000, FwdOISOASFront = -1 * fwdOisoasFront * 10000, ForwardPriceBack = fwdPriceBack, FwdLOASBack = -1*fwdLoasBack * 10000, FwdOISOASBack = -1*fwdOisoasBack * 10000, FrontUsedRepo = fwdPriceFrontResult.Item2, BackUsedRepo = fwdPriceBackResult.Item2, InstrumentType = InstrumentType.Bond, CtFlag = forwardBuilder.GetCTFlagForBond(bondStatic.MLP), CtdFlag = ctdFuture == null? CTDFlag.None : GetCTDFlagForBond(ctdFuture.Contract), Series = ((int) Math.Round( (DateTime.FromOADate(bondStatic.Maturity) - DateTime.FromOADate(bondStatic.IssueDate)).TotalDays/360.0)).ToString(), }; } catch (Exception e) { Log.Error(string.Format("Failed to compute bond spread for {0}", bondStatic.MLP), e); return null; } }
//---------------------------------------------------------------------------------------- public static double calcMeasure( string Measure, double price, BondAnalytics.Country eCountry, DateTime asof, DateTime settle, DiscountCurve discCurve, DiscountCurve fcstCurve, BondStatic bondStatic, SpreadTimeSeriesConfigs configs, List<DateTime> hols) //---------------------------------------------------------------------------------------- { DateTime effectiveDate = DateTime.FromOADate( bondStatic.EffectiveDate); DateTime maturity = DateTime.FromOADate( bondStatic.Maturity); DateTime firstCpnDate = DateTime.FromOADate(bondStatic.FirstCoupon); double coupon = bondStatic.Coupon; long bondCpnFreq = configs.bndCouponFreq; bool bOIS = !configs.bForecastCurve; BondAnalytics.DayCountType dct = configs.dct; long fixedFreq = configs.swpfixfreq; long floatFreq = configs.swpfloatfreq; double output = double.NaN; switch (Measure) { case "Price": { output= price; break; } case "Yield": { output= 10000.0 * BondAnalytics.SolveYield(eCountry, settle, price, effectiveDate, firstCpnDate, maturity, coupon, bondCpnFreq)[0]; break; } case "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 "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, fixedFreq, floatFreq, discDfDates, discDfs, fcstDfDates, fcstDfs, hols, null, null, null, null, null, firstCpnDate, (bOIS ? 5 : 0)); output= 10000.0 * mms; break; } case "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, fixedFreq, floatFreq, 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; }