public async Task <CommandHandlingResult> Handle(ProcessLimitOrderCommand command, IEventPublisher eventPublisher)
        {
            var clientId = command.LimitOrder.Order.ClientId;

            if (!_trusted.ContainsKey(clientId))
            {
                _trusted[clientId] = (await _clientAccountClient.IsTrustedAsync(clientId)).Value;
            }

            var isTrustedClient = _trusted[clientId];

            var limitOrderExecutedEvent = new LimitOrderExecutedEvent
            {
                IsTrustedClient = isTrustedClient,
                LimitOrder      = command.LimitOrder
            };

            var tradesWerePerformed = command.LimitOrder.Trades != null && command.LimitOrder.Trades.Any();

            if (!isTrustedClient)
            {
                // need previous order state for not trusted clients
                var prevOrderState = await _limitOrdersRepository.GetOrderAsync(command.LimitOrder.Order.ClientId, command.LimitOrder.Order.Id);

                var isImmediateTrade = tradesWerePerformed && command.LimitOrder.Trades.First().Timestamp == command.LimitOrder.Order.Registered;
                limitOrderExecutedEvent.HasPrevOrderState   = prevOrderState != null && !isImmediateTrade;
                limitOrderExecutedEvent.PrevRemainingVolume = prevOrderState?.RemainingVolume;

                limitOrderExecutedEvent.Aggregated = AggregateSwaps(limitOrderExecutedEvent.LimitOrder.Trades);
            }

            await _limitOrdersRepository.CreateOrUpdateAsync(command.LimitOrder.Order);

            var status = (OrderStatus)Enum.Parse(typeof(OrderStatus), command.LimitOrder.Order.Status);

            // workaround: ME sends wrong status
            if (status == OrderStatus.Processing && !tradesWerePerformed)
            {
                status = OrderStatus.InOrderBook;
            }
            else if (status == OrderStatus.PartiallyMatched && !tradesWerePerformed)
            {
                status = OrderStatus.Placed;
            }

            if (status == OrderStatus.Processing ||
                status == OrderStatus.PartiallyMatched || // new version of Processing
                status == OrderStatus.Matched ||
                status == OrderStatus.Cancelled)
            {
                limitOrderExecutedEvent.Trades = await CreateTrades(command.LimitOrder);
            }

            eventPublisher.PublishEvent(limitOrderExecutedEvent);

            return(CommandHandlingResult.Ok());
        }
Пример #2
0
        public async Task <CommandHandlingResult> Handle(ProcessLimitOrderCommand command, IEventPublisher eventPublisher)
        {
            var sw = new Stopwatch();

            sw.Start();
            var stepWatch = new Stopwatch();

            stepWatch.Start();

            try
            {
                var clientId = command.LimitOrder.Order.ClientId;

                if (!_trusted.ContainsKey(clientId))
                {
                    _trusted[clientId] = (await _clientAccountClient.IsTrustedAsync(clientId)).Value;
                }

                _log.Info("LimitOrderProcessing", new { TxHandler = new { Step = "01. Check client account is trusted", Time = stepWatch.ElapsedMilliseconds } });
                stepWatch.Restart();

                var isTrustedClient = _trusted[clientId];

                var limitOrderExecutedEvent = new LimitOrderExecutedEvent
                {
                    IsTrustedClient = isTrustedClient,
                    LimitOrder      = command.LimitOrder
                };

                var tradesWerePerformed = command.LimitOrder.Trades != null && command.LimitOrder.Trades.Any();
                if (!isTrustedClient)
                {
                    // need previous order state for not trusted clients
                    var prevOrderState = await _limitOrdersRepository.GetOrderAsync(command.LimitOrder.Order.ClientId, command.LimitOrder.Order.Id);

                    var isImmediateTrade = tradesWerePerformed && command.LimitOrder.Trades.First().Timestamp == command.LimitOrder.Order.Registered;
                    limitOrderExecutedEvent.HasPrevOrderState   = prevOrderState != null && !isImmediateTrade;
                    limitOrderExecutedEvent.PrevRemainingVolume = prevOrderState?.RemainingVolume;

                    limitOrderExecutedEvent.Aggregated = AggregateSwaps(limitOrderExecutedEvent.LimitOrder.Trades);

                    _log.Info("LimitOrderProcessing", new { TxHandler = new { Step = "02. Get Previous order state for not trusted client", Time = stepWatch.ElapsedMilliseconds } });
                    stepWatch.Restart();
                }

                if (!isTrustedClient)
                {
                    await _limitOrdersRepository.CreateOrUpdateAsync(command.LimitOrder.Order);

                    _log.Info("LimitOrderProcessing", new { TxHandler = new { Step = "03. Upsert limit order for not trusted client", Time = stepWatch.ElapsedMilliseconds } });
                    stepWatch.Restart();
                }

                var status = (OrderStatus)Enum.Parse(typeof(OrderStatus), command.LimitOrder.Order.Status);

                // workaround: ME sends wrong status
                if (status == OrderStatus.Processing && !tradesWerePerformed)
                {
                    status = OrderStatus.InOrderBook;
                }
                else if (status == OrderStatus.PartiallyMatched && !tradesWerePerformed)
                {
                    status = OrderStatus.Placed;
                }

                if (status == OrderStatus.Processing ||
                    status == OrderStatus.PartiallyMatched ||  // new version of Processing
                    status == OrderStatus.Matched ||
                    status == OrderStatus.Cancelled)
                {
                    limitOrderExecutedEvent.Trades = await CreateTrades(command.LimitOrder);
                }

                _log.Info("LimitOrderProcessing", new { TxHandler = new { Step = "04. Create trades", Time = stepWatch.ElapsedMilliseconds } });
                stepWatch.Restart();

                eventPublisher.PublishEvent(limitOrderExecutedEvent);

                return(CommandHandlingResult.Ok());
            }
            finally
            {
                sw.Stop();
                _log.Info("Command execution time",
                          context: new { TxHandler = new { Handler = nameof(LimitOrderCommandHandler), Command = nameof(ProcessLimitOrderCommand),
                                                           Time    = sw.ElapsedMilliseconds } });
            }
        }