feat: 新增外部因素分析模块+综合评分引擎+算法文档重构

新增模块:
- fund_flow_analyzer.py: 主力资金流向分析(P0, ±20)
- market_sentiment.py: 市场情绪指标(P1, ±10)
- external_factors.py: 北向资金/美股/大宗商品/汇率(P2-P4,P7)
- news_analyzer.py: 公告/并购/政策面LLM分析(P5-P6)
- score_engine.py: 综合评分引擎,整合技术面+外部因素

路由更新:
- analysis.py: deep_analyze接入综合评分,根据最终评级修正买卖建议
- market.py: 新增4个外部因素API端点
- trades.py: 交易路由更新

算法文档重构:
- 章节重排: 技术面(二三)→外部因素(四)→买卖决策(五)→数据源(六)→性能(七)
- 架构图更新为五层,标注章节对应
- 5.1/5.2标注纯技术面,5.3整合外部因素修正推荐
This commit is contained in:
selfrelease
2026-07-17 23:50:42 +08:00
parent 04f8b9f951
commit 2b5a32ca1e
23 changed files with 4191 additions and 268 deletions
+87 -4
View File
@@ -92,10 +92,24 @@
scanSummaryCollapsed: false,
fullScanSignalDist: [],
// 找牛股
bullStocksData: null, // { stages: {1:[...], 2:[...]}, summary: {}, stage_info: [...] }
// 找牛股(保留兼容)
bullStocksData: null,
bullStocksLoading: false,
bullActiveStage: 2, // 默认显示阶段2=龙抬头(最佳买点)
bullActiveStage: 2,
// 个股深析
deepCode: '',
deepReport: null,
deepLoading: false,
// 模型页子tab
modelSubTab: 'system',
// 买入分析
buyAnalysisList: [],
buyAnalysisLoading: false,
buyAnalysisProgress: 0,
buyAnalysisTotal: 0,
// 交易记录页面
trades: [],
@@ -2239,7 +2253,7 @@
params: holding ? { holdingStocks: holding } : {}
});
if (resp.data.success) {
this.bullStocksData = resp.data; // { stages, summary, total, stage_info }
this.bullStocksData = resp.data;
} else {
this.showToast(resp.data.error || '获取牛股数据失败', 'error');
}
@@ -2251,6 +2265,75 @@
}
},
async fetchDeepAnalysis() {
const code = (this.deepCode || '').trim();
if (!code || code.length < 6) {
this.showToast('请输入6位股票代码', 'error');
return;
}
this.deepLoading = true;
this.deepReport = null;
try {
const resp = await axios.post('/api/deep_analyze', { stock_code: code });
if (resp.data.success) {
this.deepReport = resp.data.report;
} else {
this.showToast(resp.data.error || '分析失败', 'error');
}
} catch (err) {
console.error('深度分析失败:', err);
this.showToast('深度分析失败: ' + (err.response?.data?.error || err.message), 'error');
} finally {
this.deepLoading = false;
}
},
async fetchBuyAnalysis() {
if (this.buyAnalysisLoading) return;
this.buyAnalysisLoading = true;
this.buyAnalysisList = [];
this.buyAnalysisProgress = 0;
try {
const scanResp = await axios.get('/api/scan_results', {
params: { per_page: 200, recommend_text: '买入' }
});
if (!scanResp.data.success) {
this.showToast('获取买入推荐失败', 'error');
return;
}
const buyStocks = scanResp.data.results || [];
this.buyAnalysisTotal = buyStocks.length;
if (buyStocks.length === 0) {
this.showToast('当前无买入推荐股票', 'info');
return;
}
const results = [];
for (let i = 0; i < buyStocks.length; i++) {
this.buyAnalysisProgress = i + 1;
try {
const resp = await axios.post('/api/deep_analyze', {
stock_code: buyStocks[i].code,
skip_llm: true
});
if (resp.data.success) {
const report = resp.data.report;
report._expanded = false;
results.push(report);
}
} catch (e) {
console.warn('分析失败:', buyStocks[i].code, e.message);
}
}
results.sort((a, b) => b.deep_score - a.deep_score);
this.buyAnalysisList = results;
} catch (err) {
console.error('买入分析失败:', err);
this.showToast('买入分析失败: ' + (err.message || '未知错误'), 'error');
} finally {
this.buyAnalysisLoading = false;
}
},
getBullStageStocks(stageNum) {
if (!this.bullStocksData || !this.bullStocksData.stages) return [];
return this.bullStocksData.stages[String(stageNum)] || [];