getFuturesStatic(List< string> tickers , string futuresStaticMoniker, ICarbonClient client, string carbonEnv,
            out Tuple<List<Tuple<string, ContractMonths>> /*rootTickers*/, List<string> /*contracts*/> tickerSplitTuple,
            DateTime? vStartDate = null, DateTime? vEndDate = null, List<string> contractSortOrder = null )
        //------------------------------------------------------------------------------------------------
        {

            // Intialisation
            if (tickers == null)
            {
                tickers = new List<string>();
            }
            DateTime startDate, endDate;
            if (vStartDate == null)
            {
                startDate = DateTime.MinValue;
            }
            else
            {
                startDate = vStartDate.Value;
            }

            if (vStartDate == null)
            {
                endDate = DateTime.MaxValue;
            }
            else
            {
                endDate = vEndDate.Value;
            }
            if (contractSortOrder == null)
            {
                contractSortOrder = new List<string>();
            }

            string cacheKey = getCacheKey(tickers, futuresStaticMoniker, startDate, endDate, contractSortOrder);


            // Divide inputs according to whether they should be used for rolling futures or not
            tickerSplitTuple                                = splitRollingFuturesFromRawTickers(tickers);
            List<string> contractTickers                    = tickerSplitTuple.Item2;
            List<Tuple<string, ContractMonths>> rootTickers = tickerSplitTuple.Item1;

            
            // Get Static From cache here if we have it, tickersplittuple has been set.
            Frame<string, string> cachedValue;
            if (StaticCache_.TryGetValue(cacheKey, out cachedValue)) return cachedValue;
            
            // Get all the roots from list
            List< string> rollingFuturesIDs                 = new List<string>();
            foreach (var tup in rootTickers)
            {
                rollingFuturesIDs.Add(tup.Item1);
            }
            
            // Get test sets.
            //      This allows us to map back names used in futures static moniker, to our original inputs
            var bbgTickerMap            = processBBGTickerList(contractTickers); 
            HashSet<string> rollingSet  = new HashSet<string>(rollingFuturesIDs);
            HashSet<string> tickerSet   = new HashSet<string>(bbgTickerMap.Keys.AsEnumerable());

            // Processing inputs
            Frame<string, string> output;
            var rowList = new List<KeyValuePair<int/*id*/, Series<string, object>/*row*/>>();

            var df = client.GetDataFrame(futuresStaticMoniker);
            var tmp = df.ToList();
            var col = tmp[0].Value as List<object>;
            var ind = tmp[1].Value as List<object>;
            var dat = tmp[2].Value as List<object>;

            //Find it's first trade date col
            int firstTradeDtCol = 0;
            int futDeliveryDtCol = 0;
            int typeCol = 0;
            for (int j = 0; j < col.Count; ++j)
            {
                string heading = col[j].ToString();
                if (heading == "fut_first_trade_dt")
                {
                    firstTradeDtCol = j;
                }
                if (heading == "fut_dlv_dt_last")
                {
                    futDeliveryDtCol = j;
                }
                if(heading == "type")
                {
                    typeCol = j;
                }
            }

            //client.getdat
            SeriesBuilder<string> sb;
            int i;
            for (i = 0; i < ind.Count; ++i)
            {
                sb = new SeriesBuilder<string>();
                var data = dat[i] as List<object>;
                var contract = data[typeCol].ToString();
                string index = (string)ind[i];

                if ((tickerSet.IsEmpty() && rollingSet.IsEmpty())
                    || (!tickerSet.Contains(index) && !rollingSet.Contains(contract)))
                {
                    continue;
                }

                DateTime firstTradeDate = DateTime.ParseExact(data[firstTradeDtCol].ToString(), "%dd/%MM/%yyyy", CultureInfo.InvariantCulture);
                DateTime futDeliveryDate = DateTime.ParseExact(data[futDeliveryDtCol].ToString(), "%dd/%MM/%yyyy", CultureInfo.InvariantCulture);
                if (rollingSet.Contains(contract) && (futDeliveryDate < startDate || firstTradeDate > endDate))
                {
                    continue;
                }

                if (bbgTickerMap.ContainsKey(index))
                    sb.Add("ticker", bbgTickerMap[index]);
                else
                    sb.Add("ticker", index); // ignores the mappings, in the rolling contract case

                for (int h = 0; h < col.Count; ++h)
                {
                    sb.Add((string)col[h], data[h]);
                }

                rowList.Add(KeyValue.Create(i, sb.Series)); 
            }

            output = Frame.FromRows(rowList).IndexRows<string>("ticker", keepColumn: true);

            if (rootTickers.IsEmpty())
            {
                output = sortFrameByInput(output, tickers);
            }
            else
            {
                output = sortFrameByNaturalOrder(output, contractSortOrder);
            }

            StaticCache_.TryAdd(cacheKey, output.Clone());

            return output;

        }