private async Task populateDates(CarbonClient cc_) { var yesterday = await cc_.RollDateAsync( date: DateTime.Today.ToNodaLocalDate(), count: -1, unit: Symmetry.Carbon.Model.DateUnit.Bd, convention: Symmetry.Carbon.Model.BusinessDayConvention.Following, calendar: Market.HolidayCode()); var spotSettle = await cc_.RollDateAsync( date: DateTime.Today.ToNodaLocalDate(), count: Market.DaysToSpot(), unit: Symmetry.Carbon.Model.DateUnit.Bd, convention: Symmetry.Carbon.Model.BusinessDayConvention.Following, calendar: Market.HolidayCode()); var yesterdaySettle = await cc_.RollDateAsync( date: yesterday, count: Market.DaysToSpot(), unit: Symmetry.Carbon.Model.DateUnit.Bd, convention: Symmetry.Carbon.Model.BusinessDayConvention.Following, calendar: Market.HolidayCode()); Today = new AsOfAndSpotSettle(DateTime.Today, spotSettle.ToDateTime()); Yesterday = new AsOfAndSpotSettle(yesterday.ToDateTime(), yesterdaySettle.ToDateTime()); }
private static DateTime Roll(DateTime date_, int units_, DateUnit unit_, BusinessDayConvention convention_, string otCalendar_, CarbonClient client_, ThrowBehavior behavior_=ThrowBehavior.DontThrow) { try { string key = getKey(date_, units_, unit_, convention_, otCalendar_); if (_cache.ContainsKey(key)) return _cache[key]; var result = client_.RollDateAsync(date_.ToNodaLocalDate(), units_, unit_, convention_, otCalendar_).Result.ToDateTime(); _cache[key] = result; return result; } catch (Exception ex_) { Exceptions.Rethrow("Error rolling date", behavior_, ex_); } return DateTime.MinValue; }
protected void getCalcs() { var conf = CountryConfig.GetCountryConfig(Market); if (Values == null) Values = new ConstructGen<double>( ((ColPosition[]) Enum.GetValues(typeof (ColPosition))).Select(x => x.ToString()).ToArray()); var crv = Singleton<CMTCurveCache>.Instance.Get( market_: Market, series_: CMTSeriesNumber, curve_: conf.OISCurve, focus_: Focus.ASW, createIfNotThere_: true); if (crv == null || crv.Data == null) return; // need to find the indexof of the tenor points in the data construct int pointIndex = -1; for (int i = 0; i < crv.Data.ArrayLength && (pointIndex == -1); ++i) { var asDbl = double.Parse(crv.Data.ColumnHeadings[i]); if (Math.Abs(asDbl - Tenor) < 1e-7) pointIndex = i; } var startDate = new DateTime(2010, 1, 1); Values.SetColumnValues((int)ColPosition.CMT_OIS, crv.Data.GetColumnValuesAsDDC(pointIndex).GetValuesBetweenDates(startDate, DateTime.Today).MultiplyBy(-100d)); Values.SetColumnValues((int)ColPosition.GC, BbgTalk.HistoryRequester.GetHistory(startDate, conf.CollateralTicker, "PX_LAST", false)); Values.SetColumnValues((int)ColPosition.OIS, BbgTalk.HistoryRequester.GetHistory(startDate, conf.OISTicker, "PX_LAST", false)); Values.SortKeys(); using (var cc = new CarbonClient("PRD")) { var fillCols = new[] { ColPosition.CMT_OIS, ColPosition.GC, ColPosition.OIS }; for (int i = 0; i < Values.Dates.Count; ++i) { var date = Values.Dates[i]; var vals = Values.GetValues(Values.Dates[i]); // fill in zeros as unlikely all series will line up if (i > 0) { foreach (var col in fillCols) { if (vals[(int)col].IsZero()) vals[(int)col] = Values.GetValues(Values.Dates[i - 1])[(int)col]; } } vals[(int)ColPosition.GCminusOIS] = vals[(int)ColPosition.GC] - vals[(int)ColPosition.OIS]; bool needToMakeCall = true; { var currentValue = Values.GetValue(date.Date, (int) ColPosition.SwapValue); if (!currentValue.IsZero()) needToMakeCall = false; } if (needToMakeCall) { Logger.Info(string.Format("Making calls for {0}.{1}.{2} carry calc on {3}",Market,Tenor,CMTSeriesNumber, date.ToString("dd-MMM-yyyy")), typeof(CMTCarry)); var settleDate = cc.RollDateAsync(date.ToNodaLocalDate(), 2, Symmetry.Carbon.Model.DateUnit.Bd, Symmetry.Carbon.Model.BusinessDayConvention.Following, conf.HolidayCalendar).Result; var swapDate = cc.RollDateAsync(settleDate, Tenor, Symmetry.Carbon.Model.DateUnit.Y, Symmetry.Carbon.Model.BusinessDayConvention.Following, conf.HolidayCalendar).Result; var swapResult = cc.PriceSwapAsync( curveName: conf.OTSwapName, startDate: settleDate, endDate: swapDate, asof: date.Date.AddHours(23), pricingSetup: "Symmetry").Result; if (swapResult == null) continue; foreach (var v in swapResult.Results) { switch (v.Key) { case "BreakEven Rate": vals[(int)ColPosition.SwapValue] = v.Value; break; case "PV01": vals[(int)ColPosition.SwapDuration] = v.Value; break; } } m_changed = true; } } if (Values.NeedsToSortKeys()) Values.SortKeys(); // 20 day moving average of difference { var series = Values.GetColumnValuesAsDDC((int)ColPosition.GCminusOIS); Values.SetColumnValues((int)ColPosition.GCminusOIS_MA20, HelperMethods.GetMA(series, 20)); } // calculate carry { var mustNotBeZero = new[] { ColPosition.CMT_OIS, ColPosition.GCminusOIS_MA20, ColPosition.SwapDuration }; foreach (var date in Values.Dates) { var series = Values.GetValues(date); foreach(var col in mustNotBeZero) if (series[(int) col].IsZero()) continue; series[(int) ColPosition.Carry] = (series[(int) ColPosition.CMT_OIS] - series[(int) ColPosition.GCminusOIS_MA20])/ series[(int) ColPosition.SwapDuration]*10000d; } } } }
public static DateTime RollDate(CarbonClient client_, DateTime date_, int units_, DateUnit unit_, BusinessDayConvention conv_, string calendar_) { var key = getDateKey(date_, units_, unit_, conv_, calendar_); if (_dateCache.ContainsKey(key)) return _dateCache[key]; var date = client_.RollDateAsync( date: DateConversions.ToNodaLocalDate(date_.Date), count: units_, unit: unit_, convention: conv_, calendar: calendar_).Result; _dateCache[key] = date.ToDateTime(); return _dateCache[key]; }
/// <summary> /// Calculate the bondspreads for the given bond over the given swap curve /// </summary> /// <param name="bond_"></param> /// <param name="priceType_">either yield or price</param> /// <param name="priceValue_">if price, then pass 100.3 rather than 1.003</param> /// <param name="curveType_">the swap curve</param> /// <param name="country_">JB's country definitions</param> /// <param name="asOf_">the date of the price. will determine the date of the curves that are used</param> /// <param name="client_">carbon client to get holidays</param> /// <param name="quoteSource_">mlp/sym</param> /// <param name="snapCode_">mlp/nyk/ldn</param> /// <param name="behavior_">whether you want exceptions to be swallowed or not</param> /// <returns></returns> public static async Task<BondSpreadResult> GetSpreads( Symmetry.Data.FIBond bond_, QuoteValueType priceType_, double priceValue_, SwapCurveType curveType_, BondAnalytics.Country country_, DateTime asOf_, CarbonClient client_, string quoteSource_, string snapCode_, ThrowBehavior behavior_ = ThrowBehavior.DontThrow) { try { var mapping = CurveMappings.GetMapping(curveType_); var settleDate = await client_.RollDateAsync( date: asOf_.Date.ToNodaLocalDate(), count: country_.SettleDateDays(), unit: DateUnit.Bd, convention: BusinessDayConvention.Following, calendar: country_.OTHolidayCode()); var holidays = CalendarRetriever.GetCalendar(country_.OTHolidayCode(), client_).ToList(); var startDate = bond_.EffectiveDate.Value; var firstCpnDate = bond_.Coupon==0 ? bond_.IssueDate.Value : bond_.FirstCouponDate.Value; var maturity = bond_.FI.Maturity; var coupon = Convert.ToDouble(bond_.Coupon); // get the persisted discount curves for the fixed and floating legs var discCurve = SObjectManager.Instance().LoadSObject<DiscountCurve>(new Moniker() { Close = snapCode_, Source = quoteSource_, Name = KnownCurveHelpers.GetKnownCurveCode(mapping.DiscountCurve), Type = "discountcurve", Date = asOf_.Date }); if (discCurve == null) { SLog.log.ErrorFormat("Could not load {0} discount curve from database for {1}", mapping.DiscountCurve, asOf_.Date); return null; } var fcstCurve = SObjectManager.Instance().LoadSObject<DiscountCurve>(new Moniker() { Close = snapCode_, Source = quoteSource_, Name = KnownCurveHelpers.GetKnownCurveCode(mapping.ForecastCurve), Type = "discountcurve", Date = asOf_.Date }); if (fcstCurve == null) { SLog.log.ErrorFormat("Could not load {0} discount curve from database for {1}", mapping.ForecastCurve, asOf_.Date); return null; } double price=0, yield=0; switch (priceType_) { case QuoteValueType.Price: price = priceValue_; yield = BondAnalytics.SolveYield( country: country_, settleDate: settleDate.ToDateTime(), cleanPrice: price, startDate: startDate, firstCpnDate: firstCpnDate, maturityDate: maturity.Value, coupon: coupon, freq: country_.BondFreq())[0]; break; case QuoteValueType.Yield: yield = priceValue_; price = BondAnalytics.PriceFromYield( country: country_, settleDate: settleDate.ToDateTime(), yield: priceValue_, startDate: startDate, firstCpnDate: firstCpnDate, maturityDate: maturity.Value, coupon: coupon, freq: country_.BondFreq())[0]; break; } var mms = BondAnalytics.CalcMMS( startDate: settleDate.ToDateTime(), maturityDate: maturity.Value, dctType: mapping.DayCountType, fixedFreq: (long) mapping.FixedFreq, floatFreq: (long) mapping.FloatFreq, discCurveDates: discCurve.AsDoubleArray().SliceColumn(0).Select(DateTime.FromOADate).ToArray(), discDfs: discCurve.AsDoubleArray().SliceColumn(1), fcstCurveDates: fcstCurve.AsDoubleArray().SliceColumn(0).Select(DateTime.FromOADate).ToArray(), fcstDfs: fcstCurve.AsDoubleArray().SliceColumn(1), holidays: holidays, stubExpiries: null, stubTenors: null, stubValues: null, fixingTenors: null, fixings: null, firstCpnDate: firstCpnDate ); var truespread = BondAnalytics.SolveZSpread( country: country_, settleDate: settleDate.ToDateTime(), cleanPrice: price, startDate: startDate, firstCpnDate: firstCpnDate, maturityDate: maturity.Value, coupon: coupon, freq: country_.BondFreq(), curveDates: fcstCurve.AsDoubleArray().SliceColumn(0).Select(DateTime.FromOADate).ToArray(), dfs: fcstCurve.AsDoubleArray().SliceColumn(1), holidays: holidays); return new BondSpreadResult { Price = price, Spreads = new BondSpread { Yield=yield, MMS=mms, TrueSpread=truespread * -1d, Spread = mms-yield, } }; } catch (Exception ex_) { Exceptions.Rethrow("Error calculating bondspread", behavior_, ex_); return null; } }
private async Task<TenorDates> GoDate(DateTime date_, TenorDates record, CarbonClient cc_, bool force_ = true, bool persistToServer_ = true) { if (record == null) throw new ArgumentNullException("record"); if (record != null && record.Dates != null && record.Dates.HasKey(date_) && !force_) return record; Logger.Info( string.Format("Generating tenor Dates for [Cal={0}, SpotDays={1}, Date={2}]", record.HolidayCode, record.SpotStart, date_.ToString("dd-MMM-yyyy")), typeof(DatesWorker)); var allTenors = (CurveDateIndex[])Enum.GetValues(typeof(CurveDateIndex)); if (record.Dates == null) // this shouldnt' happen record.Dates = new ConstructGenGen<DateTime, DateTime>(allTenors.Select(x => x.ToString()).ToArray()); // need to get the spot date first as all other dates are calculated off this var spot = await cc_.RollDateAsync( date: date_.ToNodaLocalDate(), count: record.SpotStart, unit: Symmetry.Carbon.Model.DateUnit.Bd, convention: Symmetry.Carbon.Model.BusinessDayConvention.Following, calendar: record.HolidayCode); record.Dates.SetValue(date_, (int)CurveDateIndex.Spot, spot.ToDateTime()); // then work out each tenor date and store in record foreach (var tenor in allTenors.Where(x => x != CurveDateIndex.Spot)) { var fwdDate = spot.ToDateTime().AddYears((int) tenor); //var fwdDate = await cc_.RollDateAsync( // date: spot, // count: (int)tenor, // unit: Symmetry.Carbon.Model.DateUnit.Y, // convention: Symmetry.Carbon.Model.BusinessDayConvention.Following, // calendar: record.HolidayCode); record.Dates.SetValue(date_, (int)tenor, fwdDate); } if (persistToServer_) await TenorDatesCache.Instance().AddOrUpdateDefinition(record); return record; }
public async Task<TenorDates> GoAll(string otHolidayCode_, int daysToSpot_, CarbonClient cc_, bool force_ = false) { var date = START_DATE; var record = TenorDatesCache.Instance() .InnerList.FirstOrDefault( x => x.SpotStart == daysToSpot_ && string.Compare(otHolidayCode_, x.HolidayCode, StringComparison.OrdinalIgnoreCase) == 0); var allTenors = (CurveDateIndex[])Enum.GetValues(typeof(CurveDateIndex)); var updated = false; if (record == null) { record = new TenorDates() { HolidayCode = otHolidayCode_, SpotStart = daysToSpot_, Dates = new ConstructGenGen<DateTime, DateTime>(allTenors.Select(x => x.ToString()).ToArray()) }; record.Dates.Name = string.Format("{0} tenor dates with spotStart={1}", otHolidayCode_, daysToSpot_); } else { // if we're not forcing a rebuild, then we can move the date to the last date in the series if(!force_) date = record.Dates.Keys.Last(); } while (date < END_DATE) { updated = true; await GoDate( date_: date, record: record, cc_: cc_, force_: force_, persistToServer_: false); var plusOne = await cc_.RollDateAsync(date.ToNodaLocalDate(), 1, Symmetry.Carbon.Model.DateUnit.Bd, Symmetry.Carbon.Model.BusinessDayConvention.Following, otHolidayCode_); date = plusOne.ToDateTime(); } try { if (updated) { var result = await TenorDatesCache.Instance().AddOrUpdateDefinition(record); Logger.Info( string.Format("Updated cache for {0} with {1}. Result = {2}", otHolidayCode_, daysToSpot_, result), typeof(DatesWorker)); } else { Logger.Info( string.Format("Not updating dates cache {0}.{1} as already up to date", otHolidayCode_, daysToSpot_), typeof (DatesWorker)); } } catch (Exception ex_) { Logger.Error("Error updating cache", typeof(DatesWorker), ex_); } return record; }