Stage 07.2 - auto trading real settings and strategy presets
This commit is contained in:
@@ -15,6 +15,15 @@ from src.trading.auto.service import AutoTradeService
|
|||||||
router = Router(name="auto")
|
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:
|
def _status_label(status: str) -> str:
|
||||||
mapping = {
|
mapping = {
|
||||||
"OFF": "⚪ Выключена",
|
"OFF": "⚪ Выключена",
|
||||||
@@ -42,7 +51,7 @@ def _auto_keyboard() -> InlineKeyboardMarkup:
|
|||||||
def _build_auto_text() -> str:
|
def _build_auto_text() -> str:
|
||||||
state = AutoTradeService().get_state()
|
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 "—"
|
risk = f"{state.risk_percent:.1f}%" if state.risk_percent is not None else "—"
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -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.config import load_settings
|
||||||
from src.core.constants import APP_NAME, APP_VERSION
|
from src.core.constants import APP_NAME, APP_VERSION
|
||||||
from src.trading.journal.service import JournalService
|
from src.trading.journal.service import JournalService
|
||||||
|
from src.trading.auto.service import AutoTradeService
|
||||||
|
|
||||||
|
|
||||||
router = Router(name="system")
|
router = Router(name="system")
|
||||||
@@ -169,24 +170,141 @@ async def open_auto_settings(callback: CallbackQuery) -> None:
|
|||||||
await callback.answer("Сообщение не найдено", show_alert=True)
|
await callback.answer("Сообщение не найдено", show_alert=True)
|
||||||
return
|
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 = (
|
text = (
|
||||||
"<b>🤖 Автоторговля</b>\n\n"
|
"<b>🤖 Автоторговля</b>\n\n"
|
||||||
"<b>СИСТЕМА</b> · Настройки\n\n"
|
"<b>СИСТЕМА</b> · Настройки\n\n"
|
||||||
"Статус: —\n"
|
f"Стратегия: {strategy}\n"
|
||||||
"Стратегия: —\n"
|
f"Инструмент: {state.symbol}\n"
|
||||||
"Риск: —\n\n"
|
f"Риск: {risk}\n\n"
|
||||||
"В разработке."
|
"Выберите настройку:"
|
||||||
)
|
)
|
||||||
|
|
||||||
builder = InlineKeyboardBuilder()
|
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="system:management")
|
||||||
builder.button(text="🤖 Автоторговля", callback_data="auto:home")
|
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.message.edit_text(text, reply_markup=builder.as_markup())
|
||||||
await callback.answer()
|
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")
|
@router.callback_query(F.data == "settings:trade")
|
||||||
async def open_trade_settings(callback: CallbackQuery) -> None:
|
async def open_trade_settings(callback: CallbackQuery) -> None:
|
||||||
if callback.message is None:
|
if callback.message is None:
|
||||||
|
|||||||
@@ -49,4 +49,19 @@ class AutoTradeService:
|
|||||||
return state, "Автоторговля уже выключена."
|
return state, "Автоторговля уже выключена."
|
||||||
|
|
||||||
state.status = "OFF"
|
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
|
||||||
19
docs/decisions/0016-auto-trading-settings-in-memory.md
Normal file
19
docs/decisions/0016-auto-trading-settings-in-memory.md
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
# 0016 — Auto Trading Settings in Memory
|
||||||
|
|
||||||
|
## Решение
|
||||||
|
|
||||||
|
На этапе 07.2 настройки автоторговли хранятся в памяти процесса.
|
||||||
|
|
||||||
|
## Причины
|
||||||
|
|
||||||
|
- быстрее реализовать MVP;
|
||||||
|
|
||||||
|
- не усложнять storage migration;
|
||||||
|
|
||||||
|
- достаточно для тестирования UI / logic.
|
||||||
|
|
||||||
|
## Последствия
|
||||||
|
|
||||||
|
После перезапуска бота настройки сбрасываются.
|
||||||
|
|
||||||
|
В будущем настройки будут храниться в БД / config.
|
||||||
@@ -93,7 +93,9 @@
|
|||||||
✔ mock controls
|
✔ mock controls
|
||||||
|
|
||||||
### 07.2
|
### 07.2
|
||||||
⏳ real settings
|
✔ real settings
|
||||||
|
✔ strategy presets
|
||||||
|
✔ risk presets
|
||||||
|
|
||||||
### 07.3
|
### 07.3
|
||||||
⏳ background loop
|
⏳ background loop
|
||||||
|
|||||||
@@ -16,9 +16,10 @@
|
|||||||
|
|
||||||
## 07.2 — Real settings
|
## 07.2 — Real settings
|
||||||
|
|
||||||
⏳ стратегия
|
✔ стратегия
|
||||||
⏳ риск
|
✔ риск
|
||||||
⏳ символ
|
✔ символ
|
||||||
|
✔ presets UI
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
91
docs/stages/stage-07_2-auto-trading-real-settings.md
Normal file
91
docs/stages/stage-07_2-auto-trading-real-settings.md
Normal 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
|
||||||
|
```
|
||||||
Reference in New Issue
Block a user