public static bool TryParse(string message, out TickMessage tickMessage)
        {
            tickMessage = default;
            DateTime timestamp         = default;
            double   last              = default;
            int      lastSize          = default;
            int      totalVolume       = default;
            double   bid               = default;
            double   ask               = default;
            long     tickId            = default;
            char     basisForLast      = default;
            int      tradeMarketCenter = default;

            var values = message.SplitFeedMessage();
            var parsed = values.Length >= 10 &&
                         DateTime.TryParseExact(values[0], TickDateTimeFormat, CultureInfo.InvariantCulture, DateTimeStyles.None, out timestamp) &&
                         double.TryParse(values[1], NumberStyles.Any, CultureInfo.InvariantCulture, out last) &&
                         int.TryParse(values[2], NumberStyles.Any, CultureInfo.InvariantCulture, out lastSize) &&
                         int.TryParse(values[3], NumberStyles.Any, CultureInfo.InvariantCulture, out totalVolume) &&
                         double.TryParse(values[4], NumberStyles.Any, CultureInfo.InvariantCulture, out bid) &&
                         double.TryParse(values[5], NumberStyles.Any, CultureInfo.InvariantCulture, out ask) &&
                         long.TryParse(values[6], NumberStyles.Any, CultureInfo.InvariantCulture, out tickId) &&
                         char.TryParse(values[7], out basisForLast) &&
                         int.TryParse(values[8], NumberStyles.Any, CultureInfo.InvariantCulture, out tradeMarketCenter);

            if (!parsed)
            {
                return(false);
            }

            tickMessage = new TickMessage(timestamp, last, lastSize, totalVolume, bid, ask, tickId, basisForLast, tradeMarketCenter, values[9]);
            return(true);
        }
        public static TickMessage ParseWithRequestId(string message)
        {
            if (TickMessage.TryParseWithRequestId(message, out var tickMessage))
            {
                return(tickMessage);
            }

            throw new Exception($"Unable to parse message into TickMessage with requestId\nmessage={message}");
        }
        private static bool TryParseInnerParser(string[] values, out TickMessage tickMessage,
                                                int indexBase, bool hasRequestId, int tradeAggressor,
                                                int dayCode, bool parsedTradeAggressor, bool parsedDayCode)
        {
            tickMessage = null;

            DateTime timestamp         = default;
            double   last              = default;
            int      lastSize          = default;
            int      totalVolume       = default;
            double   bid               = default;
            double   ask               = default;
            long     tickId            = default;
            char     basisForLast      = default;
            int      tradeMarketCenter = default;

            var parsed =
                DateTime.TryParseExact(values[indexBase + Field_TimeStamp], TickDateTimeFormat, CultureInfo.InvariantCulture, DateTimeStyles.None, out timestamp) &&
                double.TryParse(values[indexBase + Field_Last], NumberStyles.Any, CultureInfo.InvariantCulture, out last) &&
                int.TryParse(values[indexBase + Field_LastSize], NumberStyles.Any, CultureInfo.InvariantCulture, out lastSize) &&
                int.TryParse(values[indexBase + Field_TotalVolume], NumberStyles.Any, CultureInfo.InvariantCulture, out totalVolume) &&
                double.TryParse(values[indexBase + Field_Bid], NumberStyles.Any, CultureInfo.InvariantCulture, out bid) &&
                double.TryParse(values[indexBase + Field_Ask], NumberStyles.Any, CultureInfo.InvariantCulture, out ask) &&
                long.TryParse(values[indexBase + Field_TickId], NumberStyles.Any, CultureInfo.InvariantCulture, out tickId) &&
                char.TryParse(values[indexBase + Field_BasisForLast], out basisForLast) &&
                int.TryParse(values[indexBase + Field_TradeMarketCenter], NumberStyles.Any, CultureInfo.InvariantCulture, out tradeMarketCenter) &&
                parsedTradeAggressor &&
                parsedDayCode;

            var tradeConditions = values[indexBase + Field_TradeConditions];

            if (parsed)
            {
                tickMessage = new TickMessage(
                    timestamp,
                    last,
                    lastSize,
                    totalVolume,
                    bid,
                    ask,
                    tickId,
                    basisForLast,
                    tradeMarketCenter,
                    tradeConditions,
                    tradeAggressor,
                    dayCode,
                    hasRequestId ? values[0] : null);
            }

            return(parsed);
        }
        public static bool TryParse(string message, out TickMessage tickMessage)
        {
            DateTime timestamp         = default;
            double   last              = default;
            int      lastSize          = default;
            int      totalVolume       = default;
            double   bid               = default;
            double   ask               = default;
            long     tickId            = default;
            char     basisForLast      = default;
            int      tradeMarketCenter = default;
            int      tradeAggressor    = default;
            int      dayCode           = default;

            var  values = message.SplitFeedMessage();
            bool parsed;

            if (values.Length <= 11)
            {
                // old protocol < 6.1 data
                parsed = values.Length >= 10 &&
                         DateTime.TryParseExact(values[0], TickDateTimeFormat, CultureInfo.InvariantCulture, DateTimeStyles.None, out timestamp) &
                         double.TryParse(values[1], NumberStyles.Any, CultureInfo.InvariantCulture, out last) &
                         int.TryParse(values[2], NumberStyles.Any, CultureInfo.InvariantCulture, out lastSize) &
                         int.TryParse(values[3], NumberStyles.Any, CultureInfo.InvariantCulture, out totalVolume) &
                         double.TryParse(values[4], NumberStyles.Any, CultureInfo.InvariantCulture, out bid) &
                         double.TryParse(values[5], NumberStyles.Any, CultureInfo.InvariantCulture, out ask) &
                         long.TryParse(values[6], NumberStyles.Any, CultureInfo.InvariantCulture, out tickId) &
                         char.TryParse(values[7], out basisForLast) &
                         int.TryParse(values[8], NumberStyles.Any, CultureInfo.InvariantCulture, out tradeMarketCenter);

                tickMessage = new TickMessage(timestamp, last, lastSize, totalVolume, bid, ask, tickId, basisForLast, tradeMarketCenter, values[9]);
                return(parsed);
            }

            parsed = values.Length >= 12 &&
                     DateTime.TryParseExact(values[0], TickDateTimeFormat, CultureInfo.InvariantCulture, DateTimeStyles.None, out timestamp) &
                     double.TryParse(values[1], NumberStyles.Any, CultureInfo.InvariantCulture, out last) &
                     int.TryParse(values[2], NumberStyles.Any, CultureInfo.InvariantCulture, out lastSize) &
                     int.TryParse(values[3], NumberStyles.Any, CultureInfo.InvariantCulture, out totalVolume) &
                     double.TryParse(values[4], NumberStyles.Any, CultureInfo.InvariantCulture, out bid) &
                     double.TryParse(values[5], NumberStyles.Any, CultureInfo.InvariantCulture, out ask) &
                     long.TryParse(values[6], NumberStyles.Any, CultureInfo.InvariantCulture, out tickId) &
                     char.TryParse(values[7], out basisForLast) &
                     int.TryParse(values[8], NumberStyles.Any, CultureInfo.InvariantCulture, out tradeMarketCenter) &
                     int.TryParse(values[10], NumberStyles.Any, CultureInfo.InvariantCulture, out tradeAggressor) &
                     int.TryParse(values[11], NumberStyles.Any, CultureInfo.InvariantCulture, out dayCode);

            tickMessage = new TickMessage(timestamp, last, lastSize, totalVolume, bid, ask, tickId, basisForLast, tradeMarketCenter, values[9], tradeAggressor, dayCode);
            return(parsed);
        }
        private static bool TryParseInner(string message, out TickMessage tickMessage, bool hasRequestId)
        {
            var  messageDataIdIndex   = hasRequestId ? 1 : 0;
            var  indexBase            = messageDataIdIndex;
            bool parsedTradeAggressor = false;
            bool parsedDayCode        = false;
            int  tradeAggressor       = default;
            int  dayCode = default;

            var values = message.SplitFeedMessage();

            if (values[messageDataIdIndex] == HistoricalMessageHandler.HistoricalDataId)
            {
                // protocol ==6.2
                indexBase++;
                parsedTradeAggressor = int.TryParse(values[indexBase + Field_TradeAggressor], NumberStyles.Any, CultureInfo.InvariantCulture, out tradeAggressor);
                parsedDayCode        = int.TryParse(values[indexBase + Field_DayCode], NumberStyles.Any, CultureInfo.InvariantCulture, out dayCode);
            }

            // protocol <6.2
            if ((!hasRequestId && values.Length == 12) || (hasRequestId && values.Length == 13))
            {
                // protocol ==6.1
                parsedTradeAggressor = int.TryParse(values[indexBase + Field_TradeAggressor], NumberStyles.Any, CultureInfo.InvariantCulture, out tradeAggressor);
                parsedDayCode        = int.TryParse(values[indexBase + Field_DayCode], NumberStyles.Any, CultureInfo.InvariantCulture, out dayCode);
            }
            else
            {
                // protocol <=6.0
                //  doesn't have the extra fields
                parsedTradeAggressor = true;
                parsedDayCode        = true;
            }

            return(TryParseInnerParser(values, out tickMessage, indexBase, hasRequestId, tradeAggressor, dayCode, parsedTradeAggressor, parsedDayCode));
        }
 public static bool TryParseWithRequestId(string message, out TickMessage tickMessage)
 {
     return(TryParseInner(message, out tickMessage, true));
 }
 public static bool TryParse(string message, out TickMessage tickMessage)
 {
     return(TryParseInner(message, out tickMessage, false));
 }