Stage 07.2 - auto trading real settings and strategy presets

This commit is contained in:
2026-04-28 12:54:32 +03:00
parent b48d9c7f35
commit 83ab842f6e
7 changed files with 266 additions and 11 deletions

View File

@@ -15,6 +15,15 @@ from src.trading.auto.service import AutoTradeService
router = Router(name="auto")
def _strategy_label(strategy: str | None) -> str:
mapping = {
"TREND": "📈 Trend Following",
"GRID": "🧩 Grid Trading",
"SCALP": "⚡ Scalping",
}
return mapping.get(strategy or "", "")
def _status_label(status: str) -> str:
mapping = {
"OFF": "⚪ Выключена",
@@ -42,7 +51,7 @@ def _auto_keyboard() -> InlineKeyboardMarkup:
def _build_auto_text() -> str:
state = AutoTradeService().get_state()
strategy = state.strategy or ""
strategy = _strategy_label(state.strategy)
risk = f"{state.risk_percent:.1f}%" if state.risk_percent is not None else ""
return (

View File

@@ -11,6 +11,7 @@ from src.core.system_status import build_system_text, get_system_snapshot, has_s
from src.core.config import load_settings
from src.core.constants import APP_NAME, APP_VERSION
from src.trading.journal.service import JournalService
from src.trading.auto.service import AutoTradeService
router = Router(name="system")
@@ -169,24 +170,141 @@ async def open_auto_settings(callback: CallbackQuery) -> None:
await callback.answer("Сообщение не найдено", show_alert=True)
return
state = AutoTradeService().get_state()
strategy_map = {
"TREND": "📈 Trend Following",
"GRID": "🧩 Grid Trading",
"SCALP": "⚡ Scalping",
}
strategy = strategy_map.get(state.strategy or "", "")
risk = f"{state.risk_percent:.1f}%" if state.risk_percent is not None else ""
text = (
"<b>🤖 Автоторговля</b>\n\n"
"<b>СИСТЕМА</b> · Настройки\n\n"
"Статус: —\n"
"Стратегия: —\n"
"Риск: \n\n"
"В разработке."
f"Стратегия: {strategy}\n"
f"Инструмент: {state.symbol}\n"
f"Риск: {risk}\n\n"
"Выберите настройку:"
)
builder = InlineKeyboardBuilder()
builder.button(text="🧠 Стратегия", callback_data="settings:auto_strategy")
builder.button(text="📈 Инструмент", callback_data="settings:auto_symbol")
builder.button(text="🛡️ Риск", callback_data="settings:auto_risk")
builder.button(text="⬅️ Назад", callback_data="system:management")
builder.button(text="🤖 Автоторговля", callback_data="auto:home")
builder.adjust(2)
builder.adjust(2, 1, 2)
await callback.message.edit_text(text, reply_markup=builder.as_markup())
await callback.answer()
@router.callback_query(F.data == "settings:auto_strategy")
async def open_auto_strategy_settings(callback: CallbackQuery) -> None:
if callback.message is None:
await callback.answer("Сообщение не найдено", show_alert=True)
return
text = (
"<b>🧠 Стратегия</b>\n\n"
"<b>СИСТЕМА</b> · Настройки · Автоторговля\n\n"
"Выберите стратегию:"
)
builder = InlineKeyboardBuilder()
builder.button(text="📈 Trend", callback_data="settings:auto_strategy:trend")
builder.button(text="🧩 Grid", callback_data="settings:auto_strategy:grid")
builder.button(text="⚡ Scalp", callback_data="settings:auto_strategy:scalp")
builder.button(text="⬅️ Назад", callback_data="settings:auto")
builder.adjust(3, 1)
await callback.message.edit_text(text, reply_markup=builder.as_markup())
await callback.answer()
@router.callback_query(F.data.startswith("settings:auto_strategy:"))
async def set_auto_strategy(callback: CallbackQuery) -> None:
strategy = callback.data.split(":", 2)[2]
AutoTradeService().set_strategy(strategy.upper())
if callback.message is not None:
await open_auto_settings(callback)
await callback.answer("Стратегия обновлена")
@router.callback_query(F.data == "settings:auto_symbol")
async def open_auto_symbol_settings(callback: CallbackQuery) -> None:
if callback.message is None:
await callback.answer("Сообщение не найдено", show_alert=True)
return
settings = load_settings()
text = (
"<b>📈 Инструмент</b>\n\n"
"<b>СИСТЕМА</b> · Настройки · Автоторговля\n\n"
"Выберите инструмент:"
)
builder = InlineKeyboardBuilder()
builder.button(text=settings.default_symbol, callback_data=f"settings:auto_symbol:{settings.default_symbol}")
builder.button(text="BTCUSDT", callback_data="settings:auto_symbol:BTCUSDT")
builder.button(text="ETHUSDT", callback_data="settings:auto_symbol:ETHUSDT")
builder.button(text="⬅️ Назад", callback_data="settings:auto")
builder.adjust(1, 2, 1)
await callback.message.edit_text(text, reply_markup=builder.as_markup())
await callback.answer()
@router.callback_query(F.data.startswith("settings:auto_symbol:"))
async def set_auto_symbol(callback: CallbackQuery) -> None:
symbol = callback.data.split(":", 2)[2]
AutoTradeService().set_symbol(symbol)
if callback.message is not None:
await open_auto_settings(callback)
await callback.answer("Инструмент обновлён")
@router.callback_query(F.data == "settings:auto_risk")
async def open_auto_risk_settings(callback: CallbackQuery) -> None:
if callback.message is None:
await callback.answer("Сообщение не найдено", show_alert=True)
return
text = (
"<b>🛡️ Риск</b>\n\n"
"<b>СИСТЕМА</b> · Настройки · Автоторговля\n\n"
"Выберите риск на сделку:"
)
builder = InlineKeyboardBuilder()
builder.button(text="0.5%", callback_data="settings:auto_risk:0.5")
builder.button(text="1.0%", callback_data="settings:auto_risk:1.0")
builder.button(text="2.0%", callback_data="settings:auto_risk:2.0")
builder.button(text="⬅️ Назад", callback_data="settings:auto")
builder.adjust(3, 1)
await callback.message.edit_text(text, reply_markup=builder.as_markup())
await callback.answer()
@router.callback_query(F.data.startswith("settings:auto_risk:"))
async def set_auto_risk(callback: CallbackQuery) -> None:
risk = float(callback.data.split(":", 2)[2])
AutoTradeService().set_risk_percent(risk)
if callback.message is not None:
await open_auto_settings(callback)
await callback.answer("Риск обновлён")
@router.callback_query(F.data == "settings:trade")
async def open_trade_settings(callback: CallbackQuery) -> None:
if callback.message is None:

View File

@@ -49,4 +49,19 @@ class AutoTradeService:
return state, "Автоторговля уже выключена."
state.status = "OFF"
return state, "Автоторговля выключена."
return state, "Автоторговля выключена."
def set_symbol(self, symbol: str) -> AutoTradeState:
state = self.get_state()
state.symbol = symbol
return state
def set_strategy(self, strategy: str) -> AutoTradeState:
state = self.get_state()
state.strategy = strategy
return state
def set_risk_percent(self, risk_percent: float) -> AutoTradeState:
state = self.get_state()
state.risk_percent = risk_percent
return state

View File

@@ -0,0 +1,19 @@
# 0016 — Auto Trading Settings in Memory
## Решение
На этапе 07.2 настройки автоторговли хранятся в памяти процесса.
## Причины
- быстрее реализовать MVP;
- не усложнять storage migration;
- достаточно для тестирования UI / logic.
## Последствия
После перезапуска бота настройки сбрасываются.
В будущем настройки будут храниться в БД / config.

View File

@@ -93,7 +93,9 @@
✔ mock controls
### 07.2
real settings
real settings
✔ strategy presets
✔ risk presets
### 07.3
⏳ background loop

View File

@@ -16,9 +16,10 @@
## 07.2 — Real settings
стратегия
риск
символ
стратегия
риск
символ
✔ presets UI
---

View File

@@ -0,0 +1,91 @@
# Stage 07.2 — Auto Trading Real Settings
## Что сделано
Реализованы реальные настройки автоторговли.
---
## 1. Настройки автоторговли
Экран:
🤖 Автоторговля → 🛠️ Настройки
Теперь показывает реальные значения:
- Стратегия
- Инструмент
- Риск
---
## 2. Настройка стратегии
Добавлен выбор стратегии:
- 📈 Trend Following
- 🧩 Grid Trading
- ⚡ Scalping
В state сохраняются short-code:
- TREND
- GRID
- SCALP
---
## 3. Настройка инструмента
Добавлен выбор торгового инструмента:
Примеры:
- BTCUSD
- BTCUSDT
- ETHUSDT
Значение влияет на экран автоторговли.
---
## 4. Настройка риска
Добавлен выбор риска:
- 0.5%
- 1.0%
- 2.0%
Значение влияет на расчёт будущего position sizing.
---
## 5. Service layer update
В AutoTradeService добавлены методы:
- set_symbol()
- set_strategy()
- set_risk_percent()
---
## 6. UI improvement
Стратегии отображаются в friendly-виде:
- 📈 Trend Following
- 🧩 Grid Trading
- ⚡ Scalping
---
## Commit
```
git add .
git commit -m "Stage 07.2 - auto trading real settings and strategy presets"
git push
```