Beispiel #1
0
        //callback from the background websocket thread. Checks and updates any matching topics.
        void _api_OnDataUpdate(object sender, MarketDataSnapshot snap)
        {
            //update data cache
            _cache.MarketData[snap.Product] = snap;

            //no current subscription for this product
            if (!_topics.ContainsKey(snap.Product))
            {
                return;
            }

            Dictionary <Tuple <DataPoint, int>, Topic> productTopics = _topics[snap.Product].TopicItems;

            //iterate down the depth on the bid side, updating any currently subscribed topics
            for (int level = 0; level < snap.BidDepth.Count; level++)
            {
                //update bid
                Tuple <DataPoint, int> key = Tuple.Create(DataPoint.Bid, level);
                if (productTopics.ContainsKey(key))
                {
                    productTopics[key].UpdateValue(snap.BidDepth[level].Price);
                }

                //update bidvol
                key = Tuple.Create(DataPoint.BidVol, level);
                if (productTopics.ContainsKey(key))
                {
                    productTopics[key].UpdateValue(snap.BidDepth[level].Qty);
                }
            }

            //iterate down the depth on the ask side, updating any currently subscribed topics
            for (int level = 0; level < snap.AskDepth.Count; level++)
            {
                //update ask
                Tuple <DataPoint, int> key = Tuple.Create(DataPoint.Ask, level);
                if (productTopics.ContainsKey(key))
                {
                    productTopics[key].UpdateValue(snap.AskDepth[level].Price);
                }

                //update askvol
                key = Tuple.Create(DataPoint.AskVol, level);
                if (productTopics.ContainsKey(key))
                {
                    productTopics[key].UpdateValue(snap.AskDepth[level].Qty);
                }
            }
        }
        private void ProcessDepthSnapshot(string data)
        {
            try
            {
                BitMexStreamDepthSnap depth = JSON.ToObject <BitMexStreamDepthSnap>(data);

                if (depth.data.Count != 1)
                {
                    Logging.Log("BitMexHandler missing depth snap data");
                    return;
                }
                BitMexDepthCache info   = depth.data[0];
                string           symbol = info.symbol;

                //parse into snapshot
                MarketDataSnapshot snap = new MarketDataSnapshot(symbol);

                foreach (object[] bid in info.bids)
                {
                    decimal price  = Convert.ToDecimal(bid[0]);
                    int     rawQty = Convert.ToInt32(bid[1]);
                    snap.BidDepth.Add(new MarketDepth(price, rawQty));
                }

                foreach (object[] ask in info.asks)
                {
                    decimal price  = Convert.ToDecimal(ask[0]);
                    int     rawQty = Convert.ToInt32(ask[1]);
                    snap.AskDepth.Add(new MarketDepth(price, rawQty));
                }

                //notify listeners
                if (OnDepthUpdate != null)
                {
                    OnDepthUpdate(null, snap);
                }
            }
            catch (Exception ex)
            {
                Logging.Log("BitMexHandler Depth {0}", ex.Message);
            }
        }
Beispiel #3
0
        //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);
        }
Beispiel #4
0
        //callback from the background websocket thread. Checks and updates any matching topics.
        void _api_OnDataUpdate(object sender, MarketDataSnapshot snap)
        {
            //update data cache
            _cache.MarketData[snap.Product] = snap;

            //no current subscription for this product
            if (!_topics.ContainsKey(snap.Product))
                return;

            Dictionary<Tuple<DataPoint, int>, Topic> productTopics = _topics[snap.Product].TopicItems;

            //iterate down the depth on the bid side, updating any currently subscribed topics
            for (int level = 0; level < snap.BidDepth.Count; level++)
            {
                //update bid
                Tuple<DataPoint, int> key = Tuple.Create(DataPoint.Bid, level);
                if (productTopics.ContainsKey(key))
                    productTopics[key].UpdateValue(snap.BidDepth[level].Price);

                //update bidvol
                key = Tuple.Create(DataPoint.BidVol, level);
                if (productTopics.ContainsKey(key))
                    productTopics[key].UpdateValue(snap.BidDepth[level].Qty);
            }

            //iterate down the depth on the ask side, updating any currently subscribed topics
            for (int level = 0; level < snap.AskDepth.Count; level++)
            {
                //update ask
                Tuple<DataPoint, int> key = Tuple.Create(DataPoint.Ask, level);
                if (productTopics.ContainsKey(key))
                    productTopics[key].UpdateValue(snap.AskDepth[level].Price);

                //update askvol
                key = Tuple.Create(DataPoint.AskVol, level);
                if (productTopics.ContainsKey(key))
                    productTopics[key].UpdateValue(snap.AskDepth[level].Qty);
            }
        }
