forked from kodorvan/stcs
Compare commits
2 Commits
stable
...
0945be242a
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0945be242a | ||
|
|
4663888190 |
2
.gitignore
vendored
2
.gitignore
vendored
@@ -146,8 +146,6 @@ myenv
|
|||||||
ENV/
|
ENV/
|
||||||
env.bak/
|
env.bak/
|
||||||
venv.bak/
|
venv.bak/
|
||||||
/logger_helper/loggers
|
|
||||||
/app/bybit/logger_bybit/loggers
|
|
||||||
# Spyder project settings
|
# Spyder project settings
|
||||||
.spyderproject
|
.spyderproject
|
||||||
.spyproject
|
.spyproject
|
||||||
|
|||||||
@@ -55,12 +55,7 @@ cp .env.sample .env
|
|||||||
nvim .env
|
nvim .env
|
||||||
```
|
```
|
||||||
|
|
||||||
5. Для применения миграций выполните команду:
|
5. Запустите бота:
|
||||||
```bash
|
|
||||||
alembic upgrade head
|
|
||||||
```
|
|
||||||
|
|
||||||
6. Запустите бота:
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
python run.py
|
python run.py
|
||||||
|
|||||||
@@ -1,40 +0,0 @@
|
|||||||
"""fixed switch_side type
|
|
||||||
|
|
||||||
Revision ID: 07020b2808d3
|
|
||||||
Revises: c710f4e2259c
|
|
||||||
Create Date: 2025-10-09 14:36:07.393387
|
|
||||||
|
|
||||||
"""
|
|
||||||
from typing import Sequence, Union
|
|
||||||
|
|
||||||
from alembic import op
|
|
||||||
import sqlalchemy as sa
|
|
||||||
|
|
||||||
|
|
||||||
# revision identifiers, used by Alembic.
|
|
||||||
revision: str = '07020b2808d3'
|
|
||||||
down_revision: Union[str, Sequence[str], None] = 'c710f4e2259c'
|
|
||||||
branch_labels: Union[str, Sequence[str], None] = None
|
|
||||||
depends_on: Union[str, Sequence[str], None] = None
|
|
||||||
|
|
||||||
|
|
||||||
def upgrade() -> None:
|
|
||||||
"""Upgrade schema."""
|
|
||||||
# ### commands auto generated by Alembic - please adjust! ###
|
|
||||||
op.alter_column('user_additional_settings', 'switch_side',
|
|
||||||
existing_type=sa.BOOLEAN(),
|
|
||||||
type_=sa.String(),
|
|
||||||
existing_nullable=False,
|
|
||||||
existing_server_default=sa.text('false'))
|
|
||||||
# ### end Alembic commands ###
|
|
||||||
|
|
||||||
|
|
||||||
def downgrade() -> None:
|
|
||||||
"""Downgrade schema."""
|
|
||||||
# ### commands auto generated by Alembic - please adjust! ###
|
|
||||||
op.alter_column('user_additional_settings', 'switch_side',
|
|
||||||
existing_type=sa.String(),
|
|
||||||
type_=sa.BOOLEAN(),
|
|
||||||
existing_nullable=False,
|
|
||||||
existing_server_default=sa.text('false'))
|
|
||||||
# ### end Alembic commands ###
|
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
"""added base_quantity
|
|
||||||
|
|
||||||
Revision ID: baf03ce269e0
|
|
||||||
Revises: 07020b2808d3
|
|
||||||
Create Date: 2025-10-09 16:49:52.979556
|
|
||||||
|
|
||||||
"""
|
|
||||||
from typing import Sequence, Union
|
|
||||||
|
|
||||||
from alembic import op
|
|
||||||
import sqlalchemy as sa
|
|
||||||
|
|
||||||
|
|
||||||
# revision identifiers, used by Alembic.
|
|
||||||
revision: str = 'baf03ce269e0'
|
|
||||||
down_revision: Union[str, Sequence[str], None] = '07020b2808d3'
|
|
||||||
branch_labels: Union[str, Sequence[str], None] = None
|
|
||||||
depends_on: Union[str, Sequence[str], None] = None
|
|
||||||
|
|
||||||
|
|
||||||
def upgrade() -> None:
|
|
||||||
"""Upgrade schema."""
|
|
||||||
# ### commands auto generated by Alembic - please adjust! ###
|
|
||||||
op.add_column('user_deals', sa.Column('base_quantity', sa.Float(), nullable=True))
|
|
||||||
op.drop_column('user_deals', 'trading_type')
|
|
||||||
# ### end Alembic commands ###
|
|
||||||
|
|
||||||
|
|
||||||
def downgrade() -> None:
|
|
||||||
"""Downgrade schema."""
|
|
||||||
# ### commands auto generated by Alembic - please adjust! ###
|
|
||||||
op.add_column('user_deals', sa.Column('trading_type', sa.VARCHAR(), autoincrement=False, nullable=True))
|
|
||||||
op.drop_column('user_deals', 'base_quantity')
|
|
||||||
# ### end Alembic commands ###
|
|
||||||
@@ -46,9 +46,7 @@ class WebSocketBot:
|
|||||||
self.user_sockets.clear()
|
self.user_sockets.clear()
|
||||||
self.user_messages.clear()
|
self.user_messages.clear()
|
||||||
self.user_keys.clear()
|
self.user_keys.clear()
|
||||||
logger.info(
|
logger.info("Closed old websocket for user %s due to key change", tg_id)
|
||||||
"Closed old websocket for user %s due to key change", tg_id
|
|
||||||
)
|
|
||||||
|
|
||||||
success = await self.try_connect_user(api_key, api_secret, tg_id)
|
success = await self.try_connect_user(api_key, api_secret, tg_id)
|
||||||
if success:
|
if success:
|
||||||
|
|||||||
@@ -158,7 +158,7 @@ async def get_liquidation_price(
|
|||||||
|
|
||||||
|
|
||||||
async def calculate_total_budget(
|
async def calculate_total_budget(
|
||||||
quantity, martingale_factor, max_steps
|
quantity, martingale_factor, max_steps, commission_fee_percent
|
||||||
) -> float:
|
) -> float:
|
||||||
"""
|
"""
|
||||||
Calculate the total budget for a series of trading steps.
|
Calculate the total budget for a series of trading steps.
|
||||||
@@ -167,6 +167,7 @@ async def calculate_total_budget(
|
|||||||
quantity (float): The initial quantity of the asset.
|
quantity (float): The initial quantity of the asset.
|
||||||
martingale_factor (float): The factor by which the quantity is multiplied for each step.
|
martingale_factor (float): The factor by which the quantity is multiplied for each step.
|
||||||
max_steps (int): The maximum number of trading steps.
|
max_steps (int): The maximum number of trading steps.
|
||||||
|
commission_fee_percent (float): The commission fee percentage.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
float: The total budget for the series of trading steps.
|
float: The total budget for the series of trading steps.
|
||||||
@@ -174,8 +175,12 @@ async def calculate_total_budget(
|
|||||||
total = 0
|
total = 0
|
||||||
for step in range(max_steps):
|
for step in range(max_steps):
|
||||||
set_quantity = quantity * (martingale_factor**step)
|
set_quantity = quantity * (martingale_factor**step)
|
||||||
|
if commission_fee_percent == 0:
|
||||||
|
# Commission fee is not added to the position size
|
||||||
r_quantity = set_quantity
|
r_quantity = set_quantity
|
||||||
|
else:
|
||||||
|
# Commission fee is added to the position size
|
||||||
|
r_quantity = set_quantity * (1 + 2 * commission_fee_percent)
|
||||||
|
|
||||||
total += r_quantity
|
total += r_quantity
|
||||||
return total
|
return total
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ from aiogram.types import CallbackQuery
|
|||||||
|
|
||||||
import app.telegram.keyboards.inline as kbi
|
import app.telegram.keyboards.inline as kbi
|
||||||
import database.request as rq
|
import database.request as rq
|
||||||
|
from app.bybit import get_bybit_client
|
||||||
|
|
||||||
from app.helper_functions import calculate_total_budget, safe_float
|
from app.helper_functions import calculate_total_budget, safe_float
|
||||||
from logger_helper.logger_helper import LOGGING_CONFIG
|
from logger_helper.logger_helper import LOGGING_CONFIG
|
||||||
@@ -25,6 +26,7 @@ async def additional_settings(callback_query: CallbackQuery, state: FSMContext)
|
|||||||
try:
|
try:
|
||||||
await state.clear()
|
await state.clear()
|
||||||
tg_id = callback_query.from_user.id
|
tg_id = callback_query.from_user.id
|
||||||
|
symbol = await rq.get_user_symbol(tg_id=tg_id)
|
||||||
additional_data = await rq.get_user_additional_settings(tg_id=tg_id)
|
additional_data = await rq.get_user_additional_settings(tg_id=tg_id)
|
||||||
|
|
||||||
if not additional_data:
|
if not additional_data:
|
||||||
@@ -62,15 +64,30 @@ async def additional_settings(callback_query: CallbackQuery, state: FSMContext)
|
|||||||
max_bets = additional_data.max_bets_in_series
|
max_bets = additional_data.max_bets_in_series
|
||||||
quantity = f(additional_data.order_quantity)
|
quantity = f(additional_data.order_quantity)
|
||||||
trigger_price = f(additional_data.trigger_price) or 0
|
trigger_price = f(additional_data.trigger_price) or 0
|
||||||
|
risk_management_data = await rq.get_user_risk_management(tg_id=tg_id)
|
||||||
|
commission_fee = risk_management_data.commission_fee
|
||||||
|
client = await get_bybit_client(tg_id=tg_id)
|
||||||
|
fee_info = client.get_fee_rates(category="linear", symbol=symbol)
|
||||||
|
|
||||||
|
if commission_fee == "Yes_commission_fee":
|
||||||
|
commission_fee_percent = safe_float(
|
||||||
|
fee_info["result"]["list"][0]["takerFeeRate"]
|
||||||
|
)
|
||||||
|
|
||||||
|
else:
|
||||||
|
commission_fee_percent = 0.0
|
||||||
|
|
||||||
switch_side_mode = ""
|
switch_side_mode = ""
|
||||||
if trade_mode == "Switch":
|
if trade_mode == "Switch":
|
||||||
switch_side_mode = f"- Направление первой сделки: {switch_side}\n"
|
switch_side_mode = f"- Направление первой сделки: {switch_side}\n"
|
||||||
|
|
||||||
|
quantity_price = quantity * trigger_price
|
||||||
|
total_commission = quantity_price * commission_fee_percent
|
||||||
total_budget = await calculate_total_budget(
|
total_budget = await calculate_total_budget(
|
||||||
quantity=quantity,
|
quantity=quantity,
|
||||||
martingale_factor=martingale,
|
martingale_factor=martingale,
|
||||||
max_steps=max_bets,
|
max_steps=max_bets,
|
||||||
|
commission_fee_percent=total_commission,
|
||||||
)
|
)
|
||||||
text = (
|
text = (
|
||||||
f"Основные настройки:\n\n"
|
f"Основные настройки:\n\n"
|
||||||
@@ -82,7 +99,7 @@ async def additional_settings(callback_query: CallbackQuery, state: FSMContext)
|
|||||||
f"- Коэффициент мартингейла: {martingale:.2f}\n"
|
f"- Коэффициент мартингейла: {martingale:.2f}\n"
|
||||||
f"- Триггер цена: {trigger_price:.4f} USDT\n"
|
f"- Триггер цена: {trigger_price:.4f} USDT\n"
|
||||||
f"- Максимальное кол-во ставок в серии: {max_bets}\n\n"
|
f"- Максимальное кол-во ставок в серии: {max_bets}\n\n"
|
||||||
f"- Бюджет серии: {total_budget:.2f} USDT\n"
|
f"- Бюджет серии: {total_budget:.4f} USDT\n"
|
||||||
)
|
)
|
||||||
|
|
||||||
keyboard = kbi.get_additional_settings_keyboard(mode=trade_mode)
|
keyboard = kbi.get_additional_settings_keyboard(mode=trade_mode)
|
||||||
|
|||||||
@@ -1,10 +1,8 @@
|
|||||||
from aiogram.types import KeyboardButton, ReplyKeyboardMarkup
|
from aiogram.types import KeyboardButton, ReplyKeyboardMarkup
|
||||||
|
|
||||||
profile = ReplyKeyboardMarkup(
|
profile = ReplyKeyboardMarkup(
|
||||||
keyboard=[
|
keyboard=[[KeyboardButton(text="Панель Bybit"), KeyboardButton(text="Профиль")],
|
||||||
[KeyboardButton(text="Панель Bybit"), KeyboardButton(text="Профиль")],
|
[KeyboardButton(text="Подключить платформу Bybit")]],
|
||||||
[KeyboardButton(text="Подключить платформу Bybit")],
|
|
||||||
],
|
|
||||||
resize_keyboard=True,
|
resize_keyboard=True,
|
||||||
one_time_keyboard=True,
|
one_time_keyboard=True,
|
||||||
input_field_placeholder="Выберите пункт меню...",
|
input_field_placeholder="Выберите пункт меню...",
|
||||||
|
|||||||
@@ -12,7 +12,9 @@ logger = logging.getLogger("database")
|
|||||||
|
|
||||||
async_engine = create_async_engine(DATABASE_URL, echo=False)
|
async_engine = create_async_engine(DATABASE_URL, echo=False)
|
||||||
|
|
||||||
async_session = async_sessionmaker(async_engine, class_=AsyncSession, expire_on_commit=False)
|
async_session = async_sessionmaker(
|
||||||
|
async_engine, class_=AsyncSession, expire_on_commit=False
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
async def init_db():
|
async def init_db():
|
||||||
|
|||||||
@@ -1,6 +1,15 @@
|
|||||||
from sqlalchemy.ext.declarative import declarative_base
|
from sqlalchemy.ext.declarative import declarative_base
|
||||||
from sqlalchemy.ext.asyncio import AsyncAttrs
|
from sqlalchemy.ext.asyncio import AsyncAttrs
|
||||||
from sqlalchemy import Column, ForeignKey, Integer, String, BigInteger, Float, Boolean, UniqueConstraint
|
from sqlalchemy import (
|
||||||
|
Column,
|
||||||
|
ForeignKey,
|
||||||
|
Integer,
|
||||||
|
String,
|
||||||
|
BigInteger,
|
||||||
|
Float,
|
||||||
|
Boolean,
|
||||||
|
UniqueConstraint,
|
||||||
|
)
|
||||||
from sqlalchemy.orm import relationship
|
from sqlalchemy.orm import relationship
|
||||||
|
|
||||||
Base = declarative_base(cls=AsyncAttrs)
|
Base = declarative_base(cls=AsyncAttrs)
|
||||||
@@ -8,61 +17,77 @@ Base = declarative_base(cls=AsyncAttrs)
|
|||||||
|
|
||||||
class User(Base):
|
class User(Base):
|
||||||
"""User model."""
|
"""User model."""
|
||||||
|
|
||||||
__tablename__ = "users"
|
__tablename__ = "users"
|
||||||
|
|
||||||
id = Column(Integer, primary_key=True, autoincrement=True)
|
id = Column(Integer, primary_key=True, autoincrement=True)
|
||||||
tg_id = Column(BigInteger, nullable=False, unique=True)
|
tg_id = Column(BigInteger, nullable=False, unique=True)
|
||||||
username = Column(String, nullable=False)
|
username = Column(String, nullable=False)
|
||||||
|
|
||||||
user_api = relationship("UserApi",
|
user_api = relationship(
|
||||||
|
"UserApi",
|
||||||
back_populates="user",
|
back_populates="user",
|
||||||
cascade="all, delete-orphan",
|
cascade="all, delete-orphan",
|
||||||
passive_deletes=True,
|
passive_deletes=True,
|
||||||
uselist=False)
|
uselist=False,
|
||||||
|
)
|
||||||
|
|
||||||
user_symbol = relationship("UserSymbol",
|
user_symbol = relationship(
|
||||||
|
"UserSymbol",
|
||||||
back_populates="user",
|
back_populates="user",
|
||||||
cascade="all, delete-orphan",
|
cascade="all, delete-orphan",
|
||||||
passive_deletes=True,
|
passive_deletes=True,
|
||||||
uselist=False)
|
uselist=False,
|
||||||
|
)
|
||||||
|
|
||||||
user_additional_settings = relationship("UserAdditionalSettings",
|
user_additional_settings = relationship(
|
||||||
|
"UserAdditionalSettings",
|
||||||
back_populates="user",
|
back_populates="user",
|
||||||
cascade="all, delete-orphan",
|
cascade="all, delete-orphan",
|
||||||
passive_deletes=True,
|
passive_deletes=True,
|
||||||
uselist=False)
|
uselist=False,
|
||||||
|
)
|
||||||
|
|
||||||
user_risk_management = relationship("UserRiskManagement",
|
user_risk_management = relationship(
|
||||||
|
"UserRiskManagement",
|
||||||
back_populates="user",
|
back_populates="user",
|
||||||
cascade="all, delete-orphan",
|
cascade="all, delete-orphan",
|
||||||
passive_deletes=True,
|
passive_deletes=True,
|
||||||
uselist=False)
|
uselist=False,
|
||||||
|
)
|
||||||
|
|
||||||
user_conditional_settings = relationship("UserConditionalSettings",
|
user_conditional_settings = relationship(
|
||||||
|
"UserConditionalSettings",
|
||||||
back_populates="user",
|
back_populates="user",
|
||||||
cascade="all, delete-orphan",
|
cascade="all, delete-orphan",
|
||||||
passive_deletes=True,
|
passive_deletes=True,
|
||||||
uselist=False)
|
uselist=False,
|
||||||
|
)
|
||||||
|
|
||||||
user_deals = relationship("UserDeals",
|
user_deals = relationship(
|
||||||
|
"UserDeals",
|
||||||
back_populates="user",
|
back_populates="user",
|
||||||
cascade="all, delete-orphan",
|
cascade="all, delete-orphan",
|
||||||
passive_deletes=True)
|
passive_deletes=True,
|
||||||
|
)
|
||||||
|
|
||||||
user_auto_trading = relationship("UserAutoTrading",
|
user_auto_trading = relationship(
|
||||||
|
"UserAutoTrading",
|
||||||
back_populates="user",
|
back_populates="user",
|
||||||
cascade="all, delete-orphan",
|
cascade="all, delete-orphan",
|
||||||
passive_deletes=True)
|
passive_deletes=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class UserApi(Base):
|
class UserApi(Base):
|
||||||
"""User API model."""
|
"""User API model."""
|
||||||
|
|
||||||
__tablename__ = "user_api"
|
__tablename__ = "user_api"
|
||||||
|
|
||||||
id = Column(Integer, primary_key=True, autoincrement=True)
|
id = Column(Integer, primary_key=True, autoincrement=True)
|
||||||
user_id = Column(Integer,
|
user_id = Column(
|
||||||
ForeignKey("users.id", ondelete="CASCADE"),
|
Integer, ForeignKey("users.id", ondelete="CASCADE"), nullable=False, unique=True
|
||||||
nullable=False, unique=True)
|
)
|
||||||
api_key = Column(String, nullable=False)
|
api_key = Column(String, nullable=False)
|
||||||
api_secret = Column(String, nullable=False)
|
api_secret = Column(String, nullable=False)
|
||||||
|
|
||||||
@@ -71,12 +96,13 @@ class UserApi(Base):
|
|||||||
|
|
||||||
class UserSymbol(Base):
|
class UserSymbol(Base):
|
||||||
"""User symbol model."""
|
"""User symbol model."""
|
||||||
|
|
||||||
__tablename__ = "user_symbol"
|
__tablename__ = "user_symbol"
|
||||||
|
|
||||||
id = Column(Integer, primary_key=True, autoincrement=True)
|
id = Column(Integer, primary_key=True, autoincrement=True)
|
||||||
user_id = Column(Integer,
|
user_id = Column(
|
||||||
ForeignKey("users.id", ondelete="CASCADE"),
|
Integer, ForeignKey("users.id", ondelete="CASCADE"), nullable=False, unique=True
|
||||||
nullable=False, unique=True)
|
)
|
||||||
symbol = Column(String, nullable=False, default="BTCUSDT")
|
symbol = Column(String, nullable=False, default="BTCUSDT")
|
||||||
|
|
||||||
user = relationship("User", back_populates="user_symbol")
|
user = relationship("User", back_populates="user_symbol")
|
||||||
@@ -84,12 +110,13 @@ class UserSymbol(Base):
|
|||||||
|
|
||||||
class UserAdditionalSettings(Base):
|
class UserAdditionalSettings(Base):
|
||||||
"""User additional settings model."""
|
"""User additional settings model."""
|
||||||
|
|
||||||
__tablename__ = "user_additional_settings"
|
__tablename__ = "user_additional_settings"
|
||||||
|
|
||||||
id = Column(Integer, primary_key=True, autoincrement=True)
|
id = Column(Integer, primary_key=True, autoincrement=True)
|
||||||
user_id = Column(Integer,
|
user_id = Column(
|
||||||
ForeignKey("users.id", ondelete="CASCADE"),
|
Integer, ForeignKey("users.id", ondelete="CASCADE"), nullable=False, unique=True
|
||||||
nullable=False, unique=True)
|
)
|
||||||
trade_mode = Column(String, nullable=False, default="Merged_Single")
|
trade_mode = Column(String, nullable=False, default="Merged_Single")
|
||||||
switch_side = Column(String, nullable=False, default="По направлению")
|
switch_side = Column(String, nullable=False, default="По направлению")
|
||||||
trigger_price = Column(Float, nullable=False, default=0.0)
|
trigger_price = Column(Float, nullable=False, default=0.0)
|
||||||
@@ -104,12 +131,13 @@ class UserAdditionalSettings(Base):
|
|||||||
|
|
||||||
class UserRiskManagement(Base):
|
class UserRiskManagement(Base):
|
||||||
"""User risk management model."""
|
"""User risk management model."""
|
||||||
|
|
||||||
__tablename__ = "user_risk_management"
|
__tablename__ = "user_risk_management"
|
||||||
|
|
||||||
id = Column(Integer, primary_key=True, autoincrement=True)
|
id = Column(Integer, primary_key=True, autoincrement=True)
|
||||||
user_id = Column(Integer,
|
user_id = Column(
|
||||||
ForeignKey("users.id", ondelete="CASCADE"),
|
Integer, ForeignKey("users.id", ondelete="CASCADE"), nullable=False, unique=True
|
||||||
nullable=False, unique=True)
|
)
|
||||||
take_profit_percent = Column(Float, nullable=False, default=1)
|
take_profit_percent = Column(Float, nullable=False, default=1)
|
||||||
stop_loss_percent = Column(Float, nullable=False, default=1)
|
stop_loss_percent = Column(Float, nullable=False, default=1)
|
||||||
commission_fee = Column(String, nullable=False, default="Yes_commission_fee")
|
commission_fee = Column(String, nullable=False, default="Yes_commission_fee")
|
||||||
@@ -119,12 +147,13 @@ class UserRiskManagement(Base):
|
|||||||
|
|
||||||
class UserConditionalSettings(Base):
|
class UserConditionalSettings(Base):
|
||||||
"""User conditional settings model."""
|
"""User conditional settings model."""
|
||||||
|
|
||||||
__tablename__ = "user_conditional_settings"
|
__tablename__ = "user_conditional_settings"
|
||||||
|
|
||||||
id = Column(Integer, primary_key=True, autoincrement=True)
|
id = Column(Integer, primary_key=True, autoincrement=True)
|
||||||
user_id = Column(Integer,
|
user_id = Column(
|
||||||
ForeignKey("users.id", ondelete="CASCADE"),
|
Integer, ForeignKey("users.id", ondelete="CASCADE"), nullable=False, unique=True
|
||||||
nullable=False, unique=True)
|
)
|
||||||
|
|
||||||
timer_start = Column(Integer, nullable=False, default=0)
|
timer_start = Column(Integer, nullable=False, default=0)
|
||||||
timer_end = Column(Integer, nullable=False, default=0)
|
timer_end = Column(Integer, nullable=False, default=0)
|
||||||
@@ -134,12 +163,13 @@ class UserConditionalSettings(Base):
|
|||||||
|
|
||||||
class UserDeals(Base):
|
class UserDeals(Base):
|
||||||
"""User deals model."""
|
"""User deals model."""
|
||||||
|
|
||||||
__tablename__ = "user_deals"
|
__tablename__ = "user_deals"
|
||||||
|
|
||||||
id = Column(Integer, primary_key=True, autoincrement=True)
|
id = Column(Integer, primary_key=True, autoincrement=True)
|
||||||
user_id = Column(Integer,
|
user_id = Column(
|
||||||
ForeignKey("users.id", ondelete="CASCADE"),
|
Integer, ForeignKey("users.id", ondelete="CASCADE"), nullable=False
|
||||||
nullable=False)
|
)
|
||||||
current_step = Column(Integer, nullable=True)
|
current_step = Column(Integer, nullable=True)
|
||||||
symbol = Column(String, nullable=True)
|
symbol = Column(String, nullable=True)
|
||||||
trade_mode = Column(String, nullable=True)
|
trade_mode = Column(String, nullable=True)
|
||||||
@@ -157,19 +187,18 @@ class UserDeals(Base):
|
|||||||
|
|
||||||
user = relationship("User", back_populates="user_deals")
|
user = relationship("User", back_populates="user_deals")
|
||||||
|
|
||||||
__table_args__ = (
|
__table_args__ = (UniqueConstraint("user_id", "symbol", name="uq_user_symbol"),)
|
||||||
UniqueConstraint('user_id', 'symbol', name='uq_user_symbol'),
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class UserAutoTrading(Base):
|
class UserAutoTrading(Base):
|
||||||
"""User auto trading model."""
|
"""User auto trading model."""
|
||||||
|
|
||||||
__tablename__ = "user_auto_trading"
|
__tablename__ = "user_auto_trading"
|
||||||
|
|
||||||
id = Column(Integer, primary_key=True, autoincrement=True)
|
id = Column(Integer, primary_key=True, autoincrement=True)
|
||||||
user_id = Column(Integer,
|
user_id = Column(
|
||||||
ForeignKey("users.id", ondelete="CASCADE"),
|
Integer, ForeignKey("users.id", ondelete="CASCADE"), nullable=False
|
||||||
nullable=False)
|
)
|
||||||
symbol = Column(String, nullable=True)
|
symbol = Column(String, nullable=True)
|
||||||
auto_trading = Column(Boolean, nullable=True)
|
auto_trading = Column(Boolean, nullable=True)
|
||||||
fee = Column(Float, nullable=True)
|
fee = Column(Float, nullable=True)
|
||||||
|
|||||||
@@ -906,7 +906,7 @@ async def set_user_deal(
|
|||||||
max_bets_in_series: int,
|
max_bets_in_series: int,
|
||||||
take_profit_percent: int,
|
take_profit_percent: int,
|
||||||
stop_loss_percent: int,
|
stop_loss_percent: int,
|
||||||
base_quantity: float
|
base_quantity: float,
|
||||||
):
|
):
|
||||||
"""
|
"""
|
||||||
Set the user deal in the database.
|
Set the user deal in the database.
|
||||||
@@ -969,7 +969,7 @@ async def set_user_deal(
|
|||||||
max_bets_in_series=max_bets_in_series,
|
max_bets_in_series=max_bets_in_series,
|
||||||
take_profit_percent=take_profit_percent,
|
take_profit_percent=take_profit_percent,
|
||||||
stop_loss_percent=stop_loss_percent,
|
stop_loss_percent=stop_loss_percent,
|
||||||
base_quantity=base_quantity
|
base_quantity=base_quantity,
|
||||||
)
|
)
|
||||||
session.add(new_deal)
|
session.add(new_deal)
|
||||||
|
|
||||||
@@ -978,7 +978,9 @@ async def set_user_deal(
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error("Error setting user deal for user %s and symbol %s: %s", tg_id, symbol, e)
|
logger.error(
|
||||||
|
"Error setting user deal for user %s and symbol %s: %s", tg_id, symbol, e
|
||||||
|
)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
@@ -998,7 +1000,9 @@ async def get_user_deal_by_symbol(tg_id: int, symbol: str):
|
|||||||
deal = result_deal.scalars().first()
|
deal = result_deal.scalars().first()
|
||||||
return deal
|
return deal
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error("Error getting deal for user %s and symbol %s: %s", tg_id, symbol, e)
|
logger.error(
|
||||||
|
"Error getting deal for user %s and symbol %s: %s", tg_id, symbol, e
|
||||||
|
)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
@@ -1040,18 +1044,26 @@ async def set_fee_user_deal_by_symbol(tg_id: int, symbol: str, fee: float):
|
|||||||
if record:
|
if record:
|
||||||
record.fee = fee
|
record.fee = fee
|
||||||
else:
|
else:
|
||||||
logger.error(f"User deal with user_id={user.id} and symbol={symbol} not found")
|
logger.error(
|
||||||
|
f"User deal with user_id={user.id} and symbol={symbol} not found"
|
||||||
|
)
|
||||||
return False
|
return False
|
||||||
await session.commit()
|
await session.commit()
|
||||||
logger.info("Set fee for user %s and symbol %s", tg_id, symbol)
|
logger.info("Set fee for user %s and symbol %s", tg_id, symbol)
|
||||||
return True
|
return True
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error("Error setting user deal fee for user %s and symbol %s: %s", tg_id, symbol, e)
|
logger.error(
|
||||||
|
"Error setting user deal fee for user %s and symbol %s: %s",
|
||||||
|
tg_id,
|
||||||
|
symbol,
|
||||||
|
e,
|
||||||
|
)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
# USER AUTO TRADING
|
# USER AUTO TRADING
|
||||||
|
|
||||||
|
|
||||||
async def get_all_user_auto_trading(tg_id: int):
|
async def get_all_user_auto_trading(tg_id: int):
|
||||||
"""Get all user auto trading from the database asynchronously."""
|
"""Get all user auto trading from the database asynchronously."""
|
||||||
try:
|
try:
|
||||||
@@ -1086,7 +1098,9 @@ async def get_user_auto_trading(tg_id: int, symbol: str):
|
|||||||
auto_trading = result_auto_trading.scalars().first()
|
auto_trading = result_auto_trading.scalars().first()
|
||||||
return auto_trading
|
return auto_trading
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error("Error getting auto trading for user %s and symbol %s: %s", tg_id, symbol, e)
|
logger.error(
|
||||||
|
"Error getting auto trading for user %s and symbol %s: %s", tg_id, symbol, e
|
||||||
|
)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
@@ -1120,10 +1134,17 @@ async def set_auto_trading(tg_id: int, symbol: str, auto_trading: bool) -> bool:
|
|||||||
)
|
)
|
||||||
session.add(new_record)
|
session.add(new_record)
|
||||||
await session.commit()
|
await session.commit()
|
||||||
logger.info("Set auto_trading=%s for user %s and symbol %s", auto_trading, tg_id, symbol)
|
logger.info(
|
||||||
|
"Set auto_trading=%s for user %s and symbol %s",
|
||||||
|
auto_trading,
|
||||||
|
tg_id,
|
||||||
|
symbol,
|
||||||
|
)
|
||||||
return True
|
return True
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error("Error setting auto_trading for user %s and symbol %s: %s", tg_id, symbol, e)
|
logger.error(
|
||||||
|
"Error setting auto_trading for user %s and symbol %s: %s", tg_id, symbol, e
|
||||||
|
)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
@@ -1161,11 +1182,18 @@ async def set_fee_user_auto_trading(tg_id: int, symbol: str, fee: float) -> bool
|
|||||||
logger.info("Set fee for user %s and symbol %s", tg_id, symbol)
|
logger.info("Set fee for user %s and symbol %s", tg_id, symbol)
|
||||||
return True
|
return True
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error("Error setting user auto trading fee for user %s and symbol %s: %s", tg_id, symbol, e)
|
logger.error(
|
||||||
|
"Error setting user auto trading fee for user %s and symbol %s: %s",
|
||||||
|
tg_id,
|
||||||
|
symbol,
|
||||||
|
e,
|
||||||
|
)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
async def set_total_fee_user_auto_trading(tg_id: int, symbol: str, total_fee: float) -> bool:
|
async def set_total_fee_user_auto_trading(
|
||||||
|
tg_id: int, symbol: str, total_fee: float
|
||||||
|
) -> bool:
|
||||||
"""
|
"""
|
||||||
Set the total fee for a user auto trading in the database.
|
Set the total fee for a user auto trading in the database.
|
||||||
:param tg_id: Telegram user ID
|
:param tg_id: Telegram user ID
|
||||||
@@ -1199,5 +1227,10 @@ async def set_total_fee_user_auto_trading(tg_id: int, symbol: str, total_fee: fl
|
|||||||
logger.info("Set total fee for user %s and symbol %s", tg_id, symbol)
|
logger.info("Set total fee for user %s and symbol %s", tg_id, symbol)
|
||||||
return True
|
return True
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error("Error setting user auto trading total fee for user %s and symbol %s: %s", tg_id, symbol, e)
|
logger.error(
|
||||||
|
"Error setting user auto trading total fee for user %s and symbol %s: %s",
|
||||||
|
tg_id,
|
||||||
|
symbol,
|
||||||
|
e,
|
||||||
|
)
|
||||||
return False
|
return False
|
||||||
|
|||||||
Reference in New Issue
Block a user