Example #1
0
        public async Task <bool> CancelLimitOrderAsync(ExternalLimitOrder externalLimitOrder)
        {
            IExchange exchange = GetExchange(externalLimitOrder.Exchange);

            ExternalLimitOrderInfo externalLimitOrderInfo =
                await exchange.GetLimitOrderInfoAsync(externalLimitOrder.Id);

            switch (externalLimitOrderInfo.Status)
            {
            case ExternalLimitOrderStatus.Filled:
            case ExternalLimitOrderStatus.PartiallyFilled:
                externalLimitOrder.Execute(externalLimitOrderInfo);
                return(true);

            case ExternalLimitOrderStatus.Cancelled:
                externalLimitOrder.Cancel();
                return(true);

            case ExternalLimitOrderStatus.Active:
                return(false);

            default:
                throw new InvalidEnumArgumentException(nameof(externalLimitOrderInfo.Status),
                                                       (int)externalLimitOrderInfo.Status, typeof(ExternalLimitOrderStatus));
            }
        }
Example #2
0
        public async Task <ExternalLimitOrder> CreateLimitOrderAsync(string exchangeName, string assetPair,
                                                                     decimal price, decimal volume, OrderType orderType)
        {
            IExchange exchange = GetExchange(exchangeName);

            AssetPairModel assetPairModel = _marketInstrumentService.GetAssetPair(assetPair, exchange.Name);

            if (assetPairModel == null)
            {
                throw new FailedOperationException("Asset pair settings does not exist");
            }

            price = price.TruncateDecimalPlaces(assetPairModel.PriceAccuracy, orderType == OrderType.Sell);

            volume = Math.Round(volume, assetPairModel.VolumeAccuracy);

            if (volume < assetPairModel.MinVolume)
            {
                throw new FailedOperationException("The volume is too small");
            }

            string orderId = await exchange.CreateLimitOrderAsync(assetPair, price, volume, orderType);

            var externalLimitOrder =
                new ExternalLimitOrder(orderId, exchange.Name, assetPair, price, volume, orderType);

            return(externalLimitOrder);
        }
 public Task UpdateAsync(ExternalLimitOrder externalLimitOrder)
 {
     return(_storage.MergeAsync(GetPartitionKey(externalLimitOrder.Id), GetRowKey(externalLimitOrder.Id),
                                entity =>
     {
         Mapper.Map(externalLimitOrder, entity);
         return entity;
     }));
 }
        public async Task InsertAsync(string parentId, ExternalLimitOrder externalLimitOrder)
        {
            var entity = new ExternalLimitOrderEntity(GetPartitionKey(externalLimitOrder.Id),
                                                      GetRowKey(externalLimitOrder.Id));

            Mapper.Map(externalLimitOrder, entity);

            await _storage.InsertAsync(entity);

            var index = new AzureIndex(GetIndexPartitionKey(parentId), GetIndexRowKey(externalLimitOrder.Id), entity);

            await _indices.InsertAsync(index);
        }
Example #5
0
 public Task UpdateAsync(ExternalLimitOrder externalLimitOrder)
 {
     return(_externalLimitOrderRepository.UpdateAsync(externalLimitOrder));
 }
Example #6
0
 public Task AddAsync(string parentId, ExternalLimitOrder externalLimitOrder)
 {
     return(_externalLimitOrderRepository.InsertAsync(parentId, externalLimitOrder));
 }
        private async Task ExecuteMarketOrderAsync(MarketOrder marketOrder)
        {
            AggregatedOrderBook aggregatedOrderBook = _aggregatedOrderBookService.GetByAssetPair(marketOrder.AssetPair);

            if (aggregatedOrderBook == null)
            {
                _log.WarningWithDetails("Can not execute market order the aggregated order book does not exist",
                                        marketOrder);
                return;
            }

            IReadOnlyList <ExternalLimitOrder> externalLimitOrders =
                await _externalLimitOrderService.GetByParentIdAsync(marketOrder.Id);

            List <ExternalLimitOrder> activeLimitOrders = externalLimitOrders
                                                          .Where(o => o.Status == ExternalLimitOrderStatus.Active)
                                                          .ToList();

            decimal executedVolume = externalLimitOrders
                                     .Where(o => o.Status == ExternalLimitOrderStatus.Filled ||
                                            o.Status == ExternalLimitOrderStatus.PartiallyFilled)
                                     .Sum(o => o.Volume);

            decimal remainingVolume = marketOrder.Volume - executedVolume;

            bool rerouteFailedLimitOrders;

            var excludedExchanges = new List <string>();

            do
            {
                rerouteFailedLimitOrders = false;

                IReadOnlyList <ExchangeVolume> volumes;

                if (marketOrder.Type == OrderType.Sell)
                {
                    volumes = aggregatedOrderBook.GetBuyVolumes(remainingVolume, activeLimitOrders, excludedExchanges);
                }
                else
                {
                    volumes = aggregatedOrderBook.GetSellVolumes(remainingVolume, activeLimitOrders, excludedExchanges);
                }

                if (volumes.Count == 0)
                {
                    _log.WarningWithDetails("Can not execute market order no liquidity in aggregated order book",
                                            new
                    {
                        MarketOrder     = marketOrder,
                        RemainingVolume = remainingVolume,
                        ActiveVolume    = activeLimitOrders.Sum(o => o.Volume)
                    });
                    break;
                }

                foreach (ExchangeVolume exchangeVolume in volumes)
                {
                    ExchangeSettings exchangeSettings =
                        await _exchangeSettingsService.GetByNameAsync(exchangeVolume.Exchange);

                    decimal price;

                    if (marketOrder.Type == OrderType.Sell)
                    {
                        price = exchangeVolume.Price * (1 - exchangeSettings.SlippageMarkup);
                    }
                    else
                    {
                        price = exchangeVolume.Price * (1 + exchangeSettings.SlippageMarkup);
                    }

                    try
                    {
                        ExternalLimitOrder externalLimitOrder =
                            await _exchangeService.CreateLimitOrderAsync(exchangeVolume.Exchange, marketOrder.AssetPair,
                                                                         price, exchangeVolume.Volume, marketOrder.Type);

                        _log.InfoWithDetails("External limit order created", externalLimitOrder);

                        await _externalLimitOrderService.AddAsync(marketOrder.Id, externalLimitOrder);

                        activeLimitOrders.Add(externalLimitOrder);
                    }
                    catch (Exception exception)
                    {
                        rerouteFailedLimitOrders = true;

                        excludedExchanges.Add(exchangeSettings.Name);

                        _log.ErrorWithDetails(exception, "An error occurred while creating external limit order",
                                              new
                        {
                            MarketOrderId = marketOrder.Id,
                            exchangeVolume.Exchange,
                            marketOrder.AssetPair,
                            Price = price,
                            exchangeVolume.Volume,
                            OrderType = marketOrder.Type.ToString()
                        });
                    }
                }
            } while (rerouteFailedLimitOrders);
        }