-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathordermatching.py
More file actions
133 lines (107 loc) · 4.24 KB
/
Copy pathordermatching.py
File metadata and controls
133 lines (107 loc) · 4.24 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
from typing import Dict, List
from datamodel import Order, Portfolio
def match_order(
algo_orders: List[Order],
orderbook: Dict[str, Dict[str, Dict[int, int]]],
portfolio: Portfolio,
pos_limit: Dict[str, int],
) -> Dict[str, Dict[str, Dict[int, int]]]:
"""
Match an order with an order in the orderbook.
:param order: The order to be matched.
:param orderbook: The orderbook to match with.
:param portfolio: The portfolio to be updated.
:param pos_limit: The maximum quantity the portfolio can hold.
"""
algo_resting_orders: Dict[str, Dict[str, Dict[int, int]]] = {}
all_products = set(order.product for order in algo_orders)
for product in all_products:
if product not in algo_resting_orders:
algo_resting_orders[product] = {"BUY": {}, "SELL": {}}
for order in algo_orders:
product = order.product
unfilled_quantity = 0
if order.quantity > 0:
unfilled_quantity = match_buy_order(
order, orderbook[product]["SELL"], portfolio, pos_limit
)
if unfilled_quantity > 0:
price = order.price
book = algo_resting_orders[product]["BUY"]
if price in book:
book[price] += unfilled_quantity
else:
book[price] = unfilled_quantity
elif order.quantity < 0:
unfilled_quantity = match_sell_order(
order, orderbook[product]["BUY"], portfolio, pos_limit
)
if unfilled_quantity < 0:
price = order.price
book = algo_resting_orders[product]["SELL"]
unfilled_abs = -unfilled_quantity
if price in book:
book[price] += unfilled_abs
else:
book[price] = unfilled_abs
else:
pass
return algo_resting_orders
def match_buy_order(
order: Order,
sell_orders: Dict[int, int],
portfolio: Portfolio,
pos_limit: Dict[str, int],
) -> int:
product = order.product
product_limit = pos_limit[product]
limit_price = order.price
outstanding_quantity = order.quantity
for pricepoint in sorted(sell_orders.keys()):
if outstanding_quantity == 0:
break
if pricepoint > limit_price:
break
if sell_orders[pricepoint] > 0:
fulfilled_amount = min(
int(product_limit - portfolio.quantity.get(product, 0)),
outstanding_quantity,
sell_orders[pricepoint],
) # quantity before order limit, order quantity remaining, quantity avaliable,
if fulfilled_amount > 0:
# Update portfolio
portfolio.quantity[product] += fulfilled_amount
portfolio.cash -= fulfilled_amount * pricepoint
sell_orders[pricepoint] -= fulfilled_amount
outstanding_quantity -= fulfilled_amount
# print(f"selling {fulfilled_amount} at {buy_prices[i]}")
return outstanding_quantity
def match_sell_order(
order: Order,
buy_orders: Dict[int, int],
portfolio: Portfolio,
pos_limit: Dict[str, int],
) -> int:
product = order.product
product_limit = pos_limit[product]
limit_price = order.price
outstanding_quantity = order.quantity
for pricepoint in sorted(buy_orders.keys(), reverse=True):
if outstanding_quantity == 0:
break
if pricepoint < limit_price:
break
if buy_orders[pricepoint] > 0:
fulfilled_amount = min(
int(product_limit + portfolio.quantity.get(product, 0)),
-outstanding_quantity,
buy_orders[pricepoint],
) # quantity before order limit, order quantity remaining, quantity avaliable,
if fulfilled_amount > 0:
# Update portfolio
portfolio.quantity[product] -= fulfilled_amount
portfolio.cash += fulfilled_amount * pricepoint
buy_orders[pricepoint] -= fulfilled_amount
outstanding_quantity += fulfilled_amount
# print(f"selling {fulfilled_amount} at {buy_prices[i]}")
return outstanding_quantity