public OrderState Update(OrderUpdate update, out Fill fill) { Assert.True(Status != OrderStatus.Finished); Assert.True(update.Status != OrderStatus.Created, "Invalid update {0} for order {1}", update, this); fill = null; bool changed = false; // Do we have a new OrderID assigned by the exchange? if (update.OrderID != null && update.OrderID != _orderID) { _log.Info("Updating OrderID from {0} to {1} for order {2}", _orderID ?? "null", update.OrderID, _state); // This will throw if we already have an order with the same ID. The update will be ignored. _orders.AddOrder(update.OrderID, this); if (_orderID != null) { _orders.RemoveOrder(_orderID); } _orderID = update.OrderID; } // Have the status changed? if (update.Status.HasValue && update.Status != Status) { _state.Status = update.Status.Value; changed = true; if (Status == OrderStatus.Finished) { Finish(); } } // Orders that aren't Created or Finished must have OrderID. if (Status != OrderStatus.Finished && Status != OrderStatus.Created && _orderID == null) { // This can happen if we sent a New Order Request to the exchange and the // reply doesn't contain OrderID. _log.Warn("Removing order with unknown ID: ", this); changed = true; Finish(); } // Orders in state Created can't have OrderID. if (Status == OrderStatus.Created && _orderID != null) { // This can happen if we sent a New Order Request to the exchange and the // reply doesn't contain order status. _log.Warn("Removing order in unknown status: ", this); changed = true; Finish(); } if (update.Price.HasValue && update.Price != _state.Price) { _state.Price = update.Price; changed = true; } if (update.LeftQuantity.HasValue && update.LeftQuantity != _state.LeftQuantity) { _state.LeftQuantity = update.LeftQuantity.Value; changed = true; } if (update.FillQuantity.HasValue && update.FillQuantity.Value > _state.FillQuantity) { // This is a so called "similated" fill. It's used only if ClientConfig.SimulateFills // is true. fill = new Fill() { Side = _state.Side, Symbol = _state.Symbol, Quantity = update.FillQuantity.Value - _state.FillQuantity, Price = update.AverageFillPrice.HasValue ? update.AverageFillPrice.Value : _state.Price.HasValue ? _state.Price.Value : 0m }; _state.FillQuantity = update.FillQuantity.Value; changed = true; } // TODO: update FillQuantity. return(changed ? (OrderState)_state.Clone() : null); }