//New RTD subscription callback protected override object ConnectData(Topic topic, IList <string> topicInfo, ref bool newValues) { object result; int topicId = GetTopicId(topic); Logging.Log("ConnectData: {0} - {{{1}}}", topicId, string.Join(", ", topicInfo)); //parse and validate request //--- //count and default parameters if (topicInfo.Count < 2) { return(ExcelErrorUtil.ToComError(ExcelError.ExcelErrorNA)); //need at least a product and a datapoint } else if (topicInfo.Count == 2) { topicInfo.Add("0"); //default to top level of book } //parse parameters string product = topicInfo[0]; DataPoint dataPoint; bool dataPointOk = Enum.TryParse <DataPoint>(topicInfo[1], out dataPoint); int level; bool levelOk = Int32.TryParse(topicInfo[2], out level); //return error if parameters are invalid if (!dataPointOk || !levelOk) { return(ExcelErrorUtil.ToComError(ExcelError.ExcelErrorNA)); //incorrect level or datapoint request } if (level > 9 || level < 0) { return(ExcelErrorUtil.ToComError(ExcelError.ExcelErrorNA)); //level out of range } //store subscription request //--- //if product has not yet been subscribed, create subscription container if (!_topics.ContainsKey(product)) { _topics[product] = new TopicCollection(); } //store subscription request _topics[product].TopicItems[Tuple.Create(dataPoint, level)] = topic; if (_topicDetails.ContainsKey(topicId)) { Logging.Log("ERROR: duplicate topicId: {0} {1}", topicId, _topicDetails[topicId]); } _topicDetails.Add(topicId, new TopicSubscriptionDetails(product, dataPoint, level)); //return data //-- if (dataPoint == DataPoint.Last) { if (!_cache.Instruments.ContainsKey(product)) { //may be empty when sheet is first loaded result = ExcelErrorUtil.ToComError(ExcelError.ExcelErrorGettingData); //return "pending data" to Excel } else { //get data from cache BitMexInstrument inst = _cache.Instruments[product]; switch (dataPoint) { case DataPoint.Last: result = inst.lastPrice; break; default: result = ExcelErrorUtil.ToComError(ExcelError.ExcelErrorNA); break; } } } else //bid/ask etc { if (!_cache.MarketData.ContainsKey(product)) { //if product is not yet in cache, request snapshot //this can happen if a product doesnt update very frequently _api.GetSnapshot(product); result = ExcelErrorUtil.ToComError(ExcelError.ExcelErrorGettingData); //return "pending data" to Excel } else { //get data from cache MarketDataSnapshot snap = _cache.MarketData[product]; switch (dataPoint) { case DataPoint.Bid: result = snap.BidDepth[level].Price; break; case DataPoint.BidVol: result = snap.BidDepth[level].Qty; break; case DataPoint.Ask: result = snap.AskDepth[level].Price; break; case DataPoint.AskVol: result = snap.AskDepth[level].Qty; break; default: result = ExcelErrorUtil.ToComError(ExcelError.ExcelErrorNA); break; } } } return(result); }
//New RTD subscription callback protected override object ConnectData(Topic topic, IList<string> topicInfo, ref bool newValues) { object result; int topicId = GetTopicId(topic); Logging.Log("ConnectData: {0} - {{{1}}}", topicId, string.Join(", ", topicInfo)); //parse and validate request //--- //count and default parameters if (topicInfo.Count < 2) return ExcelErrorUtil.ToComError(ExcelError.ExcelErrorNA); //need at least a product and a datapoint else if (topicInfo.Count == 2) topicInfo.Add("0"); //default to top level of book //parse parameters string product = topicInfo[0]; DataPoint dataPoint; bool dataPointOk = Enum.TryParse<DataPoint>(topicInfo[1], out dataPoint); int level; bool levelOk = Int32.TryParse(topicInfo[2], out level); //return error if parameters are invalid if(!dataPointOk || !levelOk) return ExcelErrorUtil.ToComError(ExcelError.ExcelErrorNA); //incorrect level or datapoint request if(level > 9 || level < 0) return ExcelErrorUtil.ToComError(ExcelError.ExcelErrorNA); //level out of range //store subscription request //--- //if product has not yet been subscribed, create subscription container if (!_topics.ContainsKey(product)) _topics[product] = new TopicCollection(); //store subscription request _topics[product].TopicItems[Tuple.Create(dataPoint, level)] = topic; if(_topicDetails.ContainsKey(topicId)) Logging.Log("ERROR: duplicate topicId: {0} {1}", topicId, _topicDetails[topicId]); _topicDetails.Add(topicId, new TopicSubscriptionDetails(product, dataPoint, level)); //return data //-- if(dataPoint == DataPoint.Last) { if (!_cache.Instruments.ContainsKey(product)) { //may be empty when sheet is first loaded result = ExcelErrorUtil.ToComError(ExcelError.ExcelErrorGettingData); //return "pending data" to Excel } else { //get data from cache BitMexInstrument inst = _cache.Instruments[product]; switch(dataPoint) { case DataPoint.Last: result = inst.lastPrice; break; default: result = ExcelErrorUtil.ToComError(ExcelError.ExcelErrorNA); break; } } } else //bid/ask etc { if (!_cache.MarketData.ContainsKey(product)) { //if product is not yet in cache, request snapshot //this can happen if a product doesnt update very frequently _api.GetSnapshot(product); result = ExcelErrorUtil.ToComError(ExcelError.ExcelErrorGettingData); //return "pending data" to Excel } else { //get data from cache MarketDataSnapshot snap = _cache.MarketData[product]; switch(dataPoint) { case DataPoint.Bid: result = snap.BidDepth[level].Price; break; case DataPoint.BidVol: result = snap.BidDepth[level].Qty; break; case DataPoint.Ask: result = snap.AskDepth[level].Price; break; case DataPoint.AskVol: result = snap.AskDepth[level].Qty; break; default: result = ExcelErrorUtil.ToComError(ExcelError.ExcelErrorNA); break; } } } return result; }