-
Notifications
You must be signed in to change notification settings - Fork 0
/
bot.py
319 lines (245 loc) · 9.83 KB
/
bot.py
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
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
__author__ = 'zfei'
from time import sleep
import pprint
from api.btc2cnyapi import BTCChina
from settings import *
class Bot:
def __init__(self):
self.trader = BTCChina(API_ACCESS, API_SECRET)
self.portfolio = []
self.profit = 0
def get_lowest_market_ask(self, market_depth):
return float(market_depth['market_depth']['ask'][0]['price'])
def get_highest_market_bid(self, market_depth):
return float(market_depth['market_depth']['bid'][0]['price'])
def should_buy(self, lowest_ask, highest_bid):
return lowest_ask - highest_bid > DIFFERENCE_STEP
def get_orders(self):
orders = None
if DEBUG_MODE:
print '---'
print 'Attempting to get orders'
for trial in xrange(MAX_TRIAL):
response = self.trader.get_orders()
if not response is None:
orders = response['order']
if DEBUG_MODE:
print 'Received order information'
break
return orders
def cancel_order(self, order_id):
if DEBUG_MODE:
print '---'
print 'Attempting to cancel order', order_id
ret = None
for trial in xrange(MAX_TRIAL):
ret = self.trader.cancel(order_id)
if not ret is None:
if DEBUG_MODE:
print'Canceled order', order_id
break
return ret
def reset(self):
if CANCEL_ALL_ON_STARTUP:
if DEBUG_MODE:
print '---'
print 'Attempting to cancel over night orders'
orders = self.get_orders()
while len(orders) > 0:
if orders is None:
exit(1)
for order in orders:
if self.cancel_order(order['id']) is None:
exit(1)
orders = self.get_orders()
def get_market_depth(self):
market_depth = None
for trial in xrange(MAX_TRIAL):
market_depth = self.trader.get_market_depth({'limit': 1})
if market_depth:
break
return market_depth
def get_num_open_bids(self, orders):
bid_count = 0
if orders is None:
return None
for order in orders:
if order['type'] == 'bid':
bid_count += 1
return bid_count
def get_num_open_asks(self, orders):
ask_count = 0
if orders is None:
return None
for order in orders:
if order['type'] == 'ask':
ask_count += 1
return ask_count
def get_num_portfolio_bids(self):
bid_count = 0
for order in self.portfolio:
if order['status'] == 'buy':
bid_count += 1
return bid_count
def get_num_portfolio_asks(self):
ask_count = 0
for order in self.portfolio:
if order['status'] == 'sell':
ask_count += 1
return ask_count
def get_highest_bid(self):
highest_bid = None
highest_bid_price = -1
for order in self.portfolio:
if order['status'] == 'buy' and order['bid'] > highest_bid_price:
highest_bid_price = order['bid']
highest_bid = order
return highest_bid
def get_lowest_bid(self):
lowest_bid = None
lowest_bid_price = float('inf')
for order in self.portfolio:
if order['status'] == 'buy' and float(order['bid']) < lowest_bid_price:
lowest_bid_price = float(order['bid'])
lowest_bid = order
return lowest_bid
def get_lowest_ask(self):
lowest_ask = None
lowest_ask_price = float('inf')
for order in self.portfolio:
if order['status'] == 'sell' and float(order['ask']) < lowest_ask_price:
lowest_ask_price = float(order['ask'])
lowest_ask = order
return lowest_ask
def get_highest_bid_id(self, orders):
highest_bid_id = None
highest_bid_price = -1
for order in orders:
if order['type'] == 'bid' and float(order['price']) > highest_bid_price:
highest_bid_price = float(order['price'])
highest_bid_id = order['id']
return highest_bid_id
def get_lowest_bid_id(self, orders):
lowest_bid_id = None
lowest_bid_price = float('inf')
for order in orders:
if order['type'] == 'bid' and float(order['price']) < lowest_bid_price:
lowest_bid_price = float(order['price'])
lowest_bid_id = order['id']
return lowest_bid_id
def bid_filled(self, bid):
for trial in xrange(MAX_TRIAL):
response = self.trader.sell('{0:.2f}'.format(bid['ask']), BTC_AMOUNT)
if response is True:
bid['status'] = 'sell'
if DEBUG_MODE:
print 'will sell at', bid['ask']
break
else:
if DEBUG_MODE:
print 'Sell failed:', response
def highest_bid_filled(self):
highest_bid = self.get_highest_bid()
if highest_bid is None:
return
if DEBUG_MODE:
print '---'
print 'Bid at', highest_bid['bid'], 'filled'
print 'Attempting to put sell order at', highest_bid['ask']
self.bid_filled(highest_bid)
def lowest_ask_filled(self):
lowest_ask = self.get_lowest_ask()
if lowest_ask is None:
return
self.profit += (lowest_ask['ask'] - lowest_ask['bid']) * BTC_AMOUNT
self.portfolio.remove(lowest_ask)
if DEBUG_MODE:
print '---'
print 'Ask at', lowest_ask['ask'], 'filled, bought at', lowest_ask['bid']
print 'current profit:', '\033[93m', self.profit, '\033[0m'
def update_portfolio(self, check_old_orders=False):
orders = self.get_orders()
if orders is None:
return None
num_open_bids = self.get_num_open_bids(orders)
num_open_asks = self.get_num_open_asks(orders)
num_port_bids = self.get_num_portfolio_bids()
num_port_asks = self.get_num_portfolio_asks()
if DEBUG_MODE:
print '---'
print 'I have', num_port_asks - num_open_asks, 'asks filled'
print 'I have', num_port_bids - num_open_bids, 'bids filled'
for num_asks_filled in xrange(num_port_asks - num_open_asks):
self.lowest_ask_filled()
for num_bids_filled in xrange(num_port_bids - num_open_bids):
self.highest_bid_filled()
if check_old_orders:
if len(self.portfolio) < MAX_OPEN_ORDERS:
return orders
lowest_bid_id = self.get_lowest_bid_id(orders)
if lowest_bid_id is None:
return orders
my_lowest_bid = self.get_lowest_bid()
my_lowest_bid_price = my_lowest_bid['bid']
market_highest_bid = self.get_highest_market_bid(self.get_market_depth())
if market_highest_bid - my_lowest_bid_price >= REMOVE_THRESHOLD:
response = self.cancel_order(lowest_bid_id)
if response is True:
self.portfolio.remove(my_lowest_bid)
return orders
def loop_body(self):
orders = self.update_portfolio()
if orders is None:
return
if DEBUG_MODE:
print '---'
print 'I recorded', self.get_num_portfolio_bids(), 'open bids,', self.get_num_portfolio_asks(), 'asks.'
print 'API shows', self.get_num_open_bids(orders), 'open bids,', self.get_num_open_asks(orders), 'asks.'
if len(self.portfolio) >= MAX_OPEN_ORDERS and REMOVE_UNREALISTIC:
self.update_portfolio(True)
if len(self.portfolio) >= MAX_OPEN_ORDERS:
if DEBUG_MODE:
print '---'
print 'Too many open orders, sleep for', TOO_MANY_OPEN_SLEEP, 'seconds.'
if GET_INFO_BEFORE_SLEEP:
print '---'
print 'I have', self.get_num_portfolio_bids(), 'open bids,', self.get_num_portfolio_asks(), 'asks.'
print 'Total profit', '\033[93m', self.profit, '\033[0m'
sleep(TOO_MANY_OPEN_SLEEP)
return
market_depth = self.get_market_depth()
if not market_depth:
return
highest_bid = self.get_highest_market_bid(market_depth)
lowest_ask = self.get_lowest_market_ask(market_depth)
if not self.should_buy(lowest_ask, highest_bid):
if DEBUG_MODE:
print '---'
print 'Market spread:', str(lowest_ask - highest_bid)
print 'Nothing interesting, sleep for', NO_GOOD_SLEEP, 'seconds.'
if GET_INFO_BEFORE_SLEEP:
print '---'
print 'I have', self.get_num_portfolio_bids(), 'open bids,', self.get_num_portfolio_asks(), 'asks.'
print 'Total profit', '\033[93m', self.profit, '\033[0m'
sleep(NO_GOOD_SLEEP)
return
my_bid_price = highest_bid + CNY_STEP
my_ask_price = my_bid_price + MIN_SURPLUS
if DEBUG_MODE:
print '---'
print 'Attempting to bid at', my_bid_price
for trial in xrange(MAX_TRIAL):
if self.trader.buy('{0:.2f}'.format(my_bid_price), BTC_AMOUNT):
if DEBUG_MODE:
print 'I ordered', BTC_AMOUNT, 'bitcoins at', my_bid_price
print 'will sell at', my_ask_price
self.portfolio.append(
{'bid': my_bid_price, 'ask': my_ask_price, 'status': 'buy'})
break
def start(self):
self.reset()
while True:
self.loop_body()
if __name__ == '__main__':
bot = Bot()
bot.start()