// 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 }
// 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 }