private void OnAccountTradeUpdate(AccountTradeUpdateEventArgs e)
        {
            var symbol = e.Trade.Symbol;
            var immutableAccountTrades = _cache.GetAccountTrades(symbol);

            if (immutableAccountTrades != null)
            {
                _log.LogDebug($"new account trade recieved {e.Trade?.Id}", e);

                var mutableTrades = immutableAccountTrades.ToBuilder();

                var previousTrade = mutableTrades.FirstOrDefault(p => p.Id == e.Trade.Id);

                if (previousTrade != null)
                {
                    _log.LogDebug($"previous account trade removed {e.Trade?.Id}", e);

                    mutableTrades.Remove(previousTrade);
                }

                mutableTrades.Add(e.Trade);

                _cache.SetAccountTrades(symbol, mutableTrades.ToImmutable());

                UpdateOrders(e.Order, symbol);

                _log.LogDebug($"new account trade added {e.Trade?.Id}", e);
            }
        }
Beispiel #2
0
 private static void OnTradeUpdateEvent(object sender, AccountTradeUpdateEventArgs e)
 {
     lock (Program.ConsoleSync)
     {
         Console.WriteLine();
         Console.WriteLine($"Order [{e.Order.Id}] update: {e.OrderExecutionType}");
         Program.Display(e.Order);
         Console.WriteLine();
         Program.Display(e.Trade);
         Console.WriteLine();
     }
 }
        public void Properties()
        {
            var time = DateTimeOffset.FromUnixTimeMilliseconds(DateTime.UtcNow.ToTimestamp()).UtcDateTime;

            var               user             = new BinanceApiUser("api-key");
            var               symbol           = Symbol.BTC_USDT;
            const int         id               = 123456;
            const string      clientOrderId    = "test-order";
            const decimal     price            = 4999;
            const decimal     originalQuantity = 1;
            const decimal     executedQuantity = 0.5m;
            const OrderStatus status           = OrderStatus.PartiallyFilled;
            const TimeInForce timeInForce      = TimeInForce.IOC;
            const OrderType   orderType        = OrderType.Market;
            const OrderSide   orderSide        = OrderSide.Sell;
            const decimal     stopPrice        = 5000;
            const decimal     icebergQuantity  = 0.1m;
            const bool        isWorking        = true;

            var order = new Order(user, symbol, id, clientOrderId, price, originalQuantity, executedQuantity, status, timeInForce, orderType, orderSide, stopPrice, icebergQuantity, time, isWorking);

            const OrderRejectedReason orderRejectedReason = OrderRejectedReason.None;
            const string newClientOrderId = "new-test-order";

            const long    tradeId          = 12345;
            const long    orderId          = 54321;
            const decimal quantity         = 1;
            const decimal commission       = 10;
            const string  commissionAsset  = "BNB";
            const bool    isBuyer          = true;
            const bool    isMaker          = true;
            const bool    isBestPriceMatch = true;

            var trade = new AccountTrade(symbol, tradeId, orderId, price, quantity, commission, commissionAsset, time, isBuyer, isMaker, isBestPriceMatch);

            const decimal quantityOfLastFilledTrade = 1;

            using (var cts = new CancellationTokenSource())
            {
                var args = new AccountTradeUpdateEventArgs(time, cts.Token, order, orderRejectedReason, newClientOrderId, trade, quantityOfLastFilledTrade);

                Assert.Equal(time, args.Time);
                Assert.Equal(order, args.Order);
                Assert.Equal(OrderExecutionType.Trade, args.OrderExecutionType);
                Assert.Equal(orderRejectedReason, args.OrderRejectedReason);
                Assert.Equal(newClientOrderId, args.NewClientOrderId);
                Assert.Equal(trade, args.Trade);
                Assert.Equal(quantityOfLastFilledTrade, args.QuantityOfLastFilledTrade);
            }
        }
Beispiel #4
0
        private void OnAccountTradeUpdate(AccountTradeUpdateEventArgs e)
        {
            var symbol = e.Trade.Symbol;
            var immutableAccountTrades = _cache.GetAccountTrades(symbol);

            if (immutableAccountTrades != null)
            {
                var mutableTrades = immutableAccountTrades.ToBuilder();

                var previousTrade = mutableTrades.FirstOrDefault(p => p.Id == e.Trade.Id);

                if (previousTrade != null)
                {
                    mutableTrades.Remove(previousTrade);
                }

                mutableTrades.Add(e.Trade);

                _cache.SetAccountTrades(symbol, mutableTrades.ToImmutable());

                UpdateOrders(e.Order, symbol);
            }
        }
Beispiel #5
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 #6
0
        protected override void OnWebSocketEvent(WebSocketStreamEventArgs args, IEnumerable <Action <UserDataEventArgs> > callbacks)
        {
            if (!ListenKeys.ContainsKey(args.StreamName))
            {
                Logger?.LogError($"{nameof(UserDataWebSocketClient)}.{nameof(OnWebSocketEvent)}: Unknown listen key (\"{args.StreamName}\").  [thread: {Thread.CurrentThread.ManagedThreadId}]");
                return; // ignore.
            }

            var user = ListenKeys[args.StreamName];

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

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

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

                // 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, args.Token, new AccountInfo(user, commissions, status, jObject["u"].Value <long>().ToDateTimeK(), balances));

                    try
                    {
                        if (callbacks != null)
                        {
                            foreach (var callback in callbacks)
                            {
                                callback(eventArgs);
                            }
                        }
                        AccountUpdate?.Invoke(this, eventArgs);
                    }
                    catch (OperationCanceledException) { }
                    catch (Exception e)
                    {
                        if (!args.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>()
                            .ToDateTimeK(),                 // 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, args.Token, order, rejectedReason, newClientOrderId, trade, quantityOfLastFilledTrade);

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

                        try
                        {
                            if (callbacks != null)
                            {
                                foreach (var callback in callbacks)
                                {
                                    callback(eventArgs);
                                }
                            }
                            OrderUpdate?.Invoke(this, eventArgs);
                        }
                        catch (OperationCanceledException) { }
                        catch (Exception e)
                        {
                            if (!args.Token.IsCancellationRequested)
                            {
                                Logger?.LogError(e, $"{nameof(UserDataWebSocketClient)}: Unhandled order update event handler exception.");
                            }
                        }
                    }
                }
                else
                {
                    Logger?.LogWarning($"{nameof(UserDataWebSocketClient)}.{nameof(OnWebSocketEvent)}: Unexpected event type ({eventType}) - \"{args.Json}\"");
                }
            }
            catch (OperationCanceledException) { }
            catch (Exception e)
            {
                if (!args.Token.IsCancellationRequested)
                {
                    Logger?.LogError(e, $"{nameof(UserDataWebSocketClient)}.{nameof(OnWebSocketEvent)}");
                }
            }
        }
Beispiel #7
0
 private void OnAccountTradeUpdate(object sender, AccountTradeUpdateEventArgs args)
 {
     _onAccountTradeUpdate?.Invoke(args);
 }