Class Project FINM-32500
Matching engine
Description
A trade matching engine is the core software and hardware component of an electronic exchange. It
matches up bids and offers to complete trades. Matching engines use one or several algorithms to
allocate trades among competing bids and offers at the same price.
The most commonly used algorithm is time price priority, meaning those bids and offers entered
into the match engine first have priority over similar bids or offers that were subsequently entered
into the system. The principle of price/time priority refers to how orders are prioritized for
execution. Orders are first ranked according to their price; orders of the same price are then ranked
depending on when they were entered.
Unlike the pro-rata model, in which orders go to specialists first, in a price/time priority model,
dealers have few special privileges
In your quant/trader life, you will need to learn pretty well how an electronic exchange works. The
matching engine we are going to create in this project is basic.
Matching engines support different order types, such as a limit order or market order. Matching
engines may have unique APIs, or use standard ones such as FIX APIs.
Part I: Conception (5pts)
After some research, you will explain the way the matching engine will handle limit order, market
order, IOC orders. You will give a write-up on the way you will conceive this matching-engine.
You will also explain how to represent the orders (I would recommend a dictionary with the regular
attributes of an order but do not forget the timestamp, it is important to know when orders arrive in
the matching engine).
Part II: Creation of the class MatchingEngine (20pts)
You will create the class MatchingEngine capable of handling incoming orders and matching orders.
You will need to handle 3 types of orders:
• Limit order
• Market order
• Immediate or Cancel
I would recommend writing the following functions:
• def handle_order(order), function in charge of handling any types of orders in the matching
engine
• def handle_limit_order(order), def handle_market_order(order), def
handle_ioc_order(order)
This class will have a container of your choice for bids and offers.
Please consider that a limit order A of a quantity QA can be matched with another order B of a
quantity QB:
• if QAQB, comparable to prior case
• if QA=QB, A and B will be fully-filled
To succeed this part, you will need to show evidence that the different orders and different cases
work. For that you are required to use unit testing.
Coming from this library:
https://docs.python.org/3.6/library/unittest.html
Part III: Exchange Simulator (20pts)
Once your MatchineEngine class is created, you will create another file that you will call
ExchangeSimulator.py.
You will need to use your ExchangeSimulator. This simulation will have 100 threads representing
traders. These traders will place randomly 3 types of orders (IOC, Market Order, Limit Order). Every
order should have a different order id.
A trader can:
• place a new order
• amend the volume of an existing order (the amendment is always reducing the quantity)
• cancel an existing order
• calculate the P&L and the position each time they trade
The trader cannot create a new order if there is an existing order on the market.
This order will be sent to a deque
The communication between the thread and the matching engine will happen through a deque.
This is an example how to use a deque, a client (certainly a Trader) and a server (matching engine):
import threading
from collections import deque
import time
gbl_lock=threading.Lock()
client_to_server=deque()
server_to_client=deque()
class client(threading.Thread):
def __init__(self):
super().__init__()
def run(self):
for i in range(10):
client_to_server.appendleft("increment")
client_to_server.appendleft("get_balance")
while True:
#print('check if response from server')
if not len(server_to_client):
continue
response_from_server = server_to_client.pop()
print("Result:%d\n" % response_from_server)
class server(threading.Thread):
def __init__(self):
super().__init__()
self.balance = 0
def increment(self):
self.balance+=1
def decrement(self):
self.balance -= 1
def addition(self,num1,num2):
return num1+num2
def subtraction(self, num1, num2):
return num1 - num2
def handle_request_from_client(self,request):
if request=='increment':
return self.increment()
elif request =='decrement':
return self.decrement()
elif request == 'addition':
return self.addition()
elif request == 'subtraction':
return self.subtraction()
elif request == 'get_balance':
return self.balance
def run(self): # first function to called once the thread is started
while True:
#print('check if question from client')
if not len(client_to_server):
continue
request_from_client=client_to_server.pop()
return_function=self.\
handle_request_from_client(request_from_client)
if return_function is not None:
server_to_client.appendleft(return_function)
client1=client()
server1=server()
client1.start()
server1.start()
client1.join()
server1.join()
When a matching engine matches 2 orders (bid and offer), the two traders will need to be informed
of the trade.
Each trader will start with 1,000,000, you will draw the chart of how the cash evolves. A trader will
stop trading when its cash is 0.
Part IV: Real Exchange (10 pts)
You will now need to use a real TCP server for your matching engine, the traders will be TCP clients.