private static PriceByOrderSide FilterByPercentileTopPrices(OrderBookSideFlat asks, OrderBookSideFlat bids) { const decimal percentileRate = 0.1m; var topAsk = FilterByAmountPercentileAndGetTop(asks, percentileRate); var topBid = FilterByAmountPercentileAndGetTop(bids, percentileRate); return(new PriceByOrderSide(topBid, topAsk)); }
private static void RemoveOrders( IEnumerable <Order> notFinishedOrders, OrderBookSideFlat asks, OrderBookSideFlat bids) { foreach (var order in notFinishedOrders) { if (!order.Price.HasValue) { continue; } var bookSide = order.Side == OrderSide.Buy ? bids : asks; var index = Array.BinarySearch(bookSide.Prices, order.Price.Value, bookSide.Comparer); if (index >= 0) { bookSide.Amounts[index] -= order.Amount - order.FilledAmount; } } }
private static (OrderBookSideFlat asks, OrderBookSideFlat bids) FlattenSnapshot(ILocalOrderBookSnapshot snapshot) { SortedDictionary <decimal, decimal> asks, bids; switch (snapshot) { case L1LocalOrderBookSnapshot l1: asks = l1.GetAsks(); bids = l1.GetBids(); break; case L2LocalOrderBookSnapshot l2: asks = l2.Asks; bids = l2.Bids; break; default: throw new ArgumentOutOfRangeException(nameof(snapshot), snapshot, null); } return(new OrderBookSideFlat(asks), new OrderBookSideFlat(bids)); }
private static decimal?FilterByAmountPercentileAndGetTop(OrderBookSideFlat bookSide, decimal percentileRate) { if (bookSide.Size == 0) { return(null); } var percentileAmount = bookSide.Size >= 5 ? GetPercentileAmount(bookSide.Amounts, percentileRate) : 0m; // it is not necessary to filter side if there are not enough levels // prices are sorted, so we can go from top (because we want to remove top positions only) for (int i = 0; i < bookSide.Size; i++) { if (bookSide.Amounts[i] > percentileAmount) { return(bookSide.Prices[i]); } } return(null); }