Beispiel #5
0
        private void ProcessDepth(string data)
        {
            try
            {
                BitMexStreamDepth depth = JSON.ToObject<BitMexStreamDepth>(data);

                if (depth.data.Count <= 0)
                    return;

                string symbol = depth.data[0].symbol;

                //create cache container if not already available
                MarketDataSnapshot snap = new MarketDataSnapshot(symbol);

                //normally returns "partial" on response to getSymbol
                if( depth.action.Equals("partial"))
                {
                    foreach (BitMexDepth info in depth.data)
                    {
                        int level = info.level;

                        //extend depth if new levels added
                        if ((info.bidPrice.HasValue || info.bidSize.HasValue) && snap.BidDepth.Count < level + 1)
                            for (int i = snap.BidDepth.Count; i < level + 1; i++)
                                snap.BidDepth.Add(new MarketDepth());

                        if ((info.askPrice.HasValue || info.askSize.HasValue) && snap.AskDepth.Count < level + 1)
                            for (int i = snap.AskDepth.Count; i < level + 1; i++)
                                snap.AskDepth.Add(new MarketDepth());

                        //update values, or blank out if values are null
                        if (info.bidPrice.HasValue || info.bidSize.HasValue)
                        {
                            if (info.bidPrice.HasValue)
                                snap.BidDepth[level].Price = info.bidPrice.Value;

                            if (info.bidSize.HasValue)
                                snap.BidDepth[level].Qty = info.bidSize.Value;
                        }

                        if (info.askPrice.HasValue || info.askSize.HasValue)
                        {
                            if (info.askPrice.HasValue)
                                snap.AskDepth[level].Price = info.askPrice.Value;

                            if (info.askSize.HasValue)
                                snap.AskDepth[level].Qty = info.askSize.Value;
                        }
                    }

                    //notify listeners
                    if (OnDepthUpdate != null)
                        OnDepthUpdate(null, snap);
                }

            }
            catch (Exception ex)
            {
                Logging.Log("BitMexHandler Depth", ex);
            }

        }
Beispiel #6
0
        private void ProcessDepthSnapshot(string data)
        {
            try
            {
                BitMexStreamDepthSnap depth = JSON.ToObject<BitMexStreamDepthSnap>(data);

                if (depth.data.Count != 1)
                {
                    Logging.Log("BitMexHandler missing depth snap data");
                    return;
                }
                BitMexDepthCache info = depth.data[0];
                string symbol = info.symbol;

                //parse into snapshot
                MarketDataSnapshot snap = new MarketDataSnapshot(symbol);

                foreach (object[] bid in info.bids)
                {
                    decimal price = Convert.ToDecimal(bid[0]);
                    int rawQty = Convert.ToInt32(bid[1]);
                    snap.BidDepth.Add(new MarketDepth(price, rawQty));
                }

                foreach (object[] ask in info.asks)
                {
                    decimal price = Convert.ToDecimal(ask[0]);
                    int rawQty = Convert.ToInt32(ask[1]);
                    snap.AskDepth.Add(new MarketDepth(price, rawQty));
                }

                //notify listeners
                if(OnDepthUpdate != null)
                    OnDepthUpdate(null, snap);

            }
            catch (Exception ex)
            {
                Logging.Log("BitMexHandler Depth {0}", ex.Message);
            }
        }
        private void ProcessDepth(string data)
        {
            try
            {
                BitMexStreamDepth depth = JSON.ToObject <BitMexStreamDepth>(data);

                if (depth.data.Count <= 0)
                {
                    return;
                }

                string symbol = depth.data[0].symbol;

                //create cache container if not already available
                MarketDataSnapshot snap = new MarketDataSnapshot(symbol);

                //normally returns "partial" on response to getSymbol
                if (depth.action.Equals("partial"))
                {
                    foreach (BitMexDepth info in depth.data)
                    {
                        int level = info.level;

                        //extend depth if new levels added
                        if ((info.bidPrice.HasValue || info.bidSize.HasValue) && snap.BidDepth.Count < level + 1)
                        {
                            for (int i = snap.BidDepth.Count; i < level + 1; i++)
                            {
                                snap.BidDepth.Add(new MarketDepth());
                            }
                        }

                        if ((info.askPrice.HasValue || info.askSize.HasValue) && snap.AskDepth.Count < level + 1)
                        {
                            for (int i = snap.AskDepth.Count; i < level + 1; i++)
                            {
                                snap.AskDepth.Add(new MarketDepth());
                            }
                        }

                        //update values, or blank out if values are null
                        if (info.bidPrice.HasValue || info.bidSize.HasValue)
                        {
                            if (info.bidPrice.HasValue)
                            {
                                snap.BidDepth[level].Price = info.bidPrice.Value;
                            }

                            if (info.bidSize.HasValue)
                            {
                                snap.BidDepth[level].Qty = info.bidSize.Value;
                            }
                        }

                        if (info.askPrice.HasValue || info.askSize.HasValue)
                        {
                            if (info.askPrice.HasValue)
                            {
                                snap.AskDepth[level].Price = info.askPrice.Value;
                            }

                            if (info.askSize.HasValue)
                            {
                                snap.AskDepth[level].Qty = info.askSize.Value;
                            }
                        }
                    }

                    //notify listeners
                    if (OnDepthUpdate != null)
                    {
                        OnDepthUpdate(null, snap);
                    }
                }
            }
            catch (Exception ex)
            {
                Logging.Log("BitMexHandler Depth", ex);
            }
        }