forked from kodorvan/stcs
		
	Compare commits
	
		
			42 Commits
		
	
	
		
			42c4660fe3
			...
			stable
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| f0732607e2 | |||
|   | 458b34fcec | ||
| 56af1d8f3b | |||
|   | 4a7577b977 | ||
| 9f069df68a | |||
|   | 6e0a170f4b | ||
|   | c7b4a08a6a | ||
|   | d0971f59b4 | ||
| b92376d2da | |||
| 630f2002d3 | |||
| 0784cbb54a | |||
| eeb7f81440 | |||
| b03d05bb75 | |||
| e0e4ad5d4b | |||
| fab8ff5040 | |||
| 8071f8c896 | |||
| 3db001bd19 | |||
| 99c59be9ed | |||
| 37b7b6effd | |||
| ee285523f2 | |||
| b426eb2136 | |||
| 2df3b8b40d | |||
| 8c08451d82 | |||
| d81a47b669 | |||
| 2cdfba3537 | |||
| c89c2ad803 | |||
| 3986989dbd | |||
| c0e40dc205 | |||
| 6c6f0dbb7b | |||
| 44c4fde036 | |||
| 21a93d47d4 | |||
| 3f43d42651 | |||
| aab05994ce | |||
| a58ebe6a46 | |||
| 1ec1f1784d | |||
| 7901af86af | |||
| fedfa00c10 | |||
|   | fc8ab19ae9 | ||
| 898ff91392 | |||
| 2047dd5ac6 | |||
| fec367cc1d | |||
| aebcc9dff2 | 
							
								
								
									
										2
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @@ -146,6 +146,8 @@ myenv | ||||
| ENV/ | ||||
| env.bak/ | ||||
| venv.bak/ | ||||
| /logger_helper/loggers | ||||
| /app/bybit/logger_bybit/loggers | ||||
| # Spyder project settings | ||||
| .spyderproject | ||||
| .spyproject | ||||
|   | ||||
| @@ -55,7 +55,12 @@ cp .env.sample .env | ||||
| nvim .env | ||||
| ``` | ||||
|  | ||||
| 5. Запустите бота: | ||||
| 5. Для применения миграций выполните команду: | ||||
| ```bash | ||||
| alembic upgrade head | ||||
| ``` | ||||
|  | ||||
| 6. Запустите бота: | ||||
|  | ||||
| ```bash | ||||
| python run.py | ||||
|   | ||||
							
								
								
									
										40
									
								
								alembic/versions/07020b2808d3_fixed_switch_side_type.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								alembic/versions/07020b2808d3_fixed_switch_side_type.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,40 @@ | ||||
