private static IReadOnlyDictionary<string, double> BulkGetHistoricPricesFromCarbon(ICarbonClient client, IReadOnlyCollection<AnalyticsBondStaticData> bondDatas, DateTime date)
        {
            var dict = new ConcurrentDictionary<string, double>();
            var ids = new Dictionary<string, HashSet<string>>();
            foreach (var analyticsBondStaticData in bondDatas)
            {
                var d = GetBondPricesFromCache(analyticsBondStaticData.Id, date);
                if (d.HasValue)
                {
                    dict[analyticsBondStaticData.Id] = d.Value;
                }
                else
                {
                    var snapSource = GetBondPriceSnapSource(analyticsBondStaticData);
                    HashSet<string> bondIds;
                    if (ids.TryGetValue(snapSource, out bondIds) && !bondIds.Contains(analyticsBondStaticData.Id))
                    {
                        bondIds.Add(analyticsBondStaticData.Id);
                    }
                    else
                    {
                        ids[snapSource] = new HashSet<string> { analyticsBondStaticData.Id };
                    }
                }
            }

            if (ids.Count > 0)
            {
                Parallel.ForEach(ids, kvp =>
                {
                    Parallel.ForEach(Helper.BatchItems(kvp.Value, 32), identfiers =>
                    {
                        SLog.log.InfoFormat("Request bond price for {0} ids", identfiers.Length);
                        var datas = client.GetTimeSeriesAsync(identfiers, kvp.Key,
                            new DateTime(date.Year, date.Month, date.Day, 0, 0, 0, DateTimeKind.Utc),
                            new DateTime(date.Year, date.Month, date.Day, 0, 0, 0, DateTimeKind.Utc)).Result;
                        if (datas == null || datas.Count <= 0) return;
                        foreach (var data in datas)
                        {
                            if (data.Series == null || data.Series.Count == 0) continue;
                            var o = client.GetValueFromTimeSeriesList(new List<ITimeSeries> { data }, "close", null);
                            if (!(o is double)) continue;
                            var close = (double)o;
                            dict.AddOrUpdate(data.Identifier, close, (s, d) => close);
                            AddBondPricesToCache(data.Identifier, date, close);
                        }
                    });
                });
            }

            return dict.ToDictionary(kvp => kvp.Key, kvp => kvp.Value);
        }