//------------------------------------------------------------------------------------------------ public SpreadSeriesBuilder(string metric, FuturesSeriesBuilder rawfuturesBuilder, SwapCurveSeriesBuilder swapBuilder, Dictionary<string, TimeSeriesBondStatic> bondStatics, SpreadConventions conventions, List<DateTime> holidays=null) //------------------------------------------------------------------------------------------------ { if (holidays == null) { holidays = new List<DateTime>(); } // Setup Everything var futuresBuilder = new FuturesSeriesBuilder(rawfuturesBuilder); //use copy constructor FuturesPrices = futuresBuilder.RawFuturesPrices; FuturesStatic = futuresBuilder.FuturesStatic; BondStatic = bondStatics; CombinedStatic = SpreadSeriesBuilder.combineFuturesAndBondStatic(BondStatic, FuturesStatic); if (conventions.bForecastCurve) { ForecastCurves = swapBuilder.ForecastCurves; DiscountCurves = swapBuilder.DiscountCurves; } else { ForecastCurves = swapBuilder.DiscountCurves; DiscountCurves = swapBuilder.DiscountCurves; } SpreadMetric_ = metric; Conv_ = conventions; Holidays_ = holidays; var rawSpreads = computeFuturesSpreads(); // Now use this to get rolling futures too futuresBuilder.RawFuturesPrices = rawSpreads; futuresBuilder.interpolateRawPriceFrame(); SpreadValues = futuresBuilder.getCombinedResults(); FuturesBuilder_ = futuresBuilder; }
//------------------------------------------------------------------------------------------------ // Copy constructor public FuturesSeriesBuilder(FuturesSeriesBuilder copy2clone) //------------------------------------------------------------------------------------------------ { // Copy constructor carbonEnv_ = copy2clone.carbonEnv_; futuresStaticMoniker_ = copy2clone.futuresStaticMoniker_; startDate_ = copy2clone.startDate_; endDate_ = copy2clone.endDate_; dateRange_ = copy2clone.dateRange_; holidays_ = copy2clone.holidays_; rollMethod_ = copy2clone.rollMethod_; inputTickers_ = copy2clone.inputTickers_; contractTickers_ = copy2clone.contractTickers_; RollingContractSpecs_ = copy2clone.RollingContractSpecs_; ContractMonthLookupTable_ = copy2clone.ContractMonthLookupTable_; interpType_ = copy2clone.interpType_; contractSortOrder_ = copy2clone.contractSortOrder_; smoothingType_ = copy2clone.smoothingType_; FuturesStatic = copy2clone.FuturesStatic == null ? null : copy2clone.FuturesStatic.Clone(); RawFuturesPrices = copy2clone.RawFuturesPrices == null? null: copy2clone.RawFuturesPrices.Clone(); RollingFuturesData = copy2clone.RollingFuturesData == null? null: copy2clone.RollingFuturesData.Clone(); }
//----------------------------------------------------------------------------------- // function to return carry adjusted smooth series, together with Bond ISIN, series price, convfac public static Frame<DateTime, String> GenerateCarryAdjSeries( string ticker, DateTime start, DateTime end, string countryCode, ICarbonClient client = null ) //----------------------------------------------------------------------------------- { //variables used for futureSeriesBuilder var eRollMethod = TimeSeriesUtilities.GetRollMethods("FirstNoticeDate"); var eInterpolationTypes = TimeSeriesUtilities.GetInterpolationType("None"); var eSmoothingTypes = TimeSeriesUtilities.GetSmoothingTypes("None"); #region Configs SpreadTimeSeriesConfigs config = new SpreadTimeSeriesConfigs(countryCode, false); string ccy = config.ccy; string calendarCode = config.calendarcode; string futuresStaticMoniker = config.futuresStaticMoniker; string carbonEnv = config.carbonEnv; BondAnalytics.Country country = config.country; BondAnalytics.DayCountType dct = config.dct; List<string> contractSortOrder = config.contractSortOrder; List<DateTime> holidays = TimeSeriesUtilities.GetHolidays(calendarCode, client); #endregion // in rolling series US is following calendar of USGS rather than USNY var dateRange = TimeSeriesUtilities.GetAllDatesInDateime(start, end, countryCode.ToUpper() == "US" ? "USGS" : calendarCode, client, "1b"); //Get Rolling Series HashSet<string> futuresList = new HashSet<string> { "TU", "FV", "TY", "UXY", "US", "WN", "DU", "OE", "RX", "UB", "IK", "BTS", "OAT" }; bool tickerIsFuture = futuresList.Contains(ticker); bool isCT = ticker.ToUpper().Contains("CT"); var rollType = isCT ? "ct" : "ctd"; string moniker = string.Format("symapp.roll.{0}.{1}.{2}", rollType, ticker.Market(), ticker).ToLower(); string fmoniker; // Carbon frame // var frame = client.GetFrameAsync<DateTime>(moniker).Result; if (!frame.ColumnKeys.Contains("price")) return null;// need better null value checker here Series<DateTime, string> bondISIN = null; Series<DateTime, double> bondPrice = null; Dictionary<DateTime, string> futureTicker = new Dictionary<DateTime, string>(); Dictionary<DateTime, double> convFac = new Dictionary<DateTime, double>(); Dictionary<DateTime, double> futurePrice = new Dictionary<DateTime, double>(); Dictionary<DateTime, double> smoothSeries = new Dictionary<DateTime, double>(); Series<DateTime, double> futureConvertedPrice = null; //Repo series and carry series Dictionary<DateTime, double> repoSeries = new Dictionary<DateTime, double>(); Dictionary<DateTime, double> carrySeries = new Dictionary<DateTime, double>(); //DV01 series (Future DV01 = CTD DV01/ConvFac; CT DV01 = Bond DV01) Dictionary<DateTime, double> DV01Series = new Dictionary<DateTime, double>(); //Variables needed for futures Frame<string, string> combinedStatic = null; int RowNum = 0; try { bondISIN = frame.GetColumn<string>("ticker").Between(start, end);//Need check on sorted by date bondPrice = frame.GetColumn<double>("price").Between(start, end); } catch (Exception) { //Error handling } //Future tickers and Future Price as well as conversion factors if (tickerIsFuture) { fmoniker = string.Format("symapp.roll.{0}.{1}.{2}", "f" + rollType, ticker.Market(), ticker).ToLower(); frame = client.GetFrameAsync<DateTime>(fmoniker).Result; if (!frame.ColumnIndex.KeySequence.Contains("price")) return null;//need better null value checker here try { futureConvertedPrice = frame.GetColumn<double>("price").Between(start, end).Sort(); } catch (Exception) { //Error handling } //Get the future static table //Futures List<string> tickers = new List<string>(); tickers.Add(ticker.ToUpper() + ".Front"); FuturesSeriesBuilder seriesBuilder = new FuturesSeriesBuilder(tickers, dateRange, holidays, futuresStaticMoniker, client, carbonEnv, rollMthd: eRollMethod, interpType: eInterpolationTypes, contractSortOrder: config.contractSortOrder, smoothingType: eSmoothingTypes); var futStatic = seriesBuilder.FuturesStatic; //Bond Static Dictionary<String, TimeSeriesBondStatic> bndStatics = TimeSeriesUtilities.GetBondStaticsFromFuturesBuilder(seriesBuilder, config, client); combinedStatic = SpreadSeriesBuilder.combineFuturesAndBondStatic(bndStatics, futStatic); RowNum = combinedStatic.RowCount; } double futureConvertedPx = 0.0; double lastRepo = 0.0; double fwdPrice = 0.0; object dailyRepo = null; bool bHaveEverthing = true; DateTime prevD8 = DateTime.MinValue; //loop through each date to find the corresponding future ticker and conversion factors // and add repo and carry for bond series // can we get the sorted key list #region buildSeries foreach (DateTime d8 in bondISIN.Keys.OfType<DateTime>()) { // DV01Series string currBondISIN = bondISIN.TryGet(d8).Value; Double bondDV01 = 0.0; DateTime settleDate = d8; var currBondStatic = AnalyticsUtilities.GetBondStaticData(client, currBondISIN); if (currBondStatic == null) { bHaveEverthing = false; DV01Series.Add(d8, 0.0);//Need better handling on empty bond static } else { if (config.bondSettleLag > 0) { settleDate = BondAnalytics.NextBusDay(settleDate.AddDays(1), holidays); } if (config.bondSettleLag > 1) { settleDate = BondAnalytics.NextBusDay(settleDate.AddDays(1), holidays); } bondDV01 = BondAnalytics.SolveYield(country, settleDate, bondPrice.TryGet(d8).Value, currBondStatic.EffectiveDate, currBondStatic.FirstCouponDate, currBondStatic.MaturityDate, currBondStatic.Coupon, currBondStatic.CpnFreq)[1]; DV01Series.Add(d8, bondDV01); } if (tickerIsFuture) { //Need gaurantee that the table is sorted int i = 0; while (combinedStatic.GetColumn<DateTime>("fut_notice_first").GetAt(i) <= d8 && i < RowNum) { i++; } if (i == RowNum) { futureTicker.Add(d8, string.Empty); convFac.Add(d8, double.NaN); futurePrice.Add(d8, double.NaN); } else { futureTicker.Add(d8, combinedStatic.GetColumn<string>("ticker").GetAt(i)); convFac.Add(d8, combinedStatic.GetColumn<double>("fut_cnvs_factor").GetAt(i)); futureConvertedPx = futureConvertedPrice.TryGet(d8).Value; futurePrice.Add(d8, futureConvertedPx / combinedStatic.GetColumn<double>("fut_cnvs_factor").GetAt(i)); //update CTD DV01 to be future DV01 DV01Series[d8] = DV01Series[d8] / combinedStatic.GetColumn<double>("fut_cnvs_factor").GetAt(i); } //Add SmoothSeries if (prevD8 == DateTime.MinValue) { smoothSeries.Add(d8, futurePrice[d8]); } else { //check if there is ticker change if (futureTicker[d8] == futureTicker[prevD8]) { smoothSeries.Add(d8, smoothSeries[prevD8] + futurePrice[d8] - futurePrice[prevD8]); } else { //find the old future price on current date string oldFutureTicker = futureTicker[prevD8]; string full_ticker = oldFutureTicker + " COMDTY"; var oldFuturePrice = client.GetCbnTimeSeriesDataCell(full_ticker, "eod", d8, "settle"); if (oldFuturePrice == null) { full_ticker = AnalyticsUtilities.GetAlternativeFuturesName(full_ticker); oldFuturePrice = client.GetCbnTimeSeriesDataCell(full_ticker, "eod", d8, "settle"); } //Otherwise report error: assume no price change a good way? if (oldFuturePrice == null) oldFuturePrice = futurePrice[prevD8]; smoothSeries.Add(d8, smoothSeries[prevD8] + (oldFuturePrice as double? ?? double.NaN) - futurePrice[prevD8]);// potential problem if current res is NaN, all following value would be NaN } } } else { //repo and carry series for bond try { dailyRepo = client.GetCbnTimeSeriesDataCell(currBondISIN, "eod-mlp", d8, "wtdRate"); // repoSeries.Add(d8, dailyRepo as double?); } catch { //Missing Data //need to convert it } lastRepo = (dailyRepo as double?) ?? lastRepo; repoSeries.Add(d8, lastRepo); //need bond static info if (currBondStatic == null) { bHaveEverthing = false; carrySeries.Add(d8, 0.0);//Need better handling for missing bond static smoothSeries.Add(d8, 0.0);//Need better handling for missing bond static } else { //calculate one-day fwdPrice //Current next business day function doesn't handle number of days so get settleDate the hard way. //one day carry DateTime fwdDate = settleDate; fwdDate = BondAnalytics.NextBusDay(fwdDate.AddDays(1), holidays); if (fwdDate <= settleDate) { //error handling here : fwdDate must be bigger than settleDate } fwdPrice = BondAnalytics.CalcBondFwd(country, settleDate, bondPrice.TryGet(d8).Value, currBondStatic.EffectiveDate, currBondStatic.FirstCouponDate, currBondStatic.MaturityDate, currBondStatic.Coupon, currBondStatic.CpnFreq, fwdDate, lastRepo)[0]; carrySeries.Add(d8, bondPrice.TryGet(d8).Value - fwdPrice); //Smooth series for bond if (prevD8 == DateTime.MinValue) { smoothSeries.Add(d8, bondPrice.TryGet(d8).Value);//assume no carry added on day 1 } else { if (bondISIN.TryGet(prevD8).Value == bondISIN.TryGet(d8).Value) { //no change in series smoothSeries.Add(d8, smoothSeries[prevD8] + bondPrice.TryGet(d8).Value - bondPrice.TryGet(prevD8).Value); } else { string oldBondISIN = bondISIN.TryGet(prevD8).Value; var oldBondPrice = client.GetCbnTimeSeriesDataCell(oldBondISIN, "eod-mlp", d8, "close"); if (oldBondPrice == null) oldBondPrice = bondPrice.TryGet(prevD8).Value;// May need better way to handle this error smoothSeries.Add(d8, smoothSeries[prevD8] + (oldBondPrice as double? ?? double.NaN) - bondPrice.TryGet(prevD8).Value); } } } } //update prevD8 prevD8 = d8; } #endregion //Sort the dictionary and package into frame for output if (tickerIsFuture) { //building using dictionary Dictionary<string, Series<DateTime, string>> resHolder = new Dictionary<string, Series<DateTime, string>>(); resHolder["futureTicker"] = futureTicker.ToSeries(); var res = Frame.FromColumns(resHolder); res.AddColumn("futruePrice", futurePrice.ToSeries()); res.AddColumn("CTD_ISIN", bondISIN); res.AddColumn("ConvFac", convFac.ToSeries()); res.AddColumn("DV01", DV01Series.ToSeries()); res.AddColumn("smoothSeries", smoothSeries.ToSeries()); res.SortRowsByKey(); return res; } else { //if bond Dictionary<string, Series<DateTime, string>> resHolder = new Dictionary<string, Series<DateTime, string>>(); resHolder["BondISIN"] = bondISIN; var res = Frame.FromColumns(resHolder); res.AddColumn("BondPrice", bondPrice); res.AddColumn("repo", repoSeries.ToSeries()); res.AddColumn("carry", carrySeries.ToSeries()); res.AddColumn("DV01", DV01Series.ToSeries()); res.AddColumn("smoothSeries", smoothSeries.ToSeries()); res.SortRowsByKey(); return res; } }
//---------------------------------------------------------------------------------------- public static Frame<DateTime, String> GenerateInvoiceSpreadTRS( List<string> tickers, DateTime start, DateTime end, string countryCode, string pnlType = "InvoiceSpread", bool bCumulative = true, bool bOIS = true, string samplingFreq= "1b", string rollMethod = "FirstNoticeDate", string holcal = "", double notional = double.NaN, ICarbonClient client = null) //---------------------------------------------------------------------------------------- { var eRollMethod = TimeSeriesUtilities.GetRollMethods(rollMethod); var eInterpolationTypes = TimeSeriesUtilities.GetInterpolationType("None"); var eSmoothingTypes = TimeSeriesUtilities.GetSmoothingTypes("None"); // Don't smooth, doesn't make sense for PnL bool bForecastCurve = !bOIS; /* CARBON REQUIRES UTC TIME - MODIFY DATES TO ACCOMODATE */ start = new DateTime(start.Year, start.Month, start.Day, 0, 0, 0, DateTimeKind.Utc); end = new DateTime(end.Year, end.Month, end.Day, 0, 0, 0, DateTimeKind.Utc); #region cache string all_tickers = ";"; foreach (var s in tickers) all_tickers += s; string cacheKey = "GenerateInvoiceSpread" + tickers.ToString() + start.ToString() + end.ToString() + countryCode + pnlType + bCumulative.ToString() + bOIS.ToString() + samplingFreq + rollMethod + holcal + notional.ToString(); if (TimeSeriesCache.ContainsKey(cacheKey)) { return TimeSeriesCache[cacheKey]; } #endregion if (client == null) { throw new ArgumentException("No Carbon Client!"); } #region MeasureSetup string swapMeasure = ""; string futMeasure = ""; string ratio = ""; bool bDefaultNoCumulative = false; switch (pnlType) { case "InvoiceSpread": if (double.IsNaN(notional)) // work in DV01 terms { swapMeasure = "SwapPnlDV01Adj"; futMeasure = "FuturesPnlDV01Adj"; } else { swapMeasure = "SwapPnl"; futMeasure = "FuturesPnl"; //ratio = "SpreadHedgeRatio"; // required to construct the correct pnl } break; case "Futures": if (double.IsNaN(notional)) // work in DV01 terms { swapMeasure = ""; futMeasure = "FuturesPnlDV01Adj"; } else { swapMeasure = ""; futMeasure = "FuturesPnl"; } break; case "MMS": if (double.IsNaN(notional)) // work in DV01 terms { swapMeasure = "SwapPnlDV01Adj"; futMeasure = ""; } else { swapMeasure = "SwapPnl"; futMeasure = ""; } break; case "MMSDV01": swapMeasure = "MMSDV01"; futMeasure = ""; bDefaultNoCumulative = true; break; case "FuturesDV01": swapMeasure = "FuturesDV01"; futMeasure = ""; bDefaultNoCumulative = true; break; case "HedgeRatio": swapMeasure = "SpreadHedgeRatio"; futMeasure = ""; bDefaultNoCumulative = true; break; default: throw new ArgumentException(""); } #endregion #region Configs SpreadTimeSeriesConfigs config = new SpreadTimeSeriesConfigs(countryCode, !bOIS); string ccy = config.ccy; string calendarcode = (holcal != "") ? holcal : config.calendarcode; string futuresStaticMoniker = config.futuresStaticMoniker; string carbonEnv = config.carbonEnv; BondAnalytics.Country country = config.country; BondAnalytics.DayCountType dct = config.dct; long swpfixfreq = config.swpfixfreq; long swpfloatfreq = config.swpfloatfreq; long bndCouponFreq = config.bndCouponFreq; int BlendIndex = config.BlendIndex; string symForecastCurveName = config.SymForecastCurveName; string symDiscountCurveName = config.SymDiscountCurveName; List<string> contractSortOrder = config.contractSortOrder; List<DateTime> holidays = TimeSeriesUtilities.GetHolidays(calendarcode, client); #endregion var dateRange = TimeSeriesUtilities.GetAllDatesInDateime(start, end, calendarcode, client, samplingFreq); // Spread Static. SpreadConventions spreadconventions = new SpreadConventions(country, dct, swpfixfreq, swpfloatfreq, bndCouponFreq, bForecastCurve, BlendIndex); // Futures. FuturesSeriesBuilder seriesBuilder = new FuturesSeriesBuilder(tickers, dateRange, holidays, futuresStaticMoniker, client, carbonEnv, rollMthd: eRollMethod, interpType: eInterpolationTypes, contractSortOrder: contractSortOrder, smoothingType: eSmoothingTypes); // Bond Static var bndStatics = TimeSeriesUtilities.GetBondStaticsFromFuturesBuilder(seriesBuilder, config, client); // Swap Curves var curves = TimeSeriesUtilities.GetCurvesFromCarbon(dateRange, ccy, client); if (curves == null || bndStatics == null) return null; var forecastCurves = curves.Item1; var discountCurves = curves.Item2; SwapCurveSeriesBuilder swapBuilder = new SwapCurveSeriesBuilder(dateRange, symForecastCurveName, symDiscountCurveName, ccy, holidays, forecastCurves, discountCurves, client); // Generate Pnls Frame<DateTime,string> swapPnl = null; Frame<DateTime, string> futPnl = null; if (swapMeasure != "") { SpreadSeriesBuilder swapPnlBuilder = new SpreadSeriesBuilder(swapMeasure, seriesBuilder, swapBuilder, bndStatics, spreadconventions, holidays); swapPnl = swapPnlBuilder.SpreadValues; } if (futMeasure != "") { SpreadSeriesBuilder futPnlBuilder = new SpreadSeriesBuilder(futMeasure, seriesBuilder, swapBuilder, bndStatics, spreadconventions, holidays); futPnl = futPnlBuilder.SpreadValues; } // Setup pnl correctly Frame<DateTime, string> pnl; if ( (swapPnl != null) && (futPnl != null)) { // This allows it to match movements on the invoice spread chart. // Long TRS = pay fixed, long bond // Spread increases, mms increases, yield decreases -> swap/bond +ve pnl pnl = futPnl - swapPnl; } else if (swapPnl != null) { pnl = swapPnl; } else { pnl = futPnl; } // Make it cumulative if flagged, but not for hedge ratios etc if (bCumulative && !bDefaultNoCumulative) { pnl = pnl.SortRowsByKey(); // in case pnl = TimeSeriesUtilities.DeedleFrameCumsum(pnl); } //Notional Adjust this thing if (!double.IsNaN(notional) && pnlType!="HedgeRatio") { pnl *= notional/100; // Default 100 } TimeSeriesCache[cacheKey] = pnl; return pnl; }
//--------------------------------------------------------------------------------------------------------- //[Test] public void SpreadSeriesToArrayTests() //--------------------------------------------------------------------------------------------------------- { // Params. DateTime start = new DateTime(2016, 2, 28); DateTime end = new DateTime(2016, 3, 18); List<String> tickers = new List<string>() { "TUH6", "TUM6", "TUU6" }; string samplingFreq = "1b"; // Default Configs SpreadTimeSeriesConfigs config = new SpreadTimeSeriesConfigs("US"); string forecastCurveName = config.forecastCurveName; string discountCurveName = config.discountCurveName; string ccy = config.ccy; string calendarcode = config.calendarcode; string futuresStaticMoniker = config.futuresStaticMoniker; string carbonEnv = config.carbonEnv; BondAnalytics.Country country = config.country; BondAnalytics.DayCountType dct = config.dct; long swpfixfreq = config.swpfixfreq; long swpfloatfreq = config.swpfloatfreq; long bndCouponFreq = config.bndCouponFreq; int BlendIndex = config.BlendIndex; bool bForecastCurve = true; // Bond Static Dictionary<string, TimeSeriesBondStatic> bondstatic = new Dictionary<string, TimeSeriesBondStatic>() { {"US912828G799", new TimeSeriesBondStatic("US912828G799", new DateTime(2017,12,15), new DateTime(2015,12,15),DateTime.MinValue,1.0)}, {"US912828J686", new TimeSeriesBondStatic("US912828J686", new DateTime(2018,03,15), new DateTime(2015,03,16),DateTime.MinValue,1.0)}, {"US912828VK31", new TimeSeriesBondStatic("US912828VK31", new DateTime(2018,06,30), new DateTime(2015,07,01),DateTime.MinValue,1.0)} }; //Spread Static SpreadConventions spreadconventions = new SpreadConventions(country, dct, swpfixfreq, swpfloatfreq, bndCouponFreq, bForecastCurve, BlendIndex); // Dates var holidays = new List<DateTime>(); var dateRange = new List<DateTime>(); using (var client = new CarbonClient(carbonEnv)) { // Holidays if (calendarcode != "") { var nodaHols = client.GetCalendarAsync(calendarcode).Result.Dates; foreach (LocalDate hol in nodaHols) { holidays.Add(hol.ToDateTime()); } } // DateRange DateTime startDate = start.AddTenor(Tenor.FromString("1b"), "").AddTenor(Tenor.FromString("-1b"), ""); DateTime nextDate = end.AddTenor(Tenor.FromString("1b"), "").AddTenor(Tenor.FromString("-1b"), ""); //TimeSpan EOD = new TimeSpan(23, 59, 59); /*if (startDate > nextDate) { return "Error! Bad Inputs!"; }*/ var tenor = Tenor.FromString("-" + samplingFreq); while (nextDate >= startDate) { dateRange.Add(nextDate); nextDate = BondAnalytics.PrevBusDay(nextDate.AddTenor(tenor, ""), holidays); } } //Swap. var swapBuilder = new SwapCurveSeriesBuilder(dateRange, forecastCurveName, discountCurveName, ccy, holidays, mCarbonClient); swapBuilder.buildAllCurves(); // Futures. var seriesBuilder = new FuturesSeriesBuilder(tickers, dateRange, holidays, futuresStaticMoniker, mCarbonClient, carbonEnv); // Spread Series. Dictionary<string, double> testVals = new Dictionary<string, double>() { {"Price", 109.1015625}, {"Yield", 0.009007303 * 10000}, {"TrueSpread",6.7788999}, {"MMS", 0.009689381* 10000}, {"Spread", 6.820787365} }; Dictionary<string /*metric*/, SpreadSeriesBuilder /*builder*/> spreadbuildermap = new Dictionary<string, SpreadSeriesBuilder>(); SpreadSeriesBuilder output = null; foreach (var metric in testVals.Keys.ToList()) { output = new SpreadSeriesBuilder(metric, seriesBuilder, swapBuilder, bondstatic, spreadconventions); Console.WriteLine(metric + " :"); output.SpreadValues.Print(); var row = output.SpreadValues.GetRow<double>(new DateTime(2016, 03, 18)); double TUM6 = row.Get("TUM6"); double error = Math.Abs(TUM6 - testVals[metric]); Assert.LessOrEqual(error, Math.Pow(10, -3) * 5, "Error found in " + metric + ", test: " + testVals[metric].ToString() + ", actual: " + TUM6.ToString()); // 0.005bps Console.WriteLine("Error :{0}", error); } // Now let's look at converting this to an array if (output != null) { var objArr = output.getSpreadAsObjArr(); } }
//--------------------------------------------------------------------------------------------------------- //[Test] public void SpreadSeries() //--------------------------------------------------------------------------------------------------------- { // Params. DateTime start = new DateTime(2016, 2, 28); DateTime end = new DateTime(2016, 3, 18); List<String> tickers = new List<string>() { "TUH6", "TUM6", "TUU6","TU.Front" }; // Default Configs SpreadTimeSeriesConfigs config = new SpreadTimeSeriesConfigs("US"); string forecastCurveName = config.forecastCurveName; string discountCurveName = config.discountCurveName; string ccy = config.ccy; string calendarcode = config.calendarcode; string futuresStaticMoniker = config.futuresStaticMoniker; string carbonEnv = config.carbonEnv; BondAnalytics.Country country = config.country; BondAnalytics.DayCountType dct = config.dct; long swpfixfreq = config.swpfixfreq; long swpfloatfreq = config.swpfloatfreq; long bndCouponFreq = config.bndCouponFreq; int BlendIndex = config.BlendIndex; bool bForecastCurve = true; // Bond Static Dictionary<string, TimeSeriesBondStatic> bondstatic = new Dictionary<string, TimeSeriesBondStatic>() { {"US912828G799", new TimeSeriesBondStatic("US912828G799", new DateTime(2017,12,15), new DateTime(2015,12,15),DateTime.MinValue,1.0)}, {"US912828J686", new TimeSeriesBondStatic("US912828J686", new DateTime(2018,03,15), new DateTime(2015,03,16),DateTime.MinValue,1.0)}, {"US912828VK31", new TimeSeriesBondStatic("US912828VK31", new DateTime(2018,06,30), new DateTime(2015,07,01),DateTime.MinValue,1.0)} }; //Spread Static SpreadConventions spreadconventions = new SpreadConventions(country,dct,swpfixfreq,swpfloatfreq,bndCouponFreq,bForecastCurve,BlendIndex); //Swap. var swapBuilder = new SwapCurveSeriesBuilder(start, end, forecastCurveName, discountCurveName, ccy, mCarbonClient, calendarcode); swapBuilder.buildAllCurves(); //swapBuilder.DiscountCurves[new DateTime(2016, 03, 18)].PrintDump(); swapBuilder.ForecastCurves[new DateTime(2016, 03, 18)].PrintDump(); // Futures. var seriesBuilder = new FuturesSeriesBuilder(tickers, start, end, calendarcode, futuresStaticMoniker, mCarbonClient,carbonEnv); // Spread Series. Dictionary<string, double> testVals = new Dictionary<string, double>() { {"Price", 109.1015625}, {"Yield", 0.009007303 * 10000}, {"TrueSpread",6.7788999}, {"MMS", 0.009689381* 10000}, {"Spread", 6.820787365} }; Dictionary<string /*metric*/, SpreadSeriesBuilder /*builder*/> spreadbuildermap = new Dictionary<string, SpreadSeriesBuilder>(); SpreadSeriesBuilder output = null; foreach (var metric in testVals.Keys.ToList()) { output = new SpreadSeriesBuilder(metric, seriesBuilder, swapBuilder, bondstatic, spreadconventions); Console.WriteLine(metric + " :"); output.SpreadValues.Print(); var row = output.SpreadValues.GetRow<double>(new DateTime(2016, 03, 18)); double TUM6 = row.Get("TUM6"); double error = Math.Abs(TUM6 - testVals[metric]); Assert.LessOrEqual(error, Math.Pow(10, -3) * 5, "Error found in " + metric + ", test: " + testVals[metric].ToString() + ", actual: " + TUM6.ToString()); // 0.005bps Console.WriteLine("Error :{0}", error); } // Now let's try to index 1 Mar if (output != null) { var spreadVals = output.SpreadValues; var myList = spreadVals.RowKeys.ToList(); Console.WriteLine("Key List: {0}", myList); // Try on individual series Dictionary<string/*colname*/, Series<DateTime,object>/*actualsrs*/> tmp = new Dictionary<string, Series<DateTime, object>>(); foreach (string colname in spreadVals.ColumnKeys) { tmp[colname] = spreadVals.Columns[colname].FillMissing("#N/A"); } spreadVals = Frame.FromColumns(tmp); //spreadVals.FillMissing("#N/A").Print(); var row = spreadVals.GetRow<string>(new DateTime(2016, 03, 01)); Console.WriteLine("Row values"); row.Print(); } }
//--------------------------------------------------------------------------------------------------------- //[Test] public void FuturesSeriesWErrors() //--------------------------------------------------------------------------------------------------------- { bool errored = true; try { List<String> tickers = new List<string>() {"TUH6", "FVH6", "TUM6"}; DateTime start = new DateTime(2016, 3, 7); DateTime end = new DateTime(2016, 3, 11); string calendarCode = "USNY"; string futuresStaticMoniker = "BLIM.Futures.US.Static"; string carbonEnv = "PRD"; var seriesBuilder = new FuturesSeriesBuilder(tickers, start, end, calendarCode, futuresStaticMoniker, mCarbonClient, carbonEnv); errored = false; Frame<string, string> futStatic = seriesBuilder.FuturesStatic; futStatic.Print(); } catch(Exception e) { Console.Write(e.Message); } Assert.IsFalse(errored); }
//--------------------------------------------------------------------------------------------------------- //[Test] public void FuturesSeriesPerfectRun() //--------------------------------------------------------------------------------------------------------- { List<String> tickers = new List<string>() { "TUZ15", "FV.Front", "TUH6", "TUM6", "TUU6", "TY.Back" }; DateTime start = new DateTime(2015,11,1); DateTime end = new DateTime(2016, 3, 11); string calendarCode = "USNY"; string futuresStaticMoniker = "BLIM.Futures.US.Static"; string carbonEnv = "PRD"; FuturesSeriesBuilder.RollMethods rollMthd = FuturesSeriesBuilder.RollMethods.LastTradeDate; var seriesBuilder = new FuturesSeriesBuilder(tickers, start, end, calendarCode, futuresStaticMoniker, mCarbonClient, carbonEnv, rollMthd); Frame<string, string> futStatic = seriesBuilder.FuturesStatic; futStatic.Print(); Assert.IsFalse(futStatic.IsEmpty); // Set Rolling prices seriesBuilder.setRollingFuturesPrices(); seriesBuilder.RollingFuturesData.Print(); // Get back the combined df Console.WriteLine(""); Console.WriteLine("#--------------------------"); Console.WriteLine("Output line"); Console.WriteLine("#--------------------------"); Console.WriteLine(""); var combined = seriesBuilder.getCombinedResults(); combined.Print(); }