private async ValueTask <bool> updateTradeItem(SOrderBooks qob, List <BTradeItem> tradeItems, string stream) { var _rqo = new SOrderBooks { exchange = BNLogger.SNG.exchange_name, stream = stream, symbol = qob.symbol, sequentialId = tradeItems.Max(t => t.timestamp), result = new SOrderBook() }; var _settings = __qSettings.ContainsKey(qob.symbol) ? __qSettings[qob.symbol] : __qSettings[qob.symbol] = new Settings(); lock (__qOrderBooks) { _settings.before_trade_ask_size = qob.result.asks.Sum(o => o.quantity); _settings.before_trade_bid_size = qob.result.bids.Sum(o => o.quantity); foreach (var _t in tradeItems.OrderBy(t => t.timestamp)) { if (_settings.last_trade_time >= _t.timestamp) { continue; } _settings.last_trade_time = _t.timestamp; var _ask = qob.result.asks.Where(o => o.price == _t.price).SingleOrDefault(); if (_ask != null) { if (_ask.quantity <= _t.quantity) { var _aoi = new SOrderBookItem { action = "delete", price = _ask.price, quantity = _ask.quantity, amount = _ask.price * _ask.quantity, count = 1 }; _rqo.result.asks.Add(_aoi); _ask.quantity = 0; } else { _ask.quantity -= _t.quantity; var _aoi = new SOrderBookItem { action = "update", price = _ask.price, quantity = _ask.quantity, amount = _ask.price * _ask.quantity, count = 1 }; _rqo.result.asks.Add(_aoi); } } var _bid = qob.result.bids.Where(o => o.price == _t.price).SingleOrDefault(); if (_bid != null) { if (_bid.quantity <= _t.quantity) { var _aoi = new SOrderBookItem { action = "delete", price = _bid.price, quantity = _bid.quantity, amount = _bid.price * _bid.quantity, count = 1 }; _rqo.result.bids.Add(_aoi); _bid.quantity = 0; } else { _bid.quantity -= _t.quantity; var _aoi = new SOrderBookItem { action = "update", price = _bid.price, quantity = _bid.quantity, amount = _bid.price * _bid.quantity, count = 1 }; _rqo.result.bids.Add(_aoi); } } // orderbook에 해당 하는 price-level 보다 안쪽에 위치한 level들은 삭제 해야 한다. var _strange_asks = qob.result.asks.Where(o => o.price < _t.price); if (_strange_asks.Count() > 0) { foreach (var _qox in _strange_asks) { var _aoi = new SOrderBookItem { action = "delete", price = _qox.price, quantity = _qox.quantity, amount = _qox.price * _qox.quantity, count = 1 }; _rqo.result.asks.Add(_aoi); _qox.quantity = 0; } } var _strange_bids = qob.result.bids.Where(o => o.price > _t.price); if (_strange_bids.Count() > 0) { foreach (var _qox in _strange_bids) { var _aoi = new SOrderBookItem { action = "delete", price = _qox.price, quantity = _qox.quantity, amount = _qox.price * _qox.quantity, count = 1 }; _rqo.result.bids.Add(_aoi); _qox.quantity = 0; } } } qob.sequentialId = _rqo.sequentialId; qob.result.asks.RemoveAll(o => o.quantity == 0); qob.result.bids.RemoveAll(o => o.quantity == 0); } if (_rqo.result.asks.Count + _rqo.result.bids.Count > 0) { await publishOrderbook(_rqo); //_settings.orderbook_count = 0; } return(true); }
private async ValueTask <bool> updateOrderbook(SOrderBooks qob, SOrderBooks cob, Settings settings) { var _nob = new SOrderBooks { exchange = cob.exchange, stream = "diffbooks", symbol = cob.symbol, action = cob.action, sequentialId = cob.sequentialId, result = new SOrderBook { timestamp = cob.result.timestamp, askSumQty = 0, bidSumQty = 0 } }; lock (__qOrderBooks) { foreach (var _ci in cob.result.asks) { var _qi = qob.result.asks.Where(o => o.price == _ci.price).SingleOrDefault(); if (_qi == null) { var _ici = new SOrderBookItem { action = "insert", id = _ci.id, price = _ci.price, quantity = _ci.quantity, amount = _ci.price * _ci.quantity, count = 1 }; _nob.result.asks.Add(_ici); qob.result.asks.Add(_ici); _nob.result.askSumQty += _ci.quantity; } else if (_qi.quantity != _ci.quantity) { _nob.result.asks.Add(new SOrderBookItem { action = "update", id = _qi.id, price = _qi.price, quantity = _ci.quantity, amount = _qi.price * _ci.quantity, count = 1 }); _qi.quantity = _ci.quantity; _qi.amount = _qi.price * _qi.quantity; _nob.result.askSumQty += _ci.quantity; } } foreach (var _ci in cob.result.bids) { var _qi = qob.result.bids.Where(o => o.price == _ci.price).SingleOrDefault(); if (_qi == null) { var _ici = new SOrderBookItem { action = "insert", id = _ci.id, price = _ci.price, quantity = _ci.quantity, amount = _ci.price * _ci.quantity, count = 1 }; _nob.result.bids.Add(_ici); qob.result.bids.Add(_ici); _nob.result.bidSumQty += _ci.quantity; } else if (_qi.quantity != _ci.quantity) { _nob.result.bids.Add(new SOrderBookItem { action = "update", id = _qi.id, price = _qi.price, quantity = _ci.quantity, amount = _qi.price * _ci.quantity, count = 1 }); _qi.quantity = _ci.quantity; _qi.amount = _qi.quantity * _qi.price; _nob.result.bidSumQty += _ci.quantity; } } foreach (var _qi in qob.result.asks) { var _ci = cob.result.asks.Where(o => o.price == _qi.price).SingleOrDefault(); if (_ci == null) { _nob.result.asks.Add(new SOrderBookItem { action = "delete", id = _qi.id, price = _qi.price, quantity = _qi.quantity, amount = _qi.price * _qi.quantity, count = 1 }); _nob.result.askSumQty -= _qi.quantity; _qi.quantity = 0; _qi.amount = 0; } } foreach (var _qi in qob.result.bids) { var _ci = cob.result.bids.Where(o => o.price == _qi.price).SingleOrDefault(); if (_ci == null) { _nob.result.bids.Add(new SOrderBookItem { action = "delete", id = _qi.id, price = _qi.price, quantity = _qi.quantity, amount = _qi.price * _qi.quantity, count = 1 }); _nob.result.bidSumQty -= _qi.quantity; _qi.quantity = 0; _qi.amount = 0; } } qob.result.asks.RemoveAll(o => o.quantity == 0); qob.result.bids.RemoveAll(o => o.quantity == 0); } if (++settings.orderbook_count == __gmconfig.SnapshotSkipCounter) { qob.sequentialId = cob.sequentialId; await snapshotOrderbook(_nob.symbol); } else { _nob.result.asks.RemoveAll(o => o.quantity == 0); _nob.result.bids.RemoveAll(o => o.quantity == 0); if (_nob.result.asks.Count > 0 || _nob.result.bids.Count > 0) { await publishOrderbook(_nob); } } return(true); }
private async ValueTask <bool> updateOrderbook(SOrderBooks qob, BAOrderBook orderbook, Settings settings) { var _dqo = new SOrderBooks { exchange = BNLogger.SNG.exchange_name, stream = "diffbooks", symbol = orderbook.data.symbol, sequentialId = orderbook.data.lastId, result = new SOrderBook() }; lock (__qOrderBooks) { foreach (var _oi in orderbook.data.asks) { var _ask = qob.result.asks.Where(o => o.price == _oi[0]).SingleOrDefault(); if (_ask == null) { var _aoi = new SOrderBookItem { action = "insert", price = _oi[0], quantity = _oi[1], amount = _oi[0] * _oi[1], count = 1 }; _dqo.result.asks.Add(_aoi); qob.result.asks.Add(_aoi); } else if (_ask.quantity != _oi[1]) { var _aoi = new SOrderBookItem { action = "update", price = _oi[0], quantity = _oi[1], amount = _oi[0] * _oi[1], count = 1 }; _dqo.result.asks.Add(_aoi); _ask.quantity = _oi[1]; } } foreach (var _oi in orderbook.data.bids) { var _bid = qob.result.bids.Where(o => o.price == _oi[0]).SingleOrDefault(); if (_bid == null) { var _boi = new SOrderBookItem { action = "insert", price = _oi[0], quantity = _oi[1], amount = _oi[0] * _oi[1], count = 1 }; _dqo.result.bids.Add(_boi); qob.result.bids.Add(_boi); } else if (_bid.quantity != _oi[1]) { var _boi = new SOrderBookItem { action = "update", price = _oi[0], quantity = _oi[1], amount = _oi[0] * _oi[1], count = 1 }; _dqo.result.bids.Add(_boi); _bid.quantity = _oi[1]; } } foreach (var _qi in qob.result.asks) { var _ask = orderbook.data.asks.Where(o => o[0] == _qi.price).SingleOrDefault(); if (_ask == null) { _dqo.result.asks.Add(new SOrderBookItem { action = "delete", price = _qi.price, quantity = _qi.quantity, amount = _qi.price * _qi.quantity, count = 1 }); _qi.quantity = 0; } } foreach (var _qi in qob.result.bids) { var _bid = orderbook.data.bids.Where(o => o[0] == _qi.price).SingleOrDefault(); if (_bid == null) { _dqo.result.bids.Add(new SOrderBookItem { action = "delete", price = _qi.price, quantity = _qi.quantity, amount = _qi.price * _qi.quantity, count = 1 }); _qi.quantity = 0; } } qob.result.asks.RemoveAll(o => o.quantity == 0); qob.result.bids.RemoveAll(o => o.quantity == 0); } if (++settings.orderbook_count == __bnconfig.OrderBookCounter) { settings.orderbook_count = 0; qob.sequentialId = orderbook.data.lastId; await snapshotOrderbook(_dqo.exchange, _dqo.symbol); } else { await publishOrderbook(_dqo); } return(true); }