版本: v1.0 更新时间: 2026-01-05
┌─────────────────────────────────────────────────────────────────┐
│ 前端展示层 (Frontend) │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ 首页搜索 │ │ 分析页面 │ │ 关于页面 │ │
│ └──────────────┘ └──────────────┘ └──────────────┘ │
│ ↓ ↓ ↓ │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ JavaScript (Vanilla) + Bootstrap 5 │ │
│ │ - 股票搜索与自动补全 │ │
│ │ - Chart.js 图表可视化 │ │
│ │ - 多层参数调节面板 │ │
│ │ - 中英文双语支持 │ │
│ └──────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
↓ HTTP/REST API
┌─────────────────────────────────────────────────────────────────┐
│ API 服务层 (FastAPI) │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ 路由端点 │ │
│ │ GET /api/predict - 预测接口 │ │
│ │ GET /api/analyze - 完整分析接口 │ │
│ │ GET /api/stocks/search - 股票搜索接口 │ │
│ │ POST /api/multi-layer-detect - 多层检测接口 │ │
│ └──────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────────────┐
│ 业务逻辑层 (Core Logic) │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ 数据加载器 │ │地标点检测器 │ │ 序列提取器 │ │
│ │DataLoader │ │LandmarkDetector│ │SequenceExtractor│ │
│ └──────────────┘ └──────────────┘ └──────────────┘ │
│ ↓ ↓ ↓ │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ 多层过滤系统 (Multi-Layer Filter) │ │
│ │ Layer 1: ZigZag 算法 │ │
│ │ Layer 2: 统计确认 (频率+偏离度) │ │
│ │ Layer 3: 趋势强度过滤 │ │
│ │ Layer 4: 时间间隔验证 │ │
│ └──────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────────────┐
│ 数据访问层 (Data Layer) │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ 股票数据库 │ │ 数据获取器 │ │ 缓存管理器 │ │
│ │StockDB │ │Fetcher │ │CacheManager │ │
│ └──────────────┘ └──────────────┘ └──────────────┘ │
│ ↓ ↓ ↓ │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ 数据源 │ │
│ │ - 本地 SQLite 数据库 (历史周线数据) │ │
│ │ - 行情平台 API (实时数据获取 - 待实现) │ │
│ │ - stocks.json (股票基本信息: 代码/名称/拼音) │ │
│ └──────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
用户输入股票代码
↓
前端: 股票搜索自动补全 (本地 stocks.json)
↓
前端: 点击"分析"按钮
↓
API: GET /api/predict?symbol={code}
↓
后端: DataLoader 从本地数据库加载周线数据
↓
后端: LandmarkDetector 执行 ZigZag 算法
↓
后端: MultiLayerDetector 应用4层过滤
↓
后端: SequenceExtractor 提取时间序列
↓
后端: PatternDetector 检测数学规律
↓
后端: 返回预测结果 JSON
↓
前端: 显示预测结果
↓
用户: 点击"查看完整分析"
↓
API: GET /api/analyze?symbol={code}&include_secondary=true
↓
后端: 返回完整地标点 + 图表数据
↓
前端: Chart.js 渲染图表 + 地标点标注
位置: data/weekly/*.csv 或 SQLite 数据库
数据格式:
日期,开盘,最高,最低,收盘,成交量
2020-01-03,45.50,47.80,45.20,47.50,12345678数据来源:
- 当前: 手动从行情软件导出或使用 Tushare/AKShare 等库获取
- 未来计划: 直接对接行情平台 API
数据粒度: 周线 (Weekly OHLCV)
- 周线原因: 平滑日间噪音,减少数据点,使形态点更明显
数据更新:
- 脚本位置:
scripts/update_stock_db.py - 建议频率: 每周收盘后更新一次
位置: data/stocks.json
数据结构:
{
"000001": {
"code": "000001",
"name": "平安银行",
"pinyin": "payh",
"full_pinyin": "pinganyinhang",
"market": "sz",
"industry": "银行"
},
"600519": {
"code": "600519",
"name": "贵州茅台",
"pinyin": "gzmt",
"full_pinyin": "guizhoumaotai",
"market": "sh",
"industry": "白酒"
}
}用途:
- 前端搜索自动补全
- 支持代码、拼音、名称搜索
原理: 基于价格变化百分比识别趋势转折点。当价格变化超过阈值时,认为趋势发生反转。
算法实现 (core/landmark_detector.py):
def detect_landmarks(weekly_prices, threshold=0.10):
"""
参数:
weekly_prices: 周线收盘价序列
threshold: 价格变化阈值 (默认 10%)
返回:
landmarks: [
{
'index': 52, # 周索引
'date': '2021-01-08', # 日期
'type': 'low', # 类型: low/high
'price': 45.20, # 价格
'level': 'primary' # 级别: primary/secondary
}
]
"""当前参数: threshold = 10%
问题:
- ❌ 对震荡市过于敏感,产生大量伪信号
- ❌ 对单边趋势行情,可能会错过重要的趋势中途调整点
Layer 2: 统计确认
# 过滤条件
min_frequency = 2 # 该点在相似价格水平出现次数
min_deviation_pct = 0.20 # 与邻近点价格偏离度目的: 过滤掉偶然的价格波动点
问题:
- ❌ 参数设定过于经验化,缺乏自适应性
- ❌ 对不同行业/市值的股票,应该使用不同参数
Layer 3: 趋势强度过滤
min_trend_strength = 0.50 # 线性回归 R² 值目的: 确保地标点处于明确的趋势中
问题:
- ❌ R² = 0.50 的阈值是否合适?
- ❌ 对不同类型的趋势(单边、震荡、反转)应该分别处理
Layer 4: 时间间隔验证
min_weeks_same_type = 10 # 同类型地标点最小间隔(周)
min_weeks_alternating = 4 # 交替类型地标点最小间隔(周)目的: 避免过于密集的地标点
问题:
- ❌ 时间间隔是硬编码的,无法适应不同周期长度的趋势
当前的地标点检测结果存在以下问题:
-
遗漏重要点位
- 一些明显的重要高点/低点未被标记
- 特别是长期趋势的转折点
-
标记次要点位
- 一些无关紧要的小波动被标记为地标点
- 特别是在震荡整理阶段
-
原因分析
a) ZigZag 算法的局限性
- ZigZag 是基于百分比变化的算法
- 对不同价格区间的敏感度不同
- 例: 10元的股票涨10%是1元,100元的股票涨10%是10元
b) 固定阈值不适应所有股票
- 当前使用固定的10%阈值
- 不同波动性的股票应该使用不同阈值
- 例: 科技股 vs 银行股
c) 缺乏成交量确认
- 当前只基于价格变化
- 重要的转折点通常伴随成交量放大
- 地量可能表明缺乏确认
d) 缺乏多重时间框架分析
- 当前只看周线数据
- 月线级别的重要点位可能被忽略
- 日线级别的精确入场时机被忽略
短期改进 (可快速实施)
-
自适应阈值
# 根据股票历史波动率动态调整阈值 atr = calculate_average_true_range(prices, period=14) threshold = atr / current_price * 2 # 2倍ATR作为阈值
-
成交量过滤
# 要求重要低点伴随放量 if landmark['type'] == 'low': volume_confirm = volume[i] > ma_volume[i-20:i].mean() * 1.5
-
价格区间聚类
# 将相似价格区间的点聚类,识别真正的支撑/阻力位 from sklearn.cluster import DBSCAN price_levels = DBSCAN(eps=price_range*0.02).fit_predict(prices)
中期改进 (需要更多开发)
-
多时间框架分析
- 结合月线、周线、日线
- 月线定方向,周线找点位,日线定时机
-
机器学习方法
- 训练模型识别重要点位
- 特征: 价格变化率、成交量、振幅、时间跨度等
- 标签: 手动标注的历史重要点位
-
形态识别增强
- 识别经典技术形态 (头肩顶/底、双顶/底、三角形等)
- 这些形态的转折点通常更可靠
长期改进 (研究性)
-
市场情绪整合
- 整合舆情数据、新闻情感分析
- 重要点位通常与重大事件相关
-
资金流向分析
- 整合主力资金流向数据
- 重要转折通常伴随资金方向变化
原理: 将地标点日期转换为从IPO开始的周索引
示例:
股票 601933 上市日期: 2017-01-03 (第0周)
重要低点:
2018-01-05 → 第52周
2024-01-05 → 第366周
2026-01-05 → 第680周
当前支持的模式:
-
等差数列 (Arithmetic)
- 例: 52, 366, 680, 994 (间隔314周)
-
等比数列 (Geometric)
- 例: 52, 104, 208, 416 (间隔倍增)
检测方法 (core/pattern_detector.py):
def find_pattern(sequence):
"""
1. 计算序列中所有相邻间隔
2. 统计间隔的频率
3. 找到出现频率最高的间隔
4. 验证是否构成规律
"""问题:
- ❌ 只能识别简单的线性规律
- ❌ 无法识别复杂模式 (如斐波那契数列、周期性波动等)
当前实现:
# 如果发现等差规律,间隔为314周
next_landmark_week = last_landmark_week + 314输出格式:
{
"symbol": "601933",
"name": "人保财险",
"predicted_week": 994,
"predicted_range": "2026-01-01 至 2026-01-31",
"weeks_to_prediction": 314,
"pattern_expression": "52 + 314n (n≥0)",
"pattern_frequency": 3,
"confidence": "HIGH"
}为什么选择原生 JavaScript 而不是 React/Vue?
优势:
- ✅ 轻量级,无构建步骤
- ✅ 易于理解和修改
- ✅ 快速迭代
劣势:
- ❌ 大型应用时代码组织困难
- ❌ 缺乏组件化
结论: 对于当前规模的项目,原生JS + Bootstrap 是合适的选择。
/ - 首页 (搜索 + 预测结果)
/analysis/{symbol} - 分析页面 (图表 + 地标点表格)
/about - 关于页面 (原理说明)
/history - 历史记录页面 (待实现)
使用的库: Chart.js 4.4.0
图表配置:
{
type: 'line',
data: {
labels: ['2020-01-03', '2020-01-10', ...],
datasets: [
{
label: '收盘价',
data: [45.2, 47.5, ...],
borderColor: 'rgba(54, 162, 235, 1)',
fill: true,
tension: 0.1 // 轻微平滑
},
{
label: '低点标记',
data: [null, null, 42.5, null, ...],
pointStyle: 'triangle',
pointRadius: 10,
showLine: false
},
{
label: '高点标记',
data: [null, 48.5, null, ...],
pointStyle: 'triangle',
rotation: 180,
showLine: false
}
]
}
}问题:
- ❌ 图表加载大量数据点时性能较差
- ✅ 解决方案: 数据采样或分页
-
数据加载: 每次请求都从磁盘读取CSV
- 优化: 使用数据库 + 缓存
-
ZigZag 计算: O(n) 复杂度,但 n 可能很大
- 优化: 预计算并缓存结果
-
图表渲染: 500+ 数据点时卡顿
- 优化: 数据采样、懒加载
当前实现:
# 简单的内存缓存
@lru_cache(maxsize=128)
def load_stock_data(symbol: str):
...改进方向:
- Redis 缓存层
- 数据库查询结果缓存
- 静态资源 CDN 加速
cd web
uvicorn app:app --host 0.0.0.0 --port 8000 --reload推荐方案:
-
应用服务器: Gunicorn + Uvicorn
gunicorn web.app:app -w 4 -k uvicorn.workers.UvicornWorker --bind 0.0.0.0:8000
-
反向代理: Nginx
- 静态文件服务
- SSL/TLS 终止
- 请求限流
-
容器化: Docker
FROM python:3.10-slim WORKDIR /app COPY requirements.txt . RUN pip install -r requirements.txt COPY . . CMD ["uvicorn", "web.app:app", "--host", "0.0.0.0", "--port", "8000"]
待补充:
# tests/test_landmark_detector.py
def test_zigzag_detection():
prices = [100, 105, 110, 115, 110, 105, 100]
landmarks = detect_landmarks(prices, threshold=0.05)
assert landmarks[0]['type'] == 'low'
assert landmarks[1]['type'] == 'high'待补充:
# tests/test_api.py
def test_predict_endpoint():
response = client.get("/api/predict?symbol=600519")
assert response.status_code == 200
assert 'predicted_week' in response.json()待实现:
- 使用历史数据验证预测准确性
- 计算准确率、召回率等指标
- 实现自适应阈值
- 添加成交量确认
- 价格区间聚类
- 多时间框架分析
- 支持复杂模式 (斐波那契、周期性)
- 机器学习模型训练
- 经典技术形态识别
- 对接实时行情API
- 自动数据更新脚本
- 数据质量检查
- 移动端适配
- 图表交互优化
- 预测结果导出
- Docker 容器化
- CI/CD 流水线
- 监控告警系统
| 参数 | 初始值 | 当前值 | 调优日期 | 原因 |
|---|---|---|---|---|
| layer1_threshold | 5% | 10% | 2026-01-05 | 减少伪信号 |
| layer2_min_freq | 1 | 2 | 2026-01-05 | 过滤偶然点 |
| layer2_min_dev | 10% | 20% | 2026-01-05 | 提高确认度 |
| layer3_trend_str | 0.30 | 0.50 | 2026-01-05 | 需要明确趋势 |
| layer4_same_type | 6周 | 10周 | 2026-01-05 | 避免过密 |
| layer4_alternating | 2周 | 4周 | 2026-01-05 | 避免过密 |
| 代码 | 名称 | 行业 | 特点 |
|---|---|---|---|
| 600519 | 贵州茅台 | 白酒 | 长期趋势明显 |
| 000001 | 平安银行 | 银行 | 波动较小 |
| 300364 | 中文在线 | 传媒 | 波动较大 |
| 601933 | 人保财险 | 保险 | 周期性明显 |
| 000858 | 五粮液 | 白酒 | 与茅台对比 |
算法参考:
- ZigZag 算法原理: https://www.investopedia.com/terms/z/zigzagindicator.asp
- 时间序列分析: https://otexts.com/fppcn/
技术文档:
- FastAPI 官方文档: https://fastapi.tiangolo.com/zh/
- Chart.js 文档: https://www.chartjs.org/docs/latest/
市场研究:
- A股市场特征研究
- 技术分析有效性探讨
文档维护: 本文档应随着系统演进持续更新
最后更新: 2026-01-05 维护者: 系统开发团队