private List <ExchangeTrade> ParseTradesWebSocket(JToken token) { var trades = new List <ExchangeTrade>(); foreach (var t in token) { var ts = TimeSpan.Parse(t[3].ToStringInvariant()) + ChinaTimeOffset; if (ts < TimeSpan.FromHours(0)) { ts += TimeSpan.FromHours(24); } var dt = CryptoUtility.UtcNow.Date.Add(ts); var trade = new ExchangeTrade() { Id = t[0].ToStringInvariant(), Price = t[1].ConvertInvariant <decimal>(), Amount = t[2].ConvertInvariant <decimal>(), DateTime = dt, //todo: 这里处理方式有问题 IsBuy = t[4].ToStringInvariant().EqualsWithOption("bid"), }; trades.Add(trade); } return(trades); }
protected override IWebSocket GetTradesWebSocket(Action<ExchangeTrade> callback, params Symbol[] symbols) { Dictionary<int, string> channelIdToSymbol = new Dictionary<int, string>(); return ConnectWebSocket("/2", (_socket, msg) => //use websocket V2 (beta, but millisecond timestamp) { JToken token = JToken.Parse(msg.ToStringFromUTF8()); if (token is JArray array) { if (token[1].ToStringInvariant() == "hb") { // heartbeat } else if (token.Last.Last.HasValues == false) { //[29654, "tu", [270343572, 1532012917722, -0.003, 7465.636738]] "te"=temp/intention to execute "tu"=confirmed and ID is definitive //chan id, -- , [ID , timestamp , amount, price ]] if (channelIdToSymbol.TryGetValue(array[0].ConvertInvariant<int>(), out string symbol)) { if (token[1].ToStringInvariant() == "tu") { ExchangeTrade trade = ParseTradeWebSocket(token.Last); if (trade != null) { callback(new KeyValuePair<string, ExchangeTrade>(symbol, trade)); } } } } else { //parse snapshot here if needed } } else if (token["event"].ToStringInvariant() == "subscribed" && token["channel"].ToStringInvariant() == "trades") { //{"event": "subscribed","channel": "trades","chanId": 29654,"symbol": "tBTCUSD","pair": "BTCUSD"} int channelId = token["chanId"].ConvertInvariant<int>(); channelIdToSymbol[channelId] = token["pair"].ToStringInvariant(); } return Task.CompletedTask; }, async (_socket) => { foreach (var marketSymbol in symbols) { await _socket.SendMessageAsync(new { @event = "subscribe", channel = "trades", symbol = marketSymbol }); } }); }
/// <summary> /// Parse a trade /// </summary> /// <param name="token">Token</param> /// <param name="symbol"></param> /// <param name="formatter"></param> /// <returns>Trade</returns> internal static ExchangeTrade ParseTrade(this JToken token, Symbol symbol, TradeFormatter formatter) { DateTime date = token.ParseDatetime(formatter.TimestampFormatter); var trade = new ExchangeTrade { Symbol = symbol, Amount = token[formatter.AmountKey].ConvertInvariant <decimal>(), Price = token[formatter.PriceKey].ConvertInvariant <decimal>(), IsBuy = token[formatter.DirectionKey].ToStringInvariant().EqualsWithOption(formatter.DirectionIsBuyValue), DateTime = date }; trade.Id = formatter.IdKey == null ? trade.DateTime.Ticks.ToString() : token[formatter.IdKey].ToStringInvariant(); return(trade); }