diff --git a/app/db/paper_trading.py b/app/db/paper_trading.py index 1630974..1463bc0 100644 --- a/app/db/paper_trading.py +++ b/app/db/paper_trading.py @@ -1171,6 +1171,12 @@ def _periodized_return_pct(total_return_pct: float, running_days: float, period_ return round((growth ** (period_days / running_days) - 1) * 100, 4) +def _periodized_return_label(total_return_pct: float, running_days: float, period_days: float) -> str: + if running_days < 30: + return "样本不足" + return _fmt_pct(_periodized_return_pct(total_return_pct, running_days, period_days)) + + def send_paper_trading_report(days: int = 30) -> dict: days = max(1, min(_safe_int(days, 30), 365)) summary = get_paper_trading_summary(days=days) @@ -1186,8 +1192,10 @@ def send_paper_trading_report(days: int = 30) -> dict: return_pct = _safe_float(summary.get("account_total_return_pct")) win_rate = _safe_float(summary.get("win_rate")) running_days = _paper_running_days() - monthly_return_pct = _periodized_return_pct(return_pct, running_days, 30) - annualized_return_pct = _periodized_return_pct(return_pct, running_days, 365) + monthly_return_pct = _periodized_return_pct(return_pct, running_days, 30) if running_days >= 30 else None + annualized_return_pct = _periodized_return_pct(return_pct, running_days, 365) if running_days >= 30 else None + monthly_return_label = _periodized_return_label(return_pct, running_days, 30) + annualized_return_label = _periodized_return_label(return_pct, running_days, 365) template = "green" if total_pnl >= 0 else "red" elements = [ { @@ -1206,8 +1214,8 @@ def send_paper_trading_report(days: int = 30) -> dict: "background_style": "default", "columns": [ {"tag": "column", "width": "weighted", "weight": 1, "elements": [_card_field("账户收益率", _fmt_pct(return_pct))]}, - {"tag": "column", "width": "weighted", "weight": 1, "elements": [_card_field("月化收益率", _fmt_pct(monthly_return_pct))]}, - {"tag": "column", "width": "weighted", "weight": 1, "elements": [_card_field("年化收益率", _fmt_pct(annualized_return_pct))]}, + {"tag": "column", "width": "weighted", "weight": 1, "elements": [_card_field("月化收益率", monthly_return_label)]}, + {"tag": "column", "width": "weighted", "weight": 1, "elements": [_card_field("年化收益率", annualized_return_label)]}, ], }, { @@ -1250,6 +1258,8 @@ def send_paper_trading_report(days: int = 30) -> dict: "running_days": running_days, "monthly_return_pct": monthly_return_pct, "annualized_return_pct": annualized_return_pct, + "monthly_return_label": monthly_return_label, + "annualized_return_label": annualized_return_label, "summary": summary, "sent_at": _now(), "push_result": push_result, diff --git a/tests/test_paper_trading.py b/tests/test_paper_trading.py index e14f257..67374c9 100644 --- a/tests/test_paper_trading.py +++ b/tests/test_paper_trading.py @@ -428,8 +428,10 @@ def test_send_paper_trading_report_pushes_performance_summary(monkeypatch, buy_n assert result["ok"] is True assert result["running_days"] >= 1 - assert "monthly_return_pct" in result - assert "annualized_return_pct" in result + assert result["monthly_return_pct"] is None + assert result["annualized_return_pct"] is None + assert result["monthly_return_label"] == "样本不足" + assert result["annualized_return_label"] == "样本不足" assert pushed[-1]["metadata"]["event_type"] == "trade_report" text = _visible_card_text(pushed[-1]) assert "交易报告" in text