protected override async Task HandleMessage(FeedMessage msg) { if (msg.Type == "message") { if (msg.Subject == Subject) { var i = msg.Topic.IndexOf(":"); if (i == -1) { return; } var ticker = new KlineFeedMessage <TCandle>(); var sk = SymbolKline.Parse(msg.Topic.Substring(i + 1)); // The JSON.NET documentation states clearly that // for tricky deserialization scenarios, the fastest // way is manual deserialization. ticker.Timestamp = EpochTime.NanosecondsToDate(msg.Data["time"].ToObject <long>()); ticker.Symbol = msg.Data["symbol"].ToObject <string>(); // Here we have the candle data efficiently served as an array of strings. // In C# we want to parse this array into a strongly-typed object. var values = msg.Data["candles"].ToObject <string[]>(); var candle = new TCandle { Timestamp = EpochTime.SecondsToDate(long.Parse(values[0])), // We are going to assume that the data from the feed is correctly formatted. // If an error is thrown here, then there is a deeper problem. OpenPrice = decimal.Parse(values[1]), ClosePrice = decimal.Parse(values[2]), HighPrice = decimal.Parse(values[3]), LowPrice = decimal.Parse(values[4]), Amount = decimal.Parse(values[5]), Volume = decimal.Parse(values[6]) }; // The candlestick does not need to be a typed candle, // but if it is, we will set that value, as well. if (candle is IFullKlineCandle <KlineType> wt) { wt.Type = sk.KlineType; } ticker.Candles = candle; // push the final object. await PushNext(ticker); } } }