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