/// <summary> /// removes the level from the specified side's excess level /// </summary> /// <returns></returns> private bool RemoveLevelFromExcess(DepthLevelMap depthLevelMap, DepthLevel[] sideLevels) { if (depthLevelMap.Any()) { sideLevels.Last().UpdatePrice(depthLevelMap.First().Value.Price); sideLevels.Last().UpdateVolume(depthLevelMap.First().Value.AggregatedVolume); sideLevels.Last().UpdateOrderCount(depthLevelMap.First().Value.OrderCount); sideLevels.Last().ChangeExcessStatus(false); depthLevelMap.RemoveLevel(depthLevelMap.First().Value.Price); return(true); } return(false); }
/// <summary> /// Erase the specified level from the Depth Levels /// </summary> /// <param name="inboundLevel"> </param> /// <param name="orderSide"></param> /// <returns></returns> public bool EraseLevel(DepthLevel inboundLevel, OrderSide orderSide) { // Specifies the last element with a non-null price in the current side Depthlevel array bool isLastLevel = orderSide == OrderSide.Buy ? ( // If the provided level is the last non-null price level inboundLevel == FindLastLevel(_bidLevels) && // If the last non-null price level is the last slot in the array FindLastLevel(_bidLevels) == _bidLevels.Last()) : // If the provided level is the last non-null price level (inboundLevel == FindLastLevel(_askLevels) && // If the last non-null price level is the last slot in the array FindLastLevel(_askLevels) == _askLevels.Last()); // If the level lies in the excess levels if (inboundLevel.IsExcess) { switch (orderSide) { case OrderSide.Buy: _bidExcessLevels.RemoveLevel(inboundLevel.Price); return(true); case OrderSide.Sell: _askExcessLevels.RemoveLevel(inboundLevel.Price); return(true); } } // Otherwise, remove the level from the current slot and move all other levels to one slot back else { DepthLevel lastSideLevel = orderSide == OrderSide.Buy ? _bidLevels.Last() : _askLevels.Last(); DepthLevel[] sideLevels = orderSide == OrderSide.Buy ? _bidLevels : _askLevels; int backEndLevelIndex = Array.FindIndex(sideLevels, depthLevel => depthLevel == lastSideLevel); int inboundLevelIndex = Array.FindIndex(sideLevels, depthLevel => depthLevel == inboundLevel); int currentLevelIndex = inboundLevelIndex; ++_lastChangeId; if (currentLevelIndex >= 0) { // Move from the current level to the last while (currentLevelIndex < backEndLevelIndex) { // In the first loop, currentLevelIndex starts from the level which is being removed, inboundLevelIndex // so we make every value null if (currentLevelIndex == inboundLevelIndex) { sideLevels[currentLevelIndex].UpdatePrice(null); sideLevels[currentLevelIndex].UpdateVolume(null); sideLevels[currentLevelIndex].UpdateOrderCount(0); sideLevels[currentLevelIndex].ChangeExcessStatus(false); } sideLevels[currentLevelIndex] = sideLevels[currentLevelIndex + 1]; UpdateLevelIndex(sideLevels, currentLevelIndex, currentLevelIndex + 1); sideLevels[currentLevelIndex].LastChange(new ChangeId(_lastChangeId)); currentLevelIndex++; } // The last element after the loop is done will be the same as the second last one as the slots have been // shifted back. So we remove this level as this is the duplicate of the level before it sideLevels[currentLevelIndex] = new DepthLevel(null); if (isLastLevel || sideLevels.Last().Price == null || sideLevels.Last().Price.Value == 0) { if (orderSide == OrderSide.Buy && (isLastLevel || sideLevels.Last().Price == null || sideLevels.Last().Price.Value == 0)) { RemoveLevelFromExcess(_bidExcessLevels, _bidLevels); } else if (orderSide == OrderSide.Sell && (isLastLevel || sideLevels.Last().Price == null || sideLevels.Last().Price.Value == 0)) { RemoveLevelFromExcess(_askExcessLevels, _askLevels); } else { sideLevels[currentLevelIndex].LastChange(new ChangeId(_lastChangeId)); } } sideLevels[currentLevelIndex].LastChange(new ChangeId(_lastChangeId)); return(true); } } return(false); }