Skip to content

Commit acff586

Browse files
committed
Beautify notification layout
1 parent c1e32ec commit acff586

4 files changed

Lines changed: 27 additions & 4 deletions

File tree

application/rebalance_service.py

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -288,13 +288,13 @@ def build_dashboard(
288288
qty = positions[symbol]["quantity"]
289289
avg = positions[symbol]["avg_cost"]
290290
market_value = qty * avg
291-
position_lines.append(f" {symbol}: {qty}股 ${market_value:,.2f}")
291+
position_lines.append(f" - {symbol}: {qty} | ${market_value:,.2f}")
292292
position_text = "\n".join(position_lines) if position_lines else translator("empty_positions")
293293
signal_metadata = signal_metadata or {}
294294
allocation = _resolve_weight_allocation(signal_metadata, required=False)
295295
target_lines = []
296296
for symbol, weight in sorted(allocation.get("targets", {}).items(), key=lambda item: (-item[1], item[0])):
297-
target_lines.append(f" {symbol}: {weight:.1%}")
297+
target_lines.append(f" - {symbol}: {weight:.1%}")
298298
target_text = "\n".join(target_lines) if target_lines else translator("empty_target_weights")
299299
regime = signal_metadata.get("regime")
300300
breadth_ratio = signal_metadata.get("breadth_ratio")
@@ -323,14 +323,19 @@ def build_dashboard(
323323
else None,
324324
translator("snapshot_as_of_detail", value=_format_text(snapshot_as_of, fallback="<none>")) if snapshot_as_of else None,
325325
]
326-
diagnostics_text = " | ".join(part for part in diagnostics if part)
326+
diagnostics_lines = [f" - {part}" for part in diagnostics if part]
327+
diagnostics_text = "\n".join(diagnostics_lines)
327328
localized_status_desc = _localize_notification_text(status_desc, translator=translator)
328329
localized_signal_desc = _localize_notification_text(signal_desc, translator=translator)
329330
return (
330-
f"{translator('equity')}: ${equity:,.2f} | {translator('buying_power')}: ${buying_power:,.2f}\n"
331+
f"{translator('account_summary_title')}\n"
332+
f" - {translator('equity')}: ${equity:,.2f}\n"
333+
f" - {translator('buying_power')}: ${buying_power:,.2f}\n"
331334
f"{separator}\n"
335+
f"{translator('positions_title')}\n"
332336
f"{position_text}\n"
333337
f"{separator}\n"
338+
f"{translator('execution_summary_title')}\n"
334339
f"{diagnostics_text}\n"
335340
f"{separator}\n"
336341
f"{status_icon} {localized_status_desc}\n"

notifications/telegram.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@
1414
"buying_power": "购买力",
1515
"empty_positions": " (空仓)",
1616
"empty_target_weights": " (无目标持仓)",
17+
"account_summary_title": "📊 账户摘要",
18+
"positions_title": "💼 当前持仓",
19+
"execution_summary_title": "🧾 执行摘要",
1720
"target_weights_title": "目标持仓",
1821
"strategy_profile_detail": "策略={profile}",
1922
"execution_profile_detail": "执行配置={profile}",
@@ -93,6 +96,9 @@
9396
"buying_power": "Buying Power",
9497
"empty_positions": " (No positions)",
9598
"empty_target_weights": " (No target positions)",
99+
"account_summary_title": "📊 Account Summary",
100+
"positions_title": "💼 Current Positions",
101+
"execution_summary_title": "🧾 Execution Summary",
96102
"target_weights_title": "Target Weights",
97103
"strategy_profile_detail": "strategy_profile={profile}",
98104
"execution_profile_detail": "profile={profile}",

tests/test_notifications.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@
55
def test_build_translator_supports_chinese():
66
translate = build_translator("zh")
77
assert translate("equity") == "净值"
8+
assert translate("account_summary_title") == "📊 账户摘要"
9+
assert translate("positions_title") == "💼 当前持仓"
10+
assert translate("execution_summary_title") == "🧾 执行摘要"
811
assert translate("target_weights_title") == "目标持仓"
912
assert translate("market_status_risk_on", asset="SOXL") == "🚀 风险开启(SOXL)"
1013
assert translate("signal_risk_on", window=150, ratio="40.2%") == "SOXL 站上 150 日均线,持有 SOXL,交易层风险仓位 40.2%"

tests/test_rebalance_service.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@ def _build_test_translator():
2525
"buying_power": "buying_power",
2626
"empty_positions": "(empty positions)",
2727
"empty_target_weights": "(empty target positions)",
28+
"account_summary_title": "Account Summary",
29+
"positions_title": "Current Positions",
30+
"execution_summary_title": "Execution Summary",
2831
"target_weights_title": "Target Weights",
2932
"strategy_label": "strategy={name}",
3033
"strategy_profile_detail": "strategy_profile={profile}",
@@ -85,6 +88,9 @@ def test_build_dashboard_localizes_strategy_details():
8588
)
8689

8790
assert "🧭 策略: 全球 ETF 轮动" in dashboard
91+
assert "📊 账户摘要" in dashboard
92+
assert "💼 当前持仓" in dashboard
93+
assert "🧾 执行摘要" in dashboard
8894
assert "目标持仓" in dashboard
8995
assert "市场阶段=risk_off" in dashboard
9096
assert "快照路径" not in dashboard
@@ -209,6 +215,9 @@ def fake_execute_rebalance(
209215
assert observed["strategy_symbols"] == ("AAA", "BOXX")
210216
assert observed["signal_metadata"]["managed_symbols"] == ("AAA", "BOXX")
211217
assert observed["messages"]
218+
assert "Account Summary" in observed["messages"][0]
219+
assert "Current Positions" in observed["messages"][0]
220+
assert "Execution Summary" in observed["messages"][0]
212221
assert "📏 breadth=60.0%" in observed["messages"][0]
213222
assert "Target Weights" in observed["messages"][0]
214223

0 commit comments

Comments
 (0)