auto-sync: 2026-04-30 23:09:14
This commit is contained in:
@@ -0,0 +1,77 @@
|
||||
"""
|
||||
BacktestReport - 标准化回测报告
|
||||
|
||||
将 BacktestResult 格式化输出为文本/JSON。
|
||||
"""
|
||||
|
||||
import json
|
||||
from typing import Optional
|
||||
|
||||
from data_platform.backtest_runner import BacktestResult
|
||||
|
||||
|
||||
class BacktestReport:
|
||||
"""回测报告生成器"""
|
||||
|
||||
def __init__(self, result: BacktestResult):
|
||||
self.result = result
|
||||
|
||||
def to_text(self) -> str:
|
||||
"""生成文本格式报告"""
|
||||
r = self.result
|
||||
lines = [
|
||||
"=" * 60,
|
||||
f" 回测报告 | {r.strategy_name} | {r.code}",
|
||||
"=" * 60,
|
||||
f" 回测区间: {r.start_date.date()} ~ {r.end_date.date()}",
|
||||
f" 初始资金: {r.initial_capital:,.0f}",
|
||||
f" 最终权益: {r.final_capital:,.0f}",
|
||||
"-" * 60,
|
||||
f" 总收益率: {r.total_return:>8.2%}",
|
||||
f" 年化收益率: {r.annual_return:>8.2%}",
|
||||
f" 最大回撤: {r.max_drawdown:>8.2%}",
|
||||
f" 夏普比率: {r.sharpe_ratio:>8.2f}",
|
||||
f" 胜率: {r.win_rate:>8.2%}",
|
||||
f" 交易次数: {r.total_trades:>8d}",
|
||||
"-" * 60,
|
||||
]
|
||||
|
||||
# 交易明细(最多显示20条)
|
||||
if r.trades:
|
||||
lines.append(f" {'买入日':>12s} {'卖出日':>12s} {'买入价':>8s} "
|
||||
f"{'卖出价':>8s} {'收益率':>8s} {'股数':>6s}")
|
||||
lines.append(" " + "-" * 68)
|
||||
for t in r.trades[:20]:
|
||||
profit_str = f"{t.profit_pct:7.2%}" if t.profit_pct is not None else " N/A"
|
||||
lines.append(
|
||||
f" {t.entry_date.date()!s:>12s} {t.exit_date.date()!s:>12s} "
|
||||
f"{t.entry_price:>8.2f} {t.exit_price:>8.2f} "
|
||||
f"{profit_str} {t.shares:>6d}"
|
||||
)
|
||||
if len(r.trades) > 20:
|
||||
lines.append(f" ... 共 {len(r.trades)} 条,仅显示前20条")
|
||||
|
||||
lines.append("=" * 60)
|
||||
return "\n".join(lines)
|
||||
|
||||
def to_dict(self) -> dict:
|
||||
"""导出为字典"""
|
||||
r = self.result
|
||||
return {
|
||||
"strategy": r.strategy_name,
|
||||
"code": r.code,
|
||||
"start_date": str(r.start_date.date()),
|
||||
"end_date": str(r.end_date.date()),
|
||||
"initial_capital": r.initial_capital,
|
||||
"final_capital": round(r.final_capital, 2),
|
||||
"total_return": round(r.total_return, 4),
|
||||
"annual_return": round(r.annual_return, 4),
|
||||
"max_drawdown": round(r.max_drawdown, 4),
|
||||
"sharpe_ratio": round(r.sharpe_ratio, 2),
|
||||
"win_rate": round(r.win_rate, 4),
|
||||
"total_trades": r.total_trades,
|
||||
}
|
||||
|
||||
def to_json(self, indent: int = 2) -> str:
|
||||
"""导出为JSON"""
|
||||
return json.dumps(self.to_dict(), indent=indent, ensure_ascii=False)
|
||||
Reference in New Issue
Block a user