public void sendPackage()

in java/runner/src/intTest/java/com/epam/deltix/data/connectors/validator/L2DataValidator.java [451:595]


    public void sendPackage(PackageHeaderInfo headerInfo) {
        try {
            if ((!headerInfo.hasSymbol()) || (!CharSequenceUtils.equals(headerInfo.getSymbol(), symbol))) {
                sendMessageToLogger(headerInfo, TypeConstants.EXCHANGE_NULL, "Incorrect symbol", Severity.ERROR);
            }
            if (!headerInfo.hasEntries()) {
                sendMessageToLogger(headerInfo, TypeConstants.EXCHANGE_NULL, "Missed entries list", Severity.ERROR);
            }
            if (!headerInfo.hasPackageType()) {
                sendMessageToLogger(headerInfo, TypeConstants.EXCHANGE_NULL, "Missed package type", Severity.ERROR);
            }
            if (headerInfo.getEntries().size() == 0) {
                sendMessageToLogger(headerInfo, TypeConstants.EXCHANGE_NULL, "Empty entries list", Severity.WARNING);
                return;
            }

            checkTradePrice(headerInfo);

            checkAllEntriesFields(headerInfo);
            exchangeIds.clear();
            previousBestAsks.clear();
            previousBestBids.clear();
            if (headerInfo.getPackageType() != PackageType.INCREMENTAL_UPDATE) {
                processSnapshot(headerInfo);
                long exchangeId = headerInfo.getEntries().get(0).getExchangeId();
                exchangeIds.add(exchangeId);
                OrderBookQuote askQuote = book.getMarketSide(QuoteSide.ASK).getQuote(0);
                OrderBookQuote bidQuote = book.getMarketSide(QuoteSide.BID).getQuote(0);
                if (askQuote != null) previousBestAsks.add(askQuote.getPrice()); else previousBestAsks.add(Decimal64Utils.NEGATIVE_INFINITY);
                if (bidQuote != null) previousBestBids.add(bidQuote.getPrice()); else previousBestBids.add(Decimal64Utils.POSITIVE_INFINITY);
                book.update(headerInfo);
            } else {
                for (int i = 0; i < headerInfo.getEntries().size(); ++i) {
                    incrementHeader.getEntries().add(headerInfo.getEntries().get(i));

                    if (!exchangeIds.contains(incrementHeader.getEntries().get(0).getExchangeId())) {
                        long exchangeId = incrementHeader.getEntries().get(0).getExchangeId();
                        exchangeIds.add(exchangeId);
                        OrderBookQuote askQuote = book.getMarketSide(QuoteSide.ASK).getQuote(0);
                        OrderBookQuote bidQuote = book.getMarketSide(QuoteSide.BID).getQuote(0);
                        if (askQuote != null) previousBestAsks.add(askQuote.getPrice()); else previousBestAsks.add(Decimal64Utils.NEGATIVE_INFINITY);
                        if (bidQuote != null) previousBestBids.add(bidQuote.getPrice()); else previousBestBids.add(Decimal64Utils.POSITIVE_INFINITY);
                    }
                    if (incrementHeader.getEntries().get(0) instanceof L2EntryUpdate) {
                        L2EntryUpdate entryUpdate = (L2EntryUpdate) incrementHeader.getEntries().get(0);
                        validateIncrementEntry(headerInfo, entryUpdate);
                    } else if (incrementHeader.getEntries().get(0) instanceof L2EntryNew) {
                        L2EntryNew entryNew = (L2EntryNew) incrementHeader.getEntries().get(0);
                        validateIncrementEntry(headerInfo, entryNew);
                    }
                    book.update(incrementHeader);
                    incrementHeader.getEntries().clear();
                }
            }
            if (checkExchangeMisPrice) {
                long minAsk = Decimal64Utils.POSITIVE_INFINITY;
                long maxAsk = Decimal64Utils.NEGATIVE_INFINITY;
                long minBid = Decimal64Utils.POSITIVE_INFINITY;
                long maxBid = Decimal64Utils.NEGATIVE_INFINITY;

                MarketSide<OrderBookQuote> askQuotes = book.getMarketSide(QuoteSide.ASK);
                MarketSide<OrderBookQuote> bidQuotes = book.getMarketSide(QuoteSide.BID);
                if (askQuotes.depth() > 0) {
                    minAsk = Decimal64Utils.min(askQuotes.getQuote(0).getPrice(), minAsk);
                    maxAsk = Decimal64Utils.max(askQuotes.getQuote(0).getPrice(), maxAsk);
                }
                if (bidQuotes.depth() > 0) {
                    minBid = Decimal64Utils.min(bidQuotes.getQuote(0).getPrice(), minBid);
                    maxBid = Decimal64Utils.max(bidQuotes.getQuote(0).getPrice(), maxBid);
                }
                if (!Decimal64Utils.isZero(minAsk) && Decimal64Utils.isGreater(Decimal64Utils.divide(Decimal64Utils.subtract(maxAsk, minAsk), Decimal64Utils.abs(minAsk)), exchangeMisPrice)) {
                    sendMessageToLogger(headerInfo, TypeConstants.EXCHANGE_NULL, internalLogBuilder.clear().append("Ask Mispricing between exchanges"), Severity.WARNING);
                }
                if (!Decimal64Utils.isZero(minBid) && Decimal64Utils.isGreater(Decimal64Utils.divide(Decimal64Utils.subtract(maxBid, minBid), Decimal64Utils.abs(minBid)), exchangeMisPrice)) {
                    sendMessageToLogger(headerInfo, TypeConstants.EXCHANGE_NULL, internalLogBuilder.clear().append("Bid Mispricing between exchanges"), Severity.WARNING);
                }
            }
            if (checkLevelMisPrice) {
                MarketSide<OrderBookQuote> askQuotes = book.getMarketSide(QuoteSide.ASK);
                MarketSide<OrderBookQuote> bidQuotes = book.getMarketSide(QuoteSide.BID);
                for (int level = 1; level < askQuotes.depth() ;level++) {
                    long previousPrice = askQuotes.getQuote(level - 1).getPrice();
                    long currentPrice = askQuotes.getQuote(level).getPrice();
                    if (Decimal64Utils.isZero(currentPrice)) continue;
                    long r = Decimal64Utils.divide(previousPrice, currentPrice);
                    if (Decimal64Utils.isLess(r, Decimal64Utils.subtract(Decimal64Utils.ONE, levelMisPrice))) {
                        sendMessageToLogger(headerInfo, askQuotes.getQuote(level).getExchangeId(), internalLogBuilder.clear().append("Ask Mispricing in the exchange ").append(AlphanumericUtils.toString(askQuotes.getQuote(level).getExchangeId())).append(" at level ").append(level), Severity.WARNING);
                    }
                }
                for (int level = 1; level < bidQuotes.depth() ;level++) {
                    long previousPrice = bidQuotes.getQuote(level - 1).getPrice();
                    long currentPrice = bidQuotes.getQuote(level).getPrice();
                    long r = Decimal64Utils.divide(currentPrice, previousPrice);
                    if (Decimal64Utils.isZero(previousPrice)) continue;
                    if (Decimal64Utils.isLess(r, Decimal64Utils.subtract(Decimal64Utils.ONE, levelMisPrice))) {
                        sendMessageToLogger(headerInfo, bidQuotes.getQuote(level).getExchangeId(), internalLogBuilder.clear().append("Bid Mispricing in the exchange ").append(AlphanumericUtils.toString(bidQuotes.getQuote(level).getExchangeId())).append(" at level ").append(level), Severity.WARNING);
                    }
                }
            }
            for (int i = 0; i < exchangeIds.size(); ++i) {
                MarketSide<OrderBookQuote> askQuotes = book.getMarketSide(QuoteSide.ASK);
                MarketSide<OrderBookQuote> bidQuotes = book.getMarketSide(QuoteSide.BID);
                OrderBookQuote bestAskQuote = askQuotes != null ? askQuotes.getQuote(0) : null;
                OrderBookQuote bestBidQuote = bidQuotes != null ? bidQuotes.getQuote(0) : null;

                if (bestAskQuote != null && bestBidQuote != null) {
                    if (Decimal64Utils.isLess(bestAskQuote.getPrice(), bestBidQuote.getPrice()) && checkBidMoreThanAsk) {
                        sendMessageToLogger(headerInfo, bestAskQuote.getExchangeId(), "Bid > Ask", Severity.WARNING);
                    }
                    if (checkPackageMisPrice) {
                        if (!Decimal64Utils.isInfinity(previousBestAsks.get(i)) && !Decimal64Utils.isZero(previousBestAsks.get(i))) {
                            if (Decimal64Utils.isGreater(Decimal64Utils.abs(Decimal64Utils.divide(Decimal64Utils.subtract(previousBestAsks.get(i), bestAskQuote.getPrice()), previousBestAsks.get(i))), packageMisPrice)) {
                                sendMessageToLogger(headerInfo, bestAskQuote.getExchangeId(), "Too big ask price change after this package", Severity.WARNING);
                            }
                        }


                        if (!Decimal64Utils.isInfinity(previousBestBids.get(i)) && !Decimal64Utils.isZero(previousBestBids.get(i))) {
                            if (Decimal64Utils.isGreater(Decimal64Utils.abs(Decimal64Utils.divide(Decimal64Utils.subtract(previousBestBids.get(i), bestBidQuote.getPrice()), previousBestBids.get(i))), packageMisPrice)) {
                                sendMessageToLogger(headerInfo, bestAskQuote.getExchangeId(), "Too big bid price change after this package", Severity.WARNING);
                            }
                        }
                    }
                }

                if (bestAskQuote == null && checkEmptySide) {
                    sendMessageToLogger(headerInfo, exchangeIds.get(i), "Ask side is empty", Severity.WARNING);
                }

                if (bestBidQuote == null && checkEmptySide) {
                    sendMessageToLogger(headerInfo, exchangeIds.get(i), "Bid side is empty", Severity.WARNING);
                }

                if (askQuotes.depth() < minValidNumberOfLevels) {
                    sendMessageToLogger(headerInfo, exchangeIds.get(i), "Ask side has less than minimal valid number of levels", Severity.WARNING);
                }

                if (bidQuotes.depth() < minValidNumberOfLevels)  {
                    sendMessageToLogger(headerInfo, exchangeIds.get(i), "Bid side has less than minimal valid number of levels", Severity.WARNING);
                }
            }
        } catch (Throwable e) {
            logger.onLogEvent(this, Severity.ERROR, e, "Error in L2DataValidator.");
        }
    }