2
0
forked from kodorvan/stcs
Files
stcs/app/telegram/handlers/main_settings/risk_management.py

468 lines
18 KiB
Python

import logging.config
from aiogram import F, Router
from aiogram.fsm.context import FSMContext
from aiogram.types import CallbackQuery, Message
import app.telegram.keyboards.inline as kbi
import database.request as rq
from app.helper_functions import is_int
from app.telegram.states.states import RiskManagementState
from logger_helper.logger_helper import LOGGING_CONFIG
logging.config.dictConfig(LOGGING_CONFIG)
logger = logging.getLogger("risk_management")
router_risk_management = Router(name="risk_management")
@router_risk_management.callback_query(F.data == "take_profit_percent")
async def take_profit_percent(callback_query: CallbackQuery, state: FSMContext) -> None:
"""
Handles the 'profit_price_change' callback query.
Clears the current FSM state, edits the message text to display the take profit percent options,
and shows an inline keyboard for selection.
Args:
callback_query (CallbackQuery): Incoming callback query from Telegram inline keyboard.
state (FSMContext): Finite State Machine context for the current user session.
Logs:
Success or error messages with user identification.
"""
try:
await state.clear()
await state.set_state(RiskManagementState.take_profit_percent_state)
msg = await callback_query.message.edit_text(
text="Введите процент изменения цены для фиксации прибыли: ",
reply_markup=kbi.back_to_risk_management,
)
await state.update_data(prompt_message_id=msg.message_id)
logger.debug(
"Command profit_price_change processed successfully for user: %s",
callback_query.from_user.id,
)
except Exception as e:
await callback_query.answer(
text="Произошла ошибка. Пожалуйста, попробуйте позже."
)
logger.error(
"Error processing command profit_price_change for user %s: %s",
callback_query.from_user.id,
e,
)
@router_risk_management.message(RiskManagementState.take_profit_percent_state)
async def set_take_profit_percent(message: Message, state: FSMContext) -> None:
"""
Handles user input for setting the take profit percentage.
Updates FSM context with the selected percentage and persists the choice in database.
Sends an acknowledgement to user and clears FSM state afterward.
Args:
message (Message): Incoming message from user containing the take profit percentage.
state (FSMContext): Finite State Machine context for the current user session.
Logs:
Success or error messages with user identification.
"""
try:
try:
data = await state.get_data()
if "prompt_message_id" in data:
prompt_message_id = data["prompt_message_id"]
await message.bot.delete_message(
chat_id=message.chat.id, message_id=prompt_message_id
)
await message.delete()
except Exception as e:
if "message to delete not found" in str(e).lower():
pass # Ignore this error
else:
raise e
take_profit_percent_value = message.text
if not is_int(take_profit_percent_value):
await message.answer(
text="Ошибка: введите валидное число.",
reply_markup=kbi.back_to_risk_management,
)
logger.debug(
"User %s input invalid (not an valid number): %s",
message.from_user.id,
take_profit_percent_value,
)
return
if int(take_profit_percent_value) < 1 or int(take_profit_percent_value) > 100:
await message.answer(
text="Ошибка: введите число от 1 до 100.",
reply_markup=kbi.back_to_risk_management,
)
logger.debug(
"User %s input invalid (not an valid number): %s",
message.from_user.id,
take_profit_percent_value,
)
return
req = await rq.set_take_profit_percent(
tg_id=message.from_user.id,
take_profit_percent=int(take_profit_percent_value),
)
if req:
await message.answer(
text=f"Процент изменения цены для фиксации прибыли "
f"установлен на {take_profit_percent_value}%.",
reply_markup=kbi.back_to_risk_management,
)
else:
await message.answer(
text="Произошла ошибка при установке процента изменения цены для фиксации прибыли. "
"Пожалуйста, попробуйте позже.",
reply_markup=kbi.back_to_risk_management,
)
await state.clear()
except Exception as e:
logger.error(
"Error processing command profit_price_change for user %s: %s",
message.from_user.id,
e,
)
@router_risk_management.callback_query(F.data == "stop_loss_percent")
async def stop_loss_percent(callback_query: CallbackQuery, state: FSMContext) -> None:
"""
Handles the 'stop_loss_percent' callback query.
Clears the current FSM state, edits the message text to display the stop loss percentage options,
and shows an inline keyboard for selection.
Args:
callback_query (CallbackQuery): Incoming callback query from Telegram inline keyboard.
state (FSMContext): Finite State Machine context for the current user session.
Logs:
Success or error messages with user identification.
"""
try:
await state.clear()
await state.set_state(RiskManagementState.stop_loss_percent_state)
msg = await callback_query.message.edit_text(
text="Введите процент изменения цены для фиксации убытка: ",
reply_markup=kbi.back_to_risk_management,
)
await state.update_data(prompt_message_id=msg.message_id)
logger.debug(
"Command stop_loss_percent processed successfully for user: %s",
callback_query.from_user.id,
)
except Exception as e:
await callback_query.answer(
text="Произошла ошибка. Пожалуйста, попробуйте позже."
)
logger.error(
"Error processing command stop_loss_percent for user %s: %s",
callback_query.from_user.id,
e,
)
@router_risk_management.message(RiskManagementState.stop_loss_percent_state)
async def set_stop_loss_percent(message: Message, state: FSMContext) -> None:
"""
Handles user input for setting the stop loss percentage.
Updates FSM context with the selected percentage and persists the choice in database.
Sends an acknowledgement to user and clears FSM state afterward.
Args:
message (Message): Incoming message from user containing the stop loss percentage.
state (FSMContext): Finite State Machine context for the current user session.
Logs:
Success or error messages with user identification.
"""
try:
try:
data = await state.get_data()
if "prompt_message_id" in data:
prompt_message_id = data["prompt_message_id"]
await message.bot.delete_message(
chat_id=message.chat.id, message_id=prompt_message_id
)
await message.delete()
except Exception as e:
if "message to delete not found" in str(e).lower():
pass # Ignore this error
else:
raise e
stop_loss_percent_value = message.text
if not is_int(stop_loss_percent_value):
await message.answer(
text="Ошибка: введите валидное число.",
reply_markup=kbi.back_to_risk_management,
)
logger.debug(
"User %s input invalid (not an valid number): %s",
message.from_user.id,
stop_loss_percent_value,
)
return
if int(stop_loss_percent_value) < 1 or int(stop_loss_percent_value) > 100:
await message.answer(
text="Ошибка: введите число от 1 до 100.",
reply_markup=kbi.back_to_risk_management,
)
logger.debug(
"User %s input invalid (not an valid number): %s",
message.from_user.id,
stop_loss_percent_value,
)
return
req = await rq.set_stop_loss_percent(
tg_id=message.from_user.id, stop_loss_percent=int(stop_loss_percent_value)
)
if req:
await message.answer(
text=f"Процент изменения цены для фиксации убытка "
f"установлен на {stop_loss_percent_value}%.",
reply_markup=kbi.back_to_risk_management,
)
else:
await message.answer(
text="Произошла ошибка при установке процента изменения цены для фиксации убытка. "
"Пожалуйста, попробуйте позже.",
reply_markup=kbi.back_to_risk_management,
)
await state.clear()
except Exception as e:
await message.answer(
text="Произошла ошибка при установке процента изменения цены для фиксации убытка. "
"Пожалуйста, попробуйте позже.",
reply_markup=kbi.back_to_risk_management,
)
logger.error(
"Error processing command stop_loss_percent for user %s: %s",
message.from_user.id,
e,
)
@router_risk_management.callback_query(F.data == "max_risk_percent")
async def max_risk_percent(callback_query: CallbackQuery, state: FSMContext) -> None:
"""
Handles the 'max_risk_percent' callback query.
Clears the current FSM state, edits the message text to display the maximum risk percentage options,
and shows an inline keyboard for selection.
Args:
callback_query (CallbackQuery): Incoming callback query from Telegram inline keyboard.
state (FSMContext): Finite State Machine context for the current user session.
Logs:
Success or error messages with user identification.
"""
try:
await state.clear()
await state.set_state(RiskManagementState.max_risk_percent_state)
msg = await callback_query.message.edit_text(
text="Введите максимальный процент риска: ",
reply_markup=kbi.back_to_risk_management,
)
await state.update_data(prompt_message_id=msg.message_id)
logger.debug(
"Command max_risk_percent processed successfully for user: %s",
callback_query.from_user.id,
)
except Exception as e:
await callback_query.answer(
text="Произошла ошибка. Пожалуйста, попробуйте позже."
)
logger.error(
"Error processing command max_risk_percent for user %s: %s",
callback_query.from_user.id,
e,
)
@router_risk_management.message(RiskManagementState.max_risk_percent_state)
async def set_max_risk_percent(message: Message, state: FSMContext) -> None:
"""
Handles user input for setting the maximum risk percentage.
Updates FSM context with the selected percentage and persists the choice in database.
Sends an acknowledgement to user and clears FSM state afterward.
Args:
message (Message): Incoming message from user containing the maximum risk percentage.
state (FSMContext): Finite State Machine context for the current user session.
Logs:
Success or error messages with user identification.
"""
try:
try:
data = await state.get_data()
if "prompt_message_id" in data:
prompt_message_id = data["prompt_message_id"]
await message.bot.delete_message(
chat_id=message.chat.id, message_id=prompt_message_id
)
await message.delete()
except Exception as e:
if "message to delete not found" in str(e).lower():
pass # Ignore this error
else:
raise e
max_risk_percent_value = message.text
if not is_int(max_risk_percent_value):
await message.answer(
text="Ошибка: введите валидное число.",
reply_markup=kbi.back_to_risk_management,
)
logger.debug(
"User %s input invalid (not an valid number): %s",
message.from_user.id,
max_risk_percent_value,
)
return
if int(max_risk_percent_value) < 1 or int(max_risk_percent_value) > 100:
await message.answer(
text="Ошибка: введите число от 1 до 100.",
reply_markup=kbi.back_to_risk_management,
)
logger.debug(
"User %s input invalid (not an valid number): %s",
message.from_user.id,
max_risk_percent_value,
)
return
req = await rq.set_max_risk_percent(
tg_id=message.from_user.id, max_risk_percent=int(max_risk_percent_value)
)
if req:
await message.answer(
text=f"Максимальный процент риска установлен на {max_risk_percent_value}%.",
reply_markup=kbi.back_to_risk_management,
)
else:
await message.answer(
text="Произошла ошибка при установке максимального процента риска. "
"Пожалуйста, попробуйте позже.",
reply_markup=kbi.back_to_risk_management,
)
await state.clear()
except Exception as e:
await message.answer(
text="Произошла ошибка при установке максимального процента риска. "
"Пожалуйста, попробуйте позже.",
reply_markup=kbi.back_to_risk_management,
)
logger.error(
"Error processing command max_risk_percent for user %s: %s",
message.from_user.id,
e,
)
@router_risk_management.callback_query(F.data == "commission_fee")
async def commission_fee(callback_query: CallbackQuery, state: FSMContext) -> None:
"""
Handles the 'commission_fee' callback query.
Clears the current FSM state, edits the message text to display the commission fee options,
and shows an inline keyboard for selection.
Args:
callback_query (CallbackQuery): Incoming callback query from Telegram inline keyboard.
state (FSMContext): Finite State Machine context for the current user session.
Logs:
Success or error messages with user identification.
"""
try:
await state.clear()
await state.set_state(RiskManagementState.commission_fee_state)
msg = await callback_query.message.edit_text(
text="Учитывать комиссию биржи для расчета прибыли?: ",
reply_markup=kbi.commission_fee,
)
await state.update_data(prompt_message_id=msg.message_id)
logger.debug(
"Command commission_fee processed successfully for user: %s",
callback_query.from_user.id,
)
except Exception as e:
await callback_query.answer(
text="Произошла ошибка. Пожалуйста, попробуйте позже."
)
logger.error(
"Error processing command commission_fee for user %s: %s",
callback_query.from_user.id,
e,
)
@router_risk_management.callback_query(
lambda c: c.data in ["Yes_commission_fee", "No_commission_fee"]
)
async def set_commission_fee(callback_query: CallbackQuery, state: FSMContext) -> None:
"""
Handles user input for setting the commission fee.
Updates FSM context with the selected option and persists the choice in database.
Sends an acknowledgement to user and clears FSM state afterward.
Args:
callback_query (CallbackQuery): Incoming callback query from Telegram inline keyboard.
state (FSMContext): Finite State Machine context for the current user session.
Logs:
Success or error messages with user identification.
"""
try:
req = await rq.set_commission_fee(
tg_id=callback_query.from_user.id, commission_fee=callback_query.data
)
if not req:
await callback_query.answer(
text="Произошла ошибка при установке комиссии биржи. Пожалуйста, попробуйте позже."
)
return
if callback_query.data == "Yes_commission_fee":
await callback_query.answer(text="Комиссия биржи учитывается.")
else:
await callback_query.answer(text="Комиссия биржи не учитывается.")
except Exception as e:
logger.error(
"Error processing command commission_fee for user %s: %s",
callback_query.from_user.id,
e,
)
finally:
await state.clear()