private IEnumerable <MessageBuffer <T> > GetFormedBuffers(T msg, DateTimeOffset openTime, SecurityId secId) { var buffers = new List <MessageBuffer <T> >(); lock (_buffers.SyncRoot) { var buffer = _buffers.SafeAdd(openTime, key => new MessageBuffer <T>(openTime, _bufferSize)); buffer.AddMessage(_securityIndecies[secId], msg); if (!buffer.IsFilled) { return(Enumerable.Empty <MessageBuffer <T> >()); } // mika // далее идет обработка 4-рех ситуаций // // 1. первая свеча оказалась заполненой полностью, и мы просто удаляем начальные буфера // так как они уже никогда не заполняться. // // 2. первая свеча оказалось размазанной, тогда так же удаляем хвосты, но при этом формируем // из одной размазанной свечи N (= равное кол-ву инструментов) дозаполненных. // // 3. появилась заполненная полностью свеча, и тогда дозаполняем промежутки с _lastProcessBuffer // // 4. появилась размазанная свеча, и тогда дозаполняем промежутки с _lastProcessBuffer + формируем // из одной размазанной свечи N (= равное кол-ву инструментов) дозаполненных. var firstTimeBuffer = _lastProcessBuffer == null; // последней буфер, до которого (включительно) можно сформировать спред по текущим данным var lastBuffer = buffer; var deleteKeys = new List <DateTimeOffset>(); foreach (var time in _buffers.CachedKeys) { if (time >= lastBuffer.Time) { break; } var curr = _buffers[time]; if (firstTimeBuffer) { if (!buffer.IsFilled) { if (_lastProcessBuffer == null) { _lastProcessBuffer = curr; } else { _lastProcessBuffer.Fill(curr); _lastProcessBuffer = curr; } } } else { curr.Fill(_lastProcessBuffer); _lastProcessBuffer = curr; if (curr.IsFilled) { buffers.Add(curr); } } deleteKeys.Add(time); } if (!buffer.IsFilled) { lastBuffer.Fill(_lastProcessBuffer); } if (lastBuffer.IsFilled) { deleteKeys.Add(lastBuffer.Time); _lastProcessBuffer = lastBuffer; buffers.Add(lastBuffer); } deleteKeys.ForEach(k => _buffers.Remove(k)); } return(buffers); }