07.4.3.19.4 — Journal Runtime Standardization & Export Layer
This commit is contained in:
@@ -207,13 +207,8 @@ def _log_risk_updated(action: str) -> None:
|
||||
|
||||
try:
|
||||
JournalService().log_ui_info(
|
||||
event_type="auto_risk_settings_updated",
|
||||
message=(
|
||||
"Risk settings updated: "
|
||||
f"SL={state.stop_loss_percent}, "
|
||||
f"TP={state.take_profit_percent}, "
|
||||
f"ML={state.max_loss_usd}"
|
||||
),
|
||||
event_type="risk_settings_updated",
|
||||
message="Параметры защиты позиции обновлены.",
|
||||
screen="auto",
|
||||
action=action,
|
||||
payload={
|
||||
|
||||
@@ -126,15 +126,6 @@ async def open_journal(message: Message, state: FSMContext) -> None:
|
||||
chat_id=message.chat.id,
|
||||
)
|
||||
|
||||
JournalService().log_ui_info(
|
||||
event_type="journal_open_requested",
|
||||
message="Запрошено открытие журнала.",
|
||||
screen="journal",
|
||||
action="open",
|
||||
user_id=_user_id_from_message(message),
|
||||
chat_id=_chat_id_from_message(message),
|
||||
)
|
||||
|
||||
await _show_journal_page(
|
||||
message,
|
||||
page=1,
|
||||
@@ -157,15 +148,6 @@ async def open_journal_from_monitoring(callback: CallbackQuery, state: FSMContex
|
||||
keep_message_id=callback.message.message_id,
|
||||
)
|
||||
|
||||
JournalService().log_ui_info(
|
||||
event_type="journal_open_requested",
|
||||
message="Запрошено открытие журнала из мониторинга.",
|
||||
screen="journal",
|
||||
action="open_from_monitoring",
|
||||
user_id=_user_id_from_callback(callback),
|
||||
chat_id=_chat_id_from_callback(callback),
|
||||
)
|
||||
|
||||
await _show_journal_page(
|
||||
callback.message,
|
||||
page=1,
|
||||
@@ -195,7 +177,7 @@ async def export_journal_csv(callback: CallbackQuery) -> None:
|
||||
await callback.message.answer_document(document=document)
|
||||
|
||||
service.log_ui_info(
|
||||
event_type="journal_export_csv_success",
|
||||
event_type="journal_exported",
|
||||
message="Журнал экспортирован в CSV.",
|
||||
screen="journal",
|
||||
action="export_csv",
|
||||
@@ -207,12 +189,13 @@ async def export_journal_csv(callback: CallbackQuery) -> None:
|
||||
await callback.answer("CSV экспортирован")
|
||||
except Exception as exc:
|
||||
service.log_ui_error(
|
||||
event_type="journal_export_csv_error",
|
||||
event_type="journal_export_error",
|
||||
message="Не удалось экспортировать журнал в CSV.",
|
||||
screen="journal",
|
||||
action="export_csv",
|
||||
user_id=_user_id_from_callback(callback),
|
||||
chat_id=_chat_id_from_callback(callback),
|
||||
payload={"format": "csv"},
|
||||
raw_error=str(exc),
|
||||
)
|
||||
await callback.answer("Не удалось экспортировать CSV", show_alert=True)
|
||||
@@ -233,8 +216,8 @@ async def export_journal_xlsx(callback: CallbackQuery) -> None:
|
||||
await callback.message.answer_document(document=document)
|
||||
|
||||
service.log_ui_info(
|
||||
event_type="journal_export_xlsx_success",
|
||||
message="Журнал экспортирован в Excel.",
|
||||
event_type="journal_exported",
|
||||
message="Журнал экспортирован в XLSX.",
|
||||
screen="journal",
|
||||
action="export_xlsx",
|
||||
user_id=_user_id_from_callback(callback),
|
||||
@@ -245,12 +228,13 @@ async def export_journal_xlsx(callback: CallbackQuery) -> None:
|
||||
await callback.answer("Excel экспортирован")
|
||||
except Exception as exc:
|
||||
service.log_ui_error(
|
||||
event_type="journal_export_xlsx_error",
|
||||
message="Не удалось экспортировать журнал в Excel.",
|
||||
event_type="journal_export_error",
|
||||
message="Не удалось экспортировать журнал в XLSX.",
|
||||
screen="journal",
|
||||
action="export_xlsx",
|
||||
user_id=_user_id_from_callback(callback),
|
||||
chat_id=_chat_id_from_callback(callback),
|
||||
payload={"format": "xlsx"},
|
||||
raw_error=str(exc),
|
||||
)
|
||||
await callback.answer("Не удалось экспортировать Excel", show_alert=True)
|
||||
|
||||
@@ -21,65 +21,25 @@ LEVEL_ICONS = {
|
||||
}
|
||||
|
||||
EVENT_TITLES = {
|
||||
"auto_signal_generated": "Сигнал автоторговли",
|
||||
"auto_signal_summary": "Итог серии сигналов",
|
||||
"app_start": "Запуск приложения",
|
||||
"system_open_alert": "Система загружена с предупреждениями",
|
||||
"system_open_requested": "Открытие системы",
|
||||
"system_open_success": "Система загружена",
|
||||
"system_retry": "Система обновлена",
|
||||
"market_open_requested": "Открытие рынка",
|
||||
"market_open_success": "Рынок загружен",
|
||||
"market_open_error": "Ошибка открытия рынка",
|
||||
"market_retry_error": "Ошибка обновления рынка",
|
||||
"market_symbol_invalid": "Некорректный инструмент",
|
||||
"market_price_error": "Ошибка загрузки цены",
|
||||
"portfolio_open_requested": "Открытие портфеля",
|
||||
"portfolio_open_success": "Портфель загружен",
|
||||
"portfolio_open_error": "Ошибка открытия портфеля",
|
||||
"portfolio_retry_error": "Ошибка обновления портфеля",
|
||||
"portfolio_empty": "Портфель пуст",
|
||||
"portfolio_zero_balances": "Нет активов с балансом",
|
||||
"portfolio_partial_estimate": "Частичная оценка портфеля",
|
||||
"balance_summary_loaded": "Баланс загружен",
|
||||
"balance_summary_empty": "Баланс пуст",
|
||||
"balance_summary_error": "Ошибка загрузки баланса",
|
||||
"exchange_request_error": "Ошибка запроса к бирже",
|
||||
"trade_drafts_open": "Открытие списка черновиков",
|
||||
"trade_drafts_paginate": "Переключение страницы черновиков",
|
||||
"trade_draft_open_success": "Черновик открыт",
|
||||
"trade_draft_open_not_found": "Черновик не найден",
|
||||
"trade_draft_edit_start": "Начато редактирование черновика",
|
||||
"trade_draft_edit_error": "Ошибка редактирования черновика",
|
||||
"trade_draft_edit_not_found": "Черновик не найден",
|
||||
"trade_order_create_start": "Начато создание ордера",
|
||||
"trade_order_create_start_error": "Ошибка создания ордера",
|
||||
"trade_order_create_cancelled": "Создание ордера отменено",
|
||||
"trade_order_side_selected": "Выбрана сторона ордера",
|
||||
"trade_order_side_select_error": "Ошибка выбора стороны",
|
||||
"trade_order_type_selected": "Выбран тип ордера",
|
||||
"trade_order_type_select_error": "Ошибка выбора типа",
|
||||
"trade_order_quantity_selected": "Выбрано количество",
|
||||
"trade_order_quantity_select_error": "Ошибка выбора количества",
|
||||
"trade_order_quantity_manual_open": "Ручной ввод количества",
|
||||
"trade_order_quantity_manual_success": "Количество введено",
|
||||
"trade_order_quantity_manual_error": "Ошибка ввода количества",
|
||||
"trade_order_price_selected": "Выбрана цена",
|
||||
"trade_order_price_select_error": "Ошибка выбора цены",
|
||||
"trade_order_price_manual_open": "Ручной ввод цены",
|
||||
"trade_order_price_manual_success": "Цена введена",
|
||||
"trade_order_price_manual_error": "Ошибка ввода цены",
|
||||
"trade_order_confirm_success": "Черновик сохранён",
|
||||
"trade_order_confirm_error": "Ошибка сохранения",
|
||||
"trade_order_confirm_validation_error": "Ошибка проверки",
|
||||
"trade_order_confirm_state_error": "Ошибка состояния",
|
||||
"signal_summary": "Сводка сигнала",
|
||||
"signal_ready": "Сигнал готов",
|
||||
"position_opened": "Позиция открыта",
|
||||
"position_closed": "Позиция закрыта",
|
||||
"position_flipped": "Направление позиции изменено",
|
||||
"position_flip_blocked": "Смена направления позиции заблокирована",
|
||||
"risk_settings_updated": "Настройки защиты обновлены",
|
||||
"market_monitor_started": "Мониторинг рынка запущен",
|
||||
"market_monitor_stopped": "Мониторинг рынка остановлен",
|
||||
"market_stream_connected": "Поток рынка подключён",
|
||||
"market_stream_disconnected": "Поток рынка отключён",
|
||||
"market_symbol_changed": "Инструмент рынка изменён",
|
||||
"journal_export_error": "Ошибка экспорта журнала",
|
||||
"journal_exported": "Журнал экспортирован",
|
||||
"journal_cleared": "Журнал очищен",
|
||||
"journal_cleared_old": "Журнал очищен по сроку",
|
||||
"journal_export_csv_success": "Экспорт CSV",
|
||||
"journal_export_csv_error": "Ошибка экспорта CSV",
|
||||
"journal_export_xlsx_success": "Экспорт Excel",
|
||||
"journal_export_xlsx_error": "Ошибка экспорта Excel",
|
||||
"journal_open_requested": "Открытие журнала",
|
||||
"notification_sent": "Уведомление отправлено",
|
||||
"notification_error": "Ошибка уведомления",
|
||||
"app_started": "Приложение запущено",
|
||||
"app_bootstrap_failed": "Ошибка запуска приложения",
|
||||
}
|
||||
|
||||
TECH_TO_HUMAN_MESSAGES = {
|
||||
@@ -221,42 +181,18 @@ def _payload(event: dict) -> dict:
|
||||
|
||||
|
||||
def _render_auto_signal(event: dict, created_time: str) -> list[str]:
|
||||
payload = _payload(event)
|
||||
|
||||
signal = str(payload.get("signal", "HOLD")).upper()
|
||||
strategy = str(payload.get("strategy", "AUTO")).upper()
|
||||
symbol = str(payload.get("symbol", "—"))
|
||||
reason = str(payload.get("reason", ""))
|
||||
confidence = float(payload.get("confidence", 0.0) or 0.0)
|
||||
repeat_count = int(payload.get("repeat_count", 1) or 1)
|
||||
is_strong_signal = bool(payload.get("is_strong_signal", False))
|
||||
is_aggregated = bool(payload.get("is_aggregated", False))
|
||||
|
||||
signal_icon = {
|
||||
"BUY": "🟢",
|
||||
"SELL": "🔴",
|
||||
"HOLD": "🟡",
|
||||
}.get(signal, "•")
|
||||
|
||||
prefix = ""
|
||||
if is_strong_signal:
|
||||
prefix += "📈 "
|
||||
if is_aggregated:
|
||||
prefix += "🧠 "
|
||||
level = str(event.get("level", "INFO")).upper()
|
||||
icon = LEVEL_ICONS.get(level, "•")
|
||||
title = _event_title(str(event.get("event_type", "")))
|
||||
message = _humanize_message(str(event.get("message", "")))
|
||||
|
||||
lines = [
|
||||
f"{prefix}{signal_icon} <b>AUTO · {signal}</b>",
|
||||
f"{created_time} · {strategy} · {symbol}",
|
||||
f"{icon} <b>{level}</b> · {title}",
|
||||
f"{created_time}",
|
||||
]
|
||||
|
||||
if is_aggregated:
|
||||
lines.append(f"{repeat_count} {signal} подряд")
|
||||
|
||||
if confidence > 0:
|
||||
lines.append(f"Уверенность: {confidence:.2f}")
|
||||
|
||||
if reason:
|
||||
lines.append(f"Причина: {reason}")
|
||||
if message:
|
||||
lines.append(message)
|
||||
|
||||
return lines
|
||||
|
||||
@@ -305,7 +241,7 @@ def render(events, page, total_pages):
|
||||
|
||||
event_type = str(event.get("event_type", ""))
|
||||
|
||||
if event_type in {"auto_signal_generated", "auto_signal_summary"}:
|
||||
if event_type in {"signal_summary", "signal_ready"}:
|
||||
lines.extend(_render_auto_signal(event, created_time))
|
||||
else:
|
||||
lines.extend(_render_default_event(event, created_time))
|
||||
|
||||
Reference in New Issue
Block a user