private static void TryAddUpdateKlineCache(Dictionary <long, KlineCandleStick> primary, long keyTime, KlineCandleStick klineObj) { if (primary.ContainsKey(keyTime)) { primary[keyTime] = klineObj; } else { primary.Add(keyTime, klineObj); } }
/// <summary> /// Advanced approach to building local Kline Cache from WebSocket and API Call example (refactored) /// </summary> /// <param name="binanceClient">The BinanceClient instance</param> /// <param name="symbol">The Symbol to request</param> /// <param name="interval">The interval for Klines</param> /// <param name="klinesCandlesticksRequest">The initial request for Klines</param> /// <param name="webSocketConnectionFunc">The function to determine exiting the websocket (can be timeout or Func based on external params)</param> /// <param name="cacheObject">The cache object. Must always be provided, and can exist with data.</param> /// <returns></returns> public static async Task BuildAndUpdateLocalKlineCache(IBinanceClient binanceClient, string symbol, KlineInterval interval, GetKlinesCandlesticksRequest klinesCandlesticksRequest, WebSocketConnectionFunc webSocketConnectionFunc, Dictionary <string, KlineCacheObject> cacheObject) { Guard.AgainstNullOrEmpty(symbol); Guard.AgainstNull(webSocketConnectionFunc); Guard.AgainstNull(klinesCandlesticksRequest); Guard.AgainstNull(cacheObject); long epochTicks = new DateTime(1970, 1, 1).Ticks; if (cacheObject.ContainsKey(symbol)) { if (cacheObject[symbol].KlineInterDictionary.ContainsKey(interval)) { throw new Exception( "Symbol and Interval pairing already provided, please use a different interval/symbol or pair."); } cacheObject[symbol].KlineInterDictionary.Add(interval, new KlineIntervalCacheObject()); } else { var klineCacheObject = new KlineCacheObject { KlineInterDictionary = new Dictionary <KlineInterval, KlineIntervalCacheObject>() }; cacheObject.Add(symbol, klineCacheObject); cacheObject[symbol].KlineInterDictionary.Add(interval, new KlineIntervalCacheObject()); } // Get Kline Results, and use Cache long ticks = klinesCandlesticksRequest.StartTime.Value.Ticks; var startTimeKeyTime = (ticks - epochTicks) / TimeSpan.TicksPerSecond; var klineResults = await binanceClient.GetKlinesCandlesticks(klinesCandlesticksRequest); var oneMinKlineCache = cacheObject[symbol].KlineInterDictionary[interval]; oneMinKlineCache.TimeKlineDictionary = new Dictionary <long, KlineCandleStick>(); var instanceKlineCache = oneMinKlineCache.TimeKlineDictionary; //Populate our kline cache with initial results klineResults.ForEach(k => { instanceKlineCache.Add(((k.OpenTime.Ticks - epochTicks) / TimeSpan.TicksPerSecond), new KlineCandleStick() { Close = k.Close, High = k.High, Low = k.Low, Open = k.Open, Volume = k.Volume, }); }); // Store the last update from our result set; using (var binanceWebSocketClient = new DisposableBinanceWebSocketClient(binanceClient)) { binanceWebSocketClient.ConnectToKlineWebSocket(symbol, interval, data => { var keyTime = (data.Kline.StartTime.Ticks - epochTicks) / TimeSpan.TicksPerSecond; var klineObj = new KlineCandleStick() { Close = data.Kline.Close, High = data.Kline.High, Low = data.Kline.Low, Open = data.Kline.Open, Volume = data.Kline.Volume, }; if (!data.Kline.IsBarFinal) { if (keyTime < startTimeKeyTime) { return; } TryAddUpdateKlineCache(instanceKlineCache, keyTime, klineObj); } else { TryAddUpdateKlineCache(instanceKlineCache, keyTime, klineObj); } System.Console.Clear(); System.Console.WriteLine($"{JsonConvert.SerializeObject(instanceKlineCache, Formatting.Indented)}"); System.Console.SetWindowPosition(0, 0); }); if (webSocketConnectionFunc.IsTimout) { Thread.Sleep(webSocketConnectionFunc.Timeout); } else { while (true) { if (!webSocketConnectionFunc.ExitFunction()) { // Throttle Application Thread.Sleep(100); } else { break; } } } } }