public void OnUpdate <TB, TE>(TB buf)
            where TB : IDxEventBuf <TE>
            where TE : IDxOrder
        {
            var count = 0;
            int u = 0, a = 0, r = 0;

            using (var e = buf.GetEnumerator()) {
                if (!e.MoveNext())
                {
                    Console.WriteLine($"ERROR: Update for \"{buf.Symbol}#???\" without orders");
                    return;
                }

                var sym = $"{buf.Symbol}#{e.Current?.Source}";

                if (!state.ContainsKey(sym))
                {
                    Console.WriteLine($"ERROR: Update for \"{sym}\" without snapshot");
                    return;
                }

                var s = state[sym];

                foreach (var o in buf)
                {
                    if (o.Size == 0)
                    {
                        if (s.ContainsKey(o.Index))
                        {
                            Console.WriteLine($"\"{sym}\" removal of {o.Index}");
                            s.Remove(o.Index);
                            r++;
                        }
                    }
                    else if (s.ContainsKey(o.Index))
                    {
                        var so = new SimpleOrder(o);
                        Console.WriteLine($"\"{sym}\" replace {s[o.Index]} with {so}");
                        s[o.Index] = so;
                        u++;
                    }
                    else
                    {
                        s[o.Index] = new SimpleOrder(o);
                        Console.WriteLine($"\"{sym}\" add {s[o.Index]}");
                        a++;
                    }

                    count++;
                }

                Console.WriteLine($"\"{sym}\" update with {count} orders, A/U/R:{a}/{u}/{r}");
                CheckBidAsk(sym, s);
            }
        }
        private static void CheckBidAsk(string sym, Dictionary <long, SimpleOrder> s)
        {
            SimpleOrder ask = null;
            SimpleOrder bid = null;

            foreach (var o in s.Values)
            {
                if (o.side == Side.Buy && (bid == null || bid.price < o.price))
                {
                    bid = o;
                }
                if (o.side == Side.Sell && (ask == null || ask.price > o.price))
                {
                    ask = o;
                }
            }

            if (bid != null && ask != null && bid.price >= ask.price)
            {
                Console.WriteLine($"ERROR: \"{sym}\": Cross: Bid {bid} vs Ask {ask}");
            }
        }