public void Bid_and_ask_quotes_generates_mid_quote() { // Arrange var date1 = new DateTime(2017, 06, 23, 12, 56, 00); var date2 = new DateTime(2017, 06, 23, 12, 56, 30); // Act _generator.TryGenerate("EURUSD", false, 1, date1, 3); var mid = _generator.TryGenerate("EURUSD", true, 2, date2, 3); // Assert Assert.NotNull(mid); Assert.Equal("EURUSD", mid.AssetPair); Assert.False(mid.IsBuy); Assert.Equal(1.5, mid.Price); Assert.Equal(date2, mid.Timestamp); }
public async Task ProcessMtQuoteAsync(MtQuoteDto mtQuote) { if (mtQuote == null) { throw new ArgumentNullException(nameof(mtQuote)); } var assetPair = await _assetPairsManager.TryGetEnabledPairAsync(mtQuote.AssetPair?.Trim()); if (assetPair == null) { return; } var changedUpdates = new ConcurrentBag <CandleUpdateResult>(); var midPriceQuote = _midPriceQuoteGenerator.TryGenerate( mtQuote.AssetPair, mtQuote.Ask, mtQuote.Bid, mtQuote.Timestamp, assetPair.Accuracy); try { // Updates all intervals in parallel var processingTasks = _intervals .Select(timeInterval => Task.Factory.StartNew(() => { ProcessQuoteInterval( mtQuote.AssetPair, mtQuote.Timestamp, mtQuote.Ask, false, timeInterval, midPriceQuote, changedUpdates); })) .Concat(_intervals .Select(timeInterval => Task.Factory.StartNew(() => { ProcessQuoteInterval( mtQuote.AssetPair, mtQuote.Timestamp, mtQuote.Bid, true, timeInterval, null, changedUpdates); }))); await Task.WhenAll(processingTasks); // Publishes updated candles if (!changedUpdates.IsEmpty) { var publisher = await _candlesPublisherProvider.GetForAssetPair(assetPair.Id); await publisher.PublishAsync(changedUpdates); } } catch (Exception) { // Failed to publish one or several candles, so processing should be cancelled foreach (var updateResult in changedUpdates) { _candlesGenerator.Undo(updateResult); } throw; } }