private async Task Handle(StartSpecialLiquidationInternalCommand command, IEventPublisher publisher)
        {
            if (!_marginTradingSettings.SpecialLiquidation.Enabled)
            {
                publisher.PublishEvent(new SpecialLiquidationFailedEvent
                {
                    OperationId  = command.OperationId,
                    CreationTime = _dateService.Now(),
                    Reason       = "Special liquidation is disabled in settings",
                });

                return;
            }

            //validate the list of positions contain only the same instrument
            var positions = _ordersCache.GetPositions().Where(x => command.PositionIds.Contains(x.Id)).ToList();

            if (!string.IsNullOrEmpty(command.AccountId))
            {
                if (_accountsCacheService.TryGet(command.AccountId) == null)
                {
                    publisher.PublishEvent(new SpecialLiquidationFailedEvent
                    {
                        OperationId  = command.OperationId,
                        CreationTime = _dateService.Now(),
                        Reason       = $"Account {command.AccountId} does not exist",
                    });
                    return;
                }

                positions = positions.Where(x => x.AccountId == command.AccountId).ToList();
            }

            if (positions.Select(x => x.AssetPairId).Distinct().Count() > 1)
            {
                publisher.PublishEvent(new SpecialLiquidationFailedEvent
                {
                    OperationId  = command.OperationId,
                    CreationTime = _dateService.Now(),
                    Reason       = "The list of positions is of different instruments",
                });

                return;
            }

            // excluding positions which have already been used for Special Liquidation
            var alreadyUsedPositionIds = (await _operationExecutionInfoRepository
                                          .FilterPositionsInSpecialLiquidationAsync(positions.Select(p => p.Id))
                                          ).ToList();

            if (alreadyUsedPositionIds.Any())
            {
                await _log.WriteWarningAsync(
                    nameof(StartSpecialLiquidationInternalCommand),
                    nameof(SpecialLiquidationCommandsHandler),
                    $"Position(s) {string.Join(", ", alreadyUsedPositionIds)} will be excluded since they are already in Special Liquidation process or the process was successfully finished.");

                positions = positions.Where(p => !alreadyUsedPositionIds.Contains(p.Id)).ToList();
            }

            if (!positions.Any())
            {
                publisher.PublishEvent(new SpecialLiquidationFailedEvent
                {
                    OperationId  = command.OperationId,
                    CreationTime = _dateService.Now(),
                    Reason       = "No positions to liquidate",
                });

                return;
            }

            if (!TryGetExchangeNameFromPositions(positions, out var externalProviderId))
            {
                publisher.PublishEvent(new SpecialLiquidationFailedEvent
                {
                    OperationId  = command.OperationId,
                    CreationTime = _dateService.Now(),
                    Reason       = "All requested positions must be open on the same external exchange",
                });
                return;
            }

            var assetPairId = positions.First().AssetPairId;

            if (_assetPairsCache.GetAssetPairById(assetPairId).IsDiscontinued)
            {
                publisher.PublishEvent(new SpecialLiquidationFailedEvent
                {
                    OperationId  = command.OperationId,
                    CreationTime = _dateService.Now(),
                    Reason       = $"Asset pair {assetPairId} is discontinued",
                });

                return;
            }

            var(executionInfo, _) = await _operationExecutionInfoRepository.GetOrAddAsync(
                operationName : SpecialLiquidationSaga.OperationName,
                operationId : command.OperationId,
                factory : () => new OperationExecutionInfo <SpecialLiquidationOperationData>(
                    operationName: SpecialLiquidationSaga.OperationName,
                    id: command.OperationId,
                    lastModified: _dateService.Now(),
                    data: new SpecialLiquidationOperationData
            {
                State                = SpecialLiquidationOperationState.Initiated,
                Instrument           = assetPairId,
                PositionIds          = positions.Select(x => x.Id).ToList(),
                ExternalProviderId   = externalProviderId,
                AccountId            = command.AccountId,
                CausationOperationId = command.CausationOperationId,
                AdditionalInfo       = command.AdditionalInfo,
                OriginatorType       = command.OriginatorType
            }
                    ));

            if (executionInfo.Data.SwitchState(SpecialLiquidationOperationState.Initiated, SpecialLiquidationOperationState.Started))
            {
                publisher.PublishEvent(new SpecialLiquidationStartedInternalEvent
                {
                    OperationId  = command.OperationId,
                    CreationTime = _dateService.Now(),
                    Instrument   = positions.FirstOrDefault()?.AssetPairId,
                });

                _chaosKitty.Meow(command.OperationId);

                await _operationExecutionInfoRepository.Save(executionInfo);
            }
        }