Sending orders and receiving a market response

The main goal of a trading system is to send orders and receive market responses regarding these orders. In this section, we will cover how to send an order and how to get an update on these orders.

The role of the initiator is to initiate a connection with the acceptor. When the connection is established, the trading session is enabled. From this very moment, the trading system can send orders to the exchange. The order will have the following type of message:

8=FIX.4.4|9=155|35=D|11=3440|15=USD|21=2|38=20000|40=D|44=55.945|54=1|55=USD/RUB|59=3|60=20190909-19:35:27|64=SP|107=SPOT|117=b3fc02d3-373e-4632-80a0-e50c2119310e|167=FOR|10=150|

The initiator creates the orders by using the message type 35=D (representing a single order). All the fields of these orders will be filled in by the function of the quickfix library. Let's have a look at the code:

def makeOrder(self, snapshot):
self.logger.info("FIXSIM-CLIENT Snapshot received %s", str(snapshot))
quote = snapshot.getRandomQuote()

self.logger.info("FIXSIM-CLIENT make order for quote %s", str(quote))
order = self.fixVersion.NewOrderSingle()
order.setField(quickfix.HandlInst(quickfix.HandlInst_AUTOMATED_EXECUTION_ORDER_PUBLIC_BROKER_INTERVENTION_OK))
order.setField(quickfix.SecurityType(quickfix.SecurityType_FOREIGN_EXCHANGE_CONTRACT))

order.setField(quickfix.OrdType(quickfix.OrdType_PREVIOUSLY_QUOTED))
order.setField(quickfix.ClOrdID(self.idGen.orderID()))
order.setField(quickfix.QuoteID(quote.id))

order.setField(quickfix.SecurityDesc("SPOT"))
order.setField(quickfix.Symbol(snapshot.symbol))
order.setField(quickfix.Currency(quote.currency))
order.setField(quickfix.Side(quote.side))

order.setField(quickfix.OrderQty(quote.size))
order.setField(quickfix.FutSettDate("SP"))
order.setField(quickfix.Price(quote.price))
order.setField(quickfix.TransactTime())
order.setField(quickfix.TimeInForce(quickfix.TimeInForce_IMMEDIATE_OR_CANCEL))

Once an order is received by an exchange, it will be handled and the exchange will reply to this order with a specific FIX message. The nature of this message is the execution report 35=8.

The message will acknowledge the order by using the execution report message 35=8, the ExecType tag 150=0, and OrdStatus 39=0:

8=FIX.4.4|9=204|35=8|34=4004|49=FIXSIM-SERVER|52=20190909-19:35:27.085|56=FIXSIM-CLIENT|6=55.945|11=3440|14=20000|15=USD|17=3440|31=55.945|32=20000|37=3440|38=20000|39=0|44=55.945|54=1|55=USD/RUB|64=20190910|150=0|151=0|10=008|

The order will be filled and the server will send an execution report message indicating that 150=2 and 39=2 for a fill:

8=FIX.4.4|9=204|35=8|34=4005|49=FIXSIM-SERVER|52=20190909-19:35:27.985|56=FIXSIM-CLIENT|6=55.945|11=3440|14=20000|15=USD|17=3440|31=55.945|32=20000|37=3440|38=20000|39=2|44=55.945|54=1|55=USD/RUB|64=20190910|150=2|151=0|10=008|

The onExecutionReport callback in the code will be called once these messages are received by the trading system:


def onExecutionReport(self, connectionHandler, msg):
codec = connectionHandler.codec
if codec.protocol.fixtags.ExecType in msg:
if msg.getField(codec.protocol.fixtags.ExecType) == "0":
side = Side(int(msg.getField(codec.protocol.fixtags.Side)))
logging.debug("<--- [%s] %s: %s %s %s@%s" % (codec.protocol.msgtype.msgTypeToName(msg.getField(codec.protocol.fixtags.MsgType)), msg.getField(codec.protocol.fixtags.ClOrdID), msg.getField(codec.protocol.fixtags.Symbol), side.name, msg.getField(codec.protocol.fixtags.OrderQty), msg.getField(codec.protocol.fixtags.Price)))
elif msg.getField(codec.protocol.fixtags.ExecType) == "2":
logging.info("Order Filled")
else:
logging.error("Received execution report without ExecType")

As shown in the preceding code, we have parsed the fields that we need to get the required information from the execution report message. We have also tested whether the order has been acknowledged or filled.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.191.216.163