Exemplo n.º 1
0
        private static void ProcessExecutionReport(FixMessage msg)
        {
            ExecutionReport execReport;

            try
            {
                // отчет об исполнении может относиться не к клиентскому ордеру,
                // а к инициированной брокером процедуре (в т.ч. - стопауту)
                if (!msg.fieldValues.ContainsKey(FixMessage.TAG_CLIENT_ORDER_ID))
                {
                    ProcessBrokerInitiatedExecutionReport(msg);
                }

                // промежуточный отчет по исполнению ордера, не учитывается
                var ordStatusStr = msg[FixMessage.TAG_ORDER_STATUS];
                if (ordStatusStr == FixMessage.VALUE_ORDER_NEW ||
                    ordStatusStr == FixMessage.VALUE_ORDER_PARTIALLY_FILLED ||
                    ordStatusStr == FixMessage.VALUE_ORDER_CALCULATED)
                {
                    return;
                }

                // получить Id запроса
                var clientIdStr = msg[FixMessage.TAG_CLIENT_ORDER_ID];
                int clientId;
                if (!int.TryParse(clientIdStr, out clientId))
                {
                    loggerNoFlood.LogMessageFormatCheckFlood(LogEntryType.Debug,
                                                             LogMagicIncorrectId, 1000 * 60 * 15, "Отчет брокера: поле ClientOrderId не представлено целым [{0}]",
                                                             clientIdStr);
                    return;
                }

                execReport = new ExecutionReport {
                    brokerResponse = { RequestId = clientId, ValueDate = DateTime.Now }
                };
                if (ordStatusStr == FixMessage.VALUE_ORDER_FILLED)
                {
                    execReport.brokerResponse.Status = OrderStatus.Исполнен;
                }
                else
                if (ordStatusStr == FixMessage.VALUE_ORDER_REJECTED)
                {
                    execReport.brokerResponse.Status = OrderStatus.Отклонен;
                }
                else
                {
                    // ордер может быть либо исполнен, либо не исполнен, третьего не дано
                    loggerNoFlood.LogMessageFormatCheckFlood(LogEntryType.Debug,
                                                             LogMagicIncorrectStatus, 1000 * 60 * 15, "Отчет брокера по запросу [{0}]: статус ({1}) не поддерживается",
                                                             clientId,
                                                             ordStatusStr);
                    return;
                }

                var price = (decimal?)null;
                if (msg.fieldValues.ContainsKey(FixMessage.TAG_ARG_PX))
                {
                    price = msg.GetValueDecimal(FixMessage.TAG_ARG_PX);
                }
                else
                if (msg.fieldValues.ContainsKey(FixMessage.TAG_PRICE))
                {
                    price = msg.GetValueDecimal(FixMessage.TAG_PRICE);
                }
                // нет цены в положительной квитанции
                if (!price.HasValue && execReport.brokerResponse.Status == OrderStatus.Исполнен)
                {
                    loggerNoFlood.LogMessageFormatCheckFlood(LogEntryType.Debug,
                                                             LogMagicNoQuoteInPositiveReport, 1000 * 60 * 15,
                                                             "Отчет брокера по запросу [{0}]: статус \"Исполнен\", нет цены",
                                                             clientId);
                    return;
                }
                execReport.brokerResponse.Price = price ?? 0;
                // сообщение об ошибке
                execReport.brokerResponse.RejectReason = OrderRejectReason.None;
                if (execReport.brokerResponse.Status != OrderStatus.Исполнен)
                {
                    if (msg.fieldValues.ContainsKey(FixMessage.TAG_ORD_REJECT_REASON))
                    {
                        var rejectReasonStr = msg[FixMessage.TAG_ORD_REJECT_REASON];
                        execReport.brokerResponse.RejectReason =
                            rejectReasonStr == FixMessage.VALUE_ORDER_REJECT_BROKER_EXCHANGE_OPT
                                ? OrderRejectReason.BrokerExchangeOption
                                : rejectReasonStr == FixMessage.VALUE_ORDER_REJECT_DUPLICATE_ORDER
                                      ? OrderRejectReason.DuplicateClOrdID
                                      : rejectReasonStr == FixMessage.VALUE_ORDER_REJECT_UNKNOWN_ORDER
                                      ? OrderRejectReason.UnknownOrder : OrderRejectReason.None;
                        execReport.brokerResponse.RejectReasonString = rejectReasonStr;
                    }
                }
            }
            catch (Exception ex)
            {
                loggerNoFlood.LogMessageFormatCheckFlood(LogEntryType.Debug,
                                                         LogMagicCommonReportParseError, 1000 * 60 * 15,
                                                         "Общая ошибка обработки ответа провайдера: {0}",
                                                         ex);
                return;
            }
            // отправить отчет FIX-дилеру
            try
            {
                execReport.SendToQueue(false);
            }
            catch (Exception ex)
            {
                loggerNoFlood.LogMessageFormatCheckFlood(LogEntryType.Debug,
                                                         LogMagicSendReportError, 1000 * 60 * 15,
                                                         "Ошибка отправки сообщения в очередь: {0}",
                                                         ex);
            }
        }