private QuoteChangeMessage ApplyNewState(BookInfo info, QuoteChangeMessage quoteMsg, QuoteChangeStates newState) { var currState = info.State; void CheckSwitch() { switch (currState) { case _none: case QuoteChangeStates.SnapshotStarted: { if (newState != QuoteChangeStates.SnapshotBuilding && newState != QuoteChangeStates.SnapshotComplete) { this.AddDebugLog($"{currState}->{newState}"); } break; } case QuoteChangeStates.SnapshotBuilding: { if (newState != QuoteChangeStates.SnapshotBuilding && newState != QuoteChangeStates.SnapshotComplete) { this.AddDebugLog($"{currState}->{newState}"); } break; } case QuoteChangeStates.SnapshotComplete: case QuoteChangeStates.Increment: { if (newState == QuoteChangeStates.SnapshotBuilding) { this.AddDebugLog($"{currState}->{newState}"); } break; } } } if (currState != newState) { CheckSwitch(); if (newState == QuoteChangeStates.SnapshotStarted) { info.Bids.Clear(); info.Asks.Clear(); } switch (currState) { case _none: { info.Bids.Clear(); info.Asks.Clear(); break; } case QuoteChangeStates.SnapshotStarted: break; case QuoteChangeStates.SnapshotBuilding: break; case QuoteChangeStates.SnapshotComplete: { if (newState == QuoteChangeStates.SnapshotComplete) { info.Bids.Clear(); info.Asks.Clear(); } break; } case QuoteChangeStates.Increment: break; default: throw new ArgumentOutOfRangeException(currState.ToString()); } info.State = currState = newState; } void Apply(IEnumerable <QuoteChange> from, QuotesDict to) { foreach (var quote in from) { if (quote.Volume == 0) { to.Remove(quote.Price); } else { to[quote.Price] = Tuple.Create(quote.Volume, quote.OrdersCount, quote.Condition); } } } void ApplyByPos(IEnumerable <QuoteChange> from, QuotesByPosList to) { foreach (var quote in from) { var startPos = quote.StartPosition.Value; switch (quote.Action) { case QuoteChangeActions.New: { var tuple = Tuple.Create(quote.Price, quote.Volume, quote.OrdersCount, quote.Condition); if (startPos > to.Count) { throw new InvalidOperationException($"Pos={startPos}>Count={to.Count}"); } else if (startPos == to.Count) { to.Add(tuple); } else { to.Insert(startPos, tuple); } break; } case QuoteChangeActions.Update: { to[startPos] = Tuple.Create(quote.Price, quote.Volume, quote.OrdersCount, quote.Condition); break; } case QuoteChangeActions.Delete: { if (quote.EndPosition == null) { to.RemoveAt(startPos); } else { to.RemoveRange(startPos, (quote.EndPosition.Value - startPos) + 1); } break; } default: throw new ArgumentOutOfRangeException(nameof(from), quote.Action, LocalizedStrings.Str1219); } } } if (quoteMsg.HasPositions) { ApplyByPos(quoteMsg.Bids, info.BidsByPos); ApplyByPos(quoteMsg.Asks, info.AsksByPos); } else { Apply(quoteMsg.Bids, info.Bids); Apply(quoteMsg.Asks, info.Asks); } if (currState == QuoteChangeStates.SnapshotStarted || currState == QuoteChangeStates.SnapshotBuilding) { return(null); } IEnumerable <QuoteChange> bids; IEnumerable <QuoteChange> asks; if (quoteMsg.HasPositions) { bids = info.BidsByPos.Select(p => new QuoteChange(p.Item1, p.Item2, p.Item3, p.Item4)); asks = info.AsksByPos.Select(p => new QuoteChange(p.Item1, p.Item2, p.Item3, p.Item4)); } else { bids = info.Bids.Select(p => new QuoteChange(p.Key, p.Value.Item1, p.Value.Item2, p.Value.Item3)); asks = info.Asks.Select(p => new QuoteChange(p.Key, p.Value.Item1, p.Value.Item2, p.Value.Item3)); } return(new QuoteChangeMessage { SecurityId = quoteMsg.SecurityId, Bids = bids.ToArray(), Asks = asks.ToArray(), IsSorted = true, ServerTime = quoteMsg.ServerTime, OriginalTransactionId = quoteMsg.OriginalTransactionId, }); }
/// <summary> /// Try create full book. /// </summary> /// <param name="change">Book change.</param> /// <returns>Full book.</returns> public QuoteChangeMessage TryApply(QuoteChangeMessage change) { if (change is null) { throw new ArgumentNullException(nameof(change)); } if (change.State is null) { throw new ArgumentException(nameof(change)); } var currState = _state; var newState = change.State.Value; bool CheckSwitch() { switch (currState) { case _none: case QuoteChangeStates.SnapshotStarted: { if (newState != QuoteChangeStates.SnapshotBuilding && newState != QuoteChangeStates.SnapshotComplete) { this.AddDebugLog($"{currState}->{newState}"); return(false); } break; } case QuoteChangeStates.SnapshotBuilding: { if (newState != QuoteChangeStates.SnapshotBuilding && newState != QuoteChangeStates.SnapshotComplete) { this.AddDebugLog($"{currState}->{newState}"); return(false); } break; } case QuoteChangeStates.SnapshotComplete: case QuoteChangeStates.Increment: { if (newState == QuoteChangeStates.SnapshotBuilding) { this.AddDebugLog($"{currState}->{newState}"); return(false); } break; } } return(true); } var resetState = newState == QuoteChangeStates.SnapshotStarted || newState == QuoteChangeStates.SnapshotComplete; if (currState != newState || resetState) { if (!CheckSwitch()) { return(null); } if (currState == _none || resetState) { _bids.Clear(); _asks.Clear(); _bidsByPos.Clear(); _asksByPos.Clear(); } _state = currState = newState; }
/// <summary> /// Try create full book. /// </summary> /// <param name="change">Book change.</param> /// <returns>Full book.</returns> public QuoteChangeMessage TryApply(QuoteChangeMessage change) { if (change is null) { throw new ArgumentNullException(nameof(change)); } if (change.State == null) { throw new ArgumentException(nameof(change)); } var currState = _state; var newState = change.State.Value; void CheckSwitch() { switch (currState) { case _none: case QuoteChangeStates.SnapshotStarted: { if (newState != QuoteChangeStates.SnapshotBuilding && newState != QuoteChangeStates.SnapshotComplete) { _logs.AddDebugLog($"{currState}->{newState}"); } break; } case QuoteChangeStates.SnapshotBuilding: { if (newState != QuoteChangeStates.SnapshotBuilding && newState != QuoteChangeStates.SnapshotComplete) { _logs.AddDebugLog($"{currState}->{newState}"); } break; } case QuoteChangeStates.SnapshotComplete: case QuoteChangeStates.Increment: { if (newState == QuoteChangeStates.SnapshotBuilding) { _logs.AddDebugLog($"{currState}->{newState}"); } break; } } } if (currState != newState || newState == QuoteChangeStates.SnapshotComplete) { CheckSwitch(); if (newState == QuoteChangeStates.SnapshotStarted) { _bids.Clear(); _asks.Clear(); } switch (currState) { case _none: { _bids.Clear(); _asks.Clear(); break; } case QuoteChangeStates.SnapshotStarted: break; case QuoteChangeStates.SnapshotBuilding: break; case QuoteChangeStates.SnapshotComplete: { if (newState == QuoteChangeStates.SnapshotComplete) { _bids.Clear(); _asks.Clear(); } break; } case QuoteChangeStates.Increment: break; default: throw new ArgumentOutOfRangeException(currState.ToString()); } _state = currState = newState; } void Apply(IEnumerable <QuoteChange> from, SortedList <decimal, QuoteChange> to) { foreach (var quote in from) { if (quote.Volume == 0) { to.Remove(quote.Price); } else { to[quote.Price] = quote; } } } void ApplyByPos(IEnumerable <QuoteChange> from, List <QuoteChange> to) { foreach (var quote in from) { var startPos = quote.StartPosition.Value; switch (quote.Action) { case QuoteChangeActions.New: { var tuple = new QuoteChange(quote.Price, quote.Volume, quote.OrdersCount, quote.Condition); if (startPos > to.Count) { throw new InvalidOperationException($"Pos={startPos}>Count={to.Count}"); } else if (startPos == to.Count) { to.Add(tuple); } else { to.Insert(startPos, tuple); } break; } case QuoteChangeActions.Update: { to[startPos] = new QuoteChange(quote.Price, quote.Volume, quote.OrdersCount, quote.Condition); break; } case QuoteChangeActions.Delete: { if (quote.EndPosition == null) { to.RemoveAt(startPos); } else { to.RemoveRange(startPos, (quote.EndPosition.Value - startPos) + 1); } break; } default: throw new ArgumentOutOfRangeException(nameof(from), quote.Action, LocalizedStrings.Str1219); } } } if (change.HasPositions) { ApplyByPos(change.Bids, _bidsByPos); ApplyByPos(change.Asks, _asksByPos); } else { Apply(change.Bids, _bids); Apply(change.Asks, _asks); } if (currState == QuoteChangeStates.SnapshotStarted || currState == QuoteChangeStates.SnapshotBuilding) { return(null); } QuoteChange[] bids; QuoteChange[] asks; if (change.HasPositions) { bids = _bidsByPos.ToArray(); asks = _asksByPos.ToArray(); } else { bids = _bids.Values.ToArray(); asks = _asks.Values.ToArray(); } return(new QuoteChangeMessage { SecurityId = SecurityId, Bids = bids, Asks = asks, ServerTime = change.ServerTime, OriginalTransactionId = change.OriginalTransactionId, }); }
private QuoteChangeMessage ApplyNewState(BookInfo info, QuoteChangeMessage quoteMsg, QuoteChangeStates newState) { var currState = info.State; if (currState != newState) { switch (currState) { case _none: case QuoteChangeStates.SnapshotStarted: { if (newState != QuoteChangeStates.SnapshotBuilding && newState != QuoteChangeStates.SnapshotComplete) { this.AddDebugLog($"{currState}->{newState}"); return(null); } info.Bids.Clear(); info.Asks.Clear(); break; } case QuoteChangeStates.SnapshotBuilding: { if (newState != QuoteChangeStates.SnapshotComplete) { this.AddDebugLog($"{currState}->{newState}"); return(null); } break; } case QuoteChangeStates.SnapshotComplete: case QuoteChangeStates.Increment: { if (newState == QuoteChangeStates.SnapshotBuilding) { this.AddDebugLog($"{currState}->{newState}"); return(null); } break; } default: throw new ArgumentOutOfRangeException(currState.ToString()); } info.State = currState = newState; } void Copy(IEnumerable <QuoteChange> from, QuotesDict to) { foreach (var quote in from) { if (quote.Volume == 0) { to.Remove(quote.Price); } else { to[quote.Price] = quote.Volume; } } } Copy(quoteMsg.Bids, info.Bids); Copy(quoteMsg.Asks, info.Asks); if (currState == QuoteChangeStates.SnapshotStarted || currState == QuoteChangeStates.SnapshotBuilding) { return(null); } return(new QuoteChangeMessage { SecurityId = quoteMsg.SecurityId, Bids = info.Bids.Select(p => new QuoteChange(Sides.Buy, p.Key, p.Value)).ToArray(), Asks = info.Asks.Select(p => new QuoteChange(Sides.Sell, p.Key, p.Value)).ToArray(), IsSorted = true, ServerTime = quoteMsg.ServerTime, OriginalTransactionId = quoteMsg.OriginalTransactionId, }); }
/// <summary> /// Try create full book. /// </summary> /// <param name="change">Book change.</param> /// <param name="subscriptionId">Subscription.</param> /// <returns>Full book.</returns> public QuoteChangeMessage TryApply(QuoteChangeMessage change, long subscriptionId = default) { if (change is null) { throw new ArgumentNullException(nameof(change)); } if (change.State is null) { throw new ArgumentException(nameof(change)); } var currState = _state; var newState = change.State.Value; void WriteWarning() { var postfix = string.Empty; if (subscriptionId != default) { if (!_invalidSubscriptions.Add(subscriptionId)) { return; } postfix = $" (sub={subscriptionId})"; } this.AddWarningLog($"{currState}->{newState}{postfix}"); } bool CheckSwitch() { switch (currState) { case _none: case QuoteChangeStates.SnapshotStarted: { if (newState != QuoteChangeStates.SnapshotBuilding && newState != QuoteChangeStates.SnapshotComplete) { WriteWarning(); return(false); } break; } case QuoteChangeStates.SnapshotBuilding: { if (newState != QuoteChangeStates.SnapshotBuilding && newState != QuoteChangeStates.SnapshotComplete) { WriteWarning(); return(false); } break; } case QuoteChangeStates.SnapshotComplete: case QuoteChangeStates.Increment: { if (newState == QuoteChangeStates.SnapshotBuilding) { WriteWarning(); return(false); } break; } } return(true); } var resetState = newState == QuoteChangeStates.SnapshotStarted || newState == QuoteChangeStates.SnapshotComplete; if (currState != newState || resetState) { if (!CheckSwitch()) { return(null); } if (currState == _none || resetState) { _bids.Clear(); _asks.Clear(); _bidsByPos.Clear(); _asksByPos.Clear(); } _state = currState = newState; }