private async void OnMatch(object sender, RealtimeMatch match)
 {
     if (await checkSequenceNumber(match.Sequence))
     {
         System.Windows.Application.Current.Dispatcher.Invoke(
             System.Windows.Threading.DispatcherPriority.Background,
             new Action(() =>
         {                   // change to UI thread
             var list = GetOrderList(side: match.Side);
             list.Item2.TryGetValue(match.Price.Value, out var linkedList);
             if (linkedList == null)
             {
                 return;                           // + handle when order is not in book (say program missed some orders being added)
             }
             var order = linkedList.Where(o => o.Id == match.MakerOrderId).SingleOrDefault();
             if (order != null)
             {
                 order.Size -= match.Size;
                 if (order.Size == 0)
                 {
                     RemoveOrder(match.MakerOrderId, side: match.Side);
                 }
                 if (order.Size < 0)
                 {
                     RemoveOrder(match.MakerOrderId, side: match.Side);
                 }
             }
         }));
     }
 }
        private void OnMatch(object sender, RealtimeMatch match)
        {
            var     side = match.Side;
            var     list = GetOrderList(side: side);
            decimal newPrice;

            lock (list.Item1)
            {
                list.Item2.TryGetValue(match.Price.Value, out var linkedList);
                if (linkedList == null)
                {
                    return;                         // handle when order is not in book (say program missed some orders being added)
                }
                var order = linkedList.First.Value; // first order in queue gets matched
                order.Size -= match.Size;
                newPrice    = order.Size;
            }
            if (newPrice == 0)
            {
                RemoveOrder(match.MakerOrderId, side: side);                 // keep outside of lock to avoid deadlock
            }
        }
示例#3
0
 private void OnMatch(object sender, RealtimeMatch e)
 {
     this.Price = e.Price.Value;
     PriceChanged?.Invoke(this, e.Price.Value);
 }
