Skip to content

Instantly share code, notes, and snippets.

@vitawasalreadytaken
Last active October 25, 2019 16:20
Show Gist options
  • Save vitawasalreadytaken/7c71a3d1c341501c388f to your computer and use it in GitHub Desktop.
Save vitawasalreadytaken/7c71a3d1c341501c388f to your computer and use it in GitHub Desktop.
Skeleton of a real Quickfix application
import logging
import quickfix as fix
def _str(msg):
''' Convert a FIX message to a readable string. '''
return msg.toString().replace('\x01', '@')
class MyApplication(fix.Application):
def __init__(self, session):
'''
:param session: An object (like `fix.Session`) with a `sendToTarget` method that we can use to dispatch messages.
'''
super(MyApplication, self).__init__()
self.logger = logging.getLogger(self.__class__.__name__)
self.session = session
self.connected = False
def onCreate(self, sessionID):
'''
Called when the application is initialized.
'''
self.sessionID = sessionID
# Use our session ID as the name of the logger.
self.logger = logging.getLogger('{}({})'.format(self.__class__.__name__, sessionID.toString()))
self.logger.info('Application created with sessionID = %s.', sessionID.toString())
def onLogon(self, sessionID):
'''
Called by Quickfix on session login.
'''
self.logger.info('Logon.')
self.connected = True
def onLogout(self, sessionID):
'''
Called by Quickfix on session logout.
'''
self.logger.info('Logout.')
self.connected = False
def onMessage(self, message, sessionID):
# Still not sure when (if?) this callback is called by Quickfix.
self.logger.info('Message = %s.', _str(message))
def toAdmin(self, message, sessionID):
'''
Process outgoing session-level messages (logon, logout, heartbeat) before they are sent.
'''
self.logger.info('Sending admin message = %s.', _str(message))
def fromAdmin(self, message, sessionID):
'''
Process incoming session-level messages (logon, logout, heartbeat).
Quickfix handles them automatically and sends appropriate responses.
'''
self.logger.info('Received admin message = %s.', _str(message))
def toApp(self, message, sessionID):
'''
Process outgoing application-level messages before they are sent.
'''
self.logger.info('Sending app message = %s.', _str(message))
def fromApp(self, message, sessionID):
'''
Handle incoming application-level messages.
'''
self.logger.info('Received app message = %s.', _str(message))
msgType = fix.MsgType()
message.getHeader().getField(msgType)
msgType = msgType.getValue()
if msgType == fix.MsgType_ExecutionReport:
# Extract fields from the message here and pass to an upper layer
pass
elif msgType == fix.MsgType_OrderCancelReject:
# Extract fields from the message here and pass to an upper layer
pass
def createOrder(self, order):
'''
:param order: Dictionary describing the order to be created. Mandatory fields:
id: order ID unique for the session and the day (FIX# 11)
exchange: target exchange identifier (FIX# 100)
symbol: the traded security symbol (FIX# 55)
currency: currency code of the order (FIX# 15)
side: side of the order (1 == buy, 2 == sell) (FIX# 54)
price: price (required for limit orders) (FIX# 44)
quantity: transaction quantity (FIX# 38)
type: order type (1 == market, 2 == limit) (FIX# 40)
'''
if not self.connected:
raise RuntimeError('Application not connected')
message = fix.Message()
header = message.getHeader()
header.setField(fix.BeginString('FIX.4.2'))
header.setField(fix.MsgType('D'))
# 11
message.setField(fix.ClOrdID(str(order['id'])))
# 21
message.setField(fix.HandlInst('1'))
# 100
message.setField(fix.ExDestination(str(order['exchange'])))
# 55
message.setField(fix.Symbol(str(order['symbol'])))
# 60 (current time in UTC)
message.setField(fix.TransactTime(1))
# 15
message.setField(fix.Currency(str(order['currency'])))
# 54 (1 == buy, 2 == sell)
message.setField(fix.Side(str(order['side'])))
# 44
message.setField(fix.Price(float(order['price'])))
# 38
message.setField(fix.OrderQty(int(order['quantity'])))
# 40 (1 == market, 2 == limit)
message.setField(fix.OrdType(str(order['type'])))
self.session.sendToTarget(message, self.sessionID)
[DEFAULT]
ConnectionType=initiator
ReconnectInterval=2
FileStorePath=store
FileLogPath=log
StartTime=00:00:00
EndTime=00:00:00
UseDataDictionary=Y
DataDictionary=quickfix/FIX42.xml
SocketConnectHost=192.168.1.50
SocketConnectPort=44000
LogoutTimeout=5
ResetOnLogon=N
ResetOnDisconnect=N
[SESSION]
BeginString=FIX.4.2
SenderCompID=CLIENTID
TargetCompID=FIXENGINEID
HeartBtInt=30
import sys
sys.path.insert(0, 'path/to/your/new/quickfix/directory')
import quickfix as fix
import application
app = application.MyApplication(fix.Session)
fixSettings = fix.SessionSettings('path/to/quickfix/configuration.conf')
storeFactory = fix.FileStoreFactory(fixSettings)
initiator = fix.SocketInitiator(app, storeFactory, fixSettings)
initiator.start()
# Run your application logic here
initiator.stop()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment