public static void Main(string[] args) { NbboServiceImpl s = new NbboServiceImpl(); /* * test(s); * NBBO nbbo = (NBBO)s.GetNbboData("IBM"); * Console.WriteLine(nbbo); */ PricesGenerator generator = new PricesGenerator(s); generator.Start(); while (true) { Console.Write("enter nbbo ticker or depth ticker(ctrl-c to kill):"); string cmd = Console.ReadLine(); string[] tokens = cmd.Split(' '); if (tokens.Length > 1) { if (tokens[0].Equals("nbbo")) { NBBO nbbo = (NBBO)s.GetNbboData(tokens[1].ToUpper()); if (nbbo != null) { Console.WriteLine(nbbo); } else { Console.WriteLine("ticker not found"); } } else { KeyValuePair <string, Quote>[] depth = (KeyValuePair <string, Quote>[])s.GetMarketData(tokens[1].ToUpper()); if (depth != null) { foreach (KeyValuePair <string, Quote> item in depth) { Console.WriteLine(item.Value); } } else { Console.WriteLine("ticker not found"); } } } } }
/// <summary> /// /// data format: /// "Name=IBM,Ask=5.34,AskSize=100,Bid=4.11,BidSize=200,Last=3.4,Exch=NYSE"; /// "Name=VOD,Ask=3.12,AskSize=100,Last=2.6,Exch=ARCA"; /// "Name=VOD,Bid=1.1,BidSize=300,Exch=ARCA"; /// </summary> /// <param name="data"></param> public void OnTick(string data) { Interlocked.Increment(ref counter); Quote q = parse(data); NbboWithDepth nbboWithDepth; ConcurrentDictionary <string, Quote> depth; NBBO nbbo; bool exists = cache.TryGetValue(q.Symbol, out nbboWithDepth); if (!exists) { depth = new ConcurrentDictionary <string, Quote>(); nbbo = new NBBO(); nbboWithDepth = new NbboWithDepth { Nbbo = nbbo, Depth = depth }; cache.TryAdd(q.Symbol, nbboWithDepth); } else { depth = nbboWithDepth.Depth; nbbo = nbboWithDepth.Nbbo; } Quote oldQ; exists = depth.TryGetValue(q.Exchange, out oldQ); if (!exists) { depth.TryAdd(q.Exchange, q); } else { // combine bid and ask into one quote object Quote newQuote; if (q.Bid > 0 && q.Ask > 0) { newQuote = new Quote { Symbol = q.Symbol, Bid = q.Bid, BidSize = q.BidSize, Ask = q.Ask, AskSize = q.AskSize, Exchange = q.Exchange, Last = q.Last }; } else if (q.Ask > 0) { newQuote = new Quote { Symbol = q.Symbol, Bid = oldQ.Bid, BidSize = oldQ.BidSize, Ask = q.Ask, AskSize = q.AskSize, Exchange = q.Exchange, Last = q.Last }; } else if (q.Bid > 0) { newQuote = new Quote { Symbol = q.Symbol, Bid = q.Bid, BidSize = q.BidSize, Ask = oldQ.Ask, AskSize = oldQ.AskSize, Exchange = q.Exchange, Last = q.Last }; } else { newQuote = new Quote { Symbol = q.Symbol, Bid = oldQ.Bid, BidSize = oldQ.BidSize, Ask = oldQ.Ask, AskSize = oldQ.AskSize, Exchange = q.Exchange, Last = q.Last }; } depth.AddOrUpdate(q.Exchange, newQuote, (key, oldValue) => newQuote); q = newQuote; } //if bid ask is clearly outside out NBBO, no need to update nbbo. if (q.Bid < nbbo.Bid && q.Ask > nbbo.Ask && nbbo.Bid != 0 && nbbo.Ask != 0) { return; } decimal nbboBid = decimal.MinValue, nbboAsk = decimal.MaxValue; int bidSize = 0, askSize = 0; foreach (KeyValuePair <string, Quote> item in depth) { if (item.Value.Bid > nbboBid) { nbboBid = item.Value.Bid; bidSize = item.Value.BidSize; } else if (item.Value.Bid == nbboBid) { bidSize += item.Value.BidSize; } if (item.Value.Ask < nbboAsk) { nbboAsk = item.Value.Ask; askSize = item.Value.AskSize; } else if (item.Value.Ask == nbboAsk) { askSize += item.Value.AskSize; } } NBBO newNbbo = new NBBO { Symbol = q.Symbol, Bid = nbboBid, BidSize = bidSize, Ask = nbboAsk, AskSize = askSize }; nbboWithDepth = new NbboWithDepth { Nbbo = newNbbo, Depth = depth }; cache.AddOrUpdate(q.Symbol, nbboWithDepth, (key, oldValue) => nbboWithDepth); }
private void calculateNBBO(Order order) { //Console.WriteLine("Starting NBBO clculations..... " + order.Name); // check if NBBO is created for this security lock (locker) { if (!cache.Contains("NBBO" + order.Name)) { NBBO nbb = new NBBO(); nbb.Security = order.Name; cache.Add(new CacheItem("NBBO" + order.Name, nbb), policy); } } NBBO nbbo = (NBBO)cache.Get("NBBO" + order.Name); lock (nbbo) { HashSet <string> exchanges = (HashSet <string>)cache.Get(order.Name); List <Order> orders = new List <Order>(); foreach (string exchange in exchanges) { Order o = (Order)cache.Get(order.Name + exchange); orders.Add(o); } if (orders.Count() == 0) { return; } // find the orders having maximum bid and min ask prices double maxbid = orders.Max(o => o.Bid); double minask = orders.Min(o => o.Ask); IEnumerable <Order> maxo = orders.Where(o => o.Bid != 0 && o.Bid == maxbid); IEnumerable <Order> mino = orders.Where(o => o.Ask != 0 && o.Ask == minask); Console.WriteLine("Maxbid - " + maxbid + " list - " + maxo.Count()); Console.WriteLine("Minask - " + minask + " list - " + mino.Count()); long maxbidsize = 0; long minasksize = 0; foreach (Order o in maxo) { maxbidsize += o.BidSize; } foreach (Order o in mino) { minasksize += o.AskSize; } if (maxbidsize > 0) { nbbo.NbboBid = maxbid; nbbo.NbboBidSize = maxbidsize; } if (minasksize > 0) { nbbo.NbboAsk = minask; nbbo.NbboAskSize = minasksize; } Console.WriteLine(Thread.CurrentThread.Name + "::::NBBO:::" + "Security: " + nbbo.Security + ", Bid Price: " + nbbo.NbboBid + ", Bid Size: " + nbbo.NbboBidSize + ", Ask Price: " + nbbo.NbboAsk + ", Ask Size: " + nbbo.NbboAskSize); } }