Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
wiseplat
GitHub Repository: wiseplat/python-code
Path: blob/master/ invest-robot-contest_tinkoff_robot-master/tinkoff_robot.py
5925 views
1
import time
2
from tinkoff.invest import Client, MoneyValue, Quotation, OrderDirection, OrderType
3
4
figi_usd = "BBG0013HGFT4"
5
figi_Microsoft = "BBG000BPH459"
6
figi_Tesla = "BBG000N9MNX3"
7
8
# confidential information
9
10
token = ""
11
account_id = ""
12
13
sandbox_token = token
14
15
16
# function converts MoneyValue into float
17
def convert_price(MoneyValue):
18
price = MoneyValue.units + (MoneyValue.nano / 10**9)
19
return price
20
21
22
# function converts float into MoneyValue
23
def convert_to_MoneyValue(price, currency='rub'):
24
units = price // 1
25
nano = (price % 1) * 10**9
26
return MoneyValue(units=units, nano=nano, currency=currency)
27
28
29
# function gets info about current Limit Order Book
30
def get_LOB_data(figi_0=figi_usd):
31
32
with Client(token) as client:
33
LOB = client.market_data.get_order_book(figi=figi_0, depth=50)
34
35
ask_price = convert_price(LOB.asks[0].price)
36
bid_price = convert_price(LOB.bids[0].price)
37
38
q_a = 0
39
q_b = 0
40
41
for line in LOB.asks:
42
q_a += line.quantity
43
for line in LOB.bids:
44
q_b += line.quantity
45
46
return ((q_b, q_a), (bid_price, ask_price))
47
48
49
# function converts float into Quotation
50
def convert_to_Quotation(price, currency='rub'):
51
units = int(price // 1)
52
nano = int((price % 1) * 10**9)
53
return Quotation(units=units, nano=nano)
54
55
56
# class consists of two models: last+im and last+im+v strategy
57
class model_1:
58
def __init__(self):
59
self.cur_best_bid_price = 0
60
self.cur_best_ask_price = 0
61
62
self.last_best_bid_price = 0
63
self.last_best_ask_price = 0
64
65
self.bid_quantity = 0
66
self.ask_quantity = 0
67
68
self.ask_price = 0
69
self.bid_price = 0
70
71
self.increment = 0.1
72
self.auto_increment_flag = 1
73
self.parameter = 0.5 #default parameter value
74
self.state = 0
75
76
self.colors = dict()
77
self.color_match = dict()
78
79
self.colors["red"] = "\033[1;31m"
80
self.colors["green"] = "\033[1;32m"
81
self.colors["blue"] = "\033[1;34m"
82
self.colors["clear"] = "\033[0;0;m"
83
84
self.color_match[0] = self.colors["blue"]
85
self.color_match[1] = self.colors["green"]
86
self.color_match[-1] = self.colors["red"]
87
88
def set_parameters(self, param=0.5, increm=0):
89
self.parameter = param
90
if increm != 0:
91
self.auto_increment_flag = 0
92
self.increment = increm
93
94
def update_prices_b_a(self, bid_price, ask_price):
95
96
self.last_best_bid_price = self.cur_best_bid_price
97
self.last_best_ask_price = self.cur_best_ask_price
98
99
self.cur_best_bid_price = bid_price
100
self.cur_best_ask_price = ask_price
101
102
if self.auto_increment_flag:
103
self.increment = ask_price - bid_price
104
105
def update_LOB_data_b_a(self, b_q, a_q):
106
self.bid_quantity = b_q
107
self.ask_quantity = a_q
108
109
def last_im_strategy(self):
110
value_1 = self.bid_quantity - self.ask_quantity
111
value_2 = -value_1
112
value_3 = self.ask_quantity + self.bid_quantity
113
114
last_price = (self.cur_best_ask_price + self.cur_best_bid_price)/2
115
116
if value_1/value_3 > self.parameter: #(qb -qs)/(qb +qs)>0.5
117
self.ask_price = last_price + self.increment * 2
118
self.bid_price = last_price
119
self.state = 1
120
121
elif value_2/value_3 > self.parameter: #(qs –qb)/(qb +qs) >0.5
122
self.ask_price = last_price
123
self.bid_price = last_price - self.increment * 2
124
self.state = -1
125
126
else:
127
self.ask_price = last_price + self.increment
128
self.bid_price = last_price - self.increment
129
self.state = 0
130
131
print(self.color_match[self.state], end="")
132
print("last+im strategy")
133
print("signals: ----", end=' ')
134
print(self.bid_price, self.ask_price, sep=" : ", end='')
135
print(self.colors["clear"])
136
137
return (self.bid_price, self.ask_price)
138
139
def last_im_v_strategy(self):
140
value_1 = self.bid_quantity - self.ask_quantity
141
value_2 = -value_1
142
value_3 = self.ask_quantity + self.bid_quantity
143
144
last_price = (self.cur_best_ask_price + self.cur_best_bid_price) / 2
145
previous_price = (self.last_best_ask_price + self.last_best_bid_price) / 2
146
147
price_change = abs(last_price - previous_price)
148
149
if value_1 / value_3 > self.parameter: # (qb -qs)/(qb +qs)>0.5
150
self.ask_price = last_price + (price_change + 2) * self.increment
151
self.bid_price = last_price - price_change * self.increment
152
self.state = 1
153
154
155
elif value_2 / value_3 > self.parameter: # (qs –qb)/(qb +qs) >0.5
156
self.ask_price = last_price + price_change * self.increment
157
self.bid_price = last_price - (price_change + 2) * self.increment
158
self.state = -1
159
160
161
else:
162
self.ask_price = last_price + (price_change + 1) * self.increment
163
self.bid_price = last_price - (price_change + 1) * self.increment
164
self.state = 0
165
166
167
print(self.color_match[self.state], end="")
168
print("last+im+v strategy")
169
print("signals: ----", end=' ')
170
print(self.bid_price, self.ask_price, sep=" : ", end='')
171
print(self.colors["clear"])
172
173
174
return (self.bid_price, self.ask_price)
175
176
177
# class simulates real time activity of the model, placing orders in the sandbox.
178
class SandboxTester:
179
def __init__(self, account_id, token, figi, model=model_1(), model_type="last_im_strategy", limit_quantity=10000000, limit_percentage=100, iterations=1000):
180
model_types = dict()
181
182
model_types["last_im_strategy"] = 1
183
model_types["last_im_v_strategy"] = 2
184
185
if model_types[model_type] is None:
186
raise Exception("Model type does not exist. Existing types: last_im_strategy, last_im_v_strategy")
187
else:
188
self.model_type = model_types[model_type]
189
190
self.account_id = account_id
191
self.token = token
192
self.working_figi = figi
193
self.limit_quantity = limit_quantity
194
self.limit_percentage = limit_percentage
195
self.model = model
196
self.iterations = iterations
197
198
from model_1_hft import get_LOB_data
199
200
with Client(token=self.token) as client:
201
client_sb = client.sandbox
202
203
self.moneeey = client_sb.get_sandbox_portfolio(account_id=self.account_id).total_amount_currencies
204
time.sleep(0.6)
205
206
self.money_float = convert_price(self.moneeey)
207
max_quantity = convert_price(self.moneeey)
208
last_price = client.market_data.get_last_prices(figi=[self.working_figi]).last_prices[0].price
209
time.sleep(0.6)
210
211
self.last_price = convert_price(last_price)
212
self.max_quantity = max_quantity // self.last_price
213
214
self.cur_balance = self.money_float
215
216
def model_run(self):
217
if self.model_type == 1:
218
return self.model.last_im_strategy()
219
elif self.model_type == 2:
220
return self.model.last_im_v_strategy()
221
else:
222
return None
223
224
def update_balance(self):
225
with Client(token=self.token) as client:
226
client_sb = client.sandbox
227
self.cur_balance = client_sb.get_sandbox_portfolio(account_id=self.account_id).total_amount_currencies
228
self.cur_balance = convert_price(self.cur_balance)
229
print(self.cur_balance)
230
print("////////")
231
time.sleep(0.6)
232
# print(client_sb.get_sandbox_portfolio(account_id=self.account_id))
233
234
def place_order_ask(self, price, quantity, time_c=0):
235
if time_c > 3:
236
return "ASK order was NOT EXECUTED"
237
238
try:
239
with Client(token=self.token) as client:
240
r = client.sandbox.post_sandbox_order(
241
figi=self.working_figi,
242
price=price,
243
x_app_name="naketu.HFT",
244
quantity=quantity,
245
account_id=self.account_id,
246
order_id="sfkjhsf234897kjsdfh8has8dy3827gdslu[]" + str(time.localtime()),
247
direction=OrderDirection.ORDER_DIRECTION_SELL,
248
order_type=OrderType.ORDER_TYPE_LIMIT
249
)
250
251
time.sleep(0.6)
252
return r
253
254
except:
255
time.sleep(0.6)
256
time_c += 0.6
257
258
print("ERROR OCCURED AT ASK POST ORDER, reposting...")
259
260
r = self.place_order_bid(price, quantity, time_c)
261
return r
262
263
def place_order_bid(self, price, quantity, time_c=0):
264
if time_c > 3:
265
return "BID order was NOT EXECUTED"
266
267
try:
268
with Client(token=self.token) as client:
269
270
r = client.sandbox.post_sandbox_order(
271
figi=self.working_figi,
272
price=price,
273
#appname="naketu.HFT",
274
quantity=quantity,
275
account_id=self.account_id,
276
order_id="sfkjhsf234897kjsdfh8has8dy3827gdslu[]" + str(time.localtime()),
277
direction=OrderDirection.ORDER_DIRECTION_BUY,
278
order_type=OrderType.ORDER_TYPE_LIMIT
279
)
280
281
time.sleep(0.6)
282
return r
283
284
except:
285
time.sleep(0.6)
286
time_c += 0.6
287
288
print("ERROR OCCURED AT BID POST ORDER, reposting...")
289
290
r = self.place_order_bid(price, quantity, time_c)
291
return r
292
293
def cancel_order(self, order_id):
294
with Client(token=self.token) as client:
295
try:
296
r = client.sandbox.cancel_sandbox_order(
297
account_id=self.account_id,
298
order_id=order_id,
299
)
300
time.sleep(0.6)
301
except:
302
r = "ORDER IS NOT CANCELED"
303
return r
304
305
def check_orders(self, last_bid_price, bid_price, last_ask_price, ask_price):
306
with Client(token=self.token) as client:
307
orders = client.sandbox.get_sandbox_orders(account_id=self.account_id)
308
time.sleep(0.6)
309
310
if last_bid_price != bid_price and last_ask_price != ask_price:
311
return orders.orders
312
elif last_bid_price != bid_price:
313
orders = [ord for ord in orders.orders if ord.direction == OrderDirection.ORDER_DIRECTION_BUY]
314
return orders
315
elif last_ask_price != ask_price:
316
orders = [ord for ord in orders.orders if ord.direction == OrderDirection.ORDER_DIRECTION_SELL]
317
return orders
318
else:
319
return []
320
321
def test(self):
322
time_c = 0
323
324
last_bid_price = 0
325
last_ask_price = 0
326
327
try:
328
old_LOB = get_LOB_data(self.working_figi)
329
time.sleep(0.6)
330
except:
331
raise Exception("NO CONNECTION TO MARKET")
332
333
for i in range(self.iterations):
334
335
self.update_balance()
336
337
try:
338
LOB_data = get_LOB_data(self.working_figi)
339
except:
340
print("LOB does not responding")
341
time.sleep(2)
342
time_c += 2
343
print("loading...", time_c)
344
continue
345
346
if old_LOB[0][0] == LOB_data[0][0] and old_LOB[0][1] == LOB_data[0][1]:
347
continue
348
else:
349
self.model.update_LOB_data_b_a(LOB_data[0][0], LOB_data[0][1])
350
self.model.update_prices_b_a(LOB_data[1][0], LOB_data[1][1])
351
352
cur_price = (LOB_data[1][0] + LOB_data[1][1])/2
353
354
response = self.model_run()
355
356
bid_price = convert_to_Quotation(response[0])
357
ask_price = convert_to_Quotation(response[1])
358
359
orders = self.check_orders(last_bid_price, bid_price, last_ask_price, ask_price)
360
361
if len(orders) != 0:
362
for order in orders:
363
self.cancel_order(order.order_id)
364
365
quantity = int(min(self.limit_percentage/100 * self.money_float,
366
self.limit_quantity, self.cur_balance // cur_price))
367
368
self.place_order_ask(ask_price, quantity // 2),
369
self.place_order_bid(bid_price, quantity // 2)
370
371
# print(self.place_order_ask(ask_price, quantity // 2),
372
# self.place_order_bid(bid_price, quantity // 2))
373
374
last_bid_price = bid_price
375
last_ask_price = ask_price
376
377
time.sleep(0.6)
378
379
380
"""
381
The function simulates trading session and outputs order prices that are given out by the strategies states in model_1.
382
However, the function does not post any orders. Colored lines represent the results of the algorithm,
383
where blue, red and green represent steady state of the order book, greater amount of ask and bid orders respectively.
384
"""
385
def algo_trade(figi="BBG0013HGFT4"):
386
387
BEST_MODEL_EVER = model_1()
388
389
working_figi = figi
390
391
try: old_LOB = get_LOB_data(working_figi)
392
except:
393
print("WARNING")
394
print()
395
396
time_c = 0
397
398
print("start")
399
400
for i in range(1000):
401
402
try: LOB_data = get_LOB_data(working_figi)
403
except:
404
print("i am dead")
405
print("Too many calls ERROR")
406
time.sleep(2)
407
time_c += 2
408
print("loading...", time_c)
409
continue
410
411
if (old_LOB == None) or (old_LOB[0][0] == LOB_data[0][0] and old_LOB[0][1] == LOB_data[0][1]):
412
time.sleep(0.6)
413
time_c += 0.6
414
print("loading...", time_c)
415
416
else:
417
time_c = 0
418
print("///////////////////////////")
419
420
print("quantity: ---", LOB_data[0][0], LOB_data[0][1])
421
print("prices: -----", LOB_data[1][0], LOB_data[1][1])
422
423
BEST_MODEL_EVER.update_LOB_data_b_a(LOB_data[0][0], LOB_data[0][1])
424
BEST_MODEL_EVER.update_prices_b_a(LOB_data[1][0], LOB_data[1][1])
425
426
response1 = BEST_MODEL_EVER.last_im_strategy()
427
response2 = BEST_MODEL_EVER.last_im_v_strategy()
428
429
print("///////////////////////////")
430
431
time.sleep(0.6)
432
time_c += 0.6
433
434
old_LOB = LOB_data
435
436
437
def sandbox_quick_start(figi=figi_usd):
438
model_1_test = model_1()
439
tester_0 = SandboxTester(account_id, token, figi, model_1_test, "last_im_strategy", 1000, 10, 10000)
440
tester_0.test()
441
442
443
def pay_in():
444
with Client(token=token) as client:
445
client_sb = client.sandbox
446
client_sb.sandbox_pay_in(account_id=account_id, amount=MoneyValue(units=100000, nano=0, currency='rub'))
447
448
449
"""QUICK START:
450
Comment out one of the functions below and input initial values for token and account_id at the beginning of the file
451
If current trading balance is zero, you can add 100000 rub there by initiating pay_in() function """
452
453
454
# algo_trade(figi_Tesla)
455
# sandbox_quick_start(figi_Tesla)
456
457