public async Task CancelAsync(string assetPairId)
        {
            string walletId = _settingsService.GetWalletId();

            if (string.IsNullOrEmpty(walletId))
            {
                throw new ExchangeException("The wallet not set");
            }

            var multiLimitOrder = new MultiLimitOrderModel
            {
                Id                   = Guid.NewGuid().ToString(),
                ClientId             = walletId,
                AssetPairId          = GetAssetPair(assetPairId),
                CancelPreviousOrders = true,
                Orders               = new List <MultiOrderItemModel>(),
                CancelMode           = CancelMode.BothSides
            };

            _log.InfoWithDetails("Matching engine cancel multi limit order request", multiLimitOrder);

            MultiLimitOrderResponse response;

            try
            {
                response = await _matchingEngineClient.PlaceMultiLimitOrderAsync(multiLimitOrder);
            }
            catch (Exception exception)
            {
                _log.ErrorWithDetails(exception, "An error occurred during cancelling limit orders",
                                      multiLimitOrder);

                throw new ExchangeException("Cannot cancel limit orders an unexpected error occurred", exception);
            }

            if (response == null)
            {
                throw new ExchangeException("Matching engine returned an empty response");
            }

            _log.InfoWithDetails("Matching engine cancel multi limit order response", response);
        }
        public async Task <IActionResult> CreateLimitOrder([FromBody] LimitOrderRequest order)
        {
            var orderId = Guid.NewGuid().ToString();
            var mlm     = new MultiLimitOrderModel()
            {
                AssetId              = order.Instrument,
                ClientId             = this.ClientId(),
                CancelMode           = CancelMode.BothSides,
                CancelPreviousOrders = false,
                Id     = Guid.NewGuid().ToString(),
                Orders = new List <MultiOrderItemModel> {
                    new MultiOrderItemModel()
                    {
                        Id          = orderId,
                        OrderAction = order.TradeType == TradeType.Buy ? OrderAction.Buy : OrderAction.Sell,
                        Fee         = null,
                        OldId       = null,
                        Price       = (double)order.Price,
                        Volume      = (double)order.Volume
                    }
                }
            };

            var res = await _meclient.PlaceMultiLimitOrderAsync(mlm);

            var status = res.Statuses.Any() ? res.Statuses[0].Status : MeStatusCodes.BadRequest;

            if (status == MeStatusCodes.Ok)
            {
                var resp = new OrderIdResponse()
                {
                    OrderId = orderId
                };

                return(Ok(resp));
            }

            return(BadRequest($"incorect result: {status}"));
        }
Ejemplo n.º 3
0
        public async Task <ResponseModel <BulkOrderResponseModel> > PlaceBulkLimitOrderAsync(string clientId, AssetPair assetPair, IEnumerable <BulkOrderItemModel> items, bool cancelPrevious, CancelMode?cancelMode)
        {
            var requestId = GetNextRequestId();

            var orders = new ConcurrentBag <MultiOrderItemModel>();
            await items.ParallelForEachAsync(async item =>
            {
                var subOrder = await ToMultiOrderItemModel(clientId, assetPair, item);
                orders.Add(subOrder);
            });

            var order = new MultiLimitOrderModel
            {
                Id                   = requestId.ToString(),
                ClientId             = clientId,
                AssetPairId          = assetPair.Id,
                CancelPreviousOrders = cancelPrevious,
                Orders               = orders.ToArray()
            };

            if (cancelMode.HasValue)
            {
                order.CancelMode = cancelMode.Value.ToMeCancelModel();
            }

            var response = await _matchingEngineClient.PlaceMultiLimitOrderAsync(order);

            CheckResponseAndThrowIfNull(response);

            var result = new BulkOrderResponseModel
            {
                AssetPairId = assetPair.Id,
                Error       = response.Status != MeStatusCodes.Ok ? ErrorCodeType.Rejected : default(ErrorCodeType?),
                Statuses    = response.Statuses?.Select(ToBulkOrderItemStatusModel).ToArray()
            };

            return(ConvertToApiModel(response.Status, result));
        }
        public async Task ApplyAsync(string assetPairId, IReadOnlyCollection <LimitOrder> limitOrders)
        {
            string walletId = _settingsService.GetWalletId();

            if (string.IsNullOrEmpty(walletId))
            {
                throw new ExchangeException("The wallet not set");
            }

            var multiOrderItems = new List <MultiOrderItemModel>();

            foreach (LimitOrder limitOrder in limitOrders)
            {
                var multiOrderItem = new MultiOrderItemModel
                {
                    Id          = limitOrder.Id,
                    OrderAction = ToOrderAction(limitOrder.Type),
                    Price       = (double)limitOrder.Price,
                    Volume      = (double)Math.Abs(limitOrder.Volume)
                };

                multiOrderItems.Add(multiOrderItem);
            }

            var multiLimitOrder = new MultiLimitOrderModel
            {
                Id                   = Guid.NewGuid().ToString(),
                ClientId             = walletId,
                AssetPairId          = GetAssetPair(assetPairId),
                CancelPreviousOrders = true,
                Orders               = multiOrderItems,
                CancelMode           = CancelMode.BothSides
            };

            _log.InfoWithDetails("Matching engine place multi limit order request", multiLimitOrder);

            MultiLimitOrderResponse response;

            try
            {
                response = await _matchingEngineClient.PlaceMultiLimitOrderAsync(multiLimitOrder);
            }
            catch (Exception exception)
            {
                _log.ErrorWithDetails(exception, "An error occurred during creating limit orders", multiLimitOrder);

                throw new ExchangeException("Cannot create limit orders an unexpected error occurred", exception);
            }

            if (response == null)
            {
                throw new ExchangeException("Matching engine returned an empty response");
            }

            foreach (LimitOrderStatusModel orderStatus in response.Statuses)
            {
                LimitOrder limitOrder = limitOrders.SingleOrDefault(e => e.Id == orderStatus.Id);

                if (limitOrder != null)
                {
                    limitOrder.Error        = ToLimitOrderError(orderStatus.Status);
                    limitOrder.ErrorMessage = limitOrder.Error != LimitOrderError.Unknown
                        ? orderStatus.StatusReason
                        : !string.IsNullOrEmpty(orderStatus.StatusReason)
                            ? orderStatus.StatusReason
                            : "Unknown error";
                }
                else
                {
                    _log.WarningWithDetails("Matching engine returned status for unknown limit order",
                                            new { LimitOrderId = orderStatus.Id });
                }
            }

            string[] ignoredLimitOrders = response.Statuses
                                          .Select(x => x.Id)
                                          .Except(multiLimitOrder.Orders.Select(x => x.Id))
                                          .ToArray();

            if (ignoredLimitOrders.Any())
            {
                _log.WarningWithDetails("Matching engine response not contains status of limit order",
                                        new { AssetPairId = assetPairId, LimitOrders = ignoredLimitOrders });
            }

            _log.InfoWithDetails("Matching engine place multi limit order response", response);
        }
