forked from kodorvan/stcs
Added the ability to get a list of open trades and limit orders, as well as their closures (previously it was possible only for the selected pair)
This commit is contained in:
@@ -14,6 +14,8 @@ import app.telegram.Keyboards.inline_keyboards as inline_markup
|
|||||||
logging.config.dictConfig(LOGGING_CONFIG)
|
logging.config.dictConfig(LOGGING_CONFIG)
|
||||||
logger = logging.getLogger("futures")
|
logger = logging.getLogger("futures")
|
||||||
|
|
||||||
|
processed_trade_ids = set()
|
||||||
|
|
||||||
|
|
||||||
def safe_float(val) -> float:
|
def safe_float(val) -> float:
|
||||||
"""
|
"""
|
||||||
@@ -100,6 +102,13 @@ async def handle_execution_message(message, msg: dict) -> None:
|
|||||||
"""
|
"""
|
||||||
# logger.info(f"Исполнена сделка:\n{json.dumps(msg, indent=4, ensure_ascii=False)}")
|
# logger.info(f"Исполнена сделка:\n{json.dumps(msg, indent=4, ensure_ascii=False)}")
|
||||||
|
|
||||||
|
trade_id = msg.get('data', [{}])[0].get('orderId')
|
||||||
|
if trade_id in processed_trade_ids:
|
||||||
|
logger.info(f"Уже обработана сделка {trade_id}, дублирующее уведомление игнорируется")
|
||||||
|
return
|
||||||
|
|
||||||
|
processed_trade_ids.add(trade_id)
|
||||||
|
|
||||||
pnl = parse_pnl_from_msg(msg)
|
pnl = parse_pnl_from_msg(msg)
|
||||||
tg_id = message.from_user.id
|
tg_id = message.from_user.id
|
||||||
|
|
||||||
@@ -475,7 +484,7 @@ async def set_take_profit_stop_loss(tg_id: int, message, take_profit_price: floa
|
|||||||
|
|
||||||
async def cancel_all_tp_sl_orders(tg_id, symbol):
|
async def cancel_all_tp_sl_orders(tg_id, symbol):
|
||||||
"""
|
"""
|
||||||
Отменяет все открытые ордера TP/SL для указанного символа.
|
Отменяет лимитные ордера для указанного символа.
|
||||||
"""
|
"""
|
||||||
api_key = await rq.get_bybit_api_key(tg_id)
|
api_key = await rq.get_bybit_api_key(tg_id)
|
||||||
secret_key = await rq.get_bybit_secret_key(tg_id)
|
secret_key = await rq.get_bybit_secret_key(tg_id)
|
||||||
@@ -487,26 +496,49 @@ async def cancel_all_tp_sl_orders(tg_id, symbol):
|
|||||||
|
|
||||||
for order in orders:
|
for order in orders:
|
||||||
order_id = order.get('orderId')
|
order_id = order.get('orderId')
|
||||||
|
order_symbol = order.get('symbol')
|
||||||
cancel_resp = client.cancel_order(category='linear', symbol=symbol, orderId=order_id)
|
cancel_resp = client.cancel_order(category='linear', symbol=symbol, orderId=order_id)
|
||||||
last_response = cancel_resp
|
|
||||||
if cancel_resp.get('retCode') != 0:
|
if cancel_resp.get('retCode') != 0:
|
||||||
logger.warning(f"Не удалось отменить ордер {order_id}: {cancel_resp.get('retMsg')}")
|
logger.warning(f"Не удалось отменить ордер {order_id}: {cancel_resp.get('retMsg')}")
|
||||||
|
else:
|
||||||
|
last_response = order_symbol
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"Ошибка при отмене ордеров TP/SL: {e}")
|
logger.error(f"Ошибка при отмене ордера: {e}")
|
||||||
|
|
||||||
return last_response
|
return last_response
|
||||||
|
|
||||||
|
|
||||||
async def get_active_positions_by_symbol(tg_id, message):
|
async def get_active_positions(tg_id, message):
|
||||||
|
"""
|
||||||
|
Показывает активные позиции пользователя.
|
||||||
|
"""
|
||||||
|
api_key = await rq.get_bybit_api_key(tg_id)
|
||||||
|
secret_key = await rq.get_bybit_secret_key(tg_id)
|
||||||
|
client = HTTP(api_key=api_key, api_secret=secret_key)
|
||||||
|
|
||||||
|
active_positions = client.get_positions(category='linear', settleCoin='USDT')
|
||||||
|
|
||||||
|
positions = active_positions.get('result', {}).get('list', [])
|
||||||
|
active_symbols = [pos.get('symbol') for pos in positions if float(pos.get('size', 0)) > 0]
|
||||||
|
|
||||||
|
if active_symbols:
|
||||||
|
await message.answer("📈 Ваши активные позиции:",
|
||||||
|
reply_markup=inline_markup.create_trades_inline_keyboard(active_symbols))
|
||||||
|
else:
|
||||||
|
await message.answer("❗️ У вас нет активных позиций.", reply_markup=inline_markup.back_to_main)
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
|
async def get_active_positions_by_symbol(tg_id, symbol, message):
|
||||||
"""
|
"""
|
||||||
Показывает активные позиции пользователя по символу.
|
Показывает активные позиции пользователя по символу.
|
||||||
"""
|
"""
|
||||||
api_key = await rq.get_bybit_api_key(tg_id)
|
api_key = await rq.get_bybit_api_key(tg_id)
|
||||||
secret_key = await rq.get_bybit_secret_key(tg_id)
|
secret_key = await rq.get_bybit_secret_key(tg_id)
|
||||||
client = HTTP(api_key=api_key, api_secret=secret_key)
|
client = HTTP(api_key=api_key, api_secret=secret_key)
|
||||||
symbol = await rq.get_symbol(tg_id)
|
|
||||||
|
|
||||||
active_positions = client.get_positions(category='linear', symbol=symbol)
|
active_positions = client.get_positions(category='linear', symbol=symbol)
|
||||||
|
|
||||||
positions = active_positions.get('result', {}).get('list', [])
|
positions = active_positions.get('result', {}).get('list', [])
|
||||||
pos = positions[0] if positions else None
|
pos = positions[0] if positions else None
|
||||||
|
|
||||||
@@ -526,14 +558,33 @@ async def get_active_positions_by_symbol(tg_id, message):
|
|||||||
|
|
||||||
await message.answer(text, reply_markup=inline_markup.create_close_deal_markup(symbol))
|
await message.answer(text, reply_markup=inline_markup.create_close_deal_markup(symbol))
|
||||||
|
|
||||||
|
async def get_active_orders(tg_id, message):
|
||||||
|
"""
|
||||||
|
Показывает активные лимитные ордера пользователя.
|
||||||
|
"""
|
||||||
|
api_key = await rq.get_bybit_api_key(tg_id)
|
||||||
|
secret_key = await rq.get_bybit_secret_key(tg_id)
|
||||||
|
client = HTTP(api_key=api_key, api_secret=secret_key)
|
||||||
|
|
||||||
async def get_active_orders_by_symbol(tg_id, message):
|
response = client.get_open_orders(category='linear', settleCoin='USDT', orderType='Limit')
|
||||||
|
orders = response.get('result', {}).get('list', [])
|
||||||
|
limit_orders = [order for order in orders if order.get('orderType') == 'Limit']
|
||||||
|
|
||||||
|
if limit_orders:
|
||||||
|
symbols = [order['symbol'] for order in limit_orders]
|
||||||
|
await message.answer("📈 Ваши активные лимитные ордера:",
|
||||||
|
reply_markup=inline_markup.create_trades_inline_keyboard_limits(symbols))
|
||||||
|
else:
|
||||||
|
await message.answer("❗️ У вас нет активных лимитных ордеров.", reply_markup=inline_markup.back_to_main)
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
|
async def get_active_orders_by_symbol(tg_id, symbol, message):
|
||||||
"""
|
"""
|
||||||
Показывает активные лимитные ордера пользователя по символу.
|
Показывает активные лимитные ордера пользователя по символу.
|
||||||
"""
|
"""
|
||||||
api_key = await rq.get_bybit_api_key(tg_id)
|
api_key = await rq.get_bybit_api_key(tg_id)
|
||||||
secret_key = await rq.get_bybit_secret_key(tg_id)
|
secret_key = await rq.get_bybit_secret_key(tg_id)
|
||||||
symbol = await rq.get_symbol(tg_id)
|
|
||||||
client = HTTP(api_key=api_key, api_secret=secret_key)
|
client = HTTP(api_key=api_key, api_secret=secret_key)
|
||||||
|
|
||||||
active_orders = client.get_open_orders(category='linear', symbol=symbol)
|
active_orders = client.get_open_orders(category='linear', symbol=symbol)
|
||||||
@@ -561,7 +612,7 @@ async def get_active_orders_by_symbol(tg_id, message):
|
|||||||
)
|
)
|
||||||
texts.append(text)
|
texts.append(text)
|
||||||
|
|
||||||
await message.answer("\n\n".join(texts), reply_markup=inline_markup.create_close_deal_markup(symbol))
|
await message.answer("\n\n".join(texts), reply_markup=inline_markup.create_close_limit_markup(symbol))
|
||||||
|
|
||||||
|
|
||||||
async def close_user_trade(tg_id: int, symbol: str, message):
|
async def close_user_trade(tg_id: int, symbol: str, message):
|
||||||
@@ -574,7 +625,6 @@ async def close_user_trade(tg_id: int, symbol: str, message):
|
|||||||
secret_key = await rq.get_bybit_secret_key(tg_id)
|
secret_key = await rq.get_bybit_secret_key(tg_id)
|
||||||
data_risk_stgs = await rq.get_user_risk_management_settings(tg_id)
|
data_risk_stgs = await rq.get_user_risk_management_settings(tg_id)
|
||||||
|
|
||||||
limit_price = await rq.get_limit_price(tg_id)
|
|
||||||
include_fee = data_risk_stgs.get('commission_fee', 'Нет') == 'Да'
|
include_fee = data_risk_stgs.get('commission_fee', 'Нет') == 'Да'
|
||||||
client = HTTP(api_key=api_key, api_secret=secret_key)
|
client = HTTP(api_key=api_key, api_secret=secret_key)
|
||||||
|
|
||||||
@@ -589,66 +639,29 @@ async def close_user_trade(tg_id: int, symbol: str, message):
|
|||||||
position = positions_list[0]
|
position = positions_list[0]
|
||||||
qty = abs(safe_float(position.get('size')))
|
qty = abs(safe_float(position.get('size')))
|
||||||
side = position.get('side')
|
side = position.get('side')
|
||||||
entry_price = safe_float(position.get('avgPrice'))
|
|
||||||
if qty == 0:
|
if qty == 0:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
orders = client.get_open_orders(category='linear', symbol=symbol)
|
|
||||||
cancel_resp = await cancel_all_tp_sl_orders(tg_id, symbol)
|
|
||||||
open_orders_list = orders.get('result', {}).get('list', [])
|
|
||||||
order_id = open_orders_list[0].get('orderId') if open_orders_list else None
|
|
||||||
close_side = "Sell" if side == "Buy" else "Buy"
|
close_side = "Sell" if side == "Buy" else "Buy"
|
||||||
ticker_resp = client.get_tickers(category="linear", symbol=symbol)
|
place_resp = client.place_order(
|
||||||
current_price = 0.0
|
category="linear",
|
||||||
if ticker_resp.get('retCode') == 0:
|
symbol=symbol,
|
||||||
result = ticker_resp.get('result', {})
|
side=close_side,
|
||||||
ticker_list = []
|
orderType="Market",
|
||||||
if isinstance(result, dict):
|
qty=str(qty),
|
||||||
ticker_list = result.get('list', [])
|
timeInForce="GTC",
|
||||||
elif isinstance(result, list):
|
reduceOnly=True
|
||||||
ticker_list = result
|
)
|
||||||
if ticker_list:
|
|
||||||
current_price = float(ticker_list[0].get('lastPrice', 0.0))
|
|
||||||
|
|
||||||
place_resp = client.place_order(
|
|
||||||
category="linear",
|
|
||||||
symbol=symbol,
|
|
||||||
side=close_side,
|
|
||||||
orderType="Market",
|
|
||||||
qty=str(qty),
|
|
||||||
timeInForce="GTC",
|
|
||||||
reduceOnly=True
|
|
||||||
)
|
|
||||||
|
|
||||||
if place_resp.get('retCode', -1) == 0:
|
|
||||||
trade_fee = 0
|
|
||||||
try:
|
|
||||||
trades_resp = client.get_closed_pnl(category="linear", symbol=symbol)
|
|
||||||
if trades_resp.get('retCode') == 0:
|
|
||||||
trades = trades_resp.get('result', {}).get('list', [])
|
|
||||||
for trade in trades:
|
|
||||||
if trade.get('orderId') == order_id:
|
|
||||||
trade_fee += float(trade.get('execFee', 0))
|
|
||||||
except Exception as e:
|
|
||||||
logger.error(f"Ошибка при получении сделок: {e}")
|
|
||||||
trade_fee = 0
|
|
||||||
|
|
||||||
pnl = (current_price - entry_price) * qty if side == "Buy" else (entry_price - current_price) * qty
|
|
||||||
|
|
||||||
if include_fee:
|
|
||||||
pnl -= trade_fee
|
|
||||||
pnl_percent = (pnl / (entry_price * qty)) * 100 if entry_price * qty > 0 else 0
|
|
||||||
return True
|
|
||||||
else:
|
|
||||||
if message:
|
|
||||||
await message.answer(f"Ошибка закрытия сделки {symbol}.",
|
|
||||||
reply_markup=inline_markup.back_to_main)
|
|
||||||
return False
|
|
||||||
|
|
||||||
|
if place_resp.get('retCode') == 0:
|
||||||
|
await message.answer(f"Сделка {symbol} успешно закрыта.", reply_markup=inline_markup.back_to_main)
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
await message.answer(f"Ошибка закрытия сделки {symbol}.", reply_markup=inline_markup.back_to_main)
|
||||||
|
return False
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"Ошибка закрытия сделки {symbol} для пользователя {tg_id}: {e}", exc_info=True)
|
logger.error(f"Ошибка закрытия сделки {symbol} для пользователя {tg_id}: {e}", exc_info=True)
|
||||||
if message:
|
await message.answer("Произошла ошибка при закрытии сделки.", reply_markup=inline_markup.back_to_main)
|
||||||
await message.answer("Произошла ошибка при закрытии сделки.", reply_markup=inline_markup.back_to_main)
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
@@ -7,6 +7,7 @@ from logger_helper.logger_helper import LOGGING_CONFIG
|
|||||||
|
|
||||||
from app.services.Bybit.functions.Futures import (close_user_trade, open_position, set_take_profit_stop_loss, \
|
from app.services.Bybit.functions.Futures import (close_user_trade, open_position, set_take_profit_stop_loss, \
|
||||||
get_active_positions_by_symbol, get_active_orders_by_symbol,
|
get_active_positions_by_symbol, get_active_orders_by_symbol,
|
||||||
|
get_active_positions, get_active_orders, cancel_all_tp_sl_orders,
|
||||||
)
|
)
|
||||||
from app.services.Bybit.functions.balance import get_balance
|
from app.services.Bybit.functions.balance import get_balance
|
||||||
import app.telegram.Keyboards.inline_keyboards as inline_markup
|
import app.telegram.Keyboards.inline_keyboards as inline_markup
|
||||||
@@ -264,8 +265,7 @@ async def show_my_trades(callback: CallbackQuery) -> None:
|
|||||||
"""
|
"""
|
||||||
await callback.answer()
|
await callback.answer()
|
||||||
try:
|
try:
|
||||||
symbol = await rq.get_symbol(callback.from_user.id)
|
await callback.message.answer(f"Выберите тип сделки:",
|
||||||
await callback.message.answer(f"Выберите тип сделки для пары {symbol}:",
|
|
||||||
reply_markup=inline_markup.my_deals_select_markup)
|
reply_markup=inline_markup.my_deals_select_markup)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"Произошла ошибка при выборе типа сделки: {e}")
|
logger.error(f"Произошла ошибка при выборе типа сделки: {e}")
|
||||||
@@ -274,16 +274,30 @@ async def show_my_trades(callback: CallbackQuery) -> None:
|
|||||||
@router_functions_bybit_trade.callback_query(F.data == "clb_open_deals")
|
@router_functions_bybit_trade.callback_query(F.data == "clb_open_deals")
|
||||||
async def show_my_trades_callback(callback: CallbackQuery):
|
async def show_my_trades_callback(callback: CallbackQuery):
|
||||||
"""
|
"""
|
||||||
Показывает открытые позиции пользователя по символу.
|
Показывает открытые позиции пользователя.
|
||||||
"""
|
"""
|
||||||
await callback.answer()
|
await callback.answer()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
await get_active_positions_by_symbol(callback.from_user.id, message=callback.message)
|
await get_active_positions(callback.from_user.id, message=callback.message)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"Произошла ошибка при выборе сделки: {e}")
|
logger.error(f"Произошла ошибка при выборе сделки: {e}")
|
||||||
await callback.message.answer("Произошла ошибка при выборе сделки", reply_markup=inline_markup.back_to_main)
|
await callback.message.answer("Произошла ошибка при выборе сделки", reply_markup=inline_markup.back_to_main)
|
||||||
|
|
||||||
|
@router_functions_bybit_trade.callback_query(lambda c: c.data and c.data.startswith("show_deal_"))
|
||||||
|
async def show_deal_callback(callback_query: CallbackQuery) -> None:
|
||||||
|
"""
|
||||||
|
Показывает сделку пользователя по символу.
|
||||||
|
"""
|
||||||
|
await callback_query.answer()
|
||||||
|
try:
|
||||||
|
symbol = callback_query.data[len("show_deal_"):]
|
||||||
|
tg_id = callback_query.from_user.id
|
||||||
|
await get_active_positions_by_symbol(tg_id, symbol, message=callback_query.message)
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Произошла ошибка при выборе сделки: {e}")
|
||||||
|
await callback_query.message.answer("Произошла ошибка при выборе сделки", reply_markup=inline_markup.back_to_main)
|
||||||
|
|
||||||
|
|
||||||
@router_functions_bybit_trade.callback_query(F.data == "clb_open_orders")
|
@router_functions_bybit_trade.callback_query(F.data == "clb_open_orders")
|
||||||
async def show_my_orders_callback(callback: CallbackQuery) -> None:
|
async def show_my_orders_callback(callback: CallbackQuery) -> None:
|
||||||
@@ -293,16 +307,31 @@ async def show_my_orders_callback(callback: CallbackQuery) -> None:
|
|||||||
await callback.answer()
|
await callback.answer()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
await get_active_orders_by_symbol(callback.from_user.id, message=callback.message)
|
await get_active_orders(callback.from_user.id, message=callback.message)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"Произошла ошибка при выборе ордера: {e}")
|
logger.error(f"Произошла ошибка при выборе ордера: {e}")
|
||||||
await callback.message.answer("Произошла ошибка при выборе ордера", reply_markup=inline_markup.back_to_main)
|
await callback.message.answer("Произошла ошибка при выборе ордера", reply_markup=inline_markup.back_to_main)
|
||||||
|
|
||||||
|
|
||||||
|
@router_functions_bybit_trade.callback_query(lambda c: c.data and c.data.startswith("show_limit_"))
|
||||||
|
async def show_limit_callback(callback_query: CallbackQuery) -> None:
|
||||||
|
"""
|
||||||
|
Показывает сделку пользователя по символу.
|
||||||
|
"""
|
||||||
|
await callback_query.answer()
|
||||||
|
try:
|
||||||
|
symbol = callback_query.data[len("show_limit_"):]
|
||||||
|
tg_id = callback_query.from_user.id
|
||||||
|
await get_active_orders_by_symbol(tg_id, symbol, message=callback_query.message)
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Произошла ошибка при выборе сделки: {e}")
|
||||||
|
await callback_query.message.answer("Произошла ошибка при выборе сделки", reply_markup=inline_markup.back_to_main)
|
||||||
|
|
||||||
|
|
||||||
@router_functions_bybit_trade.callback_query(F.data == "clb_set_tp_sl")
|
@router_functions_bybit_trade.callback_query(F.data == "clb_set_tp_sl")
|
||||||
async def set_tp_sl(callback: CallbackQuery, state: FSMContext) -> None:
|
async def set_tp_sl(callback: CallbackQuery, state: FSMContext) -> None:
|
||||||
"""
|
"""
|
||||||
Показывает активные ордера пользователя.
|
Запускает процесс установки Take Profit и Stop Loss.
|
||||||
"""
|
"""
|
||||||
await callback.answer()
|
await callback.answer()
|
||||||
await state.set_state(SetTP_SL_State.waiting_for_take_profit)
|
await state.set_state(SetTP_SL_State.waiting_for_take_profit)
|
||||||
@@ -394,6 +423,25 @@ async def close_trade_callback(callback: CallbackQuery) -> None:
|
|||||||
await callback.answer()
|
await callback.answer()
|
||||||
|
|
||||||
|
|
||||||
|
@router_functions_bybit_trade.callback_query(lambda c: c.data and c.data.startswith("close_limit:"))
|
||||||
|
async def close_trade_callback(callback: CallbackQuery) -> None:
|
||||||
|
"""
|
||||||
|
Закрывает ордера пользователя по символу.
|
||||||
|
"""
|
||||||
|
symbol = callback.data.split(':')[1]
|
||||||
|
tg_id = callback.from_user.id
|
||||||
|
|
||||||
|
result = await cancel_all_tp_sl_orders(tg_id, symbol)
|
||||||
|
|
||||||
|
if result:
|
||||||
|
await callback.message.answer(f"Ордер {result} успешно закрыт.", reply_markup=inline_markup.back_to_main)
|
||||||
|
logger.info(f"Ордер {result} успешно закрыт.")
|
||||||
|
else:
|
||||||
|
await callback.message.answer(f"Не удалось закрыть ордер {result}.")
|
||||||
|
|
||||||
|
await callback.answer()
|
||||||
|
|
||||||
|
|
||||||
@router_functions_bybit_trade.callback_query(lambda c: c.data and c.data.startswith("close_deal_by_timer:"))
|
@router_functions_bybit_trade.callback_query(lambda c: c.data and c.data.startswith("close_deal_by_timer:"))
|
||||||
async def ask_close_delay(callback: CallbackQuery, state: FSMContext) -> None:
|
async def ask_close_delay(callback: CallbackQuery, state: FSMContext) -> None:
|
||||||
"""
|
"""
|
||||||
|
@@ -155,15 +155,21 @@ buttons_on_off_markup = InlineKeyboardMarkup(inline_keyboard=[ # ИЗМЕНИТ
|
|||||||
|
|
||||||
my_deals_select_markup = InlineKeyboardMarkup(inline_keyboard=[
|
my_deals_select_markup = InlineKeyboardMarkup(inline_keyboard=[
|
||||||
[InlineKeyboardButton(text='Открытые сделки', callback_data="clb_open_deals"),
|
[InlineKeyboardButton(text='Открытые сделки', callback_data="clb_open_deals"),
|
||||||
InlineKeyboardButton(text='Открытые ордера', callback_data="clb_open_orders")],
|
InlineKeyboardButton(text='Лимитные ордера', callback_data="clb_open_orders")],
|
||||||
back_btn_to_main
|
back_btn_to_main
|
||||||
])
|
])
|
||||||
|
|
||||||
def create_trades_inline_keyboard(trades):
|
def create_trades_inline_keyboard(trades):
|
||||||
builder = InlineKeyboardBuilder()
|
builder = InlineKeyboardBuilder()
|
||||||
for trade in trades:
|
for trade in trades:
|
||||||
symbol = trade['symbol'] if isinstance(trade, dict) else trade.symbol
|
builder.button(text=trade, callback_data=f"show_deal_{trade}")
|
||||||
builder.button(text=symbol, callback_data=f"show_deal_{symbol}")
|
builder.adjust(2)
|
||||||
|
return builder.as_markup()
|
||||||
|
|
||||||
|
def create_trades_inline_keyboard_limits(trades):
|
||||||
|
builder = InlineKeyboardBuilder()
|
||||||
|
for trade in trades:
|
||||||
|
builder.button(text=trade, callback_data=f"show_limit_{trade}")
|
||||||
builder.adjust(2)
|
builder.adjust(2)
|
||||||
return builder.as_markup()
|
return builder.as_markup()
|
||||||
|
|
||||||
@@ -176,6 +182,12 @@ def create_close_deal_markup(symbol: str) -> InlineKeyboardMarkup:
|
|||||||
back_btn_to_main
|
back_btn_to_main
|
||||||
])
|
])
|
||||||
|
|
||||||
|
def create_close_limit_markup(symbol: str) -> InlineKeyboardMarkup:
|
||||||
|
return InlineKeyboardMarkup(inline_keyboard=[
|
||||||
|
[InlineKeyboardButton(text="Закрыть лимитный ордер", callback_data=f"close_limit:{symbol}")],
|
||||||
|
[InlineKeyboardButton(text="Установить TP/SL", callback_data="clb_set_tp_sl_")],
|
||||||
|
back_btn_to_main
|
||||||
|
])
|
||||||
|
|
||||||
timer_markup = InlineKeyboardMarkup(inline_keyboard=[
|
timer_markup = InlineKeyboardMarkup(inline_keyboard=[
|
||||||
[InlineKeyboardButton(text="Установить таймер", callback_data="clb_set_timer")],
|
[InlineKeyboardButton(text="Установить таймер", callback_data="clb_set_timer")],
|
||||||
|
@@ -33,7 +33,7 @@ async def price_profit_message(message, state):
|
|||||||
|
|
||||||
text = 'Введите число изменения цены для фиксации прибыли: '
|
text = 'Введите число изменения цены для фиксации прибыли: '
|
||||||
|
|
||||||
await message.answer(text=text, parse_mode='html', reply_markup=None)
|
await message.answer(text=text, parse_mode='html', reply_markup=inline_markup.cancel)
|
||||||
|
|
||||||
|
|
||||||
@router_risk_management_settings.message(update_risk_management_settings.price_profit)
|
@router_risk_management_settings.message(update_risk_management_settings.price_profit)
|
||||||
@@ -62,7 +62,7 @@ async def price_loss_message(message, state):
|
|||||||
|
|
||||||
text = 'Введите число изменения цены для фиксации убытков: '
|
text = 'Введите число изменения цены для фиксации убытков: '
|
||||||
|
|
||||||
await message.answer(text=text, parse_mode='html', reply_markup=None)
|
await message.answer(text=text, parse_mode='html', reply_markup=inline_markup.cancel)
|
||||||
|
|
||||||
|
|
||||||
@router_risk_management_settings.message(update_risk_management_settings.price_loss)
|
@router_risk_management_settings.message(update_risk_management_settings.price_loss)
|
||||||
@@ -111,7 +111,7 @@ async def max_risk_deal_message(message, state):
|
|||||||
|
|
||||||
text = 'Введите число (процент от баланса) для изменения максимального риска на сделку: '
|
text = 'Введите число (процент от баланса) для изменения максимального риска на сделку: '
|
||||||
|
|
||||||
await message.answer(text=text, parse_mode='html', reply_markup=None)
|
await message.answer(text=text, parse_mode='html', reply_markup=inline_markup.cancel)
|
||||||
|
|
||||||
|
|
||||||
@router_risk_management_settings.message(update_risk_management_settings.max_risk_deal)
|
@router_risk_management_settings.message(update_risk_management_settings.max_risk_deal)
|
||||||
|
Reference in New Issue
Block a user