| """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 ### | ||||
							
								
								
									
										34
									
								
								alembic/versions/baf03ce269e0_added_base_quantity.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								alembic/versions/baf03ce269e0_added_base_quantity.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,34 @@ | ||||
| """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,7 +46,9 @@ class WebSocketBot: | ||||
|                     self.user_sockets.clear() | ||||
|                     self.user_messages.clear() | ||||
|                     self.user_keys.clear() | ||||
|                     logger.info("Closed old websocket for user %s due to key change", tg_id) | ||||
|                     logger.info( | ||||
|                         "Closed old websocket for user %s due to key change", tg_id | ||||
|                     ) | ||||
|  | ||||
|                 success = await self.try_connect_user(api_key, api_secret, tg_id) | ||||
|                 if success: | ||||
|   | ||||
| @@ -158,7 +158,7 @@ async def get_liquidation_price( | ||||
|  | ||||
|  | ||||
| async def calculate_total_budget( | ||||
|     quantity, martingale_factor, max_steps, commission_fee_percent | ||||
|     quantity, martingale_factor, max_steps | ||||
| ) -> float: | ||||
|     """ | ||||
|     Calculate the total budget for a series of trading steps. | ||||
| @@ -167,7 +167,6 @@ async def calculate_total_budget( | ||||
|         quantity (float): The initial quantity of the asset. | ||||
|         martingale_factor (float): The factor by which the quantity is multiplied for each step. | ||||
|         max_steps (int): The maximum number of trading steps. | ||||
|         commission_fee_percent (float): The commission fee percentage. | ||||
|  | ||||
|     Returns: | ||||
|         float: The total budget for the series of trading steps. | ||||
| @@ -175,12 +174,8 @@ async def calculate_total_budget( | ||||
|     total = 0 | ||||
|     for step in range(max_steps): | ||||
|         set_quantity = quantity * (martingale_factor**step) | ||||
|         if commission_fee_percent == 0: | ||||
|             # Commission fee is not added to the position size | ||||
|             r_quantity = set_quantity | ||||
|         else: | ||||
|             # Commission fee is added to the position size | ||||
|             r_quantity = set_quantity * (1 + 2 * commission_fee_percent) | ||||
|  | ||||
|         r_quantity = set_quantity | ||||
|  | ||||
|         total += r_quantity | ||||
|     return total | ||||
|   | ||||
| @@ -6,7 +6,6 @@ from aiogram.types import CallbackQuery | ||||
|  | ||||
| import app.telegram.keyboards.inline as kbi | ||||
| import database.request as rq | ||||
| from app.bybit import get_bybit_client | ||||
|  | ||||
| from app.helper_functions import calculate_total_budget, safe_float | ||||
| from logger_helper.logger_helper import LOGGING_CONFIG | ||||
| @@ -26,7 +25,6 @@ async def additional_settings(callback_query: CallbackQuery, state: FSMContext) | ||||
|     try: | ||||
|         await state.clear() | ||||
|         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) | ||||
|  | ||||
|         if not additional_data: | ||||
| @@ -64,30 +62,15 @@ async def additional_settings(callback_query: CallbackQuery, state: FSMContext) | ||||
|         max_bets = additional_data.max_bets_in_series | ||||
|         quantity = f(additional_data.order_quantity) | ||||
|         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 = "" | ||||
|         if trade_mode == "Switch": | ||||
|             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( | ||||
|             quantity=quantity, | ||||
|             martingale_factor=martingale, | ||||
|             max_steps=max_bets, | ||||
|             commission_fee_percent=total_commission, | ||||
|         ) | ||||
|         text = ( | ||||
|             f"Основные настройки:\n\n" | ||||
| @@ -99,7 +82,7 @@ async def additional_settings(callback_query: CallbackQuery, state: FSMContext) | ||||
|             f"- Коэффициент мартингейла: {martingale:.2f}\n" | ||||
|             f"- Триггер цена: {trigger_price:.4f} USDT\n" | ||||
|             f"- Максимальное кол-во ставок в серии: {max_bets}\n\n" | ||||
|             f"- Бюджет серии: {total_budget:.4f} USDT\n" | ||||
|             f"- Бюджет серии: {total_budget:.2f} USDT\n" | ||||
|         ) | ||||
|  | ||||
|         keyboard = kbi.get_additional_settings_keyboard(mode=trade_mode) | ||||
|   | ||||
| @@ -1,8 +1,10 @@ | ||||
| from aiogram.types import KeyboardButton, ReplyKeyboardMarkup | ||||
|  | ||||
| profile = ReplyKeyboardMarkup( | ||||
|     keyboard=[[KeyboardButton(text="Панель Bybit"), KeyboardButton(text="Профиль")], | ||||
|               [KeyboardButton(text="Подключить платформу Bybit")]], | ||||
|     keyboard=[ | ||||
|         [KeyboardButton(text="Панель Bybit"), KeyboardButton(text="Профиль")], | ||||
|         [KeyboardButton(text="Подключить платформу Bybit")], | ||||
|     ], | ||||
|     resize_keyboard=True, | ||||
|     one_time_keyboard=True, | ||||
|     input_field_placeholder="Выберите пункт меню...", | ||||
|   | ||||
		Reference in New Issue
	
	Block a user