Exemplo n.º 1
0
        protected override void HandleMessage(IEnumerable <Action <UserDataEventArgs> > callbacks, string stream, string json)
        {
            if (!Users.ContainsKey(stream))
            {
                Logger?.LogError($"{nameof(UserDataClient)}.{nameof(HandleMessage)}: Unknown listen key (\"{stream}\").  [thread: {Thread.CurrentThread.ManagedThreadId}]");
                return; // ignore.
            }

            var user = Users[stream];

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

                var eventType = jObject["e"].Value <string>();
                var eventTime = jObject["E"].Value <long>().ToDateTime();

                // ReSharper disable once ConvertIfStatementToSwitchStatement
                if (eventType == "outboundAccountInfo")
                {
                    var commissions = new AccountCommissions(
                        jObject["m"].Value <int>(),  // maker
                        jObject["t"].Value <int>(),  // taker
                        jObject["b"].Value <int>(),  // buyer
                        jObject["s"].Value <int>()); // seller

                    var status = new AccountStatus(
                        jObject["T"].Value <bool>(),  // can trade
                        jObject["W"].Value <bool>(),  // can withdraw
                        jObject["D"].Value <bool>()); // can deposit

                    var balances = jObject["B"]
                                   .Select(entry => new AccountBalance(
                                               entry["a"].Value <string>(),   // asset
                                               entry["f"].Value <decimal>(),  // free amount
                                               entry["l"].Value <decimal>())) // locked amount
                                   .ToList();

                    var eventArgs = new AccountUpdateEventArgs(eventTime, new AccountInfo(user, commissions, status, jObject["u"].Value <long>().ToDateTime(), balances));

                    try
                    {
                        // ReSharper disable once InconsistentlySynchronizedField
                        if (_accountUpdateSubscribers.TryGetValue(stream, out var subscribers))
                        {
                            foreach (var subcriber in subscribers)
                            {
                                subcriber(eventArgs);
                            }
                        }

                        if (callbacks != null)
                        {
                            foreach (var callback in callbacks)
                            {
                                callback(eventArgs);
                            }
                        }

                        AccountUpdate?.Invoke(this, eventArgs);
                    }
                    catch (OperationCanceledException) { /* ignore */ }
                    catch (Exception e)
                    {
                        Logger?.LogWarning(e, $"{nameof(UserDataClient)}.{nameof(HandleMessage)}: Unhandled account update event handler exception.");
                    }
                }
                else if (eventType == "executionReport")
                {
                    var order = new Order(user);

                    FillOrder(order, jObject);

                    var executionType    = ConvertOrderExecutionType(jObject["x"].Value <string>());
                    var rejectedReason   = jObject["r"].Value <string>();
                    var newClientOrderId = jObject["c"].Value <string>();

                    if (executionType == OrderExecutionType.Trade) // trade update event.
                    {
                        var trade = new AccountTrade(
                            jObject["s"].Value <string>(),  // symbol
                            jObject["t"].Value <long>(),    // ID
                            jObject["i"].Value <long>(),    // order ID
                            jObject["L"].Value <decimal>(), // price (price of last filled trade)
                            jObject["z"].Value <decimal>(), // quantity (accumulated quantity of filled trades)
                            jObject["n"].Value <decimal>(), // commission
                            jObject["N"].Value <string>(),  // commission asset
                            jObject["T"].Value <long>()
                            .ToDateTime(),                  // time
                            order.Side == OrderSide.Buy,    // is buyer
                            jObject["m"].Value <bool>(),    // is buyer maker
                            jObject["M"].Value <bool>());   // is best price

                        var quantityOfLastFilledTrade = jObject["l"].Value <decimal>();

                        var eventArgs = new AccountTradeUpdateEventArgs(eventTime, order, rejectedReason, newClientOrderId, trade, quantityOfLastFilledTrade);

                        try
                        {
                            // ReSharper disable once InconsistentlySynchronizedField
                            if (_accountTradeUpdateSubscribers.TryGetValue(stream, out var subscribers))
                            {
                                foreach (var subcriber in subscribers)
                                {
                                    subcriber(eventArgs);
                                }
                            }

                            if (callbacks != null)
                            {
                                foreach (var callback in callbacks)
                                {
                                    callback(eventArgs);
                                }
                            }

                            TradeUpdate?.Invoke(this, eventArgs);
                        }
                        catch (OperationCanceledException) { /* ignore */ }
                        catch (Exception e)
                        {
                            Logger?.LogWarning(e, $"{nameof(UserDataClient)}.{nameof(HandleMessage)}: Unhandled trade update event handler exception.");
                        }
                    }
                    else // order update event.
                    {
                        var eventArgs = new OrderUpdateEventArgs(eventTime, order, executionType, rejectedReason, newClientOrderId);

                        try
                        {
                            // ReSharper disable once InconsistentlySynchronizedField
                            if (_orderUpdateSubscribers.TryGetValue(stream, out var subscribers))
                            {
                                foreach (var subcriber in subscribers)
                                {
                                    subcriber(eventArgs);
                                }
                            }

                            if (callbacks != null)
                            {
                                foreach (var callback in callbacks)
                                {
                                    callback(eventArgs);
                                }
                            }

                            OrderUpdate?.Invoke(this, eventArgs);
                        }
                        catch (OperationCanceledException) { /* ignore */ }
                        catch (Exception e)
                        {
                            Logger?.LogWarning(e, $"{nameof(UserDataClient)}.{nameof(HandleMessage)}: Unhandled order update event handler exception.");
                        }
                    }
                }
                else
                {
                    Logger?.LogWarning($"{nameof(UserDataClient)}.{nameof(HandleMessage)}: Unexpected event type ({eventType}).");
                }
            }
            catch (OperationCanceledException) { /* ignore */ }
            catch (Exception e)
            {
                Logger?.LogError(e, $"{nameof(UserDataClient)}.{nameof(HandleMessage)}");
            }
        }
Exemplo n.º 2
0
        /// <summary>
        /// Deserialize JSON and raise <see cref="UserDataEventArgs"/> event.
        /// </summary>
        /// <param name="json"></param>
        /// <param name="token"></param>
        /// <param name="callback"></param>
        /// <returns></returns>
        protected override void DeserializeJsonAndRaiseEvent(string json, CancellationToken token, Action <UserDataEventArgs> callback = null)
        {
            Throw.IfNullOrWhiteSpace(json, nameof(json));

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

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

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

                // ReSharper disable once ConvertIfStatementToSwitchStatement
                if (eventType == "outboundAccountInfo")
                {
                    var commissions = new AccountCommissions(
                        jObject["m"].Value <int>(),  // maker
                        jObject["t"].Value <int>(),  // taker
                        jObject["b"].Value <int>(),  // buyer
                        jObject["s"].Value <int>()); // seller

                    var status = new AccountStatus(
                        jObject["T"].Value <bool>(),  // can trade
                        jObject["W"].Value <bool>(),  // can withdraw
                        jObject["D"].Value <bool>()); // can deposit

                    var balances = jObject["B"]
                                   .Select(entry => new AccountBalance(
                                               entry["a"].Value <string>(),   // asset
                                               entry["f"].Value <decimal>(),  // free amount
                                               entry["l"].Value <decimal>())) // locked amount
                                   .ToList();

                    var eventArgs = new AccountUpdateEventArgs(eventTime, token, new AccountInfo(User, commissions, status, jObject["u"].Value <long>(), balances));

                    try
                    {
                        callback?.Invoke(eventArgs);
                        AccountUpdate?.Invoke(this, eventArgs);
                    }
                    catch (OperationCanceledException) { }
                    catch (Exception e)
                    {
                        if (!token.IsCancellationRequested)
                        {
                            Logger?.LogError(e, $"{nameof(UserDataWebSocketClient)}: Unhandled account update event handler exception.");
                        }
                    }
                }
                else if (eventType == "executionReport")
                {
                    var order = new Order(User);

                    FillOrder(order, jObject);

                    var executionType    = ConvertOrderExecutionType(jObject["x"].Value <string>());
                    var rejectedReason   = ConvertOrderRejectedReason(jObject["r"].Value <string>());
                    var newClientOrderId = jObject["c"].Value <string>();

                    if (executionType == OrderExecutionType.Trade) // trade update event.
                    {
                        var trade = new AccountTrade(
                            jObject["s"].Value <string>(),  // symbol
                            jObject["t"].Value <long>(),    // ID
                            jObject["i"].Value <long>(),    // order ID
                            jObject["L"].Value <decimal>(), // price (price of last filled trade)
                            jObject["z"].Value <decimal>(), // quantity (accumulated quantity of filled trades)
                            jObject["n"].Value <decimal>(), // commission
                            jObject["N"].Value <string>(),  // commission asset
                            jObject["T"].Value <long>(),    // timestamp
                            order.Side == OrderSide.Buy,    // is buyer
                            jObject["m"].Value <bool>(),    // is buyer maker
                            jObject["M"].Value <bool>());   // is best price

                        var quantityOfLastFilledTrade = jObject["l"].Value <decimal>();

                        var eventArgs = new AccountTradeUpdateEventArgs(eventTime, token, order, rejectedReason, newClientOrderId, trade, quantityOfLastFilledTrade);

                        try
                        {
                            callback?.Invoke(eventArgs);
                            TradeUpdate?.Invoke(this, eventArgs);
                        }
                        catch (OperationCanceledException) { }
                        catch (Exception e)
                        {
                            if (!token.IsCancellationRequested)
                            {
                                Logger?.LogError(e, $"{nameof(UserDataWebSocketClient)}: Unhandled trade update event handler exception.");
                            }
                        }
                    }
                    else // order update event.
                    {
                        var eventArgs = new OrderUpdateEventArgs(eventTime, token, order, executionType, rejectedReason, newClientOrderId);

                        try
                        {
                            callback?.Invoke(eventArgs);
                            OrderUpdate?.Invoke(this, eventArgs);
                        }
                        catch (OperationCanceledException) { }
                        catch (Exception e)
                        {
                            if (!token.IsCancellationRequested)
                            {
                                Logger?.LogError(e, $"{nameof(UserDataWebSocketClient)}: Unhandled order update event handler exception.");
                            }
                        }
                    }
                }
                else
                {
                    Logger?.LogWarning($"{nameof(UserDataWebSocketClient)}.{nameof(DeserializeJsonAndRaiseEvent)}: Unexpected event type ({eventType}) - \"{json}\"");
                }
            }
            catch (OperationCanceledException) { }
            catch (Exception e)
            {
                if (!token.IsCancellationRequested)
                {
                    Logger?.LogError(e, $"{nameof(UserDataWebSocketClient)}.{nameof(DeserializeJsonAndRaiseEvent)}");
                }
            }
        }
Exemplo n.º 3
0
        private void ProcessOrderUpdateMessage(string msg)
        {
            var orderAddUpdateSummaryMessage = OrderAddUpdateSummaryMessage.Parse(msg);

            OrderUpdate?.Invoke(orderAddUpdateSummaryMessage);
        }