/// <summary> /// Report after a request about orders is made /// Possible cause: /// - New order /// - Cancel order /// - Rejected order /// - Requested order info /// - Order filled or partially filled /// </summary> /// <param name="msg"></param> /// <param name="sessionID"></param> public void OnMessage(QuickFix.FIX44.ExecutionReport msg, SessionID sessionID) { char executionReportType = msg.GetChar(Tags.ExecType); int clientOrderID = msg.GetInt(Tags.ClOrdID); switch (executionReportType) { case ExecType.NEW: { // New order execution report string avgPrice = msg.GetString(Tags.AvgPx); char side = msg.GetChar(Tags.Side); var order = new Order() { OrderID = msg.GetString(Tags.ExecID), ClientOrderID = clientOrderID, Price = double.Parse(avgPrice), Side = side }; CurrentOrders.Add(order); OrderSubmitCallback?.Invoke(false); OrderSubmitCallback = null; Log.Write($"Submission confirmed {order}", 2); break; } case ExecType.PARTIAL_FILL: { // Order executed double executionPrice = (double)msg.GetDecimal(Tags.AvgPx); int orderStatus = msg.GetInt(Tags.OrdStatus); char side = msg.GetChar(Tags.Side); double remainingQty = (double)msg.GetDecimal(Tags.LeavesQty); var order = CurrentOrders.First(o => o.ClientOrderID == clientOrderID); order.FilledVolume = order.Volume - remainingQty; Log.Write($"Partial fill {order}", 2); break; } case ExecType.FILL: { // Order executed double executionPrice = (double)msg.GetDecimal(Tags.AvgPx); int orderStatus = msg.GetInt(Tags.OrdStatus); char side = msg.GetChar(Tags.Side); var order = CurrentOrders.First(o => o.ClientOrderID == clientOrderID); order.FilledVolume = order.Volume; //CurrentOrders.Remove(order); Log.Write($"Fill {order}", 2); break; } case ExecType.CANCELED: { // Order cancel report string orderID = msg.GetString(Tags.ExecID); CurrentOrders.RemoveAll(o => o.ClientOrderID == clientOrderID); OrderCancelCallback?.Invoke(false); OrderCancelCallback = null; break; } case ExecType.REJECTED: { // Rejected order execution report OrderSubmitCallback?.Invoke(true); OrderSubmitCallback = null; string orderStatus = msg.GetString(Tags.OrdStatus); string text = msg.GetString(Tags.Text); Log.Write($"Order rejected | status: {orderStatus} | reason: {text}", 1); break; } case ExecType.PENDING_NEW: { // Requested Order info int numReports = msg.GetInt(Tags.TotNumReports); if (!CurrentOrders.Exists(o => o.ClientOrderID.Equals(clientOrderID))) { CurrentOrders.Add(new Order() { OrderID = msg.GetString(Tags.OrderID), ClientOrderID = clientOrderID, Price = (double)msg.GetDecimal(Tags.AvgPx), Side = msg.GetChar(Tags.Side) }); } break; } default: Log.Write($"Unknown execution report type {executionReportType}", 0); break; } }