public async Task <IReadOnlyList <IAssetPair> > GetAllIncludingFxParisWithFilterAsync(IEnumerable <string> assetPairIds = null, bool onlyStarted = true) { var settlementCurrency = await _settlementCurrencyService.GetSettlementCurrencyAsync(); var products = await _productsRepository.GetByProductsIdsAsync(assetPairIds); var currencies = await _currenciesRepository.GetAllAsync(); var assetPairs = products .Where(x => !onlyStarted || x.IsStarted) .Select(x => AssetPair.CreateFromProduct(x, _defaultLegalEntitySettings.DefaultLegalEntity)).ToList(); assetPairs.AddRange(currencies.Value .Where(x => !x.Id.Equals(settlementCurrency, StringComparison.InvariantCultureIgnoreCase)).Select(x => AssetPair.CreateFromCurrency(x, _defaultLegalEntitySettings.DefaultLegalEntity, settlementCurrency))); return(assetPairs); }
public async Task Handle(ProductChangedEvent @event) { switch (@event.ChangeType) { case ChangeType.Creation: case ChangeType.Edition: if ([email protected]) { _log.WriteInfo(nameof(ProductChangedProjection), nameof(Handle), $"ProductChangedEvent received for productId: {@event.NewValue.ProductId}, but it was ignored because it has not been started yet."); return; } break; case ChangeType.Deletion: if ([email protected]) { _log.WriteInfo(nameof(ProductChangedProjection), nameof(Handle), $"ProductChangedEvent received for productId: {@event.OldValue.ProductId}, but it was ignored because it has not been started yet."); return; } break; default: throw new ArgumentOutOfRangeException(); } if (@event.ChangeType == ChangeType.Deletion) { CloseAllOrders(); ValidatePositions(@event.OldValue.ProductId); _assetPairsCache.Remove(@event.OldValue.ProductId); } else { if (@event.NewValue.IsDiscontinued) { CloseAllOrders(); RemoveQuoteFromCache(); } await _tradingInstrumentsManager.UpdateTradingInstrumentsCacheAsync(); var isAdded = _assetPairsCache.AddOrUpdate(AssetPair.CreateFromProduct(@event.NewValue, _mtSettings.DefaultLegalEntitySettings.DefaultLegalEntity)); if (@event.NewValue.TradingCurrency != AssetPairConstants.BaseCurrencyId) { _assetPairsCache.AddOrUpdate(AssetPair.CreateFromCurrency(@event.NewValue.TradingCurrency, _mtSettings.DefaultLegalEntitySettings.DefaultLegalEntity)); } //only for product if (isAdded) { await _scheduleSettingsCacheService.UpdateScheduleSettingsAsync(); } if (@event.ChangeType == ChangeType.Edition && @event.OldValue.IsTradingDisabled != @event.NewValue.IsTradingDisabled) { await HandleTradingDisabled(@event.NewValue, @event.Username); } } void RemoveQuoteFromCache() { var result = _quoteCache.RemoveQuote(@event.OldValue.ProductId); if (result != RemoveQuoteErrorCode.None) { _log.WriteWarning(nameof(ProductChangedProjection), nameof(RemoveQuoteFromCache), result.Message); } } void CloseAllOrders() { try { foreach (var order in _orderReader.GetPending() .Where(x => x.AssetPairId == @event.OldValue.ProductId)) { _tradingEngine.CancelPendingOrder(order.Id, null, null, OrderCancellationReason.InstrumentInvalidated); } } catch (Exception exception) { _log.WriteError(nameof(ProductChangedProjection), nameof(CloseAllOrders), exception); throw; } } void ValidatePositions(string assetPairId) { var positions = _orderReader.GetPositions(assetPairId); if (positions.Any()) { _log.WriteFatalError(nameof(ProductChangedProjection), nameof(ValidatePositions), new Exception( $"{positions.Length} positions are opened for [{assetPairId}], first: [{positions.First().Id}].")); } } }