/// <summary>
        /// Deserialize JSON and raise <see cref="DepthUpdateEventArgs"/> event.
        /// </summary>
        /// <param name="json"></param>
        /// <param name="token"></param>
        /// <param name="callback"></param>
        protected override void DeserializeJsonAndRaiseEvent(string json, CancellationToken token, Action <DepthUpdateEventArgs> callback = null)
        {
            Throw.IfNullOrWhiteSpace(json, nameof(json));

            Logger?.LogDebug($"{nameof(DepthWebSocketClient)}: \"{json}\"");

            try
            {
                var jObject = JObject.Parse(json);

                var eventType = jObject["e"]?.Value <string>();

                DepthUpdateEventArgs eventArgs = null;

                if (eventType == null) // partial order book stream.
                {
                    // Simulate event time.
                    var eventTime = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();

                    var lastUpdateId = jObject["lastUpdateId"].Value <long>();

                    var bids = jObject["bids"].Select(entry => (entry[0].Value <decimal>(), entry[1].Value <decimal>())).ToList();
                    var asks = jObject["asks"].Select(entry => (entry[0].Value <decimal>(), entry[1].Value <decimal>())).ToList();

                    eventArgs = new DepthUpdateEventArgs(eventTime, token, Symbol, lastUpdateId, lastUpdateId, bids, asks);
                }
                else if (eventType == "depthUpdate")
                {
                    var symbol    = jObject["s"].Value <string>();
                    var eventTime = jObject["E"].Value <long>();

                    var firstUpdateId = jObject["U"].Value <long>();
                    var lastUpdateId  = jObject["u"].Value <long>();

                    var bids = jObject["b"].Select(entry => (entry[0].Value <decimal>(), entry[1].Value <decimal>())).ToList();
                    var asks = jObject["a"].Select(entry => (entry[0].Value <decimal>(), entry[1].Value <decimal>())).ToList();

                    eventArgs = new DepthUpdateEventArgs(eventTime, token, symbol, firstUpdateId, lastUpdateId, bids, asks);
                }
                else
                {
                    Logger?.LogWarning($"{nameof(DepthWebSocketClient)}.{nameof(DeserializeJsonAndRaiseEvent)}: Unexpected event type ({eventType}).");
                    return;
                }

                try
                {
                    callback?.Invoke(eventArgs);
                    DepthUpdate?.Invoke(this, eventArgs);
                }
                catch (OperationCanceledException) { }
                catch (Exception e)
                {
                    if (!token.IsCancellationRequested)
                    {
                        Logger?.LogError(e, $"{nameof(DepthWebSocketClient)}: Unhandled depth update event handler exception.");
                    }
                }
            }
            catch (OperationCanceledException) { }
            catch (Exception e)
            {
                if (!token.IsCancellationRequested)
                {
                    Logger?.LogError(e, $"{nameof(DepthWebSocketClient)}.{nameof(DeserializeJsonAndRaiseEvent)}");
                }
            }
        }
        protected override void OnWebSocketEvent(WebSocketStreamEventArgs args, IEnumerable <Action <DepthUpdateEventArgs> > callbacks)
        {
            Logger?.LogDebug($"{nameof(DepthWebSocketClient)}: \"{args.Json}\"");

            try
            {
                var jObject = JObject.Parse(args.Json);

                var eventType = jObject["e"]?.Value <string>();

                DepthUpdateEventArgs eventArgs;

                switch (eventType)
                {
                case null:     // partial depth stream.
                {
                    var symbol = args.StreamName.Split('@')[0].ToUpperInvariant();

                    // Simulate event time.
                    var eventTime = DateTime.UtcNow.ToTimestampK().ToDateTimeK();

                    var lastUpdateId = jObject["lastUpdateId"].Value <long>();

                    var bids = jObject["bids"].Select(entry => (entry[0].Value <decimal>(), entry[1].Value <decimal>())).ToArray();
                    var asks = jObject["asks"].Select(entry => (entry[0].Value <decimal>(), entry[1].Value <decimal>())).ToArray();

                    eventArgs = new DepthUpdateEventArgs(eventTime, args.Token, symbol, lastUpdateId, lastUpdateId, bids, asks);
                    break;
                }

                case "depthUpdate":
                {
                    var symbol    = jObject["s"].Value <string>();
                    var eventTime = jObject["E"].Value <long>().ToDateTimeK();

                    var firstUpdateId = jObject["U"].Value <long>();
                    var lastUpdateId  = jObject["u"].Value <long>();

                    var bids = jObject["b"].Select(entry => (entry[0].Value <decimal>(), entry[1].Value <decimal>())).ToArray();
                    var asks = jObject["a"].Select(entry => (entry[0].Value <decimal>(), entry[1].Value <decimal>())).ToArray();

                    eventArgs = new DepthUpdateEventArgs(eventTime, args.Token, symbol, firstUpdateId, lastUpdateId, bids, asks);
                    break;
                }

                default:
                    Logger?.LogWarning($"{nameof(DepthWebSocketClient)}.{nameof(OnWebSocketEvent)}: Unexpected event type ({eventType}).");
                    return;
                }

                try
                {
                    if (callbacks != null)
                    {
                        foreach (var callback in callbacks)
                        {
                            callback(eventArgs);
                        }
                    }
                    DepthUpdate?.Invoke(this, eventArgs);
                }
                catch (OperationCanceledException) { }
                catch (Exception e)
                {
                    if (!args.Token.IsCancellationRequested)
                    {
                        Logger?.LogError(e, $"{nameof(DepthWebSocketClient)}: Unhandled depth update event handler exception.");
                    }
                }
            }
            catch (OperationCanceledException) { }
            catch (Exception e)
            {
                if (!args.Token.IsCancellationRequested)
                {
                    Logger?.LogError(e, $"{nameof(DepthWebSocketClient)}.{nameof(OnWebSocketEvent)}");
                }
            }
        }
        protected override void HandleMessage(IEnumerable <Action <DepthUpdateEventArgs> > callbacks, string stream, string json)
        {
            try
            {
                var jObject = JObject.Parse(json);

                var eventType = jObject["e"]?.Value <string>();

                DepthUpdateEventArgs eventArgs;

                switch (eventType)
                {
                case null:     // partial depth stream.
                {
                    var symbol = stream.Split('@')[0].ToUpperInvariant();

                    // Simulate event time.
                    var eventTime = DateTime.UtcNow.ToTimestamp().ToDateTime();

                    var lastUpdateId = jObject["lastUpdateId"].Value <long>();

                    var bids = jObject["bids"].Select(entry => (entry[0].Value <decimal>(), entry[1].Value <decimal>())).ToArray();
                    var asks = jObject["asks"].Select(entry => (entry[0].Value <decimal>(), entry[1].Value <decimal>())).ToArray();

                    eventArgs = new DepthUpdateEventArgs(eventTime, symbol, lastUpdateId, lastUpdateId, bids, asks);
                    break;
                }

                case "depthUpdate":
                {
                    var symbol    = jObject["s"].Value <string>();
                    var eventTime = jObject["E"].Value <long>().ToDateTime();

                    var firstUpdateId = jObject["U"].Value <long>();
                    var lastUpdateId  = jObject["u"].Value <long>();

                    var bids = jObject["b"].Select(entry => (entry[0].Value <decimal>(), entry[1].Value <decimal>())).ToArray();
                    var asks = jObject["a"].Select(entry => (entry[0].Value <decimal>(), entry[1].Value <decimal>())).ToArray();

                    eventArgs = new DepthUpdateEventArgs(eventTime, symbol, firstUpdateId, lastUpdateId, bids, asks);
                    break;
                }

                default:
                    Logger?.LogWarning($"{nameof(DepthClient)}.{nameof(HandleMessage)}: Unexpected event type ({eventType}).");
                    return;
                }

                try
                {
                    if (callbacks != null)
                    {
                        foreach (var callback in callbacks)
                        {
                            callback(eventArgs);
                        }
                    }
                    DepthUpdate?.Invoke(this, eventArgs);
                }
                catch (OperationCanceledException) { /* ignore */ }
                catch (Exception e)
                {
                    Logger?.LogWarning(e, $"{nameof(DepthClient)}.{nameof(HandleMessage)}: Unhandled depth update event handler exception.");
                }
            }
            catch (OperationCanceledException) { /* ignore */ }
            catch (Exception e)
            {
                Logger?.LogError(e, $"{nameof(DepthClient)}.{nameof(HandleMessage)}");
            }
        }