Ejemplo n.º 5
0
        public async Task ApplyAsync(string assetPairId, IReadOnlyCollection <LimitOrder> limitOrders)
        {
            if (string.IsNullOrEmpty(_walletId))
            {
                throw new Exception("WalletId is not set");
            }

            var map = new Dictionary <string, LimitOrder>();

            var multiOrderItems = new List <MultiOrderItemModel>();

            foreach (LimitOrder limitOrder in limitOrders)
            {
                var multiOrderItem = new MultiOrderItemModel
                {
                    Id          = Guid.NewGuid().ToString("D"),
                    OrderAction = limitOrder.TradeType.ToOrderAction(),
                    Price       = (double)limitOrder.Price,
                    Volume      = (double)limitOrder.Volume,
                };

                map[multiOrderItem.Id] = limitOrder;

                multiOrderItems.Add(multiOrderItem);

                limitOrder.ExternalId = multiOrderItem.Id;
            }

            var multiLimitOrder = new MultiLimitOrderModel
            {
                Id                   = Guid.NewGuid().ToString(),
                ClientId             = _walletId,
                AssetPairId          = assetPairId,
                CancelPreviousOrders = true,
                Orders               = multiOrderItems,
                CancelMode           = CancelMode.BothSides
            };

            _log.Info("ME place multi limit order request", new { request = $"data: {multiLimitOrder.ToJson()}" });

            MultiLimitOrderResponse response;

            try
            {
                response = await _matchingEngineClient.PlaceMultiLimitOrderAsync(multiLimitOrder,
                                                                                 new CancellationTokenSource(Consts.MatchingEngineTimeout).Token);
            }
            catch (Exception exception)
            {
                _log.Error(exception, "An error occurred during creating limit orders",
                           new { request = $"data: {multiLimitOrder.ToJson()}" });

                throw;
            }

            if (response == null)
            {
                throw new Exception("ME response is null");
            }

            if (response.Statuses.All(x => x.Status == MeStatusCodes.Ok))
            {
                _log.Info("ME place multi limit order response", new { response = $"data: {response.ToJson()}" });
            }
            else
            {
                _log.Warning("ME place multi limit order response. Some orders have unsuccessful codes.", context: new { response = $"data: {response.ToJson()}" });
            }

            foreach (var orderStatus in response.Statuses)
            {
                if (map.TryGetValue(orderStatus.Id, out var limitOrder))
                {
                    limitOrder.Error        = orderStatus.Status.ToOrderError();
                    limitOrder.ErrorMessage = limitOrder.Error != LimitOrderError.Unknown
                        ? orderStatus.StatusReason
                        : !string.IsNullOrEmpty(orderStatus.StatusReason) ? orderStatus.StatusReason : "Unknown error";
                }
            }
        }
Ejemplo n.º 6
0
        public async Task ApplyAsync(string assetPairId, IReadOnlyCollection <LimitOrder> limitOrders)
        {
            string walletId = await _settingsService.GetWalletIdAsync();

            if (string.IsNullOrEmpty(walletId))
            {
                throw new Exception("WalletId is not set");
            }

            var map = new Dictionary <string, string>();

            var multiOrderItems = new List <MultiOrderItemModel>();

            foreach (LimitOrder limitOrder in limitOrders)
            {
                var multiOrderItem = new MultiOrderItemModel
                {
                    Id          = Guid.NewGuid().ToString("D"),
                    OrderAction = limitOrder.Type.ToOrderAction(),
                    Price       = (double)limitOrder.Price,
                    Volume      = (double)Math.Abs(limitOrder.Volume)
                };

                multiOrderItems.Add(multiOrderItem);

                map[multiOrderItem.Id] = limitOrder.Id;
            }

            var multiLimitOrder = new MultiLimitOrderModel
            {
                Id                   = Guid.NewGuid().ToString(),
                ClientId             = walletId,
                AssetPairId          = assetPairId,
                CancelPreviousOrders = true,
                Orders               = multiOrderItems,
                CancelMode           = CancelMode.BothSides
            };

            _log.InfoWithDetails("ME place multi limit order request", multiLimitOrder);

            MultiLimitOrderResponse response;

            try
            {
                response = await _matchingEngineClient.PlaceMultiLimitOrderAsync(multiLimitOrder);
            }
            catch (Exception exception)
            {
                _log.ErrorWithDetails(exception, "An error occurred during creating limit orders", multiLimitOrder);

                throw;
            }

            if (response == null)
            {
                throw new Exception("ME response is null");
            }

            foreach (LimitOrderStatusModel orderStatus in response.Statuses)
            {
                if (map.TryGetValue(orderStatus.Id, out var limitOrderId))
                {
                    var limitOrder = limitOrders.Single(e => e.Id == limitOrderId);

                    limitOrder.Error        = orderStatus.Status.ToOrderError();
                    limitOrder.ErrorMessage = limitOrder.Error != LimitOrderError.Unknown
                        ? orderStatus.StatusReason
                        : !string.IsNullOrEmpty(orderStatus.StatusReason)
                            ? orderStatus.StatusReason
                            : "Unknown error";
                }
                else
                {
                    _log.Warning("ME returned status for order which is not in the request",
                                 context: $"order: {orderStatus.Id}");
                }
            }

            string[] ignoredOrdersByMe = response.Statuses
                                         .Select(x => x.Id)
                                         .Except(multiLimitOrder.Orders.Select(x => x.Id))
                                         .ToArray();

            if (ignoredOrdersByMe.Any())
            {
                _log.WarningWithDetails("ME didn't return status for orders",
                                        $"pair: {assetPairId}, orders: {string.Join(", ", ignoredOrdersByMe)}");
            }

            _log.InfoWithDetails("ME place multi limit order response", response);
        }
Ejemplo n.º 7
0
        public override async Task <BulkLimitOrderResponse> PlaceBulkLimitOrder(BulkLimitOrderRequest request, ServerCallContext context)
        {
            var walletId = context.GetHttpContext().User.GetWalletId();

            var items = request.Orders?.ToArray() ?? Array.Empty <BulkOrder>();

            var orders = new List <MultiOrderItemModel>();

            foreach (var item in items)
            {
                var order = new MultiOrderItemModel
                {
                    Id          = Guid.NewGuid().ToString(),
                    Price       = Convert.ToDouble(item.Price),
                    Volume      = Convert.ToDouble(item.Volume),
                    OrderAction = _mapper.Map <OrderAction>(item.Side),
                    OldId       = string.IsNullOrEmpty(item.OldId) ? null : item.OldId
                };

                orders.Add(order);
            }

            var multiOrder = new MultiLimitOrderModel
            {
                Id                   = Guid.NewGuid().ToString(),
                ClientId             = walletId,
                AssetPairId          = request.AssetPairId,
                CancelPreviousOrders = request.CancelPreviousOrders,
                Orders               = orders.ToArray()
            };

            if (request.OptionalCancelModeCase != BulkLimitOrderRequest.OptionalCancelModeOneofCase.None)
            {
                multiOrder.CancelMode = _mapper.Map <Lykke.MatchingEngine.Connector.Models.Api.CancelMode>(request.CancelMode);
            }

            MultiLimitOrderResponse response = await _matchingEngineClient.PlaceMultiLimitOrderAsync(multiOrder);

            if (response == null)
            {
                return(new BulkLimitOrderResponse
                {
                    Error = new Error
                    {
                        Code = _mapper.Map <ErrorCode>(HftApiErrorCode.MeRuntime),
                        Message = "ME not available"
                    }
                });
            }

            var bulkResponse = new BulkLimitOrderResponse
            {
                Payload = new BulkLimitOrderResponse.Types.BulkLimitOrderPayload
                {
                    AssetPairId = request.AssetPairId
                }
            };

            bulkResponse.Payload.Statuses.AddRange(response.Statuses?.Select(x => new BulkOrderItemStatus
            {
                Id     = x.Id,
                Price  = x.Price.ToString(CultureInfo.InvariantCulture),
                Volume = x.Volume.ToString(CultureInfo.InvariantCulture),
                Error  = _mapper.Map <ErrorCode>(x.Status.ToHftApiError().code)
            }));

            return(bulkResponse);
        }