用户想要对比多只基金的历史回报,从多个时间维度分析谁更优。
输入
用户会提供若干基金代码(如 160615 005788 217027),通过 $ARGUMENTS 传入。
步骤
1. 获取基金基本信息
对每只基金,用 WebFetch 抓取概况页确认成立日期:
https://fundf10.eastmoney.com/jbgk_{基金代码}.html
确定可比较的年份范围(取所有基金都有完整年度数据的交集)。
2. 获取历史净值
用 WebFetch 获取每年最后一个交易日的累计净值。对每个需要的年份:
https://fundf10.eastmoney.com/F10DataApi.aspx?type=lsjz&code={基金代码}&sdate={YYYY}-12-25&edate={YYYY}-12-31&per=10
返回格式是 JS 变量包裹 HTML 表格。提取最后一个交易日的 累计净值(不是单位净值,累计净值已包含分红再投资)。
也需要获取前一年12月底的净值作为基准,以计算年度回报。
注意:
- 一定要用 累计净值(第三列),而非单位净值(第二列),否则有分红的基金回报会被低估
- 如果某年年底没有数据,往前找最近的交易日
3. 计算年度回报
年度回报 = (当年末累计净值 / 上年末累计净值 - 1) × 100%
4. 多维度对比分析
用 Python 脚本生成完整对比报告,包含以下维度:
a. 逐年回报
每年的回报率并排对比,标注每年谁最优。统计各基金获胜年数。
b. 滚动2年累计回报
从每个起始年开始的连续2年复合收益。
c. 滚动3年累计回报
从每个起始年开始的连续3年复合收益。
重要:用户明确要求不要只看"最近X年"的回报(因为一个好年份会使最近几年都好看),而是要看每个独立的时间窗口。
d. 全区间汇总
可比年份的累计回报和年化回报排名。
e. 熊市抗跌能力
找出下跌年份(多数基金亏损的年份),对比各基金的跌幅。统计2-3年连续熊市的累计表现。
f. 风险收益特征
- 年均回报
- 波动率(年度回报的标准差)
- 最差年 / 最好年
- 亏损年数
- 收益/波动比(简化版夏普比率)
5. 输出 — 可视化图表 + 文字结论
必须用 matplotlib 生成图表,不要输出纯文本表格。图表保存到工作目录下,然后用 Read 工具展示给用户。
绘图环境设置
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt
import numpy as np
# 中文字体(macOS)
plt.rcParams['font.sans-serif'] = ['PingFang HK', 'STHeiti', 'Heiti TC', 'SimHei']
plt.rcParams['axes.unicode_minus'] = False
需要生成的图表
图1:累计净值走势(归一化) fund_compare_cumulative.png
- 将所有基金以可比起始年末净值为基准归一化到1.0
- 折线图,每只基金一条线,不同颜色
- 清晰的图例、网格线
- 尺寸
figsize=(12, 6)
图2:逐年回报对比 fund_compare_annual.png
- 分组柱状图,X轴为年份,每只基金一组柱子
- 在每个年份标注最优者(如加★)
- 零线用虚线标出
- 底部附注获胜年数统计
图3:滚动3年累计回报 fund_compare_rolling3y.png
- 分组柱状图,X轴为滚动窗口区间
- 标注每个窗口的最优者
图4:风险收益散点图 fund_compare_risk_return.png
- X轴:波动率(标准差),Y轴:年化回报
- 每只基金一个点,标注名称
- 右上方为最优区域(高收益低波动)
- 可选:画出等夏普比率线
图5:熊市抗跌对比 fund_compare_bear.png
- 仅含下跌年份的分组柱状图
- 柱子向下延伸(负值),越短越抗跌
- 如果有连续熊市(如2021-2023),额外标注累计跌幅
图表风格要求
- 配色方案:使用
tab10或类似的高对比度色板,保证多只基金时颜色可区分 - 所有图表加标题、坐标轴标签
- 百分比数值格式化为
+X.X%或-X.X% - 柱状图上方/下方标注具体数值(字体小一号)
- DPI 设为 150,确保清晰度
- 图表保存后,用
Read工具将图片展示给用户
文字输出
图表之外,仍需输出简洁的文字结论(不超过10行),包括:
- 综合排名
- 最适合3-5年投资的推荐
- 关键风险提示
不要再输出大段纯文本表格,所有数据对比都通过图表呈现。
复合收益率计算
def compound(rates):
r = 1.0
for x in rates:
r *= (1 + x / 100)
return (r - 1) * 100
注意事项
- 如果基金成立时间不同,明确说明可比年份范围的限制
- 对于可比年份少于5年的对比,提醒用户数据区间较短,结论可能不够稳健
- ETF联接基金会因为现金拖累略微跑输母ETF,如需更长历史可考虑用母ETF数据补充