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