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);
        }
Пример #2
0
        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}]."));
                }
            }
        }