Beispiel #4
0
        void exchangeConnection_GoxDepthHandlers(DepthUpdate depthUpdate)
        {
            try
            {
                if (depthUpdate.Currency != Currency.USD)
                {
                    return;
                }
                if (depthUpdate.Volume <= 0)
                {
                    return;
                }


                int idOrderType;
                if (depthUpdate.TypeString == "ask")
                {
                    if (depthUpdate.Price > (double)(2 * m_decLastPrice))
                    {
                        return;
                    }
                    if (depthUpdate.Volume < (double)0.02)
                    {
                        return;
                    }
                    idOrderType = 2;
                    lblAsk.Invoke((Action)(() =>
                    {
                        lblAsk.Text = depthUpdate.Price.ToString();
                    }));
                }
                else
                {
                    if (depthUpdate.Price < (double)(0.5 * (double)m_decLastPrice))
                    {
                        return;
                    }
                    if (depthUpdate.Volume < (double)0.02)
                    {
                        return;
                    }
                    idOrderType = 1;
                    lblBid.Invoke((Action)(() =>
                    {
                        lblBid.Text = depthUpdate.Price.ToString();
                    }));
                }

                lblLastResultOrder.Invoke((Action)(() =>
                {
                    lblLastResultOrder.Text = System.DateTime.Now.ToString("M/dd/yyyy hh:mm:ss tt");
                }));

                Decimal decPrice  = Convert.ToDecimal(depthUpdate.Price);
                Decimal decVolume = Convert.ToDecimal(depthUpdate.Volume);

                RecordBidAsk(decPrice, decVolume, idOrderType, depthUpdate.TimeStamp.ToString());

                int cBidAsk = Convert.ToInt16(lblBidAskCount.Text.Length == 0 ? "0" : lblBidAskCount.Text);

                ++cBidAsk;
                lblBidAskCount.Invoke((Action)(() =>
                {
                    lblBidAskCount.Text = cBidAsk.ToString();
                }));

                lblLastResult.Invoke((Action)(() =>
                {
                    lblLastResult.Text = System.DateTime.Now.ToString("M/dd/yyyy hh:mm:ss tt");
                }));
            }
            catch (Exception ex)
            {
                Logger.Logger.LogException(ex);
            }
        }