Files
amlhc/.planning/phases/11-predictv3/11-03-PLAN.md
T
916117771 8b2590c5b5 docs(predictV3): 添加predictV3算法优化研究文档和前端功能实现
- 完成Phase 11: predictV3算法优化研究文档,涵盖6个优化方向的技术分析
- 实现置信度评估功能,提供历史命中率、得分分布、多维度一致性置信度指标
- 扩展回测指标体系,新增NDCG@K、MRR、命中率分布等排名质量评估指标
- 优化转移概率算法,引入二阶马尔可夫链和多属性联合转移增强预测准确性
- 设计权重训练机制,支持网格搜索和遗传算法进行数据驱动的参数优化
- 集成组合特征挖掘功能,采用关联规则和序列模式发现号码间潜在关联
- 实现完整的前端交互界面,支持预测结果显示、置信度展示和回测验证功能
- 建立性能优化策略,包括预计算缓存、批量计算和降级策略保障响应速度
2026-05-01 23:17:24 +08:00

278 lines
13 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
phase: 11-predictv3
plan: 03
type: execute
wave: 2
depends_on:
- 11-01
- 11-02
files_modified:
- public/assets/js/backend/history.js
autonomous: true
requirements:
- PRED-01
- PRED-02
must_haves:
truths:
- "用户可以在预测弹窗中看到每个号码的置信度百分比"
- "用户可以在回测结果区域看到 NDCG@5 和 MRR 指标"
- "用户可以看到各排名位置的命中分布柱状图"
- "用户可以看到数据不足时的警告提示"
artifacts:
- path: "public/assets/js/backend/history.js"
provides: "置信度和新回测指标前端展示"
contains: "renderPredict|confidence|ndcg_5|mrr|hit_distribution|data_warning"
key_links:
- from: "renderPredict"
to: "backtest.ndcg_5, backtest.mrr, confidence, backtest.data_warning"
via: "property access in rendering logic"
---
# Phase 11 - Plan 03: 前端展示优化
## Objective
更新前端 `renderPredict` 方法,展示新增的置信度指标和扩展的回测指标(NDCG、MRR、命中分布、数据警告)。
**Purpose:** 后端已计算置信度和新回测指标,前端需要将这些数据可视化呈现给用户,提升预测结果的可读性和决策辅助价值。
**Output:** `history.js` 中的 `renderPredict` 方法扩展,新增置信度展示区域和回测指标扩展展示。
## Tasks
### Task 1: 添加置信度展示区域(含数据警告提示)
<read_first>
- D:\code\php\amlhc\public\assets\js\backend\history.js (line 1700-1871, renderPredict 方法)
</read_first>
<action>
`renderPredict` 方法中,找到以下变量声明位置(约 line 1701):
```javascript
var predictions = data.predictions || [];
var analysis = data.analysis || {};
var hitInfo = data.hit_info || null;
var actualResult = data.actual_result || null;
var backtest = data.backtest || null;
```
`backtest` 声明后添加 `confidence` 变量:
```javascript
var confidence = data.confidence || null;
```
然后在回测验证结果展示区域(约 line 1732-1751)之前,插入置信度展示区域:
在 line 1732 之前(即 `// 回测验证结果` 注释之前)插入:
```javascript
// 置信度评估展示(V2和V3版本)
if (confidence && (version === 'v2' || version === 'v3')) {
html += '<div style="background:#fff8e1;border:1px solid #ffb300;border-radius:6px;padding:12px;margin-bottom:15px;">';
html += '<div style="font-size:13px;font-weight:bold;color:#ff8f00;margin-bottom:8px;"><i class="fa fa-star-half-o"></i> 预测置信度评估</div>';
// 数据警告提示(数据不足时显示)
if (confidence.data_warning) {
html += '<div style="font-size:11px;color:#d32f2f;background:#ffebee;padding:6px;border-radius:4px;margin-bottom:8px;"><i class="fa fa-exclamation-triangle"></i> ' + confidence.data_warning + '</div>';
}
html += '<div style="display:flex;gap:20px;align-items:center;">';
html += '<div style="text-align:center;"><div style="font-size:24px;font-weight:bold;color:#ff8f00;">' + confidence.overall_confidence + '%</div><div style="font-size:12px;color:#666;">整体置信度</div></div>';
// 各排名置信度(使用得分集中度维度)
if (confidence.confidence_scores && confidence.confidence_scores.length > 0) {
html += '<div style="display:flex;gap:8px;">';
for (var i = 0; i < confidence.confidence_scores.length; i++) {
var cs = confidence.confidence_scores[i];
// 阈值定义:>=70%高(绿)、50-70%中(橙)、<50%低(红)
var confLevel = cs.confidence >= 70 ? '高' : (cs.confidence >= 50 ? '中' : '低');
var confColor = cs.confidence >= 70 ? '#4caf50' : (cs.confidence >= 50 ? '#ff9800' : '#f44336');
html += '<div style="text-align:center;padding:5px;background:#fff;border-radius:4px;">';
html += '<div style="font-size:14px;font-weight:bold;color:' + confColor + ';">' + cs.confidence + '%</div>';
html += '<div style="font-size:10px;color:#999;">#' + cs.rank + '</div>';
html += '</div>';
}
html += '</div>';
}
html += '</div></div>';
}
```
实现要点:
- 整体置信度以大数字展示,各排名置信度以小卡片形式横向排列
- 置信度分三级:高(>=70%, 绿色)、中(50-70%, 橙色)、低(<50%, 红色)
- 只在 V2 和 V3 版本中显示
- 新增 data_warning 展示:数据不足时显示红色警告提示
</action>
<acceptance_criteria>
- grep 匹配: `confidence.overall_confidence` 在 history.js renderPredict 方法中存在
- grep 匹配: `confidence.confidence_scores` 在 history.js renderPredict 方法中存在
- grep 匹配: `confidence.data_warning` 在 history.js renderPredict 方法中存在
- grep 匹配: `confLevel``confColor` 变量在 history.js 中存在
- 置信度展示区域在回测验证结果之前显示
</acceptance_criteria>
### Task 2: 扩展回测指标展示区域(含数据警告和命中分布柱状图)
<read_first>
- D:\code\php\amlhc\public\assets\js\backend\history.js (line 1732-1751, 回测验证结果展示区域)
</read_first>
<action>
`renderPredict` 方法中,找到回测验证结果展示区域(约 line 1732-1751),现有代码展示命中率、命中次数、平均排名三个指标。
找到以下代码段:
```javascript
html += '<div style="display:flex;gap:20px;">';
html += '<div style="text-align:center;"><div style="font-size:24px;font-weight:bold;color:#2196f3;">' + backtest.hit_rate + '%</div><div style="font-size:12px;color:#666;">命中率(Top5</div></div>';
html += '<div style="text-align:center;"><div style="font-size:24px;font-weight:bold;color:#4caf50;">' + backtest.total_hits + '/' + backtest.total_tests + '</div><div style="font-size:12px;color:#666;">命中次数</div></div>';
html += '<div style="text-align:center;"><div style="font-size:24px;font-weight:bold;color:#ff9800;">' + (backtest.avg_rank || '—') + '</div><div style="font-size:12px;color:#666;">平均排名</div></div>';
html += '</div>';
```
替换为:
```javascript
// 回测数据警告提示
if (backtest.data_warning) {
html += '<div style="font-size:11px;color:#d32f2f;background:#ffebee;padding:6px;border-radius:4px;margin-bottom:8px;"><i class="fa fa-exclamation-triangle"></i> ' + backtest.data_warning + '</div>';
}
html += '<div style="display:flex;gap:15px;flex-wrap:wrap;">';
html += '<div style="text-align:center;padding:8px;"><div style="font-size:22px;font-weight:bold;color:#2196f3;">' + backtest.hit_rate + '%</div><div style="font-size:11px;color:#666;">命中率(Top5</div></div>';
html += '<div style="text-align:center;padding:8px;"><div style="font-size:22px;font-weight:bold;color:#4caf50;">' + backtest.total_hits + '/' + backtest.total_tests + '</div><div style="font-size:11px;color:#666;">命中次数</div></div>';
html += '<div style="text-align:center;padding:8px;"><div style="font-size:22px;font-weight:bold;color:#ff9800;">' + (backtest.avg_rank || '—') + '</div><div style="font-size:11px;color:#666;">平均排名</div></div>';
// 新增指标:NDCG@5 和 MRR(百分比展示)
if (backtest.ndcg_5 !== undefined) {
html += '<div style="text-align:center;padding:8px;"><div style="font-size:22px;font-weight:bold;color:#9c27b0;">' + (backtest.ndcg_5 * 100).toFixed(1) + '%</div><div style="font-size:11px;color:#666;">NDCG@5</div></div>';
}
if (backtest.mrr !== undefined) {
html += '<div style="font-size:22px;font-weight:bold;color:#00bcd4;">' + (backtest.mrr * 100).toFixed(1) + '%</div><div style="font-size:11px;color:#666;">MRR</div></div>';
}
// 转移概率阶数显示(来自11-05的transition_order字段)
if (analysis && analysis.transition_order !== undefined) {
html += '<div style="text-align:center;padding:8px;"><div style="font-size:22px;font-weight:bold;color:#607d8b;">' + analysis.transition_order + '阶</div><div style="font-size:11px;color:#666;">转移概率</div></div>';
}
html += '</div>';
// 命中分布柱状图(使用rank_1..rank_5键名)
if (backtest.hit_distribution && Object.keys(backtest.hit_distribution).length > 0) {
var distribution = backtest.hit_distribution;
var maxHit = 0;
// 找最大值用于计算柱状图高度比例
for (var r = 1; r <= 5; r++) {
var key = 'rank_' + r;
if (distribution[key] > maxHit) {
maxHit = distribution[key];
}
}
html += '<div style="margin-top:10px;font-size:11px;color:#666;">命中分布(各排名命中次数):</div>';
html += '<div style="display:flex;gap:8px;align-items:flex-end;height:60px;margin-top:5px;padding:5px;background:#f5f5f5;border-radius:4px;">';
for (var r = 1; r <= 5; r++) {
var key = 'rank_' + r;
var hitCount = distribution[key] || 0;
var barHeight = maxHit > 0 ? (hitCount / maxHit * 45) : 0;
var barColor = hitCount > 0 ? '#4caf50' : '#e0e0e0';
html += '<div style="text-align:center;min-width:50px;">';
html += '<div style="height:' + barHeight + 'px;background:' + barColor + ';border-radius:2px 2px 0 0;width:35px;margin:0 auto;"></div>';
html += '<div style="font-size:10px;color:#666;margin-top:2px;">#' + r + '</div>';
html += '<div style="font-size:11px;color:#333;font-weight:bold;">' + hitCount + '</div>';
html += '</div>';
}
html += '</div>';
}
```
实现要点:
- NDCG@5 和 MRR 以百分比形式展示(乘100后保留1位小数)
- 命中分布以简单柱状图展示,排名1-5横向排列
- 柱状图高度按最大命中次数比例计算
- 使用 rank_1..rank_5 键名格式解析分布数据
- 新增 data_warning 展示:回测数据不足时显示警告
- 转移概率阶数从 analysis.transition_order 获取(而非 backtest
</action>
<acceptance_criteria>
- grep 匹配: `backtest.ndcg_5` 在 history.js renderPredict 方法中存在
- grep 匹配: `backtest.mrr` 在 history.js renderPredict 方法中存在
- grep 匹配: `backtest.hit_distribution` 在 history.js renderPredict 方法中存在
- grep 匹配: `backtest.data_warning` 在 history.js renderPredict 方法中存在
- grep 匹配: `rank_1|rank_2|rank_3|rank_4|rank_5` 在命中分布解析中存在
- grep 匹配: `analysis.transition_order` 在 history.js renderPredict 方法中存在
- 命中分布柱状图使用 div 元素实现
</acceptance_criteria>
### Task 3: 在预测号码卡片中显示置信度(含得分集中度展示)
<read_first>
- D:\code\php\amlhc\public\assets\js\backend\history.js (line 1828-1866, 预测号码列表渲染)
</read_first>
<action>
在预测号码列表渲染区域(约 line 1828-1866),找到号码卡片渲染代码:
在现有得分显示后添加置信度显示。找到以下代码段:
```javascript
html += '<div style="font-size:11px;color:#2e7d32;font-weight:bold;">得分:' + p.score + '</div>';
```
替换为:
```javascript
html += '<div style="font-size:11px;color:#2e7d32;font-weight:bold;">得分:' + p.score + '</div>';
// 显示置信度(V3版本)
if (version === 'v3' && confidence && confidence.confidence_scores) {
var csForNum = confidence.confidence_scores.find(function(c) { return c.num === p.num; });
if (csForNum) {
// 阈值定义:>=70%高(绿)、50-70%中(橙)、<50%低(红)
var confLevel = csForNum.confidence >= 70 ? '高' : (csForNum.confidence >= 50 ? '中' : '低');
var confColor = csForNum.confidence >= 70 ? '#4caf50' : (csForNum.confidence >= 50 ? '#ff9800' : '#f44336');
html += '<div style="font-size:10px;"><span style="color:' + confColor + ';font-weight:bold;">置信度:' + confLevel + '</span> <span style="color:#666;">(' + csForNum.confidence + '%)</span></div>';
}
}
```
实现要点:
- 在号码卡片中显示置信度等级(高/中/低)和具体百分比
- 使用与整体置信度展示相同的颜色映射阈值
- 只在 V3 版本中显示
- 置信度字段使用 score_concentration(得分集中度)维度
</action>
<acceptance_criteria>
- grep 匹配: `csForNum` 变量在 history.js 中存在
- grep 匹配: `置信度:` 在号码卡片渲染代码中存在
- 置信度显示在得分下方
- grep 匹配: `csForNum.confidence` 在号码卡片渲染中存在
</acceptance_criteria>
## Verification
1. 打开 history 页面,点击"智能预测"按钮
2. 使用 V3 版本执行预测,验证:
- 置信度评估区域是否显示
- 数据不足时是否显示警告提示
- 回测结果中是否显示 NDCG@5、MRR、命中分布柱状图
- 预测号码卡片中是否显示置信度等级和百分比
## Success Criteria
1. `renderPredict` 方法已更新,新增置信度展示区域
2. 回测结果展示区域已扩展,包含 NDCG@5、MRR、命中分布、数据警告
3. 预测号码卡片显示置信度等级和百分比
4. 命中分布使用 rank_1..rank_5 键名格式解析
5. 所有新增展示样式与原有 UI 风格一致
6. 数据警告以红色背景突出显示
## Output
完成后创建 `.planning/phases/11-predictv3/11-03-SUMMARY.md`