Пример #1
0
        //------------------------------------------------------------------------------------------------
        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();

        }
Пример #3
0
        //-----------------------------------------------------------------------------------
        // 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;

            }
        }
Пример #4
0
        //----------------------------------------------------------------------------------------
        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();


         }