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); }