11#!/usr/bin/python3
2- class Side (object ):
3- """
4- Side
5- """
2+ cpdef enum Side :
63 BUY = 1
74 SELL = 2
85
9- class OrderBook (object ):
10- """
11- Order book
12- """
13- def __init__ (self ):
14- """
15- Constructor
16- """
17- self .bids = {}
18- self .asks = {}
19- self .order_id_map = {}
206
7+ cdef class Order :
8+ cdef public int order_id
9+ cdef public str instmt
10+ cdef public double price
11+ cdef public double qty
12+ cdef public double cum_qty
13+ cdef public double leaves_qty
14+ cdef public Side side
2115
22- class Order (object ):
23- """
24- Order
25- """
2616 def __init__ (self , order_id , instmt , price , qty , side ):
2717 """
2818 Constructor
@@ -36,10 +26,28 @@ def __init__(self, order_id, instmt, price, qty, side):
3626 self .side = side
3727
3828
39- class Trade (object ):
40- """
41- Trade
42- """
29+ cdef class OrderBook :
30+ cdef public dict bids
31+ cdef public dict asks
32+ cdef public dict order_id_map
33+
34+ def __init__ (self ):
35+ """
36+ Constructor
37+ """
38+ self .bids = {}
39+ self .asks = {}
40+ self .order_id_map = {}
41+
42+
43+ cdef class Trade :
44+ cdef public int order_id
45+ cdef public str instmt
46+ cdef public double trade_price
47+ cdef public double trade_qty
48+ cdef public Side trade_side
49+ cdef public int trade_id
50+
4351 def __init__ (self , order_id , instmt , trade_price , trade_qty , trade_side , trade_id ):
4452 """
4553 Constructor
@@ -52,10 +60,11 @@ def __init__(self, order_id, instmt, trade_price, trade_qty, trade_side, trade_i
5260 self .trade_id = trade_id
5361
5462
55- class LightMatchingEngine (object ):
56- """
57- Light matching engine
58- """
63+ cdef class LightMatchingEngine :
64+ cdef public dict order_books
65+ cdef public int curr_order_id
66+ cdef public int curr_trade_id
67+
5968 def __init__ (self ):
6069 """
6170 Constructor
@@ -64,7 +73,7 @@ def __init__(self):
6473 self .curr_order_id = 0
6574 self .curr_trade_id = 0
6675
67- def add_order (self , instmt , price , qty , side ):
76+ cpdef add_order (self , str instmt , double price , double qty , Side side ):
6877 """
6978 Add an order
7079 :param instmt Instrument name
@@ -74,14 +83,17 @@ def add_order(self, instmt, price, qty, side):
7483 :return The order and the list of trades.
7584 Empty list if there is no matching.
7685 """
86+ cdef list trades = []
87+ cdef int order_id
88+ cdef Order order
89+
7790 assert side == Side .BUY or side == Side .SELL , \
7891 "Invalid side %s" % side
7992
8093 # Locate the order book
8194 order_book = self .order_books .setdefault (instmt , OrderBook ())
8295
8396 # Initialization
84- trades = []
8597 self .curr_order_id += 1
8698 order_id = self .curr_order_id
8799 order = Order (order_id , instmt , price , qty , side )
@@ -92,7 +104,7 @@ def add_order(self, instmt, price, qty, side):
92104 else None
93105 while best_price is not None and \
94106 (price == 0.0 or price >= best_price ) and \
95- order .leaves_qty > 0 :
107+ order .leaves_qty >= 1e-9 :
96108 best_price_qty = sum ([ask .leaves_qty for ask in order_book .asks [best_price ]])
97109 match_qty = min (best_price_qty , order .leaves_qty )
98110 assert match_qty > 0 , "Match quantity must be larger than zero"
@@ -105,7 +117,7 @@ def add_order(self, instmt, price, qty, side):
105117 Side .BUY , self .curr_trade_id ))
106118
107119 # Generate the passive executions
108- while match_qty > 0 :
120+ while match_qty >= 1e-9 :
109121 # The order hit
110122 hit_order = order_book .asks [best_price ][0 ]
111123 # The order quantity hit
@@ -117,7 +129,7 @@ def add_order(self, instmt, price, qty, side):
117129 hit_order .cum_qty += order_match_qty
118130 hit_order .leaves_qty -= order_match_qty
119131 match_qty -= order_match_qty
120- if hit_order .leaves_qty == 0 :
132+ if hit_order .leaves_qty < 1e-9 :
121133 del order_book .asks [best_price ][0 ]
122134
123135 # If the price does not have orders, delete the particular price depth
@@ -129,7 +141,7 @@ def add_order(self, instmt, price, qty, side):
129141 else None
130142
131143 # Add the remaining order into the depth
132- if order .leaves_qty > 0 :
144+ if order .leaves_qty > 0.0 :
133145 depth = order_book .bids .setdefault (price , [])
134146 depth .append (order )
135147 order_book .order_id_map [order_id ] = order
@@ -139,10 +151,10 @@ def add_order(self, instmt, price, qty, side):
139151 else None
140152 while best_price is not None and \
141153 (price == 0.0 or price <= best_price ) and \
142- order .leaves_qty > 0 :
154+ order .leaves_qty >= 1e-9 :
143155 best_price_qty = sum ([bid .leaves_qty for bid in order_book .bids [best_price ]])
144156 match_qty = min (best_price_qty , order .leaves_qty )
145- assert match_qty > 0 , "Match quantity must be larger than zero"
157+ assert match_qty >= 1e-9 , "Match quantity must be larger than zero"
146158
147159 # Generate aggressive order trade first
148160 self .curr_trade_id += 1
@@ -152,7 +164,7 @@ def add_order(self, instmt, price, qty, side):
152164 Side .SELL , self .curr_trade_id ))
153165
154166 # Generate the passive executions
155- while match_qty > 0 :
167+ while match_qty >= 1e-9 :
156168 # The order hit
157169 hit_order = order_book .bids [best_price ][0 ]
158170 # The order quantity hit
@@ -164,7 +176,7 @@ def add_order(self, instmt, price, qty, side):
164176 hit_order .cum_qty += order_match_qty
165177 hit_order .leaves_qty -= order_match_qty
166178 match_qty -= order_match_qty
167- if hit_order .leaves_qty == 0 :
179+ if hit_order .leaves_qty < 1e-9 :
168180 del order_book .bids [best_price ][0 ]
169181
170182 # If the price does not have orders, delete the particular price depth
@@ -176,20 +188,25 @@ def add_order(self, instmt, price, qty, side):
176188 else None
177189
178190 # Add the remaining order into the depth
179- if order .leaves_qty > 0 :
191+ if order .leaves_qty >= 1e-9 :
180192 depth = order_book .asks .setdefault (price , [])
181193 depth .append (order )
182194 order_book .order_id_map [order_id ] = order
183195
184196 return order , trades
185197
186- def cancel_order (self , order_id , instmt ):
198+ cpdef cancel_order (self , int order_id , str instmt ):
187199 """
188200 Cancel order
189201 :param order_id Order ID
190202 :param instmt Instrument
191203 :return The order if the cancellation is successful
192204 """
205+ cdef Order order
206+ cdef double order_price
207+ cdef Side side
208+ cdef int index
209+
193210 assert instmt in self .order_books .keys (), \
194211 "Instrument %s is not valid in the order book" % instmt
195212 order_book = self .order_books [instmt ]
@@ -238,6 +255,3 @@ def cancel_order(self, order_id, instmt):
238255 order .leaves_qty = 0
239256
240257 return order
241-
242-
243-
0 commit comments