示例#1
0
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")
	}

}
示例#2
0
// 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
}