Skip to main content

Python Sample for the Ember FIX API

This sample explains how to run a simple Python client that sends trading orders to the Deltix FIX Gateway using the popular QuickFIX/Python library.

Pre-requisites

Before you can run the sample, ensure you have the following pre-requisites in place:

  1. Install Python 3.7+ and pip on your system using the following command:

    sudo yum install python3-devel python3-wheel  
  2. Install the QuickFIX Python library using the following pip command:

    pip3 install quickfix  

    For Windows users facing any problems with this step, you can get QuickFIX binaries here.

  3. Set up the Deltix FIX Gateway.

  4. Download the source code of this sample from GitHub.

Configure

To use the Python client with your specific Ember configuration, modify the fix-client.cfg file as follows:

  1. Point the SocketConnectHost and SocketConnectPort properties to your Deltix FIX Gateway. These properties define the host and port to which the client will connect.
  2. Make sure SenderCompID, TargetCompID, and SenderPassword match the credentials of the FIX Session you want to connect as.
  3. (Optional) If you need to specify custom file paths for storing messages and logs, update FileStorePath and FileLogPath. By default, the client uses the current working directory.

Run

To run the sample client, execute fix-client.py with fix-client.cfg as a parameter on Python 3.x:

python3 fix-client.py fix-client.cfg

If client successfully connects, it will display a message about the successful login and then show the following command prompt:

Session FIX.4.4:TCLIENT1->DELTIX successfully logged in
Received message: MessageType=News, Sender=DELTIX, HeadLine=Connector Status, Text=SIM:CONNECTED
-->

Sending Trading Orders

At this point, you can enter commands to issue BUY or SELL orders with specified parameters and time interval. The client will display any application messages (order events) received from the FIX server.

To view supported commands and parameters type help:

--> help
usage: help | exit | {buy,sell} -s SYMBOL -q QUANTITY [-t {LIMIT,MARKET}] [-p PRICE] [-d DESTINATION] [-e EXCHANGE] [-n ORDER_COUNT] [-i INTERVAL]

Example

In the example above, the last two parameters, ORDER_COUNT (default is 1) and INTERVAL (default is 5 seconds), are used to issue multiple orders with the specified time interval (in seconds) between orders.

To issue 10 LIMIT BUY orders to the SOR algorithm, buying 1 BTCUSD coin every 15 seconds, with a limit price of 8081, the command would look like this:

--> buy -s BTCUSD -q 1 -t LIMIT -p 8081 -d SOR -n 10 -i 15

In this example, the options set the following FIX tags on the order request:

-s – fix.Symbol
-t - fix.OrdType
-q - fix.OrderQty
-p - fix.Price
-d - fix.ExecBroker (ember destination, this could be simulator, matching engine, execution algo, or exchange connector)
-e - fix.ExDestination (identifies exchange)

QuickFIX API

QuickFIX provides the quickfix.Application class, which has notification methods called whenever the client sends or receives messages from the FIX server. To use QuickFIX, you should extend this class and override its notification methods. For an example, see the provided fix-client.py.

Overriding the toAdmin() Method

To supply the server with the password during login, you can override the toAdmin() method and add the password to the header of the FIX Logon message:

Here's an example:

def toAdmin(self, message, sessionID):
    msgType = fix.MsgType();
    message.getHeader().getField(msgType)
    if msgType.getValue() == fix.MsgType_Logon :
        message.getHeader().setField(fix.Password(self.sessionPwd))
    return

Overriding the fromApp() Method

To handle FIX server execution report messages, override the fromApp() method in your application:

def fromApp(self, message, sessionID):
    print("Received message: ", end='')
    print_message(message)
    return

Initializing the Client Session

To initialize the client session, pass an instance of your Application class to SocketInitiator along with the configuration settings, and then start it like this:

settings = quickfix.SessionSettings(config_file)
store_factory = quickfix.FileStoreFactory(settings)
log_factory = quickfix.FileLogFactory(settings)
application = Application()
initiator = quickfix.SocketInitiator(application, store_factory, settings, log_factory)
initiator.start()

Sending Order Requests

Once the SocketInitiator is started, and the session is initialized, the client can send order requests using the quickfix.Session.sendToTarget() method.

Here is a sample code that sends a LIMIT BUY order to the SIM algorithm:

   trade = fix.Message()
   trade.getHeader().setField(fix.BeginString(fix.BeginString_FIX44))
   trade.getHeader().setField(fix.MsgType(fix.MsgType_NewOrderSingle))
   trade.setField(fix.ClOrdID("1121212"))
   trade.setField(fix.HandlInst(fix.HandlInst_MANUAL_ORDER_BEST_EXECUTION))
   trade.setField(fix.TimeInForce(fix.TimeInForce_DAY))
   trade.setField(fix.Symbol("BTCUSD"))
   trade.setField(fix.Side(fix.Side_BUY))
   trade.setField(fix.OrdType(fix.OrdType_LIMIT))
   trade.setField(fix.OrderQty(2))
   trade.setField(fix.Price(8081))
  trade.setField(fix.TransactTime())
   trade.setField(fix.ExecBroker("SIM"))
   fix.Session.sendToTarget(trade, self.sessionID)

In this code snippet, the trade message is constructed and then sent to the target using the sendToTarget() method of the Session class.