Path: blob/master/ invest-robot-contest_trading_bot-master/bot/handlers/sell_handlers.py
5935 views
from main import dp, bot1from trading.get_account_info import get_lots_portfolio2from tinkoff.invest import Client3from trading.trade_help import is_in_portfolio, get_price_figi4from config.personal_data import get_account, get_token5from trading.place_order import sell_sfb6from aiogram.types import InlineKeyboardMarkup, InlineKeyboardButton7from trading.get_account_info import get_currency_sing, get_price_in_portfolio8from aiogram.types import Message9from bot.keyboards.start_menu_keyboard import get_start_menu10from aiogram.dispatcher import FSMContext11from aiogram.dispatcher.filters.state import State, StatesGroup12from aiogram.types import ReplyKeyboardMarkup13from aiogram import types14from trading.trade_help import in_lot_figi15from trading.get_securities import security_name_by_figi16from trading.check_av import check_time17from config.personal_data import get_account_type, get_account_access18from trading.trade_help import quotation_to_float19from trading.trade_help import get_currency_sing2021"""2223Тут представлены все хэндлеры, которые отвечают за продажу бумаг2425"""2627"""28Создаём три состояния FSM29"""303132class SellOrder(StatesGroup):33s_wait_figi = State()34s_wait_quantity = State()35s_wait_price = State()363738"""39Первый хэндлер, который запускает состояние продажи40"""414243@dp.message_handler(text="Продать")44async def start_sell(message):45if get_account_access(message.from_user.id) == 1:4647empty_portfolio = True4849user_id = message.from_user.id5051with Client(get_token(message.from_user.id)) as client:5253if get_account_type(message.from_user.id) == "sandbox":54portfolio = client.sandbox.get_sandbox_portfolio(account_id=get_account(message.from_user.id))55else:56portfolio = client.operations.get_portfolio(account_id=get_account(message.from_user.id))5758for i in portfolio.positions:59if i.instrument_type != "currency":60empty_portfolio = False6162sell_keyboard = InlineKeyboardMarkup()63sell_keyboard.add(InlineKeyboardButton(text=f"Продать", callback_data=f"sell:figi:{i.figi}"))6465if i.instrument_type == "share":66inst = "Акции"67elif i.instrument_type == "bond":68inst = "Бонды"69elif i.instrument_type == "future":70inst = "Фьючерсы"71elif i.instrument_type == "etf":72inst = "ETF"73else:74inst = i.instrument_type7576if get_account_type(message.from_user.id) == "sandbox":77text = f"🧾<b>{inst} {security_name_by_figi(figi=i.figi, user_id=user_id)}</b>\n"\78f"FIGI: {i.figi}\n\n"\79f"Лотов в портфеле: {int(quotation_to_float(i.quantity_lots))}\n"\80f"Бумаг в лоте: {in_lot_figi(figi=i.figi, user_id=user_id)}\n\n"\81f"Средняя цена бумаги: {round(quotation_to_float(i.average_position_price), 4)}{get_currency_sing(i.average_position_price.currency)}\n"\82f"Средняя цена лота: {round(quotation_to_float(i.average_position_price)*in_lot_figi(figi=i.figi, user_id=user_id), 4)}{get_currency_sing(i.average_position_price.currency)}\n\n"\83f"Итого стоимость: {round(quotation_to_float(i.average_position_price)*quotation_to_float(i.quantity), 4)}{get_currency_sing(i.average_position_price.currency)}\n "84else:85text = f"🧾<b>{inst} {security_name_by_figi(figi=i.figi, user_id=user_id)}</b>\n"\86f"FIGI: {i.figi}\n\n"\87f"Лотов в портфеле: {int(quotation_to_float(i.quantity_lots))}\n"\88f"Бумаг в лоте: {in_lot_figi(figi=i.figi, user_id=user_id)}\n\n"\89f"Цена бумаги: {round(quotation_to_float(i.current_price), 4)}{get_currency_sing(i.current_price.currency)}\n"\90f"Средняя цена лота: {round(quotation_to_float(i.current_price)*in_lot_figi(figi=i.figi, user_id=user_id), 4)}{get_currency_sing(i.average_position_price.currency)}\n\n"\91f"Итого стоимость: {round(quotation_to_float(i.current_price)*quotation_to_float(i.quantity), 4)}{get_currency_sing(i.average_position_price.currency)}\n"9293await bot.send_message(chat_id=user_id, text=text,reply_markup=sell_keyboard)9495if empty_portfolio:96await bot.send_message(chat_id=user_id, text=f"<b>У Вас нет бумаг!</b>")97else:98await bot.send_message(chat_id=message.from_user.id, text=f"<b>У Вас используется токен только для чтения!</b>")99100101@dp.callback_query_handler(lambda c: c.data and c.data.startswith("sell:figi"))102async def s_choose_quantity(callback_query, state: FSMContext):103data = callback_query.data.split(":")104figi = data[2]105106# Проверяем, есть ли такая акция в портфеле107if is_in_portfolio(figi, user_id=callback_query.from_user.id):108if check_time(user_id=callback_query.from_user.id, figi=figi)[0] or get_account_type(109user_id=callback_query.from_user.id) == "sandbox":110111lot_keyboard = ReplyKeyboardMarkup()112av_lots = get_lots_portfolio(figi=figi, user_id=callback_query.from_user.id)113for i in range(av_lots):114lot_keyboard.add(f"{i + 1}")115if i == 6:116break117lot_keyboard.add(f"Отмена")118119# Включим клавиатуру120await bot.send_message(chat_id=callback_query.from_user.id, text=f"Доступно лотов: {av_lots}\nУкажите "121f"количество лотов для продажи:",122reply_markup=lot_keyboard)123124# Запишем данные о FIGI в память125await state.update_data(s_chosen_figi=figi)126127# Перейдём в следующее состояние128await SellOrder.s_wait_quantity.set()129return130131else:132await state.reset_state()133await bot.send_message(chat_id=callback_query.from_user.id, text="Торги ещё не начались!")134await bot.send_message(chat_id=callback_query.from_user.id,135text=check_time(user_id=callback_query.from_user.id, figi=callback_query.text)[1],136reply_markup=get_start_menu(callback_query.from_user.id))137138# В случае ошибки повторим запрос139else:140await bot.send_message(chat_id=callback_query.from_user.id, text="Такой бумаги нет в портфеле!")141return142143144"""145Третий хендлер, который исполняется в состоянии s_wait_quantity146"""147148149@dp.message_handler(state=SellOrder.s_wait_quantity)150async def s_choose_price(message: Message, state: FSMContext):151# Получим цену бумаги152try:153int(message.text)154except:155await message.answer("Вы ввели неверный формат!")156else:157user_data = await state.get_data()158price = get_price_in_portfolio(user_data['s_chosen_figi'], user_id=message.from_user.id)159160# Проверяем, есть ли такое количество лотов в портфеле161if get_lots_portfolio(user_data['s_chosen_figi'], user_id=message.from_user.id) >= int(message.text) > 0:162163# Запишем данные о количестве в память164await state.update_data(s_chosen_quantity=message.text)165166# Создаём клавиатуру с ценами167# Для удобства было добавлено несколько цен на 1% и 2% меньше/больше текущей168# При этом также можно ввести свою цену169price_keyboard = ReplyKeyboardMarkup()170171price_keyboard.add(f"Лучшая цена")172price_keyboard.add(f"{round(price * 1.02, 5)}")173price_keyboard.add(f"{round(price * 1.01, 5)}")174price_keyboard.add(f"{round(price * 1.00, 6)}")175price_keyboard.add(f"{round(price * 0.99, 5)}")176price_keyboard.add(f"{round(price * 0.98, 5)}")177price_keyboard.add(f"Отмена")178179# Включаем клавиатуру180await message.answer(f"Укажите цену за бумагу (или напишите свою):",181reply_markup=price_keyboard)182183# Переходим в следующее состояние184await SellOrder.s_wait_price.set()185return186187# В случае ошибки повторяем запрос188else:189await message.answer(f"Введите доступное число лотов!")190return191192193"""194Последний хендлер, который исполняется в состоянии s_wait_price195"""196197198@dp.message_handler(state=SellOrder.s_wait_price)199async def s_finish(message: types.Message, state: FSMContext):200# Получаем цену бумаги201202if message.text == "Лучшая цена":203204user_data = await state.get_data()205206# Продаём бумаги и выводим сообщение об этом207208await state.finish()209210order = sell_sfb(figi=user_data['s_chosen_figi'], price=0.0,211quantity_lots=int(user_data['s_chosen_quantity']), user_id=message.from_user.id, via="bot")212213if order:214await message.answer(215f"Продажа ценных бумаг {security_name_by_figi(order.figi, message.from_user.id)} в количестве {order.lots_requested} лотов по цене {quotation_to_float(order.initial_order_price)}{get_currency_sing(order.initial_order_price.currency)}.\n",216reply_markup=get_start_menu(message.from_user.id))217else:218await message.answer("Ошибка!")219220else:221try:222float(message.text)223except:224await message.answer("Вы ввели неверный формат!")225else:226user_data = await state.get_data()227price = get_price_in_portfolio(user_data['s_chosen_figi'], user_id=message.from_user.id)228229# Проверяем, что цена находится в разумных пределах230231if (price * 1.20) > float(message.text) > (price * 0.80):232# Продаём бумаги и выводим сообщение об этом233234await state.finish()235236order = sell_sfb(figi=user_data['s_chosen_figi'], price=float(message.text),237quantity_lots=int(user_data['s_chosen_quantity']), user_id=message.from_user.id,238via="bot")239240if order:241await message.answer(242f"Выставлен ордер на продажу ценных бумаг {security_name_by_figi(order.figi,message.from_user.id)} в количестве {order.lots_requested} лотов по цене {quotation_to_float(order.initial_order_price)}{get_currency_sing(order.initial_order_price.currency)}.\n",243reply_markup=get_start_menu(message.from_user.id))244else:245await message.answer("Ошибка!")246247248# В случае ошибки повторяем запрос249else:250await message.answer(f"Введите корректную стоимость!")251return252253254