private (Orderbook Orderbook, ExchangeQuality PrimaryExchange, string Problem) OnNewOrderbookInternal( ExternalOrderbook orderbook) { var assetPairId = orderbook.AssetPairId; if (!_extPricesSettingsService.IsExchangeConfigured(assetPairId, orderbook.ExchangeName)) { Trace.Write(TraceLevelGroupEnum.WarnTrace, assetPairId, $"Skipping not configured exchange {orderbook.ExchangeName}", new { Event = "NotConfiguredExchangeSkipped", orderbook.ExchangeName }); return(null, null, "Skipping not configured exchange"); } var allOrderbooks = _orderbooksService.AddAndGetByAssetPair(orderbook); var now = orderbook.LastUpdatedTime; var(exchangesErrors, validOrderbooks) = MarkExchangesErrors(assetPairId, allOrderbooks, now); var primaryExchangeQuality = _primaryExchangeService.GetPrimaryExchange(assetPairId, exchangesErrors, now, orderbook.ExchangeName); if (primaryExchangeQuality == null) { return(null, null, "No primary exchange"); } var primaryExchangeName = primaryExchangeQuality.ExchangeName; if (primaryExchangeName != orderbook.ExchangeName) { return(null, primaryExchangeQuality, "Orderbook not from primary exchange"); } if (primaryExchangeQuality.ErrorState == ExchangeErrorStateDomainEnum.Outlier) { return(null, primaryExchangeQuality, "Primary exchange is an outlier, skipping price update"); } if (!allOrderbooks.TryGetValue(primaryExchangeName, out var primaryOrderbook)) { _log.WriteErrorAsync(nameof(GenerateOrderbookService), null, new Exception($"{primaryExchangeName} not found in allOrderbooks ({allOrderbooks.Keys.ToJson()})") { Data = { { "AssetPairId", assetPairId } } }); return(null, primaryExchangeQuality, "Primary exchange orderbook not found"); } _stopTradesService.FinishCycle(primaryOrderbook, now); var resultingOrderbook = Transform(primaryOrderbook, validOrderbooks); if (TryFindSkipOrderbookReason(resultingOrderbook) is string reason) { return(null, primaryExchangeQuality, reason); } return(resultingOrderbook, primaryExchangeQuality, null); }
private void LogCycle(ExternalOrderbook orderbook, [CanBeNull] Orderbook resultingOrderbook, Stopwatch watch, ExchangeQuality primaryExchangeQuality, [CanBeNull] string problem) { var elapsedMilliseconds = watch.ElapsedMilliseconds; if (elapsedMilliseconds > 20) { _telemetryService.PublishEventMetrics(nameof(GenerateOrderbookService) + '.' + nameof(OnNewOrderbook), null, new Dictionary <string, double> { { "ProcessingTime", elapsedMilliseconds } }, new Dictionary <string, string> { { "AssetPairId", orderbook.AssetPairId }, { "Exchange", orderbook.ExchangeName }, { "IsPrimary", (orderbook.ExchangeName == primaryExchangeQuality.ExchangeName).ToString() }, { "IsSkip", (resultingOrderbook == null).ToString() }, }); } var bestPrices = _bestPricesService.Calc(orderbook); var resultingBestPrices = resultingOrderbook == null ? null : _bestPricesService.Calc(resultingOrderbook); var action = resultingOrderbook == null ? "Skipped" : "Processed"; Trace.Write(TraceLevelGroupEnum.Trace, orderbook.AssetPairId, $"{action} from {orderbook.ExchangeName}, " + $"primary: {primaryExchangeQuality}, time: {elapsedMilliseconds} ms", new { Event = "ExternalOrderbook" + action, Reason = problem, orderbook.ExchangeName, PrimaryExchange = primaryExchangeQuality, ElapsedMilliseconds = elapsedMilliseconds, IsSkip = resultingOrderbook == null, bestPrices.BestBid, bestPrices.BestAsk, ResultingBestBid = resultingBestPrices?.BestBid, ResultingBestAsk = resultingBestPrices?.BestAsk, BidsDepth = orderbook.Bids.Length, AsksDepth = orderbook.Asks.Length, ResultingsBidsDepth = resultingOrderbook?.Bids.Length, ResultingsAsksDepth = resultingOrderbook?.Asks.Length, }); }