forked from kodorvan/stcs
348 lines
12 KiB
Python
348 lines
12 KiB
Python
import time
|
||
|
||
from typing import Optional
|
||
from asyncio import Handle
|
||
|
||
from annotated_types import T
|
||
from pybit import exceptions
|
||
from pybit.unified_trading import HTTP
|
||
from pybit.unified_trading import WebSocket
|
||
|
||
from app.services.Bybit.functions import price_symbol
|
||
import app.services.Bybit.functions.balance as balance_g
|
||
import app.telegram.database.requests as rq
|
||
|
||
import logging
|
||
logging.basicConfig(level=logging.DEBUG)
|
||
|
||
def handle_message(message):
|
||
print(message)
|
||
|
||
async def info_access_open_deal(message, symbol, trade_mode, margin_mode, leverage, qty):
|
||
match margin_mode:
|
||
case 'ISOLATED_MARGIN':
|
||
margin_mode = 'Isolated'
|
||
case 'REGULAR_MARGIN':
|
||
margin_mode = 'Cross'
|
||
|
||
text = f'''Позиция была успешна открыта!
|
||
Торговая пара: {symbol}
|
||
Движение: {trade_mode}
|
||
Тип-маржи: {margin_mode}
|
||
Кредитное плечо: {leverage}
|
||
Количество: {qty}
|
||
'''
|
||
|
||
await message.answer(text=text, parse_mode='html')
|
||
|
||
async def error_max_step(message):
|
||
await message.answer('Сделка не была совершена, превышен лимит максимального количества ставок')
|
||
|
||
async def error_max_risk(message):
|
||
await message.answer('Сделка не была совершена, слишком высокий риск')
|
||
|
||
async def contract_long(tg_id, message, margin_mode):
|
||
api_key = await rq.get_bybit_api_key(tg_id)
|
||
secret_key = await rq.get_bybit_secret_key(tg_id)
|
||
SYMBOL = await rq.get_symbol(tg_id)
|
||
|
||
data_main_stgs = await rq.get_user_main_settings(tg_id)
|
||
data_risk_management_stgs = await rq.get_user_risk_management_settings(tg_id)
|
||
|
||
match margin_mode:
|
||
case 'Isolated':
|
||
margin_mode = 'ISOLATED_MARGIN'
|
||
case 'Cross':
|
||
margin_mode = 'REGULAR_MARGIN'
|
||
|
||
client = HTTP(
|
||
api_key=api_key,
|
||
api_secret=secret_key
|
||
)
|
||
|
||
try:
|
||
balance = 0
|
||
price = 0
|
||
|
||
balance = await balance_g.get_balance(tg_id)
|
||
price = await price_symbol.get_price(tg_id, message)
|
||
|
||
client.set_margin_mode(
|
||
setMarginMode=margin_mode # margin_type
|
||
)
|
||
|
||
martingale_factor = float(data_main_stgs['martingale_factor']) # Исправлено: было maximal_quantity
|
||
max_martingale_steps = int(data_main_stgs['maximal_quantity'])
|
||
starting_quantity = float(data_main_stgs['starting_quantity'])
|
||
max_risk_percent = float(data_risk_management_stgs['max_risk_deal'])
|
||
loss_profit = float(data_risk_management_stgs['price_loss'])
|
||
takeProfit= float(data_risk_management_stgs['price_profit'])
|
||
|
||
# Инициализация переменных
|
||
next_quantity = starting_quantity
|
||
last_quantity = starting_quantity
|
||
realised_pnl = 0.0
|
||
|
||
current_martingale_step = 0 # Текущая ставка в серии
|
||
|
||
next_quantity = 0
|
||
realised_pnl = 0
|
||
|
||
last_quantity = starting_quantity
|
||
|
||
# Пример расчёта следующего размера позиции
|
||
try:
|
||
position_info = client.get_positions(category='linear', symbol=SYMBOL)
|
||
position = position_info['result']['list'][0] # или другой нужный индекс
|
||
|
||
realised_pnl = float(position['unrealisedPnl'])
|
||
|
||
if realised_pnl > 0:
|
||
print(f'''
|
||
=====================
|
||
=====Сделка=========
|
||
===уСПЕШНЕАЯ================
|
||
===================
|
||
=================
|
||
|
||
{realised_pnl}
|
||
|
||
===============
|
||
===============
|
||
=============
|
||
===============
|
||
==============
|
||
''')
|
||
starting_quantity = next_quantity
|
||
current_martingale_step = 0
|
||
elif not realised_pnl:
|
||
next_quantity = starting_quantity
|
||
current_martingale_step += 1
|
||
else:
|
||
current_martingale_step += 1
|
||
next_quantity = last_quantity * martingale_factor
|
||
starting_quantity = next_quantity
|
||
|
||
print(f'''
|
||
======СДЕЛКА===============
|
||
=====УБЫТОЧНАЯ==============
|
||
===================
|
||
===================
|
||
=================
|
||
|
||
{realised_pnl}
|
||
|
||
===============
|
||
===============
|
||
=============
|
||
===============
|
||
==============
|
||
''')
|
||
except Exception as e:
|
||
print("Не получены позиции")
|
||
next_quantity = starting_quantity
|
||
|
||
potential_loss = (next_quantity * float(price)) * (loss_profit / 100)
|
||
allowed_loss = float(balance) * (max_risk_percent / 100)
|
||
|
||
if current_martingale_step >= max_martingale_steps:
|
||
print("Достигнут максимум ставок в серии (8)!")
|
||
print("Торговля не продолжится")
|
||
|
||
await error_max_step(message)
|
||
else:
|
||
if potential_loss > allowed_loss:
|
||
print(f"ОШИБКА: Риск превышен!")
|
||
print(f"Ручной qty = {next_quantity} → Убыток = {potential_loss} USDT")
|
||
print(f"Разрешено = {allowed_loss} USDT (1% от баланса)")
|
||
|
||
await error_max_risk(message)
|
||
else:
|
||
print(f"Риск в допустимых пределах. Qty = {next_quantity}")
|
||
|
||
r = client.place_order(
|
||
category='linear',
|
||
symbol=SYMBOL,
|
||
side='Buy',
|
||
orderType="Market",
|
||
leverage=int(data_main_stgs['size_leverage']),
|
||
qty=next_quantity,
|
||
takeProfit=takeProfit, # TP - закрывает позицию, когда цена достигает нужного уровня
|
||
stopProfit=float(data_risk_management_stgs['price_loss']), # SL - закрывает позицию, когда убыток достигает нужного уровня
|
||
orderLinkId=f"deal_{SYMBOL}_{time.time()}"
|
||
)
|
||
|
||
await info_access_open_deal(message, SYMBOL, data_main_stgs['trading_mode'], margin_mode, data_main_stgs['size_leverage'], next_quantity)
|
||
|
||
print(f'''
|
||
=====================
|
||
===================
|
||
===================
|
||
===================
|
||
=================
|
||
|
||
{r}
|
||
|
||
===============
|
||
===============
|
||
=============
|
||
===============
|
||
==============
|
||
''')
|
||
|
||
except exceptions.InvalidRequestError as e:
|
||
await message.answer('Недостаточно баланса')
|
||
except Exception as e:
|
||
await message.answer('Непредвиденная оишбка')
|
||
|
||
async def contract_short(tg_id, message, margin_mode):
|
||
api_key = await rq.get_bybit_api_key(tg_id)
|
||
secret_key = await rq.get_bybit_secret_key(tg_id)
|
||
SYMBOL = await rq.get_symbol(tg_id)
|
||
|
||
data_main_stgs = await rq.get_user_main_settings(tg_id)
|
||
data_risk_management_stgs = await rq.get_user_risk_management_settings(tg_id)
|
||
|
||
match margin_mode:
|
||
case 'Isolated':
|
||
margin_mode = 'ISOLATED_MARGIN'
|
||
case 'Cross':
|
||
margin_mode = 'REGULAR_MARGIN'
|
||
|
||
client = HTTP(
|
||
api_key=api_key,
|
||
api_secret=secret_key
|
||
)
|
||
|
||
try:
|
||
balance = 0
|
||
price = 0
|
||
|
||
balance = await balance_g.get_balance(tg_id)
|
||
price = await price_symbol.get_price(tg_id, message)
|
||
|
||
client.set_margin_mode(
|
||
setMarginMode=margin_mode # margin_type
|
||
)
|
||
|
||
martingale_factor = float(data_main_stgs['martingale_factor']) # Исправлено: было maximal_quantity
|
||
max_martingale_steps = int(data_main_stgs['maximal_quantity'])
|
||
starting_quantity = float(data_main_stgs['starting_quantity'])
|
||
max_risk_percent = float(data_risk_management_stgs['max_risk_deal'])
|
||
loss_profit = float(data_risk_management_stgs['price_loss'])
|
||
takeProfit = float(data_risk_management_stgs['price_profit'])
|
||
|
||
# Инициализация переменных
|
||
next_quantity = starting_quantity
|
||
last_quantity = starting_quantity
|
||
realised_pnl = 0.0
|
||
|
||
current_martingale_step = 0 # Текущая ставка в серии
|
||
|
||
next_quantity = 0
|
||
realised_pnl = 0
|
||
|
||
last_quantity = starting_quantity
|
||
|
||
# Пример расчёта следующего размера позиции
|
||
try:
|
||
position_info = client.get_positions(category='linear', symbol=SYMBOL)
|
||
position = position_info['result']['list'][0] # или другой нужный индекс
|
||
|
||
realised_pnl = float(position['unrealisedPnl'])
|
||
|
||
if realised_pnl > 0:
|
||
print(f'''
|
||
=====================
|
||
=====Сделка=========
|
||
===уСПЕШНЕАЯ================
|
||
===================
|
||
=================
|
||
|
||
{realised_pnl}
|
||
|
||
===============
|
||
===============
|
||
=============
|
||
===============
|
||
==============
|
||
''')
|
||
starting_quantity = next_quantity
|
||
current_martingale_step = 0
|
||
elif not realised_pnl:
|
||
next_quantity = starting_quantity
|
||
current_martingale_step += 1
|
||
else:
|
||
current_martingale_step += 1
|
||
next_quantity = last_quantity * martingale_factor
|
||
starting_quantity = next_quantity
|
||
|
||
print(f'''
|
||
======СДЕЛКА===============
|
||
=====УБЫТОЧНАЯ==============
|
||
===================
|
||
===================
|
||
=================
|
||
|
||
{realised_pnl}
|
||
|
||
===============
|
||
===============
|
||
=============
|
||
===============
|
||
==============
|
||
''')
|
||
except Exception as e:
|
||
print("Не получены позиции")
|
||
next_quantity = starting_quantity
|
||
|
||
potential_loss = (next_quantity * float(price)) * (loss_profit / 100)
|
||
allowed_loss = float(balance) * (max_risk_percent / 100)
|
||
|
||
if current_martingale_step >= max_martingale_steps:
|
||
print("Достигнут максимум ставок в серии (8)!")
|
||
print("Торговля не продолжится")
|
||
|
||
await error_max_step(message)
|
||
else:
|
||
if potential_loss > allowed_loss:
|
||
print(f"ОШИБКА: Риск превышен!")
|
||
print(f"Ручной qty = {next_quantity} → Убыток = {potential_loss} USDT")
|
||
print(f"Разрешено = {allowed_loss} USDT (1% от баланса)")
|
||
|
||
await error_max_risk(message)
|
||
else:
|
||
print(f"Риск в допустимых пределах. Qty = {next_quantity}")
|
||
|
||
r = client.place_order(
|
||
category='linear',
|
||
symbol=SYMBOL,
|
||
side='Sell',
|
||
orderType="Market",
|
||
leverage=int(data_main_stgs['size_leverage']),
|
||
qty=next_quantity,
|
||
orderLinkId=f"deal_{SYMBOL}_{time.time()}"
|
||
)
|
||
|
||
await info_access_open_deal(message, SYMBOL, data_main_stgs['trading_mode'], margin_mode, data_main_stgs['size_leverage'], next_quantity)
|
||
|
||
print(f'''
|
||
=====================
|
||
===================
|
||
===================
|
||
===================
|
||
=================
|
||
|
||
{r}
|
||
|
||
===============
|
||
===============
|
||
=============
|
||
===============
|
||
==============
|
||
''')
|
||
|
||
except exceptions.InvalidRequestError as e:
|
||
await message.answer('Недостаточно баланса')
|
||
except Exception as e:
|
||
await message.answer('Непредвиденная оишбка') |