示例#1
0
// Create a FIXClient with common routes for market connectors
func NewFIXClient(c common.Config) *FIXClient {
	app := &FIXClient{
		MessageRouter: quickfix.NewMessageRouter(),

		marketConnectorName: c.MarketConnectorName,
	}

	// Initiate message bus listening for requests
	if msgbus, err := messagebus.Connect(c.MessageBusURL); err != nil {
		log.Fatalf("error: Cannot connect to order message bus @ %v", c.MessageBusURL)
	} else {
		app.MessageBus = msgbus
	}

	// Connect to database storage driver
	if storage, err := database.NewOrderStore(c.DatabaseDriver, c.DatabaseUrl, nil); err != nil {
		log.Fatalf("error: Cannot connect to database driver %v @ %v", c.DatabaseDriver, c.DatabaseUrl)
	} else {
		app.OrderStore = storage
	}

	// QuickFIX settings from config
	appSettings := quickfix.NewSettings()
	var settings *quickfix.SessionSettings
	settings = appSettings.GlobalSettings()
	settings.Set("SocketConnectHost", "127.0.0.1")
	settings.Set("SocketConnectPort", "5001")
	settings.Set("HeartBtInt", "30")
	settings.Set("SenderCompID", "CYAN")
	settings.Set("TargetCompID", "CORP")
	settings.Set("ResetOnLogon", "Y")
	settings.Set("FileLogPath", "tmp")

	settings = quickfix.NewSessionSettings()
	settings.Set("BeginString", "FIX.4.4")
	if session, err := appSettings.AddSession(settings); err != nil {
		log.WithError(err).Fatal("FIX Session Error")
	} else {
		app.Session = session
	}

	// FIX routes
	app.AddRoute(fix44er.Route(app.onFIX44ExecutionReport))
	app.AddRoute(fix44ocj.Route(app.onFIX44OrderCancelReject))

	// FIX logging
	logFactory := quickfix.NewNullLogFactory() // quickfix.NewScreenLogFactory()

	// Create initiator
	if initiator, err := quickfix.NewInitiator(app, quickfix.NewMemoryStoreFactory(), appSettings, logFactory); err != nil {
		log.WithError(err).Fatal("FIX NewInitiator Error")
	} else {
		app.Initiator = initiator
	}

	return app
}
示例#2
0
// Initialise OrderRouter instance and set up topic subscribers
func NewOrderRouter(c Config) *OrderRouter {

	or := &OrderRouter{
		Config: c,

		// internal variables
		stopChan: make(chan bool),
		mclist:   map[string]time.Time{},
		mcChan:   make(chan *service.Heartbeat),
		reqChan:  make(chan OrderRequest),
	}

	// Connect to database storage driver
	if storage, err := database.NewOrderStore(c.DatabaseDriver, c.DatabaseUrl, nil); err != nil {
		log.Fatalf("error: Cannot connect to database driver %v @ %v", c.DatabaseDriver, c.DatabaseUrl)
	} else {
		or.orderStore = storage
	}

	// Keep a list of active MarketConnectors
	if ncSvc, err := messagebus.Connect(c.ServiceMessageBusURL); err != nil {
		log.Fatalf("error: Cannot connect to service message bus @ %v", c.ServiceMessageBusURL)
	} else {
		or.msgbusService = ncSvc
		ncSvc.Subscribe("service.Heartbeat.MC.>", func(m *messagebus.Msg) {
			hbMsg := &service.Heartbeat{}
			if err := hbMsg.Unmarshal(m.Data); err == nil {
				or.mcChan <- hbMsg
			}
		})
	}

	// Order requests processors subscribing
	if msgbus, err := messagebus.Connect(c.MessageBusURL); err != nil {
		log.Fatalf("error: Cannot connect to order message bus @ %v", c.MessageBusURL)
	} else {
		or.msgbus = msgbus

		//CL->OR order NEW request
		msgbus.Subscribe("order.NewOrderRequest", func(m *messagebus.Msg) {
			request := new(proto.NewOrderRequest)
			if err := request.Unmarshal(m.Data); err == nil && len(m.Reply) > 0 {
				// validate basic fields
				if request.Order == nil {
					// empty request
					return
				}
				if request.Order.MarketConnector == "" {
					// empty market connect
					return
				}

				orReq := OrderRequest{
					ReplyAddr:   m.Reply,
					RequestType: REQ_NEW,
					Request:     request,
				}
				oO := order.Order{
					Order: request.Order,
				}
				log.Infof("CL->OR NEW %v", oO.String())
				or.reqChan <- orReq
			}
		})

		//CL->OR order CANCEL request
		msgbus.Subscribe("order.CancelOrderRequest", func(m *messagebus.Msg) {
			request := new(proto.CancelOrderRequest)
			if err := request.Unmarshal(m.Data); err == nil && len(m.Reply) > 0 {
				// validate basic fields
				if request.OrderId == 0 {
					// request without order id
					return
				}

				orReq := OrderRequest{
					ReplyAddr:   m.Reply,
					RequestType: REQ_CANCEL,
					Request:     request,
					OrderId:     request.OrderId,
				}

				log.Infof("CL->OR CXL OrderKey := %v OrderId := %v", request.OrderKey, request.OrderId)
				or.reqChan <- orReq
			}
		})

		//CL->OR order REPLACE request
		msgbus.Subscribe("order.ReplaceOrderRequest", func(m *messagebus.Msg) {
			request := new(proto.ReplaceOrderRequest)
			if err := request.Unmarshal(m.Data); err == nil && len(m.Reply) > 0 {
				// validate basic fields
				if request.Order == nil {
					// empty request
					return
				}
				if request.Order.OrderId == 0 {
					// request without order id
					return
				}
				if request.Order.MarketConnector == "" {
					// empty market connect
					return
				}

				orReq := OrderRequest{
					ReplyAddr:   m.Reply,
					RequestType: REQ_REPLACE,
					Request:     request,
					OrderId:     request.Order.OrderId,
				}

				log.Infof("CL->OR RPL OrderKey := %v OrderId := %v", request.Order.OrderKey, request.Order.OrderId)
				or.reqChan <- orReq

			}
		})
	}

	return or
}