示例#4
0
        private static async void Subscribe(string product, Action <RealtimeMessage> onMessageReceived)
        {
            if (String.IsNullOrWhiteSpace(product))
            {
                throw new ArgumentNullException("product");
            }

            if (onMessageReceived == null)
            {
                throw new ArgumentNullException("onMessageReceived", "Message received callback must not be null.");
            }

            var uri               = new Uri("wss://ws-feed.exchange.coinbase.com");
            var webSocketClient   = new ClientWebSocket();
            var cancellationToken = new CancellationToken();
            var requestString     = String.Format(@"{{""type"": ""subscribe"",""product_id"": ""{0}""}}", product);
            var requestBytes      = UTF8Encoding.UTF8.GetBytes(requestString);
            await webSocketClient.ConnectAsync(uri, cancellationToken);

            if (webSocketClient.State == WebSocketState.Open)
            {
                var subscribeRequest      = new ArraySegment <byte>(requestBytes);
                var sendCancellationToken = new CancellationToken();
                await webSocketClient.SendAsync(subscribeRequest, WebSocketMessageType.Text, true, sendCancellationToken);

                while (webSocketClient.State == WebSocketState.Open)
                {
                    var receiveCancellationToken = new CancellationToken();
                    var receiveBuffer            = new ArraySegment <byte>(new byte[1024 * 1024 * 5]); // 5MB buffer
                    var webSocketReceiveResult   = await webSocketClient.ReceiveAsync(receiveBuffer, receiveCancellationToken);

                    if (webSocketReceiveResult.Count == 0)
                    {
                        continue;
                    }

                    var jsonResponse = Encoding.UTF8.GetString(receiveBuffer.Array, 0, webSocketReceiveResult.Count);
                    var jToken       = JToken.Parse(jsonResponse);

                    var typeToken = jToken["type"];
                    if (typeToken == null)
                    {
                        continue;
                    }

                    var             type            = typeToken.Value <string>();
                    RealtimeMessage realtimeMessage = null;

                    switch (type)
                    {
                    case "received":
                        realtimeMessage = new RealtimeReceived(jToken);
                        break;

                    case "open":
                        realtimeMessage = new RealtimeOpen(jToken);
                        break;

                    case "done":
                        realtimeMessage = new RealtimeDone(jToken);
                        break;

                    case "match":
                        realtimeMessage = new RealtimeMatch(jToken);
                        break;

                    case "change":
                        realtimeMessage = new RealtimeChange(jToken);
                        break;

                    default:
                        break;
                    }

                    if (realtimeMessage == null)
                    {
                        continue;
                    }

                    onMessageReceived(realtimeMessage);
                }
            }
        }
        private static async void Subscribe(string product, Action <RealtimeMessage> onMessageReceived)
        {
            if (String.IsNullOrWhiteSpace(product))
            {
                throw new ArgumentNullException("product");
            }

            if (onMessageReceived == null)
            {
                throw new ArgumentNullException("onMessageReceived", "Message received callback must not be null.");
            }
            JArray aj = new JArray();


            var uri               = new Uri("wss://ws-feed.gdax.com");
            var webSocketClient   = new ClientWebSocket();
            var cancellationToken = new CancellationToken();

            //jStr.Append()
            var requestString = string.Format("");

            //String.Format(@"{{""type"": ""subscribe"",""product_id"": ""{0}""}}", product);


            //JObject jObj = new JObject(
            //    new JProperty(
            //        "type", "subscribe"),
            //    new JProperty(
            //        "product_ids", new JArray(
            //        "BTC-USD")),
            //    new JProperty(
            //        "channels", new JArray(
            //        "level2", "heartbeat", new JObject(
            //            new JProperty(
            //                "name", "ticker"), new JProperty(
            //                    "product_ids", new JArray(
            //                        "BTC-USD"))))));

            //JObject jObj = new JObject(
            //    new JProperty(
            //        "type", "subscribe"),
            //    new JProperty(
            //        "product_ids", new JArray(
            //        "BTC-USD")),
            //    new JProperty(
            //        "channels", new JArray(
            //        "heartbeat", new JObject(
            //            new JProperty(
            //                "name", "ticker"), new JProperty(
            //                    "product_ids", new JArray(
            //                        "BTC-USD"))))));


            //JObject jObj = new JObject(
            //    new JProperty(
            //        "type", "subscribe"),
            //    new JProperty(
            //        "product_ids", new JArray(
            //        "BTC-USD")),
            //    new JProperty(
            //        "channels", new JArray(
            //        "matches", "heartbeat", new JObject(
            //            new JProperty(
            //                "name", "ticker"), new JProperty(
            //                    "product_ids", new JArray(
            //                        "BTC-USD"))))));


            JObject jObj = new JObject(
                new JProperty(
                    "type", "subscribe"),
                new JProperty(
                    "product_ids", new JArray(
                        "BTC-USD", product)),
                new JProperty(
                    "channels", new JArray(
                        "matches")));

            //Console.WriteLine(jObj.ToString());

            var requestBytes = UTF8Encoding.UTF8.GetBytes(jObj.ToString());
            await webSocketClient.ConnectAsync(uri, cancellationToken);

            if (webSocketClient.State == WebSocketState.Open)
            {
                var subscribeRequest      = new ArraySegment <byte>(requestBytes);
                var sendCancellationToken = new CancellationToken();
                await webSocketClient.SendAsync(subscribeRequest, WebSocketMessageType.Text, true, sendCancellationToken);

                while (webSocketClient.State == WebSocketState.Open)
                {
                    var receiveCancellationToken = new CancellationToken();
                    var receiveBuffer            = new ArraySegment <byte>(new byte[1024 * 1024 * 1]); // 5MB buffer 1024 * 1024 * 5
                    var webSocketReceiveResult   = await webSocketClient.ReceiveAsync(receiveBuffer, receiveCancellationToken);

                    if (webSocketReceiveResult.Count == 0)
                    {
                        continue;
                    }

                    var jsonResponse = Encoding.UTF8.GetString(receiveBuffer.Array, 0, webSocketReceiveResult.Count);
                    //var jToken = JToken.Parse(jsonResponse);
                    var jToken = JObject.Parse(jsonResponse);

                    var typeToken = jToken["type"];
                    if (typeToken == null)
                    {
                        continue;
                    }

                    var             type            = typeToken.Value <string>();
                    RealtimeMessage realtimeMessage = null;

                    //Console.WriteLine("MSG TYPE: {0}", type);

                    switch (type)
                    {
                    case "received":
                        realtimeMessage = new RealtimeReceived(jToken);
                        break;

                    case "open":
                        realtimeMessage = new RealtimeOpen(jToken);
                        break;

                    case "done":
                        realtimeMessage = new RealtimeDone(jToken);
                        break;

                    case "match":
                        realtimeMessage = new RealtimeMatch(jToken);
                        break;

                    case "change":
                        realtimeMessage = new RealtimeChange(jToken);
                        break;

                    default:
                        break;
                    }

                    if (realtimeMessage == null)
                    {
                        continue;
                    }

                    onMessageReceived(realtimeMessage);
                }
            }
        }
