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); }