Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
wiseplat
GitHub Repository: wiseplat/python-code
Path: blob/master/ invest-robot-contest_trading_bot-master/bot/handlers/buy_handlers.py
5935 views
1
from main import bot
2
from aiogram.types import InlineKeyboardMarkup, InlineKeyboardButton
3
from trading.get_account_info import get_currency_sing
4
from main import dp
5
from aiogram.types import Message, ReplyKeyboardMarkup
6
from bot.keyboards.start_menu_keyboard import get_start_menu
7
from aiogram.dispatcher import FSMContext
8
from aiogram.dispatcher.filters.state import State, StatesGroup
9
from aiogram import types
10
from trading.trade_help import in_lot_figi, get_price_figi, quotation_to_float
11
from trading.place_order import buy_order
12
from trading.check_av import check_time
13
from config.personal_data import get_account_type, get_account_access, get_account
14
from trading.get_securities import get_security_list
15
from trading.get_securities import security_name_by_figi
16
"""
17
18
Тут представлены все хэндлеры, которые отвечают за продажу бумаг
19
20
"""
21
22
"""
23
Создаём три состояния FSM
24
"""
25
26
27
class SearchSecurityBuy(StatesGroup):
28
wait_sfb_buy = State()
29
30
31
class BuyOrder(StatesGroup):
32
b_wait_figi = State()
33
b_wait_quantity = State()
34
b_wait_price = State()
35
36
37
"""
38
Начало поиска бумаг
39
"""
40
41
42
@dp.message_handler(text="Купить")
43
async def start_buy(message):
44
if get_account_access(message.from_user.id) == 1:
45
await bot.send_message(chat_id=message.from_user.id, text="Введите название бумаги или FIGI:")
46
await SearchSecurityBuy.wait_sfb_buy.set()
47
else:
48
await bot.send_message(chat_id=message.from_user.id, text=f"<b>У Вас используется токен только для чтения!</b>")
49
50
51
"""
52
Поиск бумаг на покупку
53
"""
54
55
56
@dp.message_handler(state=SearchSecurityBuy.wait_sfb_buy)
57
async def search_security_buy(message: Message, state: FSMContext):
58
security_list = get_security_list(user_id=message.from_user.id, name=message.text)
59
if len(security_list) != 0:
60
for security in security_list:
61
62
choose_share_keyboard = InlineKeyboardMarkup()
63
choose_share_keyboard.add(
64
InlineKeyboardButton(text=f"Купить", callback_data=f"buy:figi:{security.figi}"))
65
66
try:
67
inst_type = security.instrument_type
68
69
if inst_type == "share":
70
inst = "Акции"
71
elif inst_type == "future":
72
inst = "Фьючерсы"
73
elif inst_type == "bond":
74
inst = "Бонды"
75
elif inst_type == "etf":
76
inst = "ETF"
77
elif inst_type == "currency":
78
inst = "Валюта"
79
else:
80
inst = inst_type
81
82
except:
83
inst = "Акции"
84
85
await message.answer(
86
text=
87
f"🧾<b>{inst} {security.name}</b>\n"
88
f"FIGI: {security.figi}\n\n"
89
f"Бумаг в лоте: {security.lot}\n"
90
f"Средняя цена бумаги: {round(get_price_figi(user_id=message.from_user.id, figi=security.figi), 4)}{get_currency_sing(security.currency)}\n"
91
f"Итого стоимость: {round(security.lot * get_price_figi(user_id=message.from_user.id, figi=security.figi), 4)}{get_currency_sing(security.currency)}\n"
92
, reply_markup=choose_share_keyboard)
93
94
await state.finish()
95
else:
96
await bot.send_message(chat_id=message.from_user.id, text=f"Такой бумаги нет!")
97
await bot.send_message(chat_id=message.from_user.id, text=f"Повторите ввод или напишите 'Отмена':")
98
return 0
99
100
101
"""
102
Выбор количества лотов
103
"""
104
105
106
@dp.callback_query_handler(lambda c: c.data and c.data.startswith("buy:figi"))
107
async def b_choose_quantity(callback_query, state: FSMContext):
108
data = callback_query.data.split(":")
109
figi = data[2]
110
111
# Проверяем, доступна ли она сейчас для покупки
112
if check_time(user_id=callback_query.from_user.id, figi=figi)[0] or get_account_type(
113
user_id=callback_query.from_user.id) == "sandbox":
114
115
# Запишем в память
116
await state.update_data(b_chosen_figi=figi)
117
118
# Создаём клавиатуру с примерами лотов
119
lot_keyboard = ReplyKeyboardMarkup()
120
lot_keyboard.add(f"1")
121
lot_keyboard.add(f"2")
122
lot_keyboard.add(f"3")
123
lot_keyboard.add(f"4")
124
lot_keyboard.add(f"Отмена")
125
126
await bot.send_message(chat_id=callback_query.from_user.id, text="Укажите количество лотов для покупки:",
127
reply_markup=lot_keyboard)
128
129
# Перейдём в следующее состояние
130
await BuyOrder.b_wait_quantity.set()
131
return
132
else:
133
await state.reset_state()
134
await bot.send_message(chat_id=callback_query.from_user.id, text="Торги ещё не начались!")
135
await bot.send_message(chat_id=callback_query.from_user.id,
136
text=check_time(user_id=callback_query.from_user.id, figi=figi)[1],
137
reply_markup=get_start_menu(callback_query.from_user.id))
138
139
140
"""
141
Третий хэндлер, который находится в состоянии b_wait_quantity
142
"""
143
144
145
@dp.message_handler(state=BuyOrder.b_wait_quantity)
146
async def b_choose_price(message: Message, state: FSMContext):
147
# Проверяем корректность введённых данных
148
try:
149
int(message.text)
150
except:
151
await message.answer("Вы ввели неверный формат!")
152
else:
153
if int(message.text) > 0:
154
155
# Запишем в память
156
await state.update_data(b_chosen_quantity=message.text)
157
158
user_data = await state.get_data()
159
price = get_price_figi(user_data['b_chosen_figi'], user_id=message.from_user.id)
160
161
# Создадим клавиатуру с примерами цены на бумагу
162
price_keyboard = ReplyKeyboardMarkup()
163
164
price_keyboard.add(f"Лучшая цена")
165
price_keyboard.add(f"{round(price * 1.02, 5)}")
166
price_keyboard.add(f"{round(price * 1.01, 5)}")
167
price_keyboard.add(f"{round(price * 1.00, 5)}")
168
price_keyboard.add(f"{round(price * 0.99, 5)}")
169
price_keyboard.add(f"{round(price * 0.98, 5)}")
170
price_keyboard.add(f"Отмена")
171
172
# Включим клавиатуру
173
await message.answer("Укажите цену за бумагу:", reply_markup=price_keyboard)
174
await BuyOrder.b_wait_price.set()
175
176
# В случае ошибки повторим запрос
177
else:
178
await message.answer("Введите корректное число лотов!")
179
180
181
"""
182
Последний хэндлер, который покупает бумаги
183
"""
184
185
186
@dp.message_handler(state=BuyOrder.b_wait_price)
187
async def b_finish(message: types.Message, state: FSMContext):
188
if message.text == "Лучшая цена":
189
190
user_data = await state.get_data()
191
192
await state.finish()
193
194
# Продадим бумаги и выведем сообщение
195
196
order = buy_order(figi=user_data['b_chosen_figi'], price=0.0,
197
quantity_lots=int(user_data['b_chosen_quantity']), user_id=message.from_user.id, via="bot")
198
199
if order:
200
await message.answer(
201
f"Покупка ценных бумаг {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",
202
reply_markup=get_start_menu(message.from_user.id))
203
else:
204
await message.answer("Ошибка! Вероятно, у Вас мало средств на счёте!")
205
else:
206
207
try:
208
float(message.text)
209
except:
210
await message.answer("Вы ввели неверный формат!")
211
else:
212
user_data = await state.get_data()
213
price = get_price_figi(user_data['b_chosen_figi'], user_id=message.from_user.id)
214
215
# Проверяем, что цена находится в разумных границах
216
217
if price * 1.20 > float(message.text) > price * 0.80:
218
await state.finish()
219
220
order = buy_order(figi=user_data['b_chosen_figi'], price=float(message.text),
221
quantity_lots=int(user_data['b_chosen_quantity']), user_id=message.from_user.id,
222
via="bot")
223
if order:
224
await message.answer(
225
f"Выставлен ордер на покупку ценных бумаг {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",
226
reply_markup=get_start_menu(message.from_user.id))
227
else:
228
await message.answer("Ошибка! Вероятно, у Вас мало средств на счёте!")
229
230
# В случае ошибки повторим запрос
231
else:
232
await message.answer("Введите корректную цену!")
233
return
234
235