//------------------------------------------------------------------------------------------------
 private string getRollField(RollMethods m)
 //------------------------------------------------------------------------------------------------
 {
     switch (m)
     {
         case RollMethods.DeliveryDate: return "fut_dlv_dt_last"; break;
         case RollMethods.LastTradeDate: return "last_tradeable_dt"; break;
         case RollMethods.FirstNoticeDate: return "fut_notice_first"; break;
         case RollMethods.Custom: return "custom_roll"; break;
     }
     return "";
 }
        //------------------------------------------------------------------------------------------------
        // 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();

        }
        //------------------------------------------------------------------------------------------------
        public Dictionary<ContractMonths, string> getXMonthContracts(DateTime asof, Frame<string/*ticker*/, string> futStatic, RollMethods rollMethod)
        //------------------------------------------------------------------------------------------------
        {
            string rollField = getRollField(rollMethod);           

            var futStatic_d8Index = futStatic.IndexRows<DateTime>(rollField, keepColumn: true);

            futStatic_d8Index = futStatic_d8Index.SortRowsByKey();

            List<DateTime> dteList  = futStatic_d8Index.GetColumn<DateTime>(rollField).Values.ToList();
            List<string> RICS       = futStatic_d8Index.GetColumn<string>("ticker").Values.ToList();
            
            int i = 1;

            // Iterate over roll field to get FM contract
            foreach (DateTime dte in dteList)
            {
                if (asof <= dte) break;
                ++i;
            }

            Dictionary<ContractMonths, string> contracts = new Dictionary<ContractMonths, string>();
            contracts[ContractMonths.PrevFrontMonth] = (i - 2 < 0) ? "" : RICS[i - 2];
            contracts[ContractMonths.FrontMonth] = RICS[i - 1];
            contracts[ContractMonths.BackMonth] = RICS[i];
            contracts[ContractMonths.SecondBackMonth] = (i + 1 == RICS.Count) ? "" : RICS[i + 1];

            return contracts;
        }
        // Allows intialisation code reuse
        //------------------------------------------------------------------------------------------------
        private void initFutureSeriesBuilder(List<string> tickers, List<DateTime> daterange, List<DateTime> holidays,
                                             string futuresStaticMoniker, ICarbonClient client, string carbonEnv = "PRD", 
                                             RollMethods rolMthd = RollMethods.FirstNoticeDate,
                                             InterpolationTypes interpType = InterpolationTypes.None,
                                             List<string> contractSortOrder = null ,
                                             Dictionary<string,DateTime> rollmap = null,
                                             SmoothingTypes smoothingType = SmoothingTypes.None)
        //------------------------------------------------------------------------------------------------
        {
            // defaults
            dateRange_ = daterange;
            startDate_ = daterange.Min();
            endDate_ = daterange.Max();
            carbonEnv_ = carbonEnv;
            rollMethod_ = rolMthd; //RollMethods.LastTradeDate; //
            holidays_ = holidays;
            futuresStaticMoniker_ = futuresStaticMoniker;
            interpType_ = interpType;
            smoothingType_ = smoothingType;

            if (contractSortOrder == null)
            {
                contractSortOrder_ = new List<string>();
            }
            else
            {
                contractSortOrder_ = contractSortOrder;
            }

            if (rolMthd == RollMethods.Custom && rollmap == null)
            {
                throw new ArgumentException("Custom roll dates required for custom rolls!");
            }

            ContractMonthLookupTable_ = new Dictionary<ContractMonths, string>
            {
                {ContractMonths.PrevFrontMonth, "PrevFront"},
                {ContractMonths.FrontMonth, "Front"},
                {ContractMonths.BackMonth, "Back"},
                {ContractMonths.SecondBackMonth, "SecondBack"}
            };

            Tuple<List<Tuple<string, ContractMonths>> /*rootTickers*/, List<string> /*contracts*/> tickerListTuple;

            // Get Static
            FuturesStatic = getFuturesStatic(tickers, futuresStaticMoniker, client, carbonEnv, out tickerListTuple, startDate_, endDate_, contractSortOrder_);

            // Add custom roll if present
            if (rollmap != null)
            {
                var sb = new SeriesBuilder<string,DateTime>();
                foreach (var kvp in rollmap)
                {
                    sb.Add(kvp.Key, kvp.Value);
                }
                FuturesStatic.AddColumn("custom_roll", sb.Series);
            }
            inputTickers_           = tickers;
            contractTickers_        = tickerListTuple.Item2;
            RollingContractSpecs_   = tickerListTuple.Item1;
            var contracts = FuturesStatic.RowKeys.ToList(); // get all the tickers (in case no tickers supplied

            // Get prices
            Console.WriteLine("Getting Futures prices");
            RawFuturesPrices = getAllFuturesPricesInDateRange(contracts, startDate_, endDate_, client);
            RawFuturesPrices.Print();

            // Align Futures Prices & interpolate gaps
            alignRawPriceFrameWithDateRange(dateRange_);
            //interpolateRawPriceFrame(interpType_);
        }
 //------------------------------------------------------------------------------------------------
 public FuturesSeriesBuilder(List<string> tickers, List<DateTime> daterange, List<DateTime> holidays,
                             string futuresStaticMoniker, ICarbonClient client, string carbonEnv = "PRD", 
                             RollMethods rollMthd = RollMethods.FirstNoticeDate,
                             InterpolationTypes interpType = InterpolationTypes.None,
                             List<string> contractSortOrder = null,
                             Dictionary<string,DateTime> rollmap = null, 
                             SmoothingTypes smoothingType = SmoothingTypes.None)
 //------------------------------------------------------------------------------------------------
 {
     initFutureSeriesBuilder(tickers, daterange, holidays, futuresStaticMoniker, client, carbonEnv, rollMthd, interpType, contractSortOrder, rollmap, smoothingType);
    
 }
        //------------------------------------------------------------------------------------------------
        public FuturesSeriesBuilder(List<string> tickers,
            DateTime start,
            DateTime end,
            string calendarCode,
            string futuresStaticMoniker,
            ICarbonClient client,
            string carbonEnv = "PRD",
            RollMethods rollMthd = RollMethods.FirstNoticeDate,
            InterpolationTypes interpType = InterpolationTypes.None,
            List<string> contractSortOrder = null ,
            Dictionary<string,DateTime> rollmap = null,
            SmoothingTypes smoothingType = SmoothingTypes.None)
        //------------------------------------------------------------------------------------------------
        {
            // defaults
            startDate_ = start;
            endDate_ = end;
            carbonEnv_ = carbonEnv;
            rollMethod_ = rollMthd; //RollMethods.FirstNoticeDate;
            smoothingType_ = smoothingType;
            futuresStaticMoniker_ = futuresStaticMoniker;

            // Holidays
            holidays_ = new List<DateTime>();
            if (calendarCode != "")
            {
                var nodaHols = client.GetCalendarAsync(calendarCode).Result.Dates;

                foreach (LocalDate hol in nodaHols)
                {
                    holidays_.Add(hol.ToDateTime());
                }
            }

            // DateRange
            dateRange_ = new List<DateTime>();

            LocalDate currentDate = client.RollDateAsync(DateUtils.ToLocalDate(startDate_), 0, DateUnit.Bd, BusinessDayConvention.Following, calendarCode).Result;
            LocalDate endDate = DateUtils.ToLocalDate(endDate_);
            while (currentDate <= endDate)
            {
                dateRange_.Add(DateUtils.ToDateTime(currentDate));

                currentDate = client.RollDateAsync(currentDate, 1, DateUnit.Bd, BusinessDayConvention.Following, calendarCode).Result;
            }

            initFutureSeriesBuilder(tickers, dateRange_, holidays_, futuresStaticMoniker_, client, carbonEnv, rollMthd, interpType, contractSortOrder);

        }