private async Task <OrderBook> CalculateDirectOrderBookAsync(Instrument instrument, DateTime iterationDateTime) { Quote[] quotes = _b2C2OrderBookService.GetQuotes(instrument.AssetPairId); if (quotes == null || quotes.Length != 2) { _log.WarningWithDetails("No quotes for instrument", instrument.AssetPairId); return(null); } Balance baseAssetBalance = null; Balance quoteAssetBalance = null; TimeSpan timeSinceLastTrade = TimeSpan.Zero; if (instrument.AllowSmartMarkup) { AssetPairLink assetPairLink = await _assetPairLinkService.GetByInternalAssetPairIdAsync(instrument.AssetPairId); if (assetPairLink != null && !assetPairLink.IsEmpty()) { baseAssetBalance = await _balanceService.GetByAssetIdAsync(ExchangeNames.B2C2, assetPairLink.ExternalBaseAssetId); quoteAssetBalance = await _balanceService.GetByAssetIdAsync(ExchangeNames.B2C2, assetPairLink.ExternalQuoteAssetId); timeSinceLastTrade = DateTime.UtcNow - _tradeService.GetLastInternalTradeTime(instrument.AssetPairId); } else { _log.WarningWithDetails("The asset pair link does not configured", new { instrument.AssetPairId }); } } AssetPair assetPair = await _assetsServiceWithCache.TryGetAssetPairAsync(instrument.AssetPairId); Asset baseAsset = await _assetsServiceWithCache.TryGetAssetAsync(assetPair.BaseAssetId); MarketMakerSettings marketMakerSettings = await _marketMakerSettingsService.GetAsync(); decimal globalMarkup = marketMakerSettings.LimitOrderPriceMarkup; decimal noQuotesMarkup = await _noFreshQuotesStopLossService.GetNoFreshQuotesMarkup(assetPair.Id); decimal pnLStopLossMarkup = await _pnLStopLossEngineService.GetTotalMarkupByAssetPairIdAsync(assetPair.Id); decimal fiatEquityStopLossMarkup = await _fiatEquityStopLossService.GetFiatEquityMarkup(assetPair.Id); _log.InfoWithDetails("Arguments for Calculator.CalculateLimitOrders(...).", new { instrument.AssetPairId, quotes, levels = instrument.Levels.ToArray(), baseAmountBalance = baseAssetBalance?.Amount ?? 0, quoteAmountBalance = quoteAssetBalance?.Amount ?? 0, timeSinceLastTradeTotalSeconds = (int)timeSinceLastTrade.TotalSeconds, instrumentHalfLifePeriod = instrument.HalfLifePeriod, instrumentAllowSmartMarkup = instrument.AllowSmartMarkup, marketMakerSettingsLimitOrderPriceMarkup = globalMarkup, pnLStopLossMarkup, fiatEquityStopLossMarkup, noQuotesMarkup, assetPairAccuracy = assetPair.Accuracy, baseAssetAccuracy = baseAsset.Accuracy, instrument }); OrderBookUpdateReport orderBookUpdateReport = null; if (_isOrderBooksUpdateReportEnabled) { orderBookUpdateReport = new OrderBookUpdateReport(iterationDateTime); orderBookUpdateReport.AssetPair = instrument.AssetPairId; orderBookUpdateReport.FirstQuoteAsk = quotes[0].Ask; orderBookUpdateReport.FirstQuoteBid = quotes[0].Bid; orderBookUpdateReport.SecondQuoteAsk = quotes[1].Ask; orderBookUpdateReport.SecondQuoteBid = quotes[1].Bid; orderBookUpdateReport.QuoteDateTime = quotes[0].Time; orderBookUpdateReport.GlobalMarkup = globalMarkup; orderBookUpdateReport.NoFreshQuoteMarkup = noQuotesMarkup; orderBookUpdateReport.PnLStopLossMarkup = pnLStopLossMarkup; orderBookUpdateReport.FiatEquityMarkup = fiatEquityStopLossMarkup; } IReadOnlyCollection <LimitOrder> limitOrders = Calculator.CalculateLimitOrders( quotes[0], quotes[1], instrument.Levels.ToArray(), baseAssetBalance?.Amount ?? 0, quoteAssetBalance?.Amount ?? 0, (int)timeSinceLastTrade.TotalSeconds, instrument.HalfLifePeriod, instrument.AllowSmartMarkup, globalMarkup, pnLStopLossMarkup, fiatEquityStopLossMarkup, noQuotesMarkup, assetPair.Accuracy, baseAsset.Accuracy, orderBookUpdateReport); await ValidateQuoteTimeoutAsync(limitOrders, quotes[0]); await ValidateQuoteTimeoutAsync(limitOrders, quotes[1]); ValidateMinVolume(limitOrders, (decimal)assetPair.MinVolume); await ValidatePriceAsync(limitOrders); await ValidateBalanceAsync(limitOrders, assetPair); WriteInfoLog(instrument.AssetPairId, quotes, timeSinceLastTrade, limitOrders, "Direct limit orders calculated"); if (orderBookUpdateReport != null) { await _orderBooksUpdatesReportPublisher.PublishAsync(orderBookUpdateReport); } return(new OrderBook { AssetPairId = instrument.AssetPairId, Time = DateTime.UtcNow, LimitOrders = limitOrders, IsDirect = true }); }
private async Task <OrderBook> CalculateDirectOrderBookAsync(Instrument instrument) { Quote[] quotes = _b2C2OrderBookService.GetQuotes(instrument.AssetPairId); if (quotes == null || quotes.Length != 2) { _log.WarningWithDetails("No quotes for instrument", instrument.AssetPairId); return(null); } Balance baseAssetBalance = null; Balance quoteAssetBalance = null; TimeSpan timeSinceLastTrade = TimeSpan.Zero; if (instrument.AllowSmartMarkup) { AssetPairLink assetPairLink = await _assetPairLinkService.GetByInternalAssetPairIdAsync(instrument.AssetPairId); if (assetPairLink != null && !assetPairLink.IsEmpty()) { baseAssetBalance = await _balanceService.GetByAssetIdAsync(ExchangeNames.B2C2, assetPairLink.ExternalBaseAssetId); quoteAssetBalance = await _balanceService.GetByAssetIdAsync(ExchangeNames.B2C2, assetPairLink.ExternalQuoteAssetId); timeSinceLastTrade = DateTime.UtcNow - _tradeService.GetLastInternalTradeTime(instrument.AssetPairId); } else { _log.WarningWithDetails("The asset pair link does not configured", new { instrument.AssetPairId }); } } AssetPair assetPair = await _assetsServiceWithCache.TryGetAssetPairAsync(instrument.AssetPairId); Asset baseAsset = await _assetsServiceWithCache.TryGetAssetAsync(assetPair.BaseAssetId); MarketMakerSettings marketMakerSettings = await _marketMakerSettingsService.GetAsync(); decimal pnLStopLossMarkup = await _pnLStopLossEngineService.GetTotalMarkupByAssetPairIdAsync(assetPair.Id); decimal fiatEquityStopLossMarkup = await _fiatEquityStopLossService.GetFiatEquityMarkup(assetPair.Id); decimal stopLossMarkup = await _noFreshQuotesStopLossService.GetNoFreshQuotesMarkup(assetPair.Id); IReadOnlyCollection <LimitOrder> limitOrders = Calculator.CalculateLimitOrders( quotes[0], quotes[1], instrument.Levels.ToArray(), baseAssetBalance?.Amount ?? 0, quoteAssetBalance?.Amount ?? 0, (int)timeSinceLastTrade.TotalSeconds, instrument.HalfLifePeriod, instrument.AllowSmartMarkup, marketMakerSettings.LimitOrderPriceMarkup, pnLStopLossMarkup, fiatEquityStopLossMarkup, stopLossMarkup, assetPair.Accuracy, baseAsset.Accuracy); await ValidateQuoteTimeoutAsync(limitOrders, quotes[0]); await ValidateQuoteTimeoutAsync(limitOrders, quotes[1]); ValidateMinVolume(limitOrders, (decimal)assetPair.MinVolume); await ValidatePriceAsync(limitOrders); await ValidateBalanceAsync(limitOrders, assetPair); WriteInfoLog(instrument.AssetPairId, quotes, timeSinceLastTrade, limitOrders, "Direct limit orders calculated"); return(new OrderBook { AssetPairId = instrument.AssetPairId, Time = DateTime.UtcNow, LimitOrders = limitOrders, IsDirect = true }); }