private ExchangeTicker ParseTicker(JToken token) { // [{ "TradePairId":100,"Label":"LTC/BTC","AskPrice":0.00006000,"BidPrice":0.02000000,"Low":0.00006000,"High":0.00006000,"Volume":1000.05639978,"LastPrice":0.00006000,"BuyVolume":34455.678,"SellVolume":67003436.37658233,"Change":-400.00000000,"Open": 0.00000500,"Close": 0.00000600, "BaseVolume": 3.58675866,"BaseBuyVolume": 11.25364758, "BaseSellVolume": 3456.06746543 }, ... ] var symbols = token["Label"].ToStringInvariant().Split('/'); ExchangeTicker ticker = new ExchangeTicker() { Id = token["TradePairId"].ToStringInvariant(), Ask = token["AskPrice"].ConvertInvariant <decimal>(), Bid = token["BidPrice"].ConvertInvariant <decimal>(), Last = token["LastPrice"].ConvertInvariant <decimal>(), // Since we're parsing a ticker for a market, we'll use the volume/baseVolume fields here and ignore the Buy/Sell Volumes // This is a quess as to ambiguous intent of these fields. Volume = new ExchangeVolume() { BaseSymbol = symbols[0], ConvertedSymbol = symbols[1], BaseVolume = token["Volume"].ConvertInvariant <decimal>(), ConvertedVolume = token["BaseVolume"].ConvertInvariant <decimal>(), Timestamp = DateTime.UtcNow // No TimeStamp is returned, but Now seems appropriate } }; return(ticker); }
protected override IWebSocket OnGetTickersWebSocket(Action <IReadOnlyCollection <KeyValuePair <string, ExchangeTicker> > > callback) { if (callback == null) { return(null); } Symbols = OnGetSymbolsMetadataAsync().GetAwaiter().GetResult(); symbolDict = Symbols.GroupBy(p => (p.MarketCurrency + p.BaseCurrency).ToLowerInvariant()).ToDictionary(k => k.Key, k => k.FirstOrDefault()); return(ConnectWebSocket(string.Empty, (msg, _socket) => { //消息返回事件 /* * {"id":"id1","status":"ok","subbed":"market.btcusdt.trade.detail","ts":1527574853489} * * * {{ * "ch": "market.btcusdt.trade.detail", * "ts": 1527574905759, * "tick": { * "id": 8232977476, * "ts": 1527574905623, * "data": [ * { * "amount": 0.3066, * "ts": 1527574905623, * "id": 82329774765058180723, * "price": 7101.81, * "direction": "buy" * } * ] * } * }} */ try { var freshTickers = new Dictionary <string, ExchangeTicker>(StringComparer.OrdinalIgnoreCase); var str = msg.UTF8StringFromGzip(); JToken token = JToken.Parse(str); if (token["status"] != null) { return; } else if (token["ping"] != null) { _socket.SendMessage(str.Replace("ping", "pong")); return; } var ch = token["ch"].ToStringInvariant(); var sArray = ch.Split('.'); var symbol = sArray[1]; var tickData = token["tick"]; var id = tickData["id"].ConvertInvariant <long>(); var ticks = tickData["data"]; string marketName = token["ch"].ToStringInvariant().Split('.')[1]; if (!symbolDict.ContainsKey(marketName)) { return; } foreach (JToken tick in ticks) { DateTime timestamp = CryptoUtility.UnixTimeStampToDateTimeMilliseconds(tick["ts"].ConvertInvariant <long>()); decimal last = tick["price"].ConvertInvariant <decimal>(); decimal volume = tick["amount"].ConvertInvariant <decimal>(); var t = new ExchangeTicker { Last = last, Volume = new ExchangeVolume { ConvertedVolume = volume, ConvertedSymbol = symbolDict[marketName].BaseCurrency, BaseSymbol = symbolDict[marketName].MarketCurrency, Timestamp = timestamp } }; freshTickers[marketName] = t; } callback(freshTickers); } catch { } }, (_socket) => { var symbols = GetSymbols().ToArray(); foreach (string symbol in symbols) { string normalizedSymbol = NormalizeSymbol(symbol); long id = Interlocked.Increment(ref webSocketId); string channel = $"market.{normalizedSymbol}.trade.detail"; string msg = $"{{\"sub\":\"{channel}\",\"id\":\"id{id}\"}}"; _socket.SendMessage(msg); } })); }
protected override IWebSocket OnGetTickersWebSocket(Action <IReadOnlyCollection <KeyValuePair <string, ExchangeTicker> > > callback) { if (callback == null) { return(null); } return(ConnectWebSocket(string.Empty, (msg, _socket) => { /* # Request # {'event':'addChannel','channel':'ok_sub_spot_bch_btc_ticker'} # Response # [ # { # "channel": "ok_sub_spot_bch_btc_ticker", # "data": { # "high": "10000", # "vol": "185.03743858", # "last": "111", # "low": "0.00000001", # "buy": "115", # "change": "101", # "sell": "115", # "dayLow": "0.00000001", # "dayHigh": "10000", # "timestamp": 1500444626000 # } # } # ] */ try { var freshTickers = new Dictionary <string, ExchangeTicker>(StringComparer.OrdinalIgnoreCase); JToken token = JToken.Parse(msg.UTF8String()); token = token[0]; var channel = token["channel"].ToStringInvariant(); if (channel.EqualsWithOption("addChannel")) { return; } var sArray = channel.Split('_'); var marketName = sArray[3] + "_" + sArray[4]; var tickData = token["data"]; DateTime timestamp = CryptoUtility.UnixTimeStampToDateTimeMilliseconds(tickData["timestamp"].ConvertInvariant <long>()); decimal last = tickData["last"].ConvertInvariant <decimal>(); decimal volume = tickData["vol"].ConvertInvariant <decimal>(); var t = new ExchangeTicker { Last = last, Volume = new ExchangeVolume { ConvertedVolume = volume, ConvertedSymbol = sArray[4].ToUpperInvariant(), BaseSymbol = sArray[3].ToUpperInvariant(), Timestamp = timestamp } }; freshTickers[marketName] = t; callback(freshTickers); } catch { } }, (_socket) => { var symbols = GetSymbols().ToArray(); foreach (string symbol in symbols) { string normalizedSymbol = NormalizeSymbol(symbol); string channel = $"ok_sub_spot_{normalizedSymbol}_ticker"; string msg = $"{{\'event\':\'addChannel\',\'channel\':\'{channel}\'}}"; _socket.SendMessage(msg); } })); }
protected override IWebSocket OnGetTickersWebSocket(Action <IReadOnlyCollection <KeyValuePair <string, ExchangeTicker> > > callback) { if (callback == null) { return(null); } Dictionary <int, string> channelIdToSymbol = new Dictionary <int, string>(); return(ConnectWebSocket(string.Empty, (msg, _socket) => { try { var timeStamp = DateTime.UtcNow; JToken token = JToken.Parse(msg.UTF8String()); Debug.WriteLine(token); if (token["type"].ToStringInvariant() == "hello") { /* * { * "type": "hello", * "ts": 1533027469340 * } */ var i = 1; } else if (token["type"].ToStringInvariant() == "topics") { /* * { * "id": "1", * "type": "topics", * "topics": [ * "ticker.btcusdt" * ] * } */ var j = 1; } else { /* * { * "ticker": [ * 8069.65, * 0.0061, * 8066.0, * 0.222, * 8069.65, * 0.0939, * 8165.27, * 8203.94, * 7860.01, * 84405.603216565, * 685600090.31904662 * ], * "type": "ticker.btcusdt", * "seq": 161002981 * } */ var tick = token["ticker"]; var symbol = token["type"].ToString().Split('.')[1]; List <KeyValuePair <string, ExchangeTicker> > tickerList = new List <KeyValuePair <string, ExchangeTicker> >(); ExchangeTicker ticker = ParseTickerWebSocket(symbol, tick); ticker.Volume.Timestamp = timeStamp; if (ticker != null) { callback(new KeyValuePair <string, ExchangeTicker>[] { new KeyValuePair <string, ExchangeTicker>(symbol, ticker) }); } } } catch (Exception ex) { Debug.WriteLine(ex.Message); } }, (_socket) => { var symbols = GetSymbols(); foreach (var symbol in symbols) { /* {"cmd":"sub","args":["depth.L100.btcusdt"],"id":"1"} */ long id = Interlocked.Increment(ref webSocketId); string channel = $"ticker.{symbol}"; string msg = $"{{\"cmd\":\"sub\",\"args\":[\"{channel.ToLowerInvariant()}\"],\"id\":\"{id}\"}}"; _socket.SendMessage(msg); } })); }
// working on it. Hitbtc has extensive support for sockets, including trading protected override IWebSocket OnGetTickersWebSocket(Action <IReadOnlyCollection <KeyValuePair <string, ExchangeTicker> > > callback) { if (callback == null) { return(null); } Dictionary <int, string> channelIdToSymbol = new Dictionary <int, string>(); return(ConnectWebSocket(string.Empty, (msg, _socket) => { try { var timeStamp = DateTime.UtcNow; JToken token = JToken.Parse(msg.UTF8String()); Debug.WriteLine(token); if (token["result"].ToStringInvariant() == "true") { /* * { * "jsonrpc": "2.0", * "result": true, * "id": 1 * } */ var i = 1; } else if (token["type"].ToStringInvariant() == "topics") { /* * { * "id": "1", * "type": "topics", * "topics": [ * "ticker.btcusdt" * ] * } */ var j = 1; } else if (token["method"].ToStringInvariant() == "ticker") { /* * { * "jsonrpc": "2.0", * "method": "ticker", * "params": { * "ask": "0.054464", * "bid": "0.054463", * "last": "0.054463", * "open": "0.057133", * "low": "0.053615", * "high": "0.057559", * "volume": "33068.346", * "volumeQuote": "1832.687530809", * "timestamp": "2017-10-19T15:45:44.941Z", * "symbol": "ETHBTC" * } * } */ var tick = token["params"]; var symbol = tick["symbol"].ToStringInvariant(); List <KeyValuePair <string, ExchangeTicker> > tickerList = new List <KeyValuePair <string, ExchangeTicker> >(); ExchangeTicker ticker = ParseTickerWebSocket(symbol, tick); if (ticker != null) { callback(new KeyValuePair <string, ExchangeTicker>[] { new KeyValuePair <string, ExchangeTicker>(symbol, ticker) }); } } } catch (Exception ex) { Debug.WriteLine(ex.Message); } }, (_socket) => { var symbols = GetSymbols(); foreach (var symbol in symbols) { /* { * "method": "subscribeTicker", * "params": { * "symbol": "ETHBTC" * }, * "id": 123 * } */ long id = Interlocked.Increment(ref webSocketId); string channel = $"{symbol}"; string msg = $"{{\"method\":\"subscribeTicker\",\"params\":{{\"symbol\":\"{channel}\"}},\"id\":{id}}}"; _socket.SendMessage(msg); } })); }
protected override IWebSocket OnGetTickersWebSocket(Action <IReadOnlyCollection <KeyValuePair <string, ExchangeTicker> > > callback) { if (callback == null) { return(null); } void innerCallback(string json) { #region sample json /* * { * Nonce : int, * Deltas : * [ * { * MarketName : string, * High : decimal, * Low : decimal, * Volume : decimal, * Last : decimal, * BaseVolume : decimal, * TimeStamp : date, * Bid : decimal, * Ask : decimal, * OpenBuyOrders : int, * OpenSellOrders : int, * PrevDay : decimal, * Created : date * } * ] * } */ #endregion var freshTickers = new Dictionary <string, ExchangeTicker>(StringComparer.OrdinalIgnoreCase); JToken token = JToken.Parse(json); token = token["D"]; foreach (JToken ticker in token) { string marketName = ticker["M"].ToStringInvariant(); decimal last = ticker["l"].ConvertInvariant <decimal>(); decimal ask = ticker["A"].ConvertInvariant <decimal>(); decimal bid = ticker["B"].ConvertInvariant <decimal>(); decimal volume = ticker["V"].ConvertInvariant <decimal>(); decimal baseVolume = ticker["m"].ConvertInvariant <decimal>(); DateTime timestamp = CryptoUtility.UnixTimeStampToDateTimeMilliseconds(ticker["T"].ConvertInvariant <long>()); var t = new ExchangeTicker { Ask = ask, Bid = bid, Last = last, Volume = new ExchangeVolume { ConvertedVolume = volume, ConvertedSymbol = marketName.Split('-')[0], BaseVolume = baseVolume, BaseSymbol = marketName.Split('-')[1], Timestamp = timestamp } }; freshTickers[marketName] = t; } callback(freshTickers); } var client = SocketManager; return(client.SubscribeToSummaryDeltas(innerCallback)); }