Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 66 additions & 4 deletions application/rebalance_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,25 @@ def _append_status_lines(lines, *, execution, translator, signal_key):
lines.extend(_build_benchmark_lines(execution, translator=translator))


def _first_detail_line(text) -> str:
parts = _split_labeled_text(text)
return parts[0] if parts else ""


def _append_compact_status_lines(lines, *, execution, translator, signal_key):
status_summary = _first_detail_line(
_localize_notification_text(execution.get("status_display"), translator=translator)
)
if status_summary:
lines.append(translator("market_status", status=status_summary))

signal_summary = _first_detail_line(
_localize_notification_text(execution.get("signal_display"), translator=translator)
)
if signal_summary:
lines.append(translator(signal_key, msg=signal_summary))



def _append_strategy_line(lines, *, strategy_display_name, translator):
name = str(strategy_display_name or "").strip()
Expand Down Expand Up @@ -555,9 +574,25 @@ def record_dry_run(symbol, side, quantity, price, *, order_type):
signal_key="signal",
)
tg_lines.extend([separator, translator("order_logs_title"), formatted_logs])
tg_message = "\n".join(tg_lines)
print(with_prefix(tg_message), flush=True)
send_tg_message(tg_message)
detailed_tg_message = "\n".join(tg_lines)
compact_lines = [translator("rebalance_title")]
_append_strategy_line(
compact_lines,
strategy_display_name=strategy_display_name,
translator=translator,
)
if dry_run_only:
compact_lines.append(translator("dry_run_banner"))
_append_compact_status_lines(
compact_lines,
execution=execution,
translator=translator,
signal_key="signal",
)
compact_lines.extend([separator, translator("order_logs_title"), formatted_logs])
compact_tg_message = "\n".join(compact_lines)
print(with_prefix(detailed_tg_message), flush=True)
send_tg_message(compact_tg_message)
else:
equity_text = f"{total_strategy_equity:,.2f}"
cash_summary = translator(
Expand Down Expand Up @@ -610,8 +645,35 @@ def record_dry_run(symbol, side, quantity, price, *, order_type):
f"{translator('notes_title')}\n"
+ "\n".join(f" - {log}" for log in note_logs)
)
compact_no_trade_lines = [
translator("heartbeat_title"),
]
_append_strategy_line(
compact_no_trade_lines,
strategy_display_name=strategy_display_name,
translator=translator,
)
compact_no_trade_lines.append(translator("equity", value=equity_text))
if dry_run_only:
compact_no_trade_lines.append(translator("dry_run_banner"))
_append_compact_status_lines(
compact_no_trade_lines,
execution=execution,
translator=translator,
signal_key="heartbeat_signal",
)
compact_no_trade_lines.append(
translator("no_executable_orders") if (skip_logs or note_logs) else translator("no_trades")
)
if skip_logs:
compact_no_trade_lines.extend([separator, translator("skipped_actions")])
compact_no_trade_lines.extend(f" - {log}" for log in skip_logs)
if note_logs:
compact_no_trade_lines.extend([separator, translator("notes_title")])
compact_no_trade_lines.extend(f" - {log}" for log in note_logs)
compact_no_trade_message = "\n".join(compact_no_trade_lines)
print(with_prefix(no_trade_message), flush=True)
send_tg_message(no_trade_message)
send_tg_message(compact_no_trade_message)


def safe_quote_last_price(quote_context, symbol, *, fetch_last_price, notify_issue):
Expand Down
20 changes: 10 additions & 10 deletions tests/test_rebalance_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -348,8 +348,8 @@ def test_zero_investable_cash_is_silently_skipped(self):
)

self.assertEqual(len(sent_messages), 1)
self.assertIn("账户现金", sent_messages[0])
self.assertIn("可投资现金: $0.00", sent_messages[0])
self.assertNotIn("账户现金", sent_messages[0])
self.assertNotIn("可投资现金: $0.00", sent_messages[0])
self.assertIn("✅ 无需调仓", sent_messages[0])
self.assertNotIn("本轮没有可执行订单", sent_messages[0])
self.assertNotIn("说明", sent_messages[0])
Expand Down Expand Up @@ -617,9 +617,9 @@ def test_heartbeat_accepts_normalized_portfolio_and_execution_sections(self):
self.assertEqual(len(sent_messages), 1)
self.assertIn("💓 【心跳检测】", sent_messages[0])
self.assertIn("可投资现金", sent_messages[0])
self.assertIn("💵 资金\n - 账户现金:", sent_messages[0])
self.assertIn("💼 持仓", sent_messages[0])
self.assertIn(" - SOXX:", sent_messages[0])
self.assertNotIn("💵 资金\n - 账户现金:", sent_messages[0])
self.assertNotIn("💼 持仓", sent_messages[0])
self.assertNotIn(" - SOXX:", sent_messages[0])

def test_hybrid_heartbeat_hides_empty_semiconductor_fields_and_shows_benchmark_line(self):
plan = _build_plan(
Expand Down Expand Up @@ -660,11 +660,11 @@ def test_hybrid_heartbeat_hides_empty_semiconductor_fields_and_shows_benchmark_l
self.assertIn("💓 【心跳检测】", sent_messages[0])
self.assertIn("🧭 策略: TQQQ 增长收益", sent_messages[0])
self.assertIn("🧪 模拟运行模式", sent_messages[0])
self.assertIn("💼 持仓", sent_messages[0])
self.assertIn(" - TQQQ: $0.00", sent_messages[0])
self.assertIn(" - BOXX: $0.00", sent_messages[0])
self.assertIn(" - QQQI: $0.00", sent_messages[0])
self.assertIn("📈 QQQ 基准\n - QQQ: 588.50\n - MA200: 595.25\n - 退出线: 573.00", sent_messages[0])
self.assertNotIn("💼 持仓", sent_messages[0])
self.assertNotIn(" - TQQQ: $0.00", sent_messages[0])
self.assertNotIn(" - BOXX: $0.00", sent_messages[0])
self.assertNotIn(" - QQQI: $0.00", sent_messages[0])
self.assertNotIn("📈 QQQ 基准\n - QQQ: 588.50\n - MA200: 595.25\n - 退出线: 573.00", sent_messages[0])
self.assertIn("🎯 信号: 💤 等待信号", sent_messages[0])
self.assertNotIn("账户现金: $0.00 | 可投资现金", sent_messages[0])
self.assertNotIn("TQQQ: $0.00 BOXX", sent_messages[0])
Expand Down