· 6 years ago · Mar 09, 2020, 09:16 PM
1import signal
2import requests
3import time
4from time import sleep
5import sys
6
7class ApiException(Exception):
8 pass
9
10def signal_handler(signum, frame):
11 global shutdown
12 signal.signal(signal.SIGINT, signal.SIG_DFL)
13 shutdown = True
14
15
16API_KEY = {'X-API-Key': 'XC904YR5'}
17shutdown = False
18
19MAX_VOLUME = 5000
20MAX_ORDERS = 5
21SPREAD = .05
22number_of_orders = 0
23total_speedbumps = 0
24
25def speedbump(transaction_time):
26
27 global total_speedbumps
28 global number_of_orders
29
30 order_speedbump = -transaction_time + 1/MAX_ORDERS
31
32 total_speedbumps = total_speedbumps + order_speedbump
33
34 number_of_orders = number_of_orders + 1
35
36 sleep(total_speedbumps/number_of_orders)
37
38#function returns the current 'tick' of the running case
39def get_tick(session):
40 resp = session.get('http://localhost:9999/v1/case')
41 if resp.ok:
42 case = resp.json()
43 return case['tick']
44 raise ApiException('Authorization error Please check API key')
45
46#function returns the bid and ask first row of the security
47def ticker_bid_ask(session,ticker):
48 payload = {'ticker': ticker}
49 resp = session.get('http://localhost:9999/v1/securities/book', params = payload)
50 if resp.ok:
51 book = resp.json()
52 return book['bids'][0]['price'], book['asks'][0]['price']
53 raise ApiException('Authorization error Please check API key')
54
55#function returns info about the open sell orders
56def open_sells(session):
57 resp = session.get('http://localhost:9999/v1/orders?status=OPEN')
58 if resp.ok:
59 open_sells_volume = 0 # combined volume of sell orders
60 ids = [] # open sell order Ids
61 prices = []
62 order_volumes = []
63 volume_filled = []
64
65 open_orders = resp.json()
66 for order in open_orders:
67 if order['action'] == 'SELL':
68 volume_filled.append(order['quantity_filled'])
69 order_volumes.append(order['quantity'])
70 open_sells_volume = open_sells_volume + order['quantity']
71 prices.append(order['price'])
72 ids.append(order['order_id'])
73
74 return volume_filled, open_sells_volume, ids, prices, order_volumes
75
76#function returns info about the open buy orders
77def open_buys(session):
78 resp = session.get('http://localhost:9999/v1/orders?status=OPEN')
79 if resp.ok:
80 open_buys_volume = 0 # combined volume of buy orders
81 ids = [] # open sell order Ids
82 prices = []
83 order_volumes = []
84 volume_filled = []
85
86 open_orders = resp.json()
87 for order in open_orders:
88 if order['action'] == 'BUY':
89 open_buys_volume = open_buys_volume + order['quantity']
90 volume_filled.append(order['quantity_filled'])
91 order_volumes.append(order['quantity'])
92 prices.append(order['price'])
93 ids.append(order['order_id'])
94
95 return volume_filled, open_buys_volume, ids, prices, order_volumes
96
97
98#This function will buy and sell the max number of shares
99
100def buy_sell(session, sell_price, buy_price):
101 for i in range(MAX_ORDERS):
102 session.post('http://localhost:9999/v1/orders', params = {'ticker': 'ALGO', 'type': 'LIMIT', 'quantity': MAX_VOLUME, 'price': sell_price, 'action': 'SELL'})
103 session.post('http://localhost:9999/v1/orders', params = {'ticker': 'ALGO', 'type': 'LIMIT', 'quantity': MAX_VOLUME, 'price': buy_price, 'action': 'BUY'})
104
105#This function re-orders all open buys or sell orders
106
107def re_order(session, number_of_orders, ids, volumes_filled, volumes, price, action):
108 for i in range(number_of_orders):
109 id = ids[i]
110 volume = volumes[i]
111 volume_filled = volumes_filled[i]
112 #if the order is partially filled
113 if(volume_filled != 0 ):
114 volume = MAX_VOLUME - volume_filled
115
116 #delete then re-purchase
117 deleted = session.delete('http://localhost:9999/v1/orders/{}'.format(id))
118 if(deleted.ok):
119 session.post('http://localhost:9999/v1/orders', params = {'ticker': 'ALGO', 'type': 'LIMIT', 'quantity': volume, 'price': price, 'action': action})
120
121def main():
122 #declare buy order variables
123 buy_ids = []
124 buy_prices = []
125 buy_volumes = []
126 volume_filled_buys = []
127 open_buys_volume = 0
128
129 #declare buy order variables
130 sell_ids = []
131 sell_prices = []
132 sell_volumes = []
133 volume_filled_sells = []
134 open_sells_volume = 0
135
136 #declare variables when just one side of the book has been completely filled
137 single_side_filled = False
138 single_side_transaction_time = 0
139
140 #create session to manage connection with the RIT
141 with requests.Session() as s:
142 s.headers.update(API_KEY)
143 tick = get_tick(s)
144
145 #between 5 and 295 ticks do this function
146 while tick > 5 and tick < 295 and not shutdown and number_of_orders < MAX_ORDERS:
147 start = time.time()
148 #update case info
149 volume_filled_sells, open_sells_volume, sell_ids, sell_prices, sell_volumes = open_sells(s)
150 volume_filled_buys, open_buys_volume, buy_ids, buy_prices, buy_volumes = open_buys(s)
151 bid_price, ask_price = ticker_bid_ask(s,'ALGO')
152
153 #check if you have 0 open orders
154 if(open_sells_volume == 0 and open_buys_volume == 0):
155 #both sides are filled now
156 single_side_filled = False
157
158 #calculate the spread
159 bid_ask_spread = ask_price - bid_price
160
161 #set the prices
162 sell_price = ask_price
163 buy_price = bid_price
164
165 #compare our set spread and actual spread
166 if(bid_ask_spread >= SPREAD):
167 #buy and sell max no of shares
168 buy_sell(s,sell_price, buy_price)
169 transaction_time = time.time() - start
170 speedbump(transaction_time)
171
172 else: #there are outstanding orders
173
174 #one side of the book has no open orders
175 if(not single_side_filled and (open_buys_volume == 0 or open_sells_volume == 0)):
176 single_side_filled = True
177 single_side_transaction_time = tick
178
179 #ask side has been filled
180 if(open_sells_volume == 0):
181 #current buy orders are at the top of the book
182 if(buy_price == bid_price):
183 continue
184
185 #its been more than 3 seconds since a single side has been filled
186 elif(tick - single_side_transaction_time >= 3):
187 #calculate the potential profit you can make
188 next_buy_price = bid_price + .01
189 potential_profit = sell_price - next_buy_price - .02
190
191 #if potential profit is greater than or equal to a cent or its been more than 6 seconds
192 if(potential_profit >= .01 or tick - single_side_transaction_time >= 6):
193 action = 'BUY'
194 number_of_orders = len(buy_ids)
195 buy_price = bid_price + .01
196 price = buy_price
197 ids = buy_ids
198 volumes = buy_volumes
199 volumes_filled = volume_filled_buys
200
201 #delete buys and re-buy
202 re_order(s,number_of_orders, ids, volumes_filled, volumes, price, action)
203 transaction_time = time.time() - start
204 speedbump(transaction_time)
205
206 #bid side has been filled
207 elif(open_buys_volume == 0):
208 #current sell orders are at the top of the book
209 if(sell_price == ask_price):
210 continue
211
212 #its been more than 3 seconds since a single side has been filled
213 elif(tick - single_side_transaction_time >= 3):
214 #calculate the potential profit you can make
215 next_sell_price = ask_price - .01
216 potential_profit = next_sell_price - buy_price - .02
217
218 #if potential profit is greater than or equal to a cent or its been more than 6 seconds
219 if(potential_profit >= .01 or tick - single_side_transaction_time >= 6):
220 action = 'SELL'
221 number_of_orders = len(sell_ids)
222 sell_price = ask_price - .01
223 price = sell_price
224 ids = sell_ids
225 volumes = sell_volumes
226 volumes_filled = volume_filled_sells
227
228 #delete buys and re-buy
229 re_order(s,number_of_orders, ids, volumes_filled, volumes, price, action)
230 transaction_time = time.time() - start
231 speedbump(transaction_time)
232
233
234 #refresh the case time. IMPORTANT FOR WHILE LOOP
235 tick = get_tick(s)
236
237if __name__ == '__main__':
238 signal.signal(signal.SIGINT, signal_handler)
239 main()