这个项目是一个基金自动化分析与邮件报告系统。
一、项目需求文档
1. 业务背景
用户持有多只基金,需要每日自动获取最新净值、判断当前是否处于卖出信号区间(波峰回调)、生成可视化报告并通过邮件发送,以便快速做出交易决策。
2. 功能需求
| 模块 | 需求描述 |
|---|
| 净值更新 | 从 efinance 接口获取指定基金的最新净值,更新到本地 CSV 文件中,避免重复记录同一日期 |
| 波峰波谷识别 | 基于移动平均 + 显著性检测,识别基金净值的波峰(peak)和波谷(trough),支持按基金独立设置参数(涨幅阈值、跌幅阈值、窗口大小等) |
| 交易信号判断 | 判断最近一个完整波段:波谷 → 波峰涨幅 ≥ 阈值,且当前净值从波峰回调 ≥ 阈值,触发“卖出信号” |
| 百分位计算 | 计算当前净值在历史中的百分位(历史最高=100%,最低=0%) |
| HTML报告生成 | 生成手机友好的 HTML 报告,包含:基金基本信息、历史百分位、最新净值、波谷→波峰涨幅、波峰→当前回调、极值点序列 |
| 邮件自动发送 | 将 HTML 报告作为邮件正文发送给指定收件人 |
| 定时调度 | 每日自动执行:更新净值 → 等待15秒 → 生成报告并发送邮件,日志自动轮转保留最近7天 |
3. 非功能需求
| 类型 | 要求 |
|---|
| 可配置性 | 每只基金可独立设置分析参数(涨幅/跌幅阈值、窗口等) |
| 可扩展性 | 新增基金只需在配置中添加代码和参数 |
| 容错性 | 单只基金失败不影响其他基金分析 |
| 可观测性 | 所有操作记录日志,支持文件轮转 |
| 自动化 | 支持通过 scheduls_sample.py 或 cron 定时触发 |
4. 基金清单(示例)
| 基金代码 | 名称 | 涨幅阈值 | 跌幅阈值 |
|---|
| 011840 | 人工智能 | 10% | 4% |
| 013180 | 新能源电池 | 5% | 4% |
| 015599 | 国证航天军工 | 10% | 4% |
二、系统架构设计
1. 整体架构图
┌─────────────────────────────────────────────────────────────┐
│ 定时触发层 │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ scheduls_sample.py / cron │ │
│ └─────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ 执行流程层 │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ up_fund.py │ → │ 等待15秒 │ → │ send_email.py │ │
│ │ 更新净值 │ │ 数据落盘 │ │ 分析+发邮件 │ │
│ └──────────────┘ └──────────────┘ └──────────────┘ │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ 核心业务层 │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ BatchFundAnalyzer │ │
│ │ - 批量循环分析 │ │
│ │ - 交易信号判断 │ │
│ │ - HTML报告生成 │ │
│ └─────────────────────────────────────────────────────┘ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ MovingAveragePeakTroughFinder │ │
│ │ - 平滑曲线 │ │
│ │ - 候选极值点检测(scipy.signal.find_peaks) │ │
│ │ - 真实极值点精确定位 │ │
│ │ - 涨幅/跌幅双向过滤 │ │
│ └─────────────────────────────────────────────────────┘ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ PercentileAnalyzer │ │
│ │ - 历史百分位计算 │ │
│ └─────────────────────────────────────────────────────┘ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ FundParameterConfig │ │
│ │ - 基金参数配置管理 │ │
│ └─────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ 数据层 │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ 011840.csv │ │ 013180.csv │ │ 015599.csv │ │
│ │ (净值历史) │ │ (净值历史) │ │ (净值历史) │ │
│ └──────────────┘ └──────────────┘ └──────────────┘ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ logs/scheduler.log (日志,自动轮转) │ │
│ └─────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ 输出层 │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ 邮件(HTML正文) → 收件人邮箱 │ │
│ └─────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
2. 模块职责划分
| 模块文件 | 职责 |
|---|
up_fund.py | 从 efinance 拉取最新净值,更新本地 CSV |
model.py | 核心算法:波峰波谷识别、信号生成、统计计算 |
size.py | 基金参数配置(每只基金的阈值、窗口、描述) |
fund_analysis.py | 批量分析调度、交易信号判断、HTML 报告生成 |
percentile_simple.py | 历史百分位计算 |
send_email.py | 调用分析模块,发送 HTML 邮件 |
scheduls_sample.py | 定时调度(先更新、后发送),日志轮转 |
.env | 邮件服务器配置(发件人、密码、收件人) |
3. 核心算法流程(波峰波谷识别)
原始净值序列
│
▼
移动平均平滑(ma_window)
│
▼
在平滑曲线上用 find_peaks 找候选波峰/波谷
(参数:prominence_pct, min_distance)
│
▼
在原始数据上,以候选点为中心 ±search_window 找真实极值
│
▼
涨幅/跌幅过滤:
- 波谷→波峰涨幅 >= min_rise_pct
- 波峰→波谷跌幅 >= min_fall_pct
│
▼
输出交替出现的波谷/波峰序列
4. 数据流图
efinance API
│
▼ (最新净值)
[011840.csv] ──┐
[013180.csv] ──┼──► BatchFundAnalyzer ──► extremums + 信号
[015599.csv] ──┘ │
│
▼
generate_html_report()
│
▼
HTML 字符串 ──► 邮件发送
5. 配置示例(.env)
EMAIL_SERVER=smtp.qq.com
EMAIL_PORT=465
EMAIL_ADDR=your_email@qq.com
EMAIL_PWD=your_authorization_code
SEND_EMAIL=target_email@example.com
6. 扩展性设计
- 新增基金:在
size.py 的 FUND_TYPE_TEMPLATES 中添加代码和参数
- 调整阈值:修改对应基金的
min_rise_pct / min_fall_pct
- 更换数据源:只需修改
up_fund.py 中的获取逻辑
- 增加报告维度:在
generate_html_report() 中添加更多指标