示例#6
0
        public async Task SubscribeAsync(bool reConnectOnDisconnect)
        {
            var uri = ExchangeClientBase.IsSandbox ? WSS_SANDBOX_ENDPOINT_URL : WSS_ENDPOINT_URL;

            if (_authContainer != null)             // authenticated feed
            {
                uri = new Uri(uri, "/users/self/verify");
            }
            cancellationTokenSource = new CancellationTokenSource();

            while (!cancellationTokenSource.IsCancellationRequested)
            {
                string disconnectReason = "";
                try
                {
                    webSocketClient = new ClientWebSocket();
                    await webSocketClient.ConnectAsync(uri, cancellationTokenSource.Token);

                    if (webSocketClient.State == System.Net.WebSockets.WebSocketState.Open && !cancellationTokenSource.IsCancellationRequested)
                    {
                        await rateGateRealtime.WaitToProceedAsync();                         // don't subscribe at too high of a rate
                        await sendSubscriptionMsgAsync(Products : Products, gdax_Channel : gdax_Channel);

                        // key is product name, value is whether connection was just opened
                        if (webSocketClient.State == System.Net.WebSockets.WebSocketState.Open && !cancellationTokenSource.IsCancellationRequested)
                        {                         // checking again bc maybe the server disconnected after the subscribe msg was sent
                                                  // + move to processing subscriptions section below later
                            foreach (var product in Products)
                            {
                                ConnectionOpened?.Invoke(product, gdax_Channel);
                            }
                        }
                        while (webSocketClient.State == System.Net.WebSockets.WebSocketState.Open && !cancellationTokenSource.IsCancellationRequested)
                        {
                            using (var timeoutCTS = new CancellationTokenSource(6500))                             // heartbeat every 1000 ms, so give it 5 hearbeat chances
                                using (var linkedTokenSource = CancellationTokenSource.CreateLinkedTokenSource(timeoutCTS.Token, cancellationTokenSource.Token))
                                    using (var stream = new MemoryStream(1024))
                                    {
                                        var  receiveBuffer = new ArraySegment <byte>(new byte[1024 * 8]);
                                        bool timedOut      = false;
                                        WebSocketReceiveResult webSocketReceiveResult;
                                        do
                                        {
                                            try
                                            {
                                                webSocketReceiveResult = await webSocketClient.ReceiveAsync(receiveBuffer, linkedTokenSource.Token);
                                            }
                                            catch (OperationCanceledException)
                                            {
                                                timedOut         = true;
                                                disconnectReason = " - stream timed out";
                                                break;
                                            }
                                            await stream.WriteAsync(receiveBuffer.Array, receiveBuffer.Offset, webSocketReceiveResult.Count, cancellationTokenSource.Token);
                                        } while (!webSocketReceiveResult.EndOfMessage && !cancellationTokenSource.IsCancellationRequested);

                                        if (!timedOut && !cancellationTokenSource.IsCancellationRequested)
                                        {
                                            var message       = stream.ToArray().Where(b => b != 0).ToArray();
                                            var messageString = Encoding.ASCII.GetString(message, 0, message.Length);
                                            if (!String.IsNullOrEmpty(messageString))
                                            {
                                                try
                                                {
                                                    var jToken = JToken.Parse(messageString);

                                                    var typeToken = jToken["type"];
                                                    if (typeToken == null)
                                                    {
                                                        RealtimeDataError?.Invoke(this, new RealtimeError("null typeToken: + " + Encoding.ASCII.GetString(message, 0, message.Length)));
                                                        return;                                         // go to next msg
                                                    }

                                                    var type = typeToken.Value <string>();
                                                    switch (type)
                                                    {
                                                    case "subscriptions":
                                                        // + process initial subscription confirmation
                                                        // + also for unsubscribe confirmation
                                                        break;

                                                    case "received":
                                                        var rr = new RealtimeReceived(jToken);
                                                        if (rr.Message != null)
                                                        {
                                                            RealtimeDataError?.Invoke(this, rr);
                                                        }
                                                        RealtimeReceived?.Invoke(this, rr);
                                                        break;

                                                    case "open":
                                                        var ro = new RealtimeOpen(jToken);
                                                        if (ro.Message != null)
                                                        {
                                                            RealtimeDataError?.Invoke(this, ro);
                                                        }
                                                        RealtimeOpen?.Invoke(this, ro);
                                                        break;

                                                    case "done":
                                                        var rd = new RealtimeDone(jToken);
                                                        if (rd.Message != null)
                                                        {
                                                            RealtimeDataError?.Invoke(this, rd);
                                                        }
                                                        RealtimeDone?.Invoke(this, rd);
                                                        break;

                                                    case "match":
                                                        var rm = new RealtimeMatch(jToken);
                                                        if (rm.Message != null)
                                                        {
                                                            RealtimeDataError?.Invoke(this, rm);
                                                        }
                                                        RealtimeMatch?.Invoke(this, rm);
                                                        break;

                                                    case "last_match":
                                                        var rlm = new RealtimeMatch(jToken);
                                                        if (rlm.Message != null)
                                                        {
                                                            RealtimeDataError?.Invoke(this, rlm);
                                                        }
                                                        RealtimeLastMatch?.Invoke(this, rlm);
                                                        break;

                                                    case "change":
                                                        var rc = new RealtimeChange(jToken);
                                                        if (rc.Message != null)
                                                        {
                                                            RealtimeDataError?.Invoke(this, rc);
                                                        }
                                                        RealtimeChange?.Invoke(this, rc);
                                                        break;

                                                    case "heartbeat":
                                                        // + should implement this (checking LastTraderId)
                                                        var hb = new Heartbeat(jToken);
                                                        Heartbeat?.Invoke(this, hb);
                                                        break;

                                                    case "error":
                                                        RealtimeDataError?.Invoke(this, new RealtimeError(jToken));
                                                        break;

                                                    default:
                                                        RealtimeDataError?.Invoke(this, new RealtimeError("Unexpected type: " + jToken));
                                                        break;
                                                    }
                                                }
                                                catch (JsonReaderException e)
                                                {
                                                    RealtimeDataError?.Invoke(this, new RealtimeError(
                                                                                  "JsonReaderException: " + e.Message + ":" + messageString));
                                                }
                                            }
                                            else
                                            {
                                                RealtimeDataError?.Invoke(this, new RealtimeError("empty message received. Connection state: "
                                                                                                  + webSocketClient.State + ", linkedToken: " + linkedTokenSource.Token.IsCancellationRequested));
                                            }
                                        }
                                    }
                        }
                    }
                }
                catch (Exception e)
                {
                    if (e.Message == "The remote party closed the WebSocket connection without completing the close handshake.")                     // System.Net.WebSockets.WebSocketException
                    {
                        disconnectReason = " - remote closed the WebSocket w/o completing the close handshake";
                    }
                    else if (e.Message == "Unable to connect to the remote server") // System.Net.WebSockets.WebSocketException
                    {
                        disconnectReason = " - unable to connect to server";        // shorten it a bit
                        await Task.Delay(10000);                                    // if unable to connect, then wait 10 seconds before trying to connect again
                    }
                    else
                    {
                        RealtimeStreamError?.Invoke(this, new RealtimeError("other exception caught: " + e.GetType() + " : " + e.Message));
                    }
                }
                if (!reConnectOnDisconnect)
                {
                    UnSubscribe();
                }
                foreach (var product in Products)
                {
                    RealtimeStreamError?.Invoke(this, new RealtimeError("disconnected" + disconnectReason));
                    ConnectionClosed?.Invoke(product, gdax_Channel);
                }
                if (!reConnectOnDisconnect)
                {
                    break;
                }
            }
        }
        private static async void Subscribe(string product, Action<RealtimeMessage> onMessageReceived)
        {
            if (String.IsNullOrWhiteSpace(product))
                throw new ArgumentNullException("product");

            if (onMessageReceived == null)
                throw new ArgumentNullException("onMessageReceived", "Message received callback must not be null.");

            var uri = new Uri("wss://ws-feed.exchange.coinbase.com");
            var webSocketClient = new ClientWebSocket();
            var cancellationToken = new CancellationToken();
            var requestString = String.Format(@"{{""type"": ""subscribe"",""product_id"": ""{0}""}}", product);
            var requestBytes = UTF8Encoding.UTF8.GetBytes(requestString);
            await webSocketClient.ConnectAsync(uri, cancellationToken);

            if (webSocketClient.State == WebSocketState.Open)
            {
                var subscribeRequest = new ArraySegment<byte>(requestBytes);
                var sendCancellationToken = new CancellationToken();
                await webSocketClient.SendAsync(subscribeRequest, WebSocketMessageType.Text, true, sendCancellationToken);

                while (webSocketClient.State == WebSocketState.Open)
                {
                    var receiveCancellationToken = new CancellationToken();
                    var receiveBuffer = new ArraySegment<byte>(new byte[1024 * 1024 * 5]); // 5MB buffer
                    var webSocketReceiveResult = await webSocketClient.ReceiveAsync(receiveBuffer, receiveCancellationToken);
                    if (webSocketReceiveResult.Count == 0) continue;

                    var jsonResponse = Encoding.UTF8.GetString(receiveBuffer.Array, 0, webSocketReceiveResult.Count);
                    var jToken = JToken.Parse(jsonResponse);

                    var typeToken = jToken["type"];
                    if (typeToken == null) continue;

                    var type = typeToken.Value<string>();
                    RealtimeMessage realtimeMessage = null;

                    switch (type)
                    {
                        case "received":
                            realtimeMessage = new RealtimeReceived(jToken);
                            break;
                        case "open":
                            realtimeMessage = new RealtimeOpen(jToken);
                            break;
                        case "done":
                            realtimeMessage = new RealtimeDone(jToken);
                            break;
                        case "match":
                            realtimeMessage = new RealtimeMatch(jToken);
                            break;
                        case "change":
                            realtimeMessage = new RealtimeChange(jToken);
                            break;
                        default:
                            break;
                    }

                    if (realtimeMessage == null)
                        continue;

                    onMessageReceived(realtimeMessage);
                }
            }
        }
 private async void OnLastMatch(object sender, RealtimeMatch lastMatch)
 {
     await checkSequenceNumber(lastMatch.Sequence);
 }