func TestNewMarketConnectorNewOrderRequest(t *testing.T) { //config sc := common.NewConfig() sc.MessageBusURL = "nats://localhost:22222" sc.DatabaseDriver = "memstore" //start MC svc := NewMarketConnector(sc) svc.Start() time.Sleep(100 * time.Millisecond) // mock a NewOrderRequest, really should come from OrderRouter request := &proto.NewOrderRequest{ Order: testOrder.MockOrder(), } request.Order.OrderStatus = proto.OrderStatus_ORDER_RECEIVED request.Order.SubmitDatetime = time.Now().UTC().Format(time.RFC3339Nano) request.Order.MessageType = proto.Order_NEW request.Order.OrderKey = int32(321) svc.app.OrderStore.OrderCreate(request.Order) // subscribe to check if we can receive a fill execution report from sim broker recvExecutionReport := false svc.app.MessageBus.Subscribe("order.Execution", func(m *messagebus.Msg) { recvExecutionReport = true exec := new(proto.Execution) if err := exec.Unmarshal(m.Data); err == nil { if exec.ClientOrderId != "321.1" { t.Fatalf("unexpected execution report ClOrdId %v, expecting 321.1", exec.ClientOrderId) } if exec.OrderId != 1 { t.Fatalf("unexpected execution report OrderId %v, expecting 1", exec.OrderId) } } else { t.Fatalf("unexpected execution report: %v", err) } }) // send above mock NewOrderRequest data, _ := request.Marshal() svc.app.MessageBus.Publish("order.NewOrderRequest.MC."+MarketConnectorName, data) time.Sleep(100 * time.Millisecond) //stop and disconnect MC svc.Close() if recvExecutionReport == false { t.Fatal("No execution report received from mock order new request") } }
// Common behaviours to persist and publish populated Execution entity into our data layer and message bus func (app FIXClient) processExecutionReport(er *proto.Execution) quickfix.MessageRejectError { // Find the Order by using the OrderKey without the Version // Need to try to LOAD the order, if that fails then alert stating unsolicited order received keyVersion := strings.Split(er.ClientOrderId, ".") if len(keyVersion) != 2 { return quickfix.ValueIsIncorrect(tag.ClOrdID) } if oKey, err := strconv.Atoi(keyVersion[0]); err != nil { return quickfix.ValueIsIncorrect(tag.ClOrdID) } else { if ord, err := app.OrderStore.OrderGetByOrderKey(int32(oKey)); err != nil { log.WithError(err).Warnf("Received ExecutionReport with OrderKey(%v) does not exist.", oKey) return nil // TODO: ignore or quickfix.ValueIsIncorrect(tag.ClOrdID) } else { er.OrderId = ord.OrderId } } // Persist the execution report if err := app.OrderStore.ExecutionCreate(er); err == nil { //publish to message bus data, _ := er.Marshal() app.MessageBus.Publish("order.Execution", data) } else { log.WithField("execution", er).WithError(err).Error("[ MC ] ERROR Create Reject Execution") } // Do any validating and if we are good to continue // Check if we need to cancel any execution // Check if we need to correct any execution switch er.ExecType { case proto.Execution_TRADE_CANCEL: case proto.Execution_TRADE_CORRECT: //TODO: TryGetAmendedExecution case proto.Execution_RESTATED: case proto.Execution_REJECTED: } // Check if the trade is fully filled or is done for day or canceled // .. Send message to TradePump to say trade filled and already to book. return nil }