Ejemplo n.º 1
0
        public async Task <ResponseModel <LimitOrderResponseModel> > PlaceLimitOrderAsync(string clientId, AssetPair assetPair, OrderAction orderAction, decimal volume,
                                                                                          decimal price, bool cancelPreviousOrders = false)
        {
            var requestId = GetNextRequestId();
            var fees      = _calculateOrderFees
                ? await _feeCalculator.GetLimitOrderFees(clientId, assetPair, orderAction)
                : Array.Empty <LimitOrderFeeModel>();

            var order = new LimitOrderModel
            {
                Id                   = requestId.ToString(),
                AssetPairId          = assetPair.Id,
                ClientId             = clientId,
                Price                = (double)price,
                CancelPreviousOrders = cancelPreviousOrders,
                Volume               = (double)Math.Abs(volume),
                OrderAction          = orderAction.ToMeOrderAction(),
                Fees                 = fees
            };

            var response = await _matchingEngineClient.PlaceLimitOrderAsync(order);

            CheckResponseAndThrowIfNull(response);

            var result = new LimitOrderResponseModel
            {
                Id = requestId
            };

            return(ConvertToApiModel(response.Status, result));
        }
        public async Task PlaceRegularLimitOrder()
        {
            var client = CreateConnection(Url);

            var model = new LimitOrderModel
            {
                Id                   = GenerateUid(),
                ClientId             = ClientId,
                CancelPreviousOrders = true,
                AssetPairId          = "LKKCHF",
                OrderAction          = OrderAction.Buy,
                Price                = 0.005,
                Volume               = 10
            };

            // Check that valid request is accepted
            var response = await client.Retry(x => x.PlaceLimitOrderAsync(model));

            ValidateResponse(response, MeStatusCodes.Ok);

            // Check that resend results in duplicate
            response = await client.Retry(x => x.PlaceLimitOrderAsync(model));

            ValidateResponse(response, MeStatusCodes.Duplicate);

            // Check that missing price gives InvalidPrice
            model.Id    = GenerateUid();
            model.Price = 0;

            response = await client.Retry(x => x.PlaceLimitOrderAsync(model));

            ValidateResponse(response, MeStatusCodes.InvalidPrice);
        }
Ejemplo n.º 3
0
 public static MeNewLimitOrderModel ToNewMeModel(this LimitOrderModel model)
 {
     return(MeNewLimitOrderModel.CreateMeLimitOrder(
                model.Id,
                model.ClientId,
                model.AssetPairId,
                model.OrderAction,
                model.Volume,
                model.Price,
                model.CancelPreviousOrders,
                model.Fee?.ToMeModel(),
                model.Fees?.Select(item => item.ToMeModel()).ToArray()));
 }
Ejemplo n.º 4
0
        public async Task PlaceLimitOrderAsync(LimitOrder limitOrder)
        {
            var model = new LimitOrderModel
            {
                AssetPairId          = limitOrder.AssetPairId,
                CancelPreviousOrders = false,
                ClientId             = _walletId,
                Id          = Guid.NewGuid().ToString(),
                OrderAction = limitOrder.TradeType.ToOrderAction(),
                Price       = (double)limitOrder.Price,
                Volume      = (double)limitOrder.Volume,
            };

            limitOrder.ExternalId = model.Id;

            MeResponseModel response;

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

                throw;
            }

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

            if (response.Status == MeStatusCodes.Ok)
            {
                _log.Info("ME place limit order response", new { response = $"data: {response.ToJson()}" });

                limitOrder.Error = LimitOrderError.None;
            }
            else
            {
                _log.Warning("ME place limit order response unsuccessful code.", context: new { response = $"data: {response.ToJson()}" });
                limitOrder.Error        = response.Status.ToOrderError();
                limitOrder.ErrorMessage = limitOrder.Error != LimitOrderError.Unknown
                    ? response.Message
                    : !string.IsNullOrEmpty(response.Message) ? response.Message : "Unknown error";
            }
        }
Ejemplo n.º 5
0
        ///<inheritdoc cref="IMatchingEngineClient"/>
        public Task <MeResponseModel> PlaceLimitOrderAsync(LimitOrderModel model,
                                                           CancellationToken cancellationToken = default)
        {
            if (model == null)
            {
                throw new ArgumentNullException(nameof(model));
            }

            return(SendData(
                       model.ToNewMeModel(),
                       _newTasksManager,
                       x => x.ToDomainModel(),
                       _meResponsePolicy,
                       cancellationToken,
                       model.Id,
                       $"{model.OrderAction} {model.AssetPairId}"
                       ));
        }
Ejemplo n.º 6
0
        public async Task <IActionResult> PlaceLimitOrder(PlaceLimitOrderRequest request)
        {
            var walletId = User.GetWalletId();

            var result = await _validationService.ValidateLimitOrderAsync(walletId, request.AssetPairId, request.Side, request.Price, request.Volume);

            if (result != null)
            {
                throw HftApiException.Create(result.Code, result.Message).AddField(result.FieldName);
            }

            var order = new LimitOrderModel
            {
                Id                   = Guid.NewGuid().ToString(),
                AssetPairId          = request.AssetPairId,
                ClientId             = walletId,
                Price                = (double)request.Price,
                CancelPreviousOrders = false,
                Volume               = (double)Math.Abs(request.Volume),
                OrderAction          = request.Side
            };

            MeResponseModel response = await _matchingEngineClient.PlaceLimitOrderAsync(order);

            if (response == null)
            {
                throw HftApiException.Create(HftApiErrorCode.MeRuntime, "ME not available");
            }

            (HftApiErrorCode code, string message) = response.Status.ToHftApiError();

            if (code == HftApiErrorCode.Success)
            {
                return(Ok(ResponseModel <LimitOrderResponse> .Ok(new LimitOrderResponse {
                    OrderId = response.TransactionId
                })));
            }

            throw HftApiException.Create(code, message);
        }
Ejemplo n.º 7
0
        public override async Task <LimitOrderResponse> PlaceLimitOrder(LimitOrderRequest request, ServerCallContext context)
        {
            var walletId = context.GetHttpContext().User.GetWalletId();

            var result = await _validationService.ValidateLimitOrderAsync(request.AssetPairId, Convert.ToDecimal(request.Price), Convert.ToDecimal(request.Volume));

            if (result != null)
            {
                return(new LimitOrderResponse
                {
                    Error = new Error
                    {
                        Code = (int)result.Code,
                        Message = result.Message
                    }
                });
            }

            var order = new LimitOrderModel
            {
                Id                   = Guid.NewGuid().ToString(),
                AssetPairId          = request.AssetPairId,
                ClientId             = walletId,
                Price                = Convert.ToDouble(request.Price),
                CancelPreviousOrders = false,
                Volume               = Math.Abs(Convert.ToDouble(request.Volume)),
                OrderAction          = request.Side == Side.Buy ? OrderAction.Buy : OrderAction.Sell
            };

            MeResponseModel response = await _matchingEngineClient.PlaceLimitOrderAsync(order);

            if (response == null)
            {
                return(new LimitOrderResponse
                {
                    Error = new Error
                    {
                        Code = (int)HftApiErrorCode.MeRuntime,
                        Message = "ME not available"
                    }
                });
            }

            (HftApiErrorCode code, string message) = response.Status.ToHftApiError();

            if (code == HftApiErrorCode.Success)
            {
                return new LimitOrderResponse
                       {
                           Payload = new LimitOrderResponse.Types.LimitOrderPayload
                           {
                               OrderId = response.TransactionId
                           }
                       }
            }
            ;

            return(new LimitOrderResponse
            {
                Error = new Error
                {
                    Code = (int)code,
                    Message = message
                }
            });
        }
Ejemplo n.º 8
0
        public async Task <IActionResult> PlaceLimitOrder([FromBody] LimitOrderRequest order)
        {
            var clientId = _requestContext.ClientId;

            var pair = await _assetsServiceWithCache.TryGetAssetPairAsync(order.AssetPairId);

            if (pair == null)
            {
                return(NotFound());
            }

            if (pair.IsDisabled)
            {
                return(BadRequest());
            }

            var asset = await _assetsServiceWithCache.TryGetAssetAsync(pair.BaseAssetId);

            if (asset == null || asset.IsDisabled)
            {
                return(BadRequest());
            }

            var volume = order.Volume.TruncateDecimalPlaces(asset.Accuracy);

            if (Math.Abs(volume) < double.Epsilon)
            {
                return(BadRequest());
            }

            var id = Guid.NewGuid().ToString();

            var price = order.Price.TruncateDecimalPlaces(pair.Accuracy);

            var request = new LimitOrderCreateRequest
            {
                AssetPairId = pair.Id,
                ClientId    = clientId,
                CreatedAt   = DateTime.Now,
                Id          = id,
                Price       = price,
                Volume      = Math.Abs(volume) * (order.OrderAction == Models.Orders.OrderAction.Buy ? 1 : -1),
                Straight    = true,
            };

            await _limitOrdersRepository.AddAsync(request);

            try
            {
                var limitOrderModel = new LimitOrderModel
                {
                    AssetPairId = pair.Id,
                    ClientId    = clientId,
                    Id          = id,
                    Price       = price,
                    Volume      = Math.Abs(volume),
                    OrderAction = ToMeOrderAction(order.OrderAction),
                };

                if (_baseSettings.EnableFees)
                {
                    limitOrderModel.Fee = await GetLimitOrderFee(clientId, pair, order.OrderAction);
                }

                var response = await _matchingEngineClient.PlaceLimitOrderAsync(limitOrderModel);

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

                if (response.Status != MeStatusCodes.Ok)
                {
                    var status = MeStatusCodeToOperationsRepositoryOrderStatus(response.Status);

                    await _limitOrdersRepository.FinalizeAsync(
                        new LimitOrderFinalizeRequest
                    {
                        OrderId     = id,
                        OrderStatus = status
                    });

                    return(BadRequest(CreateErrorMessage($"ME responded: {response.Status}")));
                }
            }
            catch (Exception)
            {
                await _limitOrdersRepository.RemoveAsync(clientId, id);

                throw;
            }

            return(Ok(id));
        }