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
13 changes: 9 additions & 4 deletions application/rebalance_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -288,13 +288,13 @@ def build_dashboard(
qty = positions[symbol]["quantity"]
avg = positions[symbol]["avg_cost"]
market_value = qty * avg
position_lines.append(f" {symbol}: {qty}股 ${market_value:,.2f}")
position_lines.append(f" - {symbol}: {qty}股 | ${market_value:,.2f}")
position_text = "\n".join(position_lines) if position_lines else translator("empty_positions")
signal_metadata = signal_metadata or {}
allocation = _resolve_weight_allocation(signal_metadata, required=False)
target_lines = []
for symbol, weight in sorted(allocation.get("targets", {}).items(), key=lambda item: (-item[1], item[0])):
target_lines.append(f" {symbol}: {weight:.1%}")
target_lines.append(f" - {symbol}: {weight:.1%}")
target_text = "\n".join(target_lines) if target_lines else translator("empty_target_weights")
regime = signal_metadata.get("regime")
breadth_ratio = signal_metadata.get("breadth_ratio")
Expand Down Expand Up @@ -323,14 +323,19 @@ def build_dashboard(
else None,
translator("snapshot_as_of_detail", value=_format_text(snapshot_as_of, fallback="<none>")) if snapshot_as_of else None,
]
diagnostics_text = " | ".join(part for part in diagnostics if part)
diagnostics_lines = [f" - {part}" for part in diagnostics if part]
diagnostics_text = "\n".join(diagnostics_lines)
localized_status_desc = _localize_notification_text(status_desc, translator=translator)
localized_signal_desc = _localize_notification_text(signal_desc, translator=translator)
return (
f"{translator('equity')}: ${equity:,.2f} | {translator('buying_power')}: ${buying_power:,.2f}\n"
f"{translator('account_summary_title')}\n"
f" - {translator('equity')}: ${equity:,.2f}\n"
f" - {translator('buying_power')}: ${buying_power:,.2f}\n"
f"{separator}\n"
f"{translator('positions_title')}\n"
f"{position_text}\n"
f"{separator}\n"
f"{translator('execution_summary_title')}\n"
f"{diagnostics_text}\n"
f"{separator}\n"
f"{status_icon} {localized_status_desc}\n"
Expand Down
6 changes: 6 additions & 0 deletions notifications/telegram.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@
"buying_power": "购买力",
"empty_positions": " (空仓)",
"empty_target_weights": " (无目标持仓)",
"account_summary_title": "📊 账户摘要",
"positions_title": "💼 当前持仓",
"execution_summary_title": "🧾 执行摘要",
"target_weights_title": "目标持仓",
"strategy_profile_detail": "策略={profile}",
"execution_profile_detail": "执行配置={profile}",
Expand Down Expand Up @@ -93,6 +96,9 @@
"buying_power": "Buying Power",
"empty_positions": " (No positions)",
"empty_target_weights": " (No target positions)",
"account_summary_title": "📊 Account Summary",
"positions_title": "💼 Current Positions",
"execution_summary_title": "🧾 Execution Summary",
"target_weights_title": "Target Weights",
"strategy_profile_detail": "strategy_profile={profile}",
"execution_profile_detail": "profile={profile}",
Expand Down
3 changes: 3 additions & 0 deletions tests/test_notifications.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@
def test_build_translator_supports_chinese():
translate = build_translator("zh")
assert translate("equity") == "净值"
assert translate("account_summary_title") == "📊 账户摘要"
assert translate("positions_title") == "💼 当前持仓"
assert translate("execution_summary_title") == "🧾 执行摘要"
assert translate("target_weights_title") == "目标持仓"
assert translate("market_status_risk_on", asset="SOXL") == "🚀 风险开启(SOXL)"
assert translate("signal_risk_on", window=150, ratio="40.2%") == "SOXL 站上 150 日均线,持有 SOXL,交易层风险仓位 40.2%"
Expand Down
9 changes: 9 additions & 0 deletions tests/test_rebalance_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ def _build_test_translator():
"buying_power": "buying_power",
"empty_positions": "(empty positions)",
"empty_target_weights": "(empty target positions)",
"account_summary_title": "Account Summary",
"positions_title": "Current Positions",
"execution_summary_title": "Execution Summary",
"target_weights_title": "Target Weights",
"strategy_label": "strategy={name}",
"strategy_profile_detail": "strategy_profile={profile}",
Expand Down Expand Up @@ -85,6 +88,9 @@ def test_build_dashboard_localizes_strategy_details():
)

assert "🧭 策略: 全球 ETF 轮动" in dashboard
assert "📊 账户摘要" in dashboard
assert "💼 当前持仓" in dashboard
assert "🧾 执行摘要" in dashboard
assert "目标持仓" in dashboard
assert "市场阶段=risk_off" in dashboard
assert "快照路径" not in dashboard
Expand Down Expand Up @@ -209,6 +215,9 @@ def fake_execute_rebalance(
assert observed["strategy_symbols"] == ("AAA", "BOXX")
assert observed["signal_metadata"]["managed_symbols"] == ("AAA", "BOXX")
assert observed["messages"]
assert "Account Summary" in observed["messages"][0]
assert "Current Positions" in observed["messages"][0]
assert "Execution Summary" in observed["messages"][0]
assert "📏 breadth=60.0%" in observed["messages"][0]
assert "Target Weights" in observed["messages"][0]

Expand Down