Beispiel #1
0
        public void Properties()
        {
            var user        = new BinanceApiUser("api-key");
            var commissions = new AccountCommissions(10, 10, 0, 0);
            var status      = new AccountStatus(true, true, true);
            var time        = DateTimeOffset.FromUnixTimeMilliseconds(DateTime.UtcNow.ToTimestamp()).UtcDateTime;
            var balances    = new[] { new AccountBalance("BTC", 0.1m, 0.2m) };

            var account = new AccountInfo(user, commissions, status, time);

            Assert.Equal(commissions, account.Commissions);
            Assert.Equal(status, account.Status);
            Assert.Equal(time, account.Time);
            Assert.NotNull(account.Balances);
            Assert.Empty(account.Balances);

            account = new AccountInfo(user, commissions, status, time, balances);

            Assert.Equal(commissions, account.Commissions);
            Assert.Equal(status, account.Status);
            Assert.Equal(time, account.Time);
            Assert.NotNull(account.Balances);
            Assert.NotEmpty(account.Balances);
            Assert.Equal(balances[0].Asset, account.Balances.First().Asset);
        }
Beispiel #2
0
        public void Properties()
        {
            var  user        = new BinanceApiUser("api-key");
            var  commissions = new AccountCommissions(10, 10, 0, 0);
            var  status      = new AccountStatus(true, true, true);
            long updateTime  = 1234567890;
            var  balances    = new[] { new AccountBalance("BTC", 0.1m, 0.2m) };

            var account = new AccountInfo(user, commissions, status, updateTime);

            Assert.Equal(commissions, account.Commissions);
            Assert.Equal(status, account.Status);
            Assert.Equal(updateTime, account.Timestamp);
            Assert.NotNull(account.Balances);
            Assert.Empty(account.Balances);

            account = new AccountInfo(user, commissions, status, updateTime, balances);

            Assert.Equal(commissions, account.Commissions);
            Assert.Equal(status, account.Status);
            Assert.Equal(updateTime, account.Timestamp);
            Assert.NotNull(account.Balances);
            Assert.NotEmpty(account.Balances);
            Assert.Equal(balances[0].Asset, account.Balances.First().Asset);
        }
Beispiel #3
0
        public void Throws()
        {
            var user        = new BinanceApiUser("api-key");
            var commissions = new AccountCommissions(10, 10, 0, 0);
            var time        = DateTimeOffset.FromUnixTimeMilliseconds(DateTime.UtcNow.ToTimestamp()).UtcDateTime;
            var status      = new AccountStatus(true, true, true);

            Assert.Throws <ArgumentNullException>("user", () => new AccountInfo(null, commissions, status, time));
            Assert.Throws <ArgumentNullException>("commissions", () => new AccountInfo(user, null, status, time));
            Assert.Throws <ArgumentNullException>("status", () => new AccountInfo(user, commissions, null, time));
        }
Beispiel #4
0
        public void Throws()
        {
            var  user        = new BinanceApiUser("api-key");
            var  commissions = new AccountCommissions(10, 10, 0, 0);
            long updateTime  = 1234567890;
            var  status      = new AccountStatus(true, true, true);

            Assert.Throws <ArgumentNullException>("user", () => new AccountInfo(null, commissions, status, updateTime));
            Assert.Throws <ArgumentNullException>("commissions", () => new AccountInfo(user, null, status, updateTime));
            Assert.Throws <ArgumentNullException>("status", () => new AccountInfo(user, commissions, null, updateTime));
            Assert.Throws <ArgumentException>("updateTime", () => new AccountInfo(user, commissions, status, -1));
            Assert.Throws <ArgumentException>("updateTime", () => new AccountInfo(user, commissions, status, 0));
        }
        public void Properties()
        {
            var maker  = 10;
            var taker  = 20;
            var buyer  = 30;
            var seller = 40;

            var commissions = new AccountCommissions(maker, taker, buyer, seller);

            Assert.Equal(maker, commissions.Maker);
            Assert.Equal(taker, commissions.Taker);
            Assert.Equal(buyer, commissions.Buyer);
            Assert.Equal(seller, commissions.Seller);
        }
Beispiel #6
0
        public void Properties()
        {
            var  user        = new BinanceApiUser("api-key");
            var  commissions = new AccountCommissions(10, 10, 0, 0);
            var  status      = new AccountStatus(true, true, true);
            long updateTime  = 1234567890;
            var  balances    = new[] { new AccountBalance("BTC", 0.1m, 0.2m) };

            var accountInfo = new AccountInfo(user, commissions, status, updateTime, balances);

            var args = new AccountInfoCacheEventArgs(accountInfo);

            Assert.Equal(accountInfo, args.AccountInfo);
        }
Beispiel #7
0
        public void Properties()
        {
            var user        = new BinanceApiUser("api-key");
            var commissions = new AccountCommissions(10, 10, 0, 0);
            var status      = new AccountStatus(true, true, true);
            var time        = DateTimeOffset.FromUnixTimeMilliseconds(DateTime.UtcNow.ToTimestamp()).UtcDateTime;
            var balances    = new[] { new AccountBalance("BTC", 0.1m, 0.2m) };

            var accountInfo = new AccountInfo(user, commissions, status, time, balances);

            var args = new AccountInfoCacheEventArgs(accountInfo);

            Assert.Equal(accountInfo, args.AccountInfo);
        }
        public void Throws()
        {
            var user        = new BinanceApiUser("api-key");
            var commissions = new AccountCommissions(10, 10, 0, 0);
            var status      = new AccountStatus(true, true, true);
            var time        = DateTimeOffset.FromUnixTimeMilliseconds(DateTime.UtcNow.ToTimestamp()).UtcDateTime;
            var balances    = new[] { new AccountBalance("BTC", 0.1m, 0.2m) };

            var account = new AccountInfo(user, commissions, status, time, balances);

            using (var cts = new CancellationTokenSource())
            {
                Assert.Throws <ArgumentNullException>("accountInfo", () => new AccountUpdateEventArgs(time, cts.Token, null));
            }
        }
        public void Properties()
        {
            var user        = new BinanceApiUser("api-key");
            var commissions = new AccountCommissions(10, 10, 0, 0);
            var status      = new AccountStatus(true, true, true);
            var time        = DateTimeOffset.FromUnixTimeMilliseconds(DateTime.UtcNow.ToTimestamp()).UtcDateTime;
            var balances    = new[] { new AccountBalance("BTC", 0.1m, 0.2m) };

            var account = new AccountInfo(user, commissions, status, time, balances);

            using (var cts = new CancellationTokenSource())
            {
                var args = new AccountUpdateEventArgs(time, cts.Token, account);

                Assert.Equal(time, args.Time);
                Assert.Equal(account, args.AccountInfo);
            }
        }
Beispiel #10
0
        public void Serialization()
        {
            var maker  = 10;
            var taker  = 20;
            var buyer  = 30;
            var seller = 40;

            var commissions = new AccountCommissions(maker, taker, buyer, seller);

            var json = JsonConvert.SerializeObject(commissions);

            commissions = JsonConvert.DeserializeObject <AccountCommissions>(json);

            Assert.Equal(maker, commissions.Maker);
            Assert.Equal(taker, commissions.Taker);
            Assert.Equal(buyer, commissions.Buyer);
            Assert.Equal(seller, commissions.Seller);
        }
Beispiel #11
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)}");
                }
            }
        }
Beispiel #12
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)}");
            }
        }