90 lines
4.6 KiB
Python
90 lines
4.6 KiB
Python
# -*- coding: utf-8 -*-
|
|
"""前端追加「量化推荐」区(筛选按钮 + 事件渲染 + 表格 + 权重展示)"""
|
|
import io
|
|
|
|
p = r'src\web\index.html'
|
|
s = io.open(p, encoding='utf-8').read()
|
|
|
|
# 1) 筛选按钮
|
|
old1 = ' <button data-f="事件影响分析">事件影响</button>'
|
|
new1 = (old1 + '\n <button data-f="量化推荐">量化推荐</button>\n'
|
|
' <button data-f="模型微调">微调</button>')
|
|
assert old1 in s, 'filters not found'
|
|
s = s.replace(old1, new1)
|
|
|
|
# 2) 主区追加量化推荐表格
|
|
old2 = ' <ul id="feed"><li class="empty">等待服务端推送…</li></ul>\n</main>'
|
|
new2 = (' <ul id="feed"><li class="empty">等待服务端推送…</li></ul>\n</main>\n'
|
|
'<section style="max-width:1100px;margin:0 auto 30px">\n'
|
|
' <h2 style="font-size:15px;color:var(--text)">量化模型 · 自适应推荐'
|
|
'(多因子 + IC 微调)</h2>\n'
|
|
' <div style="font-size:12px;color:var(--text2);margin-bottom:8px">'
|
|
'权重:<span id="qw">加载中…</span></div>\n'
|
|
' <div style="background:var(--surface);border:1px solid var(--border);'
|
|
'border-radius:8px;overflow:auto">\n'
|
|
' <table style="width:100%;border-collapse:collapse;font-size:13px" id="qtable">\n'
|
|
' <thead><tr style="color:var(--text2);text-align:left">\n'
|
|
' <th style="padding:8px 10px">代码</th><th style="padding:8px 10px">名称</th>\n'
|
|
' <th style="padding:8px 10px">现价</th><th style="padding:8px 10px">模型分</th>\n'
|
|
' <th style="padding:8px 10px">购入区间</th>'
|
|
'<th style="padding:8px 10px">预计收益(回测口径)</th>\n'
|
|
' <th style="padding:8px 10px">推荐指数</th>'
|
|
'<th style="padding:8px 10px">简易原因</th>\n'
|
|
' </tr></thead><tbody></tbody>\n'
|
|
' </table>\n'
|
|
' </div>\n'
|
|
' <div style="margin-top:6px;font-size:11px;color:#6b7280">'
|
|
'⚠ 购入区间与预计收益为模型回测/推测口径,不构成投资建议。</div>\n'
|
|
'</section>')
|
|
assert old2 in s, 'feed ul not found'
|
|
s = s.replace(old2, new2)
|
|
|
|
# 3) WS 事件渲染分支(量化推荐)
|
|
old3 = (" } else {\n"
|
|
" const txt = typeof d === 'object' ? JSON.stringify(d) : String(d)\n"
|
|
" li.innerHTML = `<span class=\"t\">${e.ts}</span><span class=\"k ${e.kind}\">${e.kind}"
|
|
"</span><span class=\"d\">${esc(txt)}</span>`\n }")
|
|
new3 = (" } else if (e.kind === '量化推荐') {\n"
|
|
" renderQuant(e.data)\n"
|
|
" const txt = '自适应模型推送 ' + ((d.list || []).length) + ' 只推荐'\n"
|
|
" li.innerHTML = `<span class=\"t\">${e.ts}</span><span class=\"k ${e.kind}\">${e.kind}"
|
|
"</span><span class=\"d\">${esc(txt)}</span>`\n"
|
|
" } else {\n"
|
|
" const txt = typeof d === 'object' ? JSON.stringify(d) : String(d)\n"
|
|
" li.innerHTML = `<span class=\"t\">${e.ts}</span><span class=\"k ${e.kind}\">${e.kind}"
|
|
"</span><span class=\"d\">${esc(txt)}</span>`\n }")
|
|
assert old3 in s, 'render branch not found'
|
|
s = s.replace(old3, new3)
|
|
|
|
# 4) 渲染函数与加载
|
|
old4 = 'connect()'
|
|
new4 = (
|
|
"function renderQuant(d) {\n"
|
|
" const tb = document.querySelector('#qtable tbody')\n"
|
|
" if (!tb) return\n"
|
|
" tb.innerHTML = (d.list || []).map(r =>\n"
|
|
" '<tr><td style=\"padding:6px 10px\">' + esc(r.code) + '</td>' +\n"
|
|
" '<td style=\"padding:6px 10px\">' + esc(r.name) + '</td>' +\n"
|
|
" '<td style=\"padding:6px 10px\">' + r.price + '</td>' +\n"
|
|
" '<td style=\"padding:6px 10px\">' + r.score + '</td>' +\n"
|
|
" '<td style=\"padding:6px 10px\">' + r.buy_low + ' ~ ' + r.buy_high + '</td>' +\n"
|
|
" '<td style=\"padding:6px 10px\">' + (r.expected_return_pct == null ? '—' : r.expected_return_pct + '%') + '</td>' +\n"
|
|
" '<td style=\"padding:6px 10px\" class=\"stars\">' + '★'.repeat(r.stars) + '</td>' +\n"
|
|
" '<td style=\"padding:6px 10px\">' + esc(r.reason) + '</td></tr>').join('')\n"
|
|
"}\n"
|
|
"function loadQuant() {\n"
|
|
" fetch('/api/quant/recommendations').then(r => r.json()).then(renderQuant).catch(() => {})\n"
|
|
" fetch('/api/quant/weights').then(r => r.json()).then(w => {\n"
|
|
" document.getElementById('qw').textContent =\n"
|
|
" Object.entries(w || {}).map(([k, v]) => k + '=' + Number(v).toFixed(2)).join(' ') || '—'\n"
|
|
" }).catch(() => {})\n"
|
|
"}\n"
|
|
"loadQuant()\n"
|
|
"setInterval(loadQuant, 60000)\n"
|
|
"connect()")
|
|
assert old4 in s
|
|
s = s.replace(old4, new4, 1)
|
|
|
|
io.open(p, 'w', encoding='utf-8').write(s)
|
|
print('index.html 量化推荐区 OK')
|