Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
wiseplat
GitHub Repository: wiseplat/python-code
Path: blob/master/ invest-robot-contest_tinkoff_invest_competition-master/app/daily_check_functions.py
7824 views
1
import pandas as pd
2
import tinvest as ti
3
from openapi_client import openapi
4
#import yfinance as yf
5
import datetime
6
from datetime import timedelta
7
import pytz
8
import time
9
import telebot
10
from telebot import types
11
import sys
12
import time
13
import traceback
14
import config
15
import parameters_of_trading
16
import os
17
18
19
bot = telebot.TeleBot(config.telegram_bot_id())
20
client = ti.SyncClient(config.token_tinkoff_invest())
21
client2 = openapi.api_client(config.token_tinkoff_invest())
22
23
24
class CheckRobot2_0:
25
"Класс проверяющий текущие ордера"
26
def __init__(self, address_of_orders, index_of_process):
27
self.address_of_orders = address_of_orders
28
self.index_of_process = index_of_process
29
self.chat_id = config.telegram_сhat_id()
30
self.send = ''
31
self.position = 0
32
self.price = 500
33
34
"Отсылка сообщений в tg бот"
35
def message_alarm(self):
36
if self.index_of_process == 1:
37
self.send = 'Нет открытых позиций, робот готов к покупке ' + str(datetime.datetime.now().strftime("%Y_%m_%d-%H:%M:%S"))
38
try:
39
bot.send_message(self.chat_id, self.send)
40
except:
41
print(str(traceback.format_exc()))
42
43
44
"""Получение всех ордеров"""
45
def get_all_orders(self):
46
df_all_orders = pd.read_csv(self.address_of_orders, names = ['time','figi','price','type','order_id','status'])
47
df_all_orders['time'] = pd.to_datetime(df_all_orders['time'], format="%Y_%m_%d-%H:%M:%S")
48
49
"""Максимальное значение времени по ордеру ReallSell"""
50
max_reallsell = df_all_orders[df_all_orders['type'] == 'ReallSell']
51
time_ = list(max_reallsell[max_reallsell['time'] == max_reallsell['time'].max()]['time'])[0]
52
df_all_orders = df_all_orders[df_all_orders['time'] > time_]
53
if len(df_all_orders) == 0:
54
return -1
55
else:
56
return 1
57
58
"""Получение нужной позиции """
59
def get_all_for_sell(self):
60
date_, figi, type_, price, quantity, currency, commission, payment, ticker = [],[],[],[],[],[],[],[],[]
61
df_all_orders = pd.read_csv(self.address_of_orders, names = ['time','figi','price','type','order_id','status'])
62
df_all_orders['time'] = pd.to_datetime(df_all_orders['time'], format="%Y_%m_%d-%H:%M:%S")
63
64
"""Максимальное значение времени по ордеру ReallSell"""
65
max_reallsell = df_all_orders[df_all_orders['type'] == 'ReallSell']
66
time_ = list(max_reallsell[max_reallsell['time'] == max_reallsell['time'].max()]['time'])[0]
67
df_all_orders = df_all_orders[df_all_orders['time'] > time_]
68
figi_ = list(df_all_orders['figi'])[0]
69
tz = pytz.timezone('Europe/Moscow')
70
date_start = datetime.datetime(time_.year, time_.month, time_.day, time_.hour-3, time_.minute, time_.second)
71
date_start = pytz.utc.localize(date_start).astimezone(tz).isoformat()
72
date_end = datetime.datetime(datetime.datetime.now().year, datetime.datetime.now().month, datetime.datetime.now().day, datetime.datetime.now().hour, datetime.datetime.now().minute, datetime.datetime.now().second)
73
date_end = pytz.utc.localize(date_end).astimezone(tz).isoformat()
74
operat = client2.operations.operations_get(_from=date_start, to=date_end)
75
76
for ind_ in range(len(operat.payload.operations)):
77
try:
78
ttype_ = operat.payload.operations[ind_].operation_type
79
if (ttype_ == 'Sell') or (ttype_ == 'Buy'):
80
try:
81
type_.append(operat.payload.operations[ind_].operation_type)
82
except:
83
type_.append('NONE')
84
try:
85
date_.append(operat.payload.operations[ind_].date)
86
except:
87
date_.append('NONE')
88
try:
89
commission.append(operat.payload.operations[ind_].commission.value)
90
except:
91
commission.append('NONE')
92
try:
93
figi.append(operat.payload.operations[ind_].figi)
94
except:
95
figi.append('NONE')
96
try:
97
price.append(operat.payload.operations[ind_].price)
98
except:
99
price.append('NONE')
100
try:
101
quantity.append(operat.payload.operations[ind_].quantity)
102
except:
103
quantity.append('NONE')
104
try:
105
payment.append(operat.payload.operations[ind_].payment)
106
except:
107
payment.append('NONE')
108
try:
109
currency.append(operat.payload.operations[ind_].currency)
110
except:
111
currency.append('NONE')
112
try:
113
ticker.append(operat.payload.operations[ind_].status)
114
except:
115
ticker.append('NONE')
116
except:
117
continue
118
119
120
df_all_orders_for_analysis = pd.DataFrame(
121
{'date': date_,
122
'commission': commission,
123
'figi': figi,
124
'price': price,
125
'quantity': quantity,
126
'payment': payment,
127
'currency': currency,
128
'type': type_,
129
'status': ticker
130
})
131
df_all_orders_for_analysis = df_all_orders_for_analysis[df_all_orders_for_analysis['figi'] == figi_]
132
df_all_orders_for_analysis['date2'] = df_all_orders_for_analysis['date'].apply(lambda x: x.timestamp())
133
df_all_orders_for_analysis = df_all_orders_for_analysis[df_all_orders_for_analysis['date2'] >= (time_.timestamp()-3*3600)] #не разобрался с таймзоной - поэтому так лол ;)
134
df_all_orders_for_analysis = df_all_orders_for_analysis[df_all_orders_for_analysis['status'] == 'Done']
135
df_all_orders_for_analysis['total'] = df_all_orders_for_analysis['payment']/df_all_orders_for_analysis['price']
136
df_all_orders_for_analysis['commission'] = df_all_orders_for_analysis['commission']*3
137
return df_all_orders_for_analysis
138
139
140
141
class CheckRobotSellOrder:
142
def __init__(self, profit_value, df_orders):
143
self.profit_value = profit_value
144
self.payment_list = list(df_orders['payment'])
145
self.commission_list = list(df_orders['commission'])
146
self.total_list = list(df_orders['total'].apply(lambda x: round(x, 1)))
147
self.figi_ = list(df_orders['figi'])[0]
148
self.payment = 0
149
self.total = 0
150
self.price = 0
151
self.list_of_orders = []
152
self.figis = []
153
self.orders_for_potential_del = []
154
self.output_value = 0
155
self.del_post_orders = 0
156
157
158
def make_do_order(self):
159
for ind_ in range(len(self.total_list)):
160
self.payment = self.payment + self.payment_list[ind_] + self.commission_list[ind_]
161
self.total = self.total + self.total_list[ind_]
162
163
if self.total != 0:
164
self.list_of_orders = client.orders.orders_get().payload
165
self.price = round((self.payment/self.total)*self.profit_value, 2)
166
self.total = round(abs(self.total))
167
for ind_ in range(len(self.list_of_orders)):
168
if self.list_of_orders[ind_].figi == self.figi_:
169
self.figis.append(self.list_of_orders[ind_].figi)
170
self.orders_for_potential_del.append(self.list_of_orders[ind_].order_id)
171
172
if len(self.figis) == 0:
173
self.output_value = 1
174
return self.output_value, self.figi_, self.total, self.price, self.payment
175
else:
176
for order_id in self.orders_for_potential_del:
177
try:
178
client2.orders.orders_cancel_post(order_id=order_id)
179
self.del_post_orders+=1
180
except:
181
pass
182
if self.del_post_orders == 0:
183
self.output_value = 0
184
self.figi_ = ''
185
self.total = 0
186
self.price = 0
187
return self.output_value, self.figi_, self.total, self.price, self.payment
188
else:
189
self.output_value = 2
190
return self.output_value, self.figi_, self.total, self.price, self.payment
191
else:
192
self.output_value = -1
193
self.price = 0
194
return self.output_value, self.figi_, self.total, self.price, self.payment
195
196
197
class CheckRobotSellOrderAveraging:
198
def __init__(self, address_of_positions, address_of_progons, price, position_limit, rsi_threshold, number_of_stocks):
199
self.df_of_positions = pd.read_csv(address_of_positions, names = ['time','figi','price','type','order_id','status'])
200
self.df_of_progons = pd.read_csv(address_of_progons, names = ['time', 'ticker', 'price', 'RSI', 'type'])
201
self.price = price
202
self.position_limit = position_limit
203
self.rsi_threshold = rsi_threshold
204
self.status_of_average = 0
205
self.number_of_stocks = number_of_stocks
206
207
208
def make_do_average_order(self):
209
210
values, currency, balance, figi, ticker, name, evalue = [],[],[],[],[],[],[]
211
self.df_of_positions['time'] = pd.to_datetime(self.df_of_positions['time'], format="%Y_%m_%d-%H:%M:%S")
212
max_reallsell = self.df_of_positions[self.df_of_positions['type'] == 'ReallSell']
213
time_ = list(max_reallsell[max_reallsell['time'] == max_reallsell['time'].max()]['time'])[0]
214
self.df_of_positions = self.df_of_positions[self.df_of_positions['time'] > time_]
215
length_ = len(list(self.df_of_positions['figi']))
216
if length_ > 0:
217
figi_ = list(self.df_of_positions['figi'])[0]
218
pf = client.portfolio.portfolio_get()
219
tick = client2.market.market_search_by_figi_get(figi_).payload.ticker
220
for ind_ in range(len(pf.payload.positions)):
221
if pf.payload.positions[ind_].figi == figi_: #figi_
222
values.append(pf.payload.positions[ind_].average_position_price.value)
223
currency.append(pf.payload.positions[ind_].average_position_price.value)
224
balance.append(pf.payload.positions[ind_].balance)
225
figi.append(pf.payload.positions[ind_].figi)
226
ticker.append(pf.payload.positions[ind_].ticker)
227
name.append(pf.payload.positions[ind_].name)
228
evalue.append(pf.payload.positions[ind_].expected_yield.value)
229
portfolio = pd.DataFrame({
230
'ticker': ticker,
231
'name': name,
232
'values': values,
233
'balance': balance,
234
'expected_value': evalue,
235
'currency': currency,
236
'figi': figi
237
})
238
portfolio['current_price'] = round((portfolio['values']*portfolio['balance'] + portfolio['expected_value'])/portfolio['balance'], 2)
239
portfolio['position'] = portfolio['values']*portfolio['balance']
240
241
curr_price = portfolio['current_price'][0]
242
position = portfolio['position'][0]
243
244
self.df_of_progons = self.df_of_progons[self.df_of_progons['ticker'] == tick]
245
self.df_of_progons = self.df_of_progons.reset_index(drop = True)
246
self.df_of_progons['ind_'] = self.df_of_progons.index
247
self.df_of_progons = self.df_of_progons.sort_values(by = 'ind_',ascending=False)
248
self.df_of_progons = self.df_of_progons[0:2]
249
rsi_ = (list(self.df_of_progons['RSI'])[0] +list(self.df_of_progons['RSI'])[1])/2
250
251
if position < self.position_limit and (100*(curr_price - self.price)/self.price) < -1 and rsi_ < self.rsi_threshold:
252
"""Очищаются все ордера на продажу по этому FIGI"""
253
del_post_orders = 0
254
list_of_orders = list(self.df_of_positions[self.df_of_positions['type'] == 'Sell']['order_id'])
255
for order_id in list_of_orders:
256
order_id = int(float(order_id))
257
try:
258
client2.orders.orders_cancel_post(order_id=order_id)
259
del_post_orders+=1
260
except:
261
pass
262
263
if del_post_orders == 0:
264
self.status_of_average = -1
265
return self.status_of_average, figi_, self.number_of_stocks, curr_price
266
else:
267
self.status_of_average = 1
268
return self.status_of_average, figi_, self.number_of_stocks, curr_price
269
270
return self.status_of_average, figi_, self.number_of_stocks, curr_price
271
272
273
else:
274
figi_ = ''
275
self.number_of_stocks = 0
276
curr_price = 0
277
return self.status_of_average, figi_, self.number_of_stocks, curr_price
278
279
280
281
282
class MakeBuyAverageOrder:
283
def __init__(self, figi, lots_of_average, current_price, total, price, log_file_address, evalute_sell_price_after_average):
284
self.figi = figi
285
self.lots_of_average = lots_of_average
286
self.current_price = current_price
287
"""Старые значения величин позиций и цен"""
288
self.total = total
289
self.price = price
290
self.log_file_address = log_file_address
291
self.sell_price = evalute_sell_price_after_average
292
293
def make_order_average_buy(self):
294
order_response = client2.orders.orders_limit_order_post(figi = figi, limit_order_request={"lots": self.lots_of_average, "operation": 'Buy', "price": self.current_price})
295
"""Задержка в минуту для возможного исполнения ордера"""
296
time.sleep(60)
297
try:
298
order_list, status_list, operation_list, figi_list = [],[],[],[]
299
for ind_ in range(len(client2.orders.orders_get().payload)):
300
order_list.append(client2.orders.orders_get().payload[ind_].order_id)
301
status_list.append(client2.orders.orders_get().payload[ind_].status)
302
operation_list.append(client2.orders.orders_get().payload[ind_].operation)
303
figi_list.append(client2.orders.orders_get().payload[ind_].figi)
304
df = pd.DataFrame({
305
'order_id': order_list,
306
'status': status_list,
307
'operation': operation_list,
308
'figi': figi_list
309
})
310
except:
311
"""Делалась ранее задержка в 10 секунд для потенциального обновления API - на тестах
312
были случаи когда ордера не успевали обновиться"""
313
time.sleep(10)
314
order_list, status_list, operation_list, figi_list = [],[],[],[]
315
for ind_ in range(len(client2.orders.orders_get().payload)):
316
order_list.append(client2.orders.orders_get().payload[ind_].order_id)
317
status_list.append(client2.orders.orders_get().payload[ind_].status)
318
operation_list.append(client2.orders.orders_get().payload[ind_].operation)
319
figi_list.append(client2.orders.orders_get().payload[ind_].figi)
320
df = pd.DataFrame({
321
'order_id': order_list,
322
'status': status_list,
323
'operation': operation_list,
324
'figi': figi_list
325
})
326
327
if len(df[df['order_id'] == str(order_response.payload.order_id)]) > 0:
328
"""Ecли ордер не смог выполниться - удаляем ордер"""
329
client2.orders.orders_cancel_post(order_id=order_response.payload.order_id)
330
"""И тут же ставим ордер на продажу по старому объему акций """
331
order_response_sell = client2.orders.orders_limit_order_post(figi = self.figi, limit_order_request={"lots": self.total, "operation": 'Sell', "price": self.price})
332
f = open(self.log_file_address, 'a+', encoding='utf-8')
333
f.write(str(datetime.datetime.now().strftime("%Y_%m_%d-%H:%M:%S") + ',' + str(self.figi) + ',' + str(round(self.price, 2)) + ',' + 'Sell' + ',' + str(order_response_sell.payload.order_id) + ',' + str(order_response_sell.payload.status)))
334
f.write('\n')
335
f.close()
336
337
else:
338
"""Если ордер исполнился - логгируем покупку"""
339
f = open(self.log_file_address, 'a+', encoding='utf-8')
340
f.write(str(datetime.datetime.now().strftime("%Y_%m_%d-%H:%M:%S") + ',' + str(self.figi) + ',' + str(self.current_price) + ',' + 'Buy' + ',' + str(order_response.payload.order_id) + ',' + str(order_response.payload.status)))
341
f.write('\n')
342
f.close()
343
"""Высчитываем нужную цену продажи и ставим условие на продажу и логгируем продажу"""
344
order_response_sell = client2.orders.orders_limit_order_post(figi = self.figi, limit_order_request={"lots": (self.total + self.lots_of_average), "operation": 'Sell', "price": self.sell_price})
345
f = open(self.log_file_address, 'a+', encoding='utf-8')
346
f.write(str(datetime.datetime.now().strftime("%Y_%m_%d-%H:%M:%S") + ',' + str(self.figi) + ',' + str(sell_price) + ',' + 'Sell' + ',' + str(order_response_sell.payload.order_id) + ',' + str(order_response_sell.payload.status)))
347
f.write('\n')
348
f.close()
349
350
351
352
class MakeOrders:
353
def __init__(self, value, figi, total, price, order_response_sell, log_file_address):
354
self.value = value
355
self.figi = figi
356
self.total = total
357
self.price = price
358
self.chat_id = config.telegram_сhat_id()
359
self.send = 0
360
self.order_response_sell = order_response_sell
361
self.log_file_address = log_file_address
362
363
def update_data_and_send_to_bot(self):
364
if self.value == 0:
365
self.send = 'Не удалось удалить ни одного ордера - код завершен с ошибкой'
366
elif self.value == -1:
367
self.send = 'TradeSucsess - profit: ' + str(self.price)
368
f = open(self.log_file_address, 'a+', encoding='utf-8')
369
f.write(str(datetime.datetime.now().strftime("%Y_%m_%d-%H:%M:%S") + ',' + str(self.figi) + ',' + str(round(self.price, 2)) + ',' + 'ReallSell' + ',' + str(11111) + ',' + str('tradeSucsess')))
370
f.write('\n')
371
f.close()
372
elif self.value == 1:
373
self.send = 'Начальный ордер поставлен:' + ' ' + str(self.order_response_sell.payload.status)
374
f = open(self.log_file_address, 'a+', encoding='utf-8')
375
f.write(str(datetime.datetime.now().strftime("%Y_%m_%d-%H:%M:%S") + ',' + str(self.figi) + ',' + str(round(self.price, 2)) + ',' + 'Sell' + ',' + str(self.order_response_sell.payload.order_id) + ',' + str(self.order_response_sell.payload.status)))
376
f.write('\n')
377
f.close()
378
elif self.value == 2:
379
self.send = 'Послеусредненный ордер поставлен:' + ' ' + str(order_response_sell.payload.status)
380
f = open(self.log_file_address, 'a+', encoding='utf-8')
381
f.write(str(datetime.datetime.now().strftime("%Y_%m_%d-%H:%M:%S") + ',' + str(self.figi) + ',' + str(round(self.price, 2)) + ',' + 'Sell' + ',' + str(self.order_response_sell.payload.order_id) + ',' + str(self.order_response_sell.payload.status)))
382
f.write('\n')
383
f.close()
384
385
try:
386
bot.send_message(self.chat_id, self.send)
387
except:
388
print(str(traceback.format_exc()))
389
390
391
392