// Common Order FIX client routines serving requests from order router // if a market connector has special case it will need to implement its own start routine like below func (app FIXClient) Start() error { err := app.Initiator.Start() // Subscribe to order flow topics // NEW app.MessageBus.Subscribe("order.NewOrderRequest.MC."+app.marketConnectorName, func(m *messagebus.Msg) { request := new(proto.NewOrderRequest) if err := request.Unmarshal(m.Data); err == nil { order := request.Order //TODO: this is only prototype, migrate common tasks: instruments / limits processing fixmsg := fix44nos.Message{ ClOrdID: strconv.Itoa(int(order.OrderKey)) + "." + strconv.Itoa(int(order.Version)), Side: util.ProtoEnumToFIXEnum(int(order.Side)), TransactTime: time.Now(), OrdType: util.ProtoEnumToFIXEnum(int(order.OrderType)), } // Instrument specific fixmsg.Instrument.Symbol = &order.Symbol fixmsg.OrderQty = &order.Quantity if order.OrderType == proto.OrderType_LIMIT || order.OrderType == proto.OrderType_LIMIT_ON_CLOSE { fixmsg.Price = &order.LimitPrice } // Broker specific fixmsg.Account = &order.BrokerAccount fixmsg.HandlInst = stringPtr(util.ProtoEnumToFIXEnum(int(order.HandleInst))) // 142 SenderLocationID // Mandatory for CME exchanges. It contains a 2-character country. For the US and Canada, the state/province is included. fixmsg.SenderLocationID = stringPtr("UK") log.Info("MC->FIX FIX44NewOrderSingle") if err := quickfix.SendToTarget(fixmsg, app.Session); err != nil { log.WithError(err).Fatal("FIX quickfix.SendToTarget Error") } } }) // TODO: CANCEL // TODO: REPLACE return err }
func (e *Executor) OnFIX44NewOrderSingle(msg fix44nos.Message, sessionID quickfix.SessionID) (err quickfix.MessageRejectError) { symbol, err := msg.Symbol() if err != nil { return } side, err := msg.Side() if err != nil { return } orderQty, err := msg.OrderQty() if err != nil { return } ordType, err := msg.OrdType() if err != nil { return } if ordType.Value != enum.OrdType_LIMIT { err = quickfix.ValueIsIncorrect(ordType.Tag()) return } price, err := msg.Price() if err != nil { return } clOrdID, err := msg.ClOrdID() if err != nil { return } execReport := fix44er.Builder( field.NewOrderID(e.genOrderID()), field.NewExecID(e.genExecID()), field.NewExecType(enum.ExecType_FILL), field.NewOrdStatus(enum.OrdStatus_FILLED), side, field.NewLeavesQty(0), field.NewCumQty(orderQty.Value), field.NewAvgPx(price.Value)) execReport.Body().Set(clOrdID) execReport.Body().Set(symbol) execReport.Body().Set(orderQty) execReport.Body().Set(field.NewLastQty(orderQty.Value)) execReport.Body().Set(field.NewLastPx(price.Value)) if acct, err := msg.Account(); err != nil { execReport.Body().Set(acct) } quickfix.SendToTarget(execReport.MessageBuilder, sessionID) return }