void _dataDelivery_DataHistoryUpdateDelegate(ISourceDataDelivery dataDelivery, DataSessionInfo session, DataHistoryUpdate update) { if (session.Equals(_session) == false || update.DataTicksUnsafe.Count == 0) { return; } DataTickUpdateType?updateType = null; if (_dataTicks.Count == 0) { updateType = DataTickUpdateType.HistoryUpdate; } lock (this) { _lastDataUpdate = DateTime.Now; for (int i = 0; i < update.DataTicksUnsafe.Count; i++) { if (_dataTicks.Count == 0 || update.DataTicksUnsafe[i].DateTime > _dataTicks[_dataTicks.Count - 1].DateTime) { if (updateType.HasValue == false) { updateType = DataTickUpdateType.HistoryUpdate; } _dataTicks.Add(update.DataTicksUnsafe[i]); _cachedDataTickIndexSearches.Add(update.DataTicksUnsafe[i].DateTime, i); } } // Also check the last 5 units for any requotes that might have been sent, // this happens when price changes and we get updates for the last unit. for (int i = 0; i < 5 && update.DataTicksUnsafe.Count - 1 - i > 0 && _dataTicks.Count - 1 - i > 0; i++) { if (update.DataTicksUnsafe[update.DataTicksUnsafe.Count - 1 - i].DateTime == _dataTicks[_dataTicks.Count - 1 - i].DateTime && update.DataTicksUnsafe[update.DataTicksUnsafe.Count - 1 - i].Equals(_dataTicks[_dataTicks.Count - 1 - i]) == false) { // Since this update is only when the date times are the same, the helper cache dictionary needs not be updated. _dataTicks[_dataTicks.Count - 1 - i] = update.DataTicksUnsafe[update.DataTicksUnsafe.Count - 1 - i]; if (updateType.HasValue == false) { updateType = DataTickUpdateType.HistoryUpdate; } } } } if (updateType.HasValue && DataTickHistoryUpdateEvent != null) { DataTickHistoryUpdateEvent(this, updateType.Value); } }
void _dataDelivery_QuoteUpdateEvent(ISourceDataDelivery dataDelivery, DataSessionInfo session, Quote?quote) { if (_sessionInfo.Equals(session) == false) { return; } lock (this) { _lastQuoteTime = DateTime.Now; _currentQuote = quote; } if (QuoteUpdateEvent != null) { QuoteUpdateEvent(this); } }
/// <summary> /// Follow quotes update. /// </summary> void _dataDelivery_QuoteUpdateEvent(ISourceDataDelivery dataDelivery, DataSessionInfo session, Quote?quote) { if (_sessionInfo.Equals(session) == false || _period.HasValue == false || quote.HasValue == false) { return; } DataBar?lastBar = null; if (_dataBars.Count > 0) { lastBar = _dataBars[_dataBars.Count - 1]; } else {// If there are no existing bars, we do not operate, to evade mixing up start / end period etc. return; } TimeSpan?period = _period; DataBarUpdateType?updateType = null; // The time of a bar is its open time, so everything after a "period" closeVolume of time after it is part of that bar. if (lastBar.Value.DateTime + period < quote.Value.Time) {// We need to append a new bar. DateTime newBarDateTime = lastBar.Value.DateTime; int i = 0; while (newBarDateTime.Add(period.Value) < quote.Value.Time) {// Establish end time of new bar (max 1000 steps to evade potential lockups). newBarDateTime = newBarDateTime.Add(period.Value); i++; if (i > 1000) {// We have tried and failed to establish proper new period so just abort. SystemMonitor.OperationError("We have tried and failed to establish proper new period so quote aborted."); return; } } DataBar?newBar = BarFromQuote(lastBar, newBarDateTime, quote.Value); if (newBar.HasValue == false) {// Failed to establish bar from quote. return; } updateType = DataBarUpdateType.NewPeriod; lock (this) {// Add the new bar. _lastDataUpdate = DateTime.Now; _dataBars.Add(newBar.Value); } } else { updateType = DataBarUpdateType.CurrentBarUpdate; lock (this) {// Just update the current last bar. _lastDataUpdate = DateTime.Now; _dataBars[_dataBars.Count - 1] = UpdateCurrentBar(lastBar.Value, quote.Value); } } if (updateType.HasValue && DataBarHistoryUpdateEvent != null) { DataBarHistoryUpdateEvent(this, updateType.Value, 1); } }