Beispiel #1
0
// 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
}
Beispiel #2
0
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
}