Path: blob/master/ invest-robot-contest_tinkoff_invest_competition-master/app/daily_check_functions.py
7824 views
import pandas as pd1import tinvest as ti2from openapi_client import openapi3#import yfinance as yf4import datetime5from datetime import timedelta6import pytz7import time8import telebot9from telebot import types10import sys11import time12import traceback13import config14import parameters_of_trading15import os161718bot = telebot.TeleBot(config.telegram_bot_id())19client = ti.SyncClient(config.token_tinkoff_invest())20client2 = openapi.api_client(config.token_tinkoff_invest())212223class CheckRobot2_0:24"Класс проверяющий текущие ордера"25def __init__(self, address_of_orders, index_of_process):26self.address_of_orders = address_of_orders27self.index_of_process = index_of_process28self.chat_id = config.telegram_сhat_id()29self.send = ''30self.position = 031self.price = 5003233"Отсылка сообщений в tg бот"34def message_alarm(self):35if self.index_of_process == 1:36self.send = 'Нет открытых позиций, робот готов к покупке ' + str(datetime.datetime.now().strftime("%Y_%m_%d-%H:%M:%S"))37try:38bot.send_message(self.chat_id, self.send)39except:40print(str(traceback.format_exc()))414243"""Получение всех ордеров"""44def get_all_orders(self):45df_all_orders = pd.read_csv(self.address_of_orders, names = ['time','figi','price','type','order_id','status'])46df_all_orders['time'] = pd.to_datetime(df_all_orders['time'], format="%Y_%m_%d-%H:%M:%S")4748"""Максимальное значение времени по ордеру ReallSell"""49max_reallsell = df_all_orders[df_all_orders['type'] == 'ReallSell']50time_ = list(max_reallsell[max_reallsell['time'] == max_reallsell['time'].max()]['time'])[0]51df_all_orders = df_all_orders[df_all_orders['time'] > time_]52if len(df_all_orders) == 0:53return -154else:55return 15657"""Получение нужной позиции """58def get_all_for_sell(self):59date_, figi, type_, price, quantity, currency, commission, payment, ticker = [],[],[],[],[],[],[],[],[]60df_all_orders = pd.read_csv(self.address_of_orders, names = ['time','figi','price','type','order_id','status'])61df_all_orders['time'] = pd.to_datetime(df_all_orders['time'], format="%Y_%m_%d-%H:%M:%S")6263"""Максимальное значение времени по ордеру ReallSell"""64max_reallsell = df_all_orders[df_all_orders['type'] == 'ReallSell']65time_ = list(max_reallsell[max_reallsell['time'] == max_reallsell['time'].max()]['time'])[0]66df_all_orders = df_all_orders[df_all_orders['time'] > time_]67figi_ = list(df_all_orders['figi'])[0]68tz = pytz.timezone('Europe/Moscow')69date_start = datetime.datetime(time_.year, time_.month, time_.day, time_.hour-3, time_.minute, time_.second)70date_start = pytz.utc.localize(date_start).astimezone(tz).isoformat()71date_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)72date_end = pytz.utc.localize(date_end).astimezone(tz).isoformat()73operat = client2.operations.operations_get(_from=date_start, to=date_end)7475for ind_ in range(len(operat.payload.operations)):76try:77ttype_ = operat.payload.operations[ind_].operation_type78if (ttype_ == 'Sell') or (ttype_ == 'Buy'):79try:80type_.append(operat.payload.operations[ind_].operation_type)81except:82type_.append('NONE')83try:84date_.append(operat.payload.operations[ind_].date)85except:86date_.append('NONE')87try:88commission.append(operat.payload.operations[ind_].commission.value)89except:90commission.append('NONE')91try:92figi.append(operat.payload.operations[ind_].figi)93except:94figi.append('NONE')95try:96price.append(operat.payload.operations[ind_].price)97except:98price.append('NONE')99try:100quantity.append(operat.payload.operations[ind_].quantity)101except:102quantity.append('NONE')103try:104payment.append(operat.payload.operations[ind_].payment)105except:106payment.append('NONE')107try:108currency.append(operat.payload.operations[ind_].currency)109except:110currency.append('NONE')111try:112ticker.append(operat.payload.operations[ind_].status)113except:114ticker.append('NONE')115except:116continue117118119df_all_orders_for_analysis = pd.DataFrame(120{'date': date_,121'commission': commission,122'figi': figi,123'price': price,124'quantity': quantity,125'payment': payment,126'currency': currency,127'type': type_,128'status': ticker129})130df_all_orders_for_analysis = df_all_orders_for_analysis[df_all_orders_for_analysis['figi'] == figi_]131df_all_orders_for_analysis['date2'] = df_all_orders_for_analysis['date'].apply(lambda x: x.timestamp())132df_all_orders_for_analysis = df_all_orders_for_analysis[df_all_orders_for_analysis['date2'] >= (time_.timestamp()-3*3600)] #не разобрался с таймзоной - поэтому так лол ;)133df_all_orders_for_analysis = df_all_orders_for_analysis[df_all_orders_for_analysis['status'] == 'Done']134df_all_orders_for_analysis['total'] = df_all_orders_for_analysis['payment']/df_all_orders_for_analysis['price']135df_all_orders_for_analysis['commission'] = df_all_orders_for_analysis['commission']*3136return df_all_orders_for_analysis137138139140class CheckRobotSellOrder:141def __init__(self, profit_value, df_orders):142self.profit_value = profit_value143self.payment_list = list(df_orders['payment'])144self.commission_list = list(df_orders['commission'])145self.total_list = list(df_orders['total'].apply(lambda x: round(x, 1)))146self.figi_ = list(df_orders['figi'])[0]147self.payment = 0148self.total = 0149self.price = 0150self.list_of_orders = []151self.figis = []152self.orders_for_potential_del = []153self.output_value = 0154self.del_post_orders = 0155156157def make_do_order(self):158for ind_ in range(len(self.total_list)):159self.payment = self.payment + self.payment_list[ind_] + self.commission_list[ind_]160self.total = self.total + self.total_list[ind_]161162if self.total != 0:163self.list_of_orders = client.orders.orders_get().payload164self.price = round((self.payment/self.total)*self.profit_value, 2)165self.total = round(abs(self.total))166for ind_ in range(len(self.list_of_orders)):167if self.list_of_orders[ind_].figi == self.figi_:168self.figis.append(self.list_of_orders[ind_].figi)169self.orders_for_potential_del.append(self.list_of_orders[ind_].order_id)170171if len(self.figis) == 0:172self.output_value = 1173return self.output_value, self.figi_, self.total, self.price, self.payment174else:175for order_id in self.orders_for_potential_del:176try:177client2.orders.orders_cancel_post(order_id=order_id)178self.del_post_orders+=1179except:180pass181if self.del_post_orders == 0:182self.output_value = 0183self.figi_ = ''184self.total = 0185self.price = 0186return self.output_value, self.figi_, self.total, self.price, self.payment187else:188self.output_value = 2189return self.output_value, self.figi_, self.total, self.price, self.payment190else:191self.output_value = -1192self.price = 0193return self.output_value, self.figi_, self.total, self.price, self.payment194195196class CheckRobotSellOrderAveraging:197def __init__(self, address_of_positions, address_of_progons, price, position_limit, rsi_threshold, number_of_stocks):198self.df_of_positions = pd.read_csv(address_of_positions, names = ['time','figi','price','type','order_id','status'])199self.df_of_progons = pd.read_csv(address_of_progons, names = ['time', 'ticker', 'price', 'RSI', 'type'])200self.price = price201self.position_limit = position_limit202self.rsi_threshold = rsi_threshold203self.status_of_average = 0204self.number_of_stocks = number_of_stocks205206207def make_do_average_order(self):208209values, currency, balance, figi, ticker, name, evalue = [],[],[],[],[],[],[]210self.df_of_positions['time'] = pd.to_datetime(self.df_of_positions['time'], format="%Y_%m_%d-%H:%M:%S")211max_reallsell = self.df_of_positions[self.df_of_positions['type'] == 'ReallSell']212time_ = list(max_reallsell[max_reallsell['time'] == max_reallsell['time'].max()]['time'])[0]213self.df_of_positions = self.df_of_positions[self.df_of_positions['time'] > time_]214length_ = len(list(self.df_of_positions['figi']))215if length_ > 0:216figi_ = list(self.df_of_positions['figi'])[0]217pf = client.portfolio.portfolio_get()218tick = client2.market.market_search_by_figi_get(figi_).payload.ticker219for ind_ in range(len(pf.payload.positions)):220if pf.payload.positions[ind_].figi == figi_: #figi_221values.append(pf.payload.positions[ind_].average_position_price.value)222currency.append(pf.payload.positions[ind_].average_position_price.value)223balance.append(pf.payload.positions[ind_].balance)224figi.append(pf.payload.positions[ind_].figi)225ticker.append(pf.payload.positions[ind_].ticker)226name.append(pf.payload.positions[ind_].name)227evalue.append(pf.payload.positions[ind_].expected_yield.value)228portfolio = pd.DataFrame({229'ticker': ticker,230'name': name,231'values': values,232'balance': balance,233'expected_value': evalue,234'currency': currency,235'figi': figi236})237portfolio['current_price'] = round((portfolio['values']*portfolio['balance'] + portfolio['expected_value'])/portfolio['balance'], 2)238portfolio['position'] = portfolio['values']*portfolio['balance']239240curr_price = portfolio['current_price'][0]241position = portfolio['position'][0]242243self.df_of_progons = self.df_of_progons[self.df_of_progons['ticker'] == tick]244self.df_of_progons = self.df_of_progons.reset_index(drop = True)245self.df_of_progons['ind_'] = self.df_of_progons.index246self.df_of_progons = self.df_of_progons.sort_values(by = 'ind_',ascending=False)247self.df_of_progons = self.df_of_progons[0:2]248rsi_ = (list(self.df_of_progons['RSI'])[0] +list(self.df_of_progons['RSI'])[1])/2249250if position < self.position_limit and (100*(curr_price - self.price)/self.price) < -1 and rsi_ < self.rsi_threshold:251"""Очищаются все ордера на продажу по этому FIGI"""252del_post_orders = 0253list_of_orders = list(self.df_of_positions[self.df_of_positions['type'] == 'Sell']['order_id'])254for order_id in list_of_orders:255order_id = int(float(order_id))256try:257client2.orders.orders_cancel_post(order_id=order_id)258del_post_orders+=1259except:260pass261262if del_post_orders == 0:263self.status_of_average = -1264return self.status_of_average, figi_, self.number_of_stocks, curr_price265else:266self.status_of_average = 1267return self.status_of_average, figi_, self.number_of_stocks, curr_price268269return self.status_of_average, figi_, self.number_of_stocks, curr_price270271272else:273figi_ = ''274self.number_of_stocks = 0275curr_price = 0276return self.status_of_average, figi_, self.number_of_stocks, curr_price277278279280281class MakeBuyAverageOrder:282def __init__(self, figi, lots_of_average, current_price, total, price, log_file_address, evalute_sell_price_after_average):283self.figi = figi284self.lots_of_average = lots_of_average285self.current_price = current_price286"""Старые значения величин позиций и цен"""287self.total = total288self.price = price289self.log_file_address = log_file_address290self.sell_price = evalute_sell_price_after_average291292def make_order_average_buy(self):293order_response = client2.orders.orders_limit_order_post(figi = figi, limit_order_request={"lots": self.lots_of_average, "operation": 'Buy', "price": self.current_price})294"""Задержка в минуту для возможного исполнения ордера"""295time.sleep(60)296try:297order_list, status_list, operation_list, figi_list = [],[],[],[]298for ind_ in range(len(client2.orders.orders_get().payload)):299order_list.append(client2.orders.orders_get().payload[ind_].order_id)300status_list.append(client2.orders.orders_get().payload[ind_].status)301operation_list.append(client2.orders.orders_get().payload[ind_].operation)302figi_list.append(client2.orders.orders_get().payload[ind_].figi)303df = pd.DataFrame({304'order_id': order_list,305'status': status_list,306'operation': operation_list,307'figi': figi_list308})309except:310"""Делалась ранее задержка в 10 секунд для потенциального обновления API - на тестах311были случаи когда ордера не успевали обновиться"""312time.sleep(10)313order_list, status_list, operation_list, figi_list = [],[],[],[]314for ind_ in range(len(client2.orders.orders_get().payload)):315order_list.append(client2.orders.orders_get().payload[ind_].order_id)316status_list.append(client2.orders.orders_get().payload[ind_].status)317operation_list.append(client2.orders.orders_get().payload[ind_].operation)318figi_list.append(client2.orders.orders_get().payload[ind_].figi)319df = pd.DataFrame({320'order_id': order_list,321'status': status_list,322'operation': operation_list,323'figi': figi_list324})325326if len(df[df['order_id'] == str(order_response.payload.order_id)]) > 0:327"""Ecли ордер не смог выполниться - удаляем ордер"""328client2.orders.orders_cancel_post(order_id=order_response.payload.order_id)329"""И тут же ставим ордер на продажу по старому объему акций """330order_response_sell = client2.orders.orders_limit_order_post(figi = self.figi, limit_order_request={"lots": self.total, "operation": 'Sell', "price": self.price})331f = open(self.log_file_address, 'a+', encoding='utf-8')332f.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)))333f.write('\n')334f.close()335336else:337"""Если ордер исполнился - логгируем покупку"""338f = open(self.log_file_address, 'a+', encoding='utf-8')339f.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)))340f.write('\n')341f.close()342"""Высчитываем нужную цену продажи и ставим условие на продажу и логгируем продажу"""343order_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})344f = open(self.log_file_address, 'a+', encoding='utf-8')345f.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)))346f.write('\n')347f.close()348349350351class MakeOrders:352def __init__(self, value, figi, total, price, order_response_sell, log_file_address):353self.value = value354self.figi = figi355self.total = total356self.price = price357self.chat_id = config.telegram_сhat_id()358self.send = 0359self.order_response_sell = order_response_sell360self.log_file_address = log_file_address361362def update_data_and_send_to_bot(self):363if self.value == 0:364self.send = 'Не удалось удалить ни одного ордера - код завершен с ошибкой'365elif self.value == -1:366self.send = 'TradeSucsess - profit: ' + str(self.price)367f = open(self.log_file_address, 'a+', encoding='utf-8')368f.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')))369f.write('\n')370f.close()371elif self.value == 1:372self.send = 'Начальный ордер поставлен:' + ' ' + str(self.order_response_sell.payload.status)373f = open(self.log_file_address, 'a+', encoding='utf-8')374f.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)))375f.write('\n')376f.close()377elif self.value == 2:378self.send = 'Послеусредненный ордер поставлен:' + ' ' + str(order_response_sell.payload.status)379f = open(self.log_file_address, 'a+', encoding='utf-8')380f.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)))381f.write('\n')382f.close()383384try:385bot.send_message(self.chat_id, self.send)386except:387print(str(traceback.format_exc()))388389390391392