<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>investing on peago · 空想家</title><link>https://peagothedreamer.github.io/investing/</link><description>Recent content in investing on peago · 空想家</description><generator>Hugo</generator><language>zh-cn</language><lastBuildDate>Fri, 16 Oct 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://peagothedreamer.github.io/investing/index.xml" rel="self" type="application/rss+xml"/><item><title>大盘估值分位监控</title><link>https://peagothedreamer.github.io/investing/valuation-percentile/</link><pubDate>Fri, 16 Oct 2026 00:00:00 +0000</pubDate><guid>https://peagothedreamer.github.io/investing/valuation-percentile/</guid><description>&lt;p&gt;把几个常用的择时指标拼成一个可复算的分数：趋势偏离、VIX 分位、ERP、恐惧贪婪。分数越高越偏恐惧/便宜，越低越偏贪婪/贵。&lt;/p&gt;&#10;&#10;&lt;div class="valuation" id="vd"&gt;&#10;&lt;style&gt;&#10;.valuation{font-family:var(--mono);font-size:.9375rem;line-height:1.6;color:var(--fg);margin:1.5rem 0}&#10;.valuation *{box-sizing:border-box}&#10;.valuation p{margin:0;max-width:none}&#10;.valuation .vd-topline{display:flex;flex-wrap:wrap;align-items:baseline;justify-content:space-between;gap:.5rem 1rem;color:var(--dim);font-size:.75rem;margin:0 0 .75rem}&#10;.valuation .vd-topline b{color:var(--fg);font-weight:600}&#10;.valuation .vd-verdict{background:rgba(127,127,127,.07);border:1px solid rgba(127,127,127,.3);border-left:4px solid var(--fg);padding:.75rem .875rem;border-radius:8px;font-size:.9375rem;line-height:1.65;margin:0 0 1rem}&#10;.valuation .vd-scorewrap{text-align:center;padding:.25rem 0 0}&#10;.valuation .vd-score{font-size:3.5rem;font-weight:800;line-height:1;color:var(--fg)}&#10;.valuation .vd-scorelabel{color:var(--dim);font-size:.75rem;margin-top:.25rem}&#10;.valuation .vd-gauge{height:10px;border-radius:5px;background:linear-gradient(90deg,rgba(127,127,127,.2),rgba(127,127,127,.75));position:relative;margin:.75rem 0 .25rem}&#10;.valuation .vd-gauge i,.valuation .vd-bar i{position:absolute;top:-4px;width:4px;height:18px;background:var(--fg);border-radius:2px;box-shadow:0 0 0 2px var(--bg);transform:translateX(-50%)}&#10;.valuation .vd-labels{display:flex;justify-content:space-between;font-size:.6875rem;color:var(--dim)}&#10;.valuation .vd-card{background:rgba(127,127,127,.06);border:1px solid rgba(127,127,127,.28);border-radius:10px;padding:1rem;margin:1rem 0}&#10;.valuation .vd-card h3{margin:0 0 .5rem;font-size:.9375rem;line-height:1.4;font-weight:600;color:var(--fg)}&#10;.valuation .vd-big{font-size:1.5rem;font-weight:700}&#10;.valuation .vd-muted{color:var(--dim);font-size:.75rem;line-height:1.65;margin-top:.375rem}&#10;.valuation .vd-bar{height:8px;border-radius:4px;background:linear-gradient(90deg,rgba(127,127,127,.2),rgba(127,127,127,.75));position:relative;margin:.625rem 0 .25rem}&#10;.valuation .vd-barlabels{display:flex;justify-content:space-between;gap:.375rem;font-size:.6875rem;color:var(--dim)}&#10;.valuation .vd-btns{display:grid;grid-template-columns:repeat(4,1fr);gap:.5rem}&#10;.valuation .vd-btn{background:transparent;color:var(--fg);border:1px solid rgba(127,127,127,.4);border-radius:6px;padding:.5rem 0;cursor:pointer;font:inherit;font-size:.8125rem;min-height:2.5rem}&#10;.valuation .vd-btn.on{background:var(--fg);border-color:var(--fg);color:var(--bg)}&#10;.valuation .vd-tablewrap{overflow-x:auto}&#10;.valuation table{width:100%;border-collapse:collapse;margin:.25rem 0 0;font-size:.8125rem}&#10;.valuation th,.valuation td{border-bottom:1px solid rgba(127,127,127,.22);padding:.45rem .35rem;text-align:left;vertical-align:top}&#10;.valuation th{color:var(--dim);font-weight:500}&#10;.valuation .vd-kv{display:flex;justify-content:space-between;gap:.75rem;padding:.35rem 0;border-bottom:1px solid rgba(127,127,127,.22)}&#10;.valuation .vd-kv:last-child{border-bottom:0}&#10;.valuation .vd-src{display:block;color:var(--dim);font-size:.6875rem;line-height:1.5;font-weight:400;margin-top:.125rem}&#10;.valuation .vd-metric{padding:.625rem 0;border-bottom:1px solid rgba(127,127,127,.22)}&#10;.valuation .vd-metric:last-child{border-bottom:0;padding-bottom:0}&#10;.valuation .vd-metrichead{display:flex;justify-content:space-between;align-items:baseline;gap:.625rem;flex-wrap:wrap}&#10;.valuation a{color:inherit}&#10;@media(max-width:30rem){.valuation .vd-score{font-size:3rem}.valuation .vd-card{padding:.75rem}}&#10;&lt;/style&gt;&#10;&#10;&lt;div class="vd-topline"&gt;&lt;span id="vd-asof"&gt;&lt;/span&gt;&lt;b id="vd-scoremini"&gt;—&lt;/b&gt;&lt;/div&gt;&#10;&lt;div class="vd-verdict" id="vd-verdict"&gt;加载中…&lt;/div&gt;&#10;&#10;&lt;div class="vd-scorewrap"&gt;&lt;div class="vd-score" id="vd-score"&gt;—&lt;/div&gt;&lt;div class="vd-scorelabel"&gt;买点评分 0–100（越高越值得买）&lt;/div&gt;&lt;/div&gt;&#10;&lt;div class="vd-gauge"&gt;&lt;i id="vd-gauge" style="left:50%"&gt;&lt;/i&gt;&lt;/div&gt;&#10;&lt;div class="vd-labels"&gt;&lt;span&gt;0 极贵/贪婪&lt;/span&gt;&lt;span&gt;50 中性&lt;/span&gt;&lt;span&gt;100 极便宜/恐惧&lt;/span&gt;&lt;/div&gt;&#10;&#10;&lt;div class="vd-card"&gt;&lt;h3&gt;回看窗口&lt;/h3&gt;&#10;&lt;div class="vd-btns" id="vd-wins"&gt;&lt;button class="vd-btn" data-w="1"&gt;1年&lt;/button&gt;&lt;button class="vd-btn on" data-w="3"&gt;3年&lt;/button&gt;&lt;button class="vd-btn" data-w="5"&gt;5年&lt;/button&gt;&lt;button class="vd-btn" data-w="10"&gt;10年&lt;/button&gt;&lt;/div&gt;&#10;&lt;p class="vd-muted"&gt;切换后趋势偏离分位、VIX 分位与买点评分按该窗口重算；估值/情绪为当前截面，不随窗口变。&lt;/p&gt;&#10;&lt;p class="vd-muted" id="vd-refresh"&gt;&lt;/p&gt;&lt;/div&gt;&#10;&#10;&lt;div class="vd-card"&gt;&lt;h3&gt;① 趋势/波动层 &lt;span class="vd-src" id="vd-trendsrc"&gt;&lt;/span&gt;&lt;/h3&gt;&#10;&lt;p class="vd-muted"&gt;方法：SPX/NDX 对窗口内日收盘取对数做线性回归得趋势线，偏离 = 现价/趋势值−1，分位 = 窗口内“偏离≤当前偏离”的交易日占比（分位越高越贵）；VIX 为当前值在窗口内的取值分位（分位越高越恐慌）。条形统一为该项的买入子分：0 = 不构成买点，100 = 强买点。&lt;/p&gt;&#10;&lt;div id="vd-trend"&gt;&lt;/div&gt;&lt;/div&gt;&#10;&#10;&lt;div class="vd-card"&gt;&lt;h3&gt;② 估值层 · ERP（股权风险溢价）&lt;span class="vd-src" id="vd-valsrc"&gt;&lt;/span&gt;&lt;/h3&gt;&#10;&lt;div id="vd-valrows"&gt;&lt;/div&gt;&#10;&lt;p class="vd-big" id="vd-erpbig" style="margin:.75rem 0 .25rem"&gt;&lt;/p&gt;&#10;&lt;p class="vd-muted" id="vd-erpnote"&gt;&lt;/p&gt;&#10;&lt;div class="vd-bar"&gt;&lt;i id="vd-erpmark" style="left:0%"&gt;&lt;/i&gt;&lt;/div&gt;&#10;&lt;div class="vd-barlabels"&gt;&lt;span&gt;ERP −2% 贵&lt;/span&gt;&lt;span id="vd-erpnow"&gt;&lt;/span&gt;&lt;span&gt;+3% 便宜&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&#10;&#10;&lt;div class="vd-card"&gt;&lt;h3&gt;③ 情绪层 · CNN 恐惧贪婪指数 &lt;span class="vd-src" id="vd-fgsrc"&gt;&lt;/span&gt;&lt;/h3&gt;&#10;&lt;p style="margin:.25rem 0"&gt;&lt;span class="vd-big" id="vd-fgval"&gt;&lt;/span&gt; / 100 · &lt;b id="vd-fglabel"&gt;&lt;/b&gt;&lt;/p&gt;&#10;&lt;div class="vd-bar"&gt;&lt;i id="vd-fgmark" style="left:0%"&gt;&lt;/i&gt;&lt;/div&gt;&#10;&lt;div class="vd-barlabels"&gt;&lt;span&gt;0 极度恐惧&lt;/span&gt;&lt;span&gt;50 中性&lt;/span&gt;&lt;span&gt;100 极度贪婪&lt;/span&gt;&lt;/div&gt;&#10;&lt;p class="vd-muted" id="vd-fgnote"&gt;&lt;/p&gt;&lt;/div&gt;&#10;&#10;&lt;div class="vd-card"&gt;&lt;h3&gt;④ 买点评分拆解（可回溯复算）&lt;/h3&gt;&#10;&lt;div class="vd-tablewrap"&gt;&lt;table id="vd-break"&gt;&lt;/table&gt;&lt;/div&gt;&#10;&lt;p class="vd-muted"&gt;判定带：0–25 偏贪婪/非买点｜25–50 中性偏贵｜50–75 有买点｜75–100 极端恐惧/大买点。&lt;/p&gt;&lt;/div&gt;&#10;&#10;&lt;div class="vd-card"&gt;&lt;h3&gt;评分权重（固定·写死）&lt;/h3&gt;&#10;&lt;div class="vd-kv"&gt;&lt;span&gt;标普趋势偏离（反向）&lt;/span&gt;&lt;b&gt;20%&lt;/b&gt;&lt;/div&gt;&#10;&lt;div class="vd-kv"&gt;&lt;span&gt;纳指100趋势偏离（反向）&lt;/span&gt;&lt;b&gt;15%&lt;/b&gt;&lt;/div&gt;&#10;&lt;div class="vd-kv"&gt;&lt;span&gt;VIX 分位&lt;/span&gt;&lt;b&gt;20%&lt;/b&gt;&lt;/div&gt;&#10;&lt;div class="vd-kv"&gt;&lt;span&gt;股权风险溢价 ERP&lt;/span&gt;&lt;b&gt;25%&lt;/b&gt;&lt;/div&gt;&#10;&lt;div class="vd-kv"&gt;&lt;span&gt;CNN恐惧贪婪（反向）&lt;/span&gt;&lt;b&gt;20%&lt;/b&gt;&lt;/div&gt;&#10;&lt;p class="vd-muted"&gt;合计100%。注意：VIX 与 CNN 恐惧贪婪高度相关（后者本身含 VIX 分项），标普与纳指趋势也高度相关——实际独立信息少于五项。无黑箱：上方“评分拆解”逐项可复算。&lt;/p&gt;&lt;/div&gt;&#10;&#10;&lt;div class="vd-card"&gt;&lt;h3&gt;数据源与使用说明&lt;/h3&gt;&#10;&lt;div id="vd-srclist"&gt;&lt;/div&gt;&#10;&lt;p class="vd-muted"&gt;参考：&lt;a href="https://finance.yahoo.com"&gt;Yahoo Finance&lt;/a&gt; · &lt;a href="https://www.cnn.com/markets/fear-and-greed"&gt;CNN Fear &amp;amp; Greed&lt;/a&gt; · &lt;a href="https://insight.factset.com"&gt;FactSet Insight&lt;/a&gt;&lt;/p&gt;&#10;&lt;p class="vd-muted"&gt;不构成投资建议。买卖决定请自行判断。&lt;/p&gt;&lt;/div&gt;&#10;&#10;&lt;script&gt;&#10;'use strict';&#10;(function () {&#10; &#10; var FALLBACK = {&#10; asOf: '2026-10-16',&#10; close: '美股收盘',&#10; valuation: {&#10; ttmPE: 26.12, &#10; ttmPEAsOf: '2026-10-16',&#10; ttmPESource: 'multpl.com',&#10; forwardEpsGrowth: 0.10, &#10; tenYearYield: 5.10, &#10; tenYearAsOf: '2026-10-16'&#10; },&#10; sentiment: { fearGreed: 18, source: '用户提供', asOf: '2026-10-16' },&#10; windows: {&#10; 1: { spx: { price: 7645.67, deviation: -1.8, percentile: 14 }, ndx: { price: 29122.54, deviation: -4.8, percentile: 15 }, vix: { value: 20.2, percentile: 83 } },&#10; 3: { spx: { price: 7645.67, deviation: -2.1, percentile: 22 }, ndx: { price: 29122.54, deviation: -2.9, percentile: 22 }, vix: { value: 20.2, percentile: 83 } },&#10; 5: { spx: { price: 7645.67, deviation: 3.3, percentile: 66 }, ndx: { price: 29122.54, deviation: 2.1, percentile: 59 }, vix: { value: 20.2, percentile: 68 } },&#10; 10: { spx: { price: 7645.67, deviation: 7.9, percentile: 85 }, ndx: { price: 29122.54, deviation: 3.2, percentile: 66 }, vix: { value: 20.2, percentile: 70 } }&#10; }&#10; };&#10; var S = FALLBACK;&#10; var DATA_URL = '\/data\/valuation.json';&#10;&#10; var W = { spx: 20, ndx: 15, vix: 20, erp: 25, fg: 20 };&#10; var clamp = function (v) { return Math.max(0, Math.min(100, v)); };&#10; var fmt1 = function (v) { return (v &gt;= 0 ? '+' : '') + v.toFixed(1) + '%'; };&#10; var fmt2 = function (v) { return (v &gt;= 0 ? '+' : '') + v.toFixed(2) + '%'; };&#10; var $ = function (id) { return document.getElementById(id); };&#10;&#10; &#10; var V, ttmEY, fwdPE, fwdEY, erpTTM, erpFwd, ERP_SCORE, FG, FG_SCORE;&#10; function compute() {&#10; V = S.valuation;&#10; ttmEY = 100 / V.ttmPE;&#10; fwdPE = V.ttmPE / (1 + V.forwardEpsGrowth);&#10; fwdEY = 100 / fwdPE;&#10; erpTTM = ttmEY - V.tenYearYield;&#10; erpFwd = fwdEY - V.tenYearYield;&#10; ERP_SCORE = clamp((erpFwd + 2) / 5 * 100); &#10; FG = S.sentiment.fearGreed;&#10; FG_SCORE = 100 - FG;&#10; }&#10;&#10; &#10; function partsFor(w) {&#10; var d = S.windows[w];&#10; return [&#10; { name: '标普500 趋势偏离（反向）', raw: '偏离 ' + fmt1(d.spx.deviation) + ' · 分位 ' + d.spx.percentile, sub: clamp(100 - d.spx.percentile), weight: W.spx },&#10; { name: '纳指100 趋势偏离（反向）', raw: '偏离 ' + fmt1(d.ndx.deviation) + ' · 分位 ' + d.ndx.percentile, sub: clamp(100 - d.ndx.percentile), weight: W.ndx },&#10; { name: 'VIX 分位（高波动=恐惧）', raw: 'VIX ' + d.vix.value.toFixed(1) + ' · 分位 ' + d.vix.percentile, sub: d.vix.percentile, weight: W.vix },&#10; { name: '股权风险溢价 ERP', raw: '前瞻 ' + fmt2(erpFwd), sub: ERP_SCORE, weight: W.erp },&#10; { name: 'CNN 恐惧贪婪（反向）', raw: FG + ' / 100', sub: FG_SCORE, weight: W.fg }&#10; ];&#10; }&#10; function totalFor(w) {&#10; return partsFor(w).reduce(function (s, p) { return s + p.sub * p.weight / 100; }, 0);&#10; }&#10;&#10; &#10; function fgLabel(v) {&#10; if (v &lt;= 25) return 'Extreme Fear（极度恐惧）';&#10; if (v &lt;= 45) return 'Fear（恐惧）';&#10; if (v &lt;= 55) return 'Neutral（中性）';&#10; if (v &lt;= 75) return 'Greed（贪婪）';&#10; return 'Extreme Greed（极度贪婪）';&#10; }&#10; function band(t) {&#10; if (t &lt; 25) return '当前偏贪婪，不是买点';&#10; if (t &lt; 50) return '中性偏贵，谈不上恐惧买点';&#10; if (t &lt; 75) return '出现买点，但还不是极端恐惧';&#10; return '极端恐惧，大买点';&#10; }&#10; function divergence(w) {&#10; var d = S.windows[w];&#10; var trend = (clamp(100 - d.spx.percentile) + clamp(100 - d.ndx.percentile)) / 2;&#10; var senti = (d.vix.percentile + FG_SCORE) / 2;&#10; if (senti - ERP_SCORE &gt;= 15 &amp;&amp; trend &gt;= 50) return '情绪和趋势已偏恐惧，但估值（ERP）仍不便宜——属于贵市里的回调，不是低估。';&#10; if (ERP_SCORE &gt;= 60) return '估值本身也给出了安全边际。';&#10; return '信号分歧不大，按仓位纪律分批即可。';&#10; }&#10;&#10; &#10; function renderTrend(w) {&#10; var d = S.windows[w];&#10; var rows = [&#10; { name: '标普500', value: d.spx.price.toLocaleString('en-US', { minimumFractionDigits: 2 }), desc: '偏离趋势 ' + fmt1(d.spx.deviation) + ' · 分位 ' + d.spx.percentile + '（越高越贵）', sub: clamp(100 - d.spx.percentile) },&#10; { name: '纳指100', value: d.ndx.price.toLocaleString('en-US', { minimumFractionDigits: 2 }), desc: '偏离趋势 ' + fmt1(d.ndx.deviation) + ' · 分位 ' + d.ndx.percentile + '（越高越贵）', sub: clamp(100 - d.ndx.percentile) },&#10; { name: 'VIX', value: d.vix.value.toFixed(1), desc: '分位 ' + d.vix.percentile + '（越高越恐慌）', sub: d.vix.percentile }&#10; ];&#10; $('vd-trend').innerHTML = rows.map(function (r) {&#10; return '&lt;div class="vd-metric"&gt;' +&#10; '&lt;div class="vd-metrichead"&gt;&lt;b&gt;' + r.name + '&lt;/b&gt;&lt;span class="vd-big" style="font-size:1.25rem"&gt;' + r.value + '&lt;/span&gt;&lt;/div&gt;' +&#10; '&lt;div class="vd-muted" style="margin-top:0"&gt;' + r.desc + '&lt;/div&gt;' +&#10; '&lt;div class="vd-bar"&gt;&lt;i style="left:' + r.sub + '%"&gt;&lt;/i&gt;&lt;/div&gt;' +&#10; '&lt;div class="vd-barlabels"&gt;&lt;span&gt;0 不构成买点&lt;/span&gt;&lt;span&gt;子分 ' + Math.round(r.sub) + '&lt;/span&gt;&lt;span&gt;100 强买点&lt;/span&gt;&lt;/div&gt;' +&#10; '&lt;/div&gt;';&#10; }).join('');&#10; }&#10;&#10; function renderValuation() {&#10; var rows = [&#10; ['标普500 TTM PE', V.ttmPE.toFixed(1)],&#10; ['TTM 盈利收益率', ttmEY.toFixed(2) + '%'],&#10; ['前瞻 PE（按 ' + Math.round(V.forwardEpsGrowth * 100) + '% EPS 增长推算）', fwdPE.toFixed(1)],&#10; ['前瞻盈利收益率', fwdEY.toFixed(2) + '%'],&#10; ['10 年美债', V.tenYearYield.toFixed(2) + '%']&#10; ];&#10; $('vd-valrows').innerHTML = rows.map(function (r) {&#10; return '&lt;div class="vd-kv"&gt;&lt;span&gt;' + r[0] + '&lt;/span&gt;&lt;b&gt;' + r[1] + '&lt;/b&gt;&lt;/div&gt;';&#10; }).join('');&#10; $('vd-erpbig').textContent = '前瞻 ERP ≈ ' + fmt2(erpFwd);&#10; $('vd-erpnote').innerHTML = 'TTM 口径 ERP = ' + ttmEY.toFixed(2) + '% − ' + V.tenYearYield.toFixed(2) + '% = &lt;b&gt;' + fmt2(erpTTM) + '&lt;/b&gt;（按已实现盈利，股票相对债券无溢价）。ERP 子分映射：−2%→0，+3%→100，当前 ' + fmt2(erpFwd) + ' → &lt;b&gt;' + Math.round(ERP_SCORE) + ' 分&lt;/b&gt;。历史中枢约 +2~3%，当前明显偏低。前瞻 PE 按 ' + Math.round(V.forwardEpsGrowth * 100) + '% EPS 增长由 TTM 推算。';&#10; $('vd-erpmark').style.left = clamp((erpFwd + 2) / 5 * 100) + '%';&#10; $('vd-erpnow').textContent = '当前 ' + fmt2(erpFwd);&#10; }&#10;&#10; function renderSentiment() {&#10; $('vd-fgval').textContent = FG;&#10; $('vd-fglabel').textContent = fgLabel(FG);&#10; $('vd-fgmark').style.left = FG + '%';&#10; $('vd-fgnote').textContent = '买点子分 = 100 − ' + FG + ' = ' + FG_SCORE + '。指数由动量、宽度、Put/Call、VIX 等 7 项合成（CNN 官方口径）。';&#10; }&#10;&#10; function renderBreakdown(w) {&#10; var ps = partsFor(w);&#10; var total = ps.reduce(function (s, p) { return s + p.sub * p.weight / 100; }, 0);&#10; $('vd-break').innerHTML = '&lt;tr&gt;&lt;th&gt;子项&lt;/th&gt;&lt;th&gt;子分&lt;/th&gt;&lt;th&gt;权重&lt;/th&gt;&lt;th&gt;贡献&lt;/th&gt;&lt;/tr&gt;' +&#10; ps.map(function (p) {&#10; return '&lt;tr&gt;&lt;td&gt;' + p.name + '&lt;span class="vd-src"&gt;' + p.raw + '&lt;/span&gt;&lt;/td&gt;&lt;td&gt;' + Math.round(p.sub) + '&lt;/td&gt;&lt;td&gt;' + p.weight + '%&lt;/td&gt;&lt;td&gt;' + (p.sub * p.weight / 100).toFixed(1) + '&lt;/td&gt;&lt;/tr&gt;';&#10; }).join('') +&#10; '&lt;tr&gt;&lt;td&gt;&lt;b&gt;合计&lt;/b&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;100%&lt;/td&gt;&lt;td&gt;&lt;b&gt;' + total.toFixed(0) + '&lt;/b&gt;&lt;/td&gt;&lt;/tr&gt;';&#10; }&#10;&#10; function renderVerdict(w) {&#10; var total = totalFor(w);&#10; var all = Object.keys(S.windows).map(function (k) { return totalFor(+k); });&#10; var lo = Math.min.apply(null, all), hi = Math.max.apply(null, all);&#10; var sens = hi - lo &gt;= 15&#10; ? '各窗口 ' + lo.toFixed(0) + '–' + hi.toFixed(0) + ' 分，结论对窗口敏感。'&#10; : '各窗口 ' + lo.toFixed(0) + '–' + hi.toFixed(0) + ' 分，结论稳定。';&#10; $('vd-verdict').innerHTML = '一句话结论：&lt;b&gt;' + band(total) + '。&lt;/b&gt; 当前 ' + w + ' 年窗口 ' + total.toFixed(0) + ' 分。' + sens + divergence(w);&#10; }&#10;&#10; function render(w) {&#10; renderTrend(w);&#10; renderValuation();&#10; renderSentiment();&#10; renderBreakdown(w);&#10; renderVerdict(w);&#10; var total = totalFor(w);&#10; $('vd-score').textContent = total.toFixed(0);&#10; $('vd-scoremini').textContent = '评分 ' + total.toFixed(0) + '/100';&#10; $('vd-gauge').style.left = total + '%';&#10; }&#10;&#10; &#10; function renderMeta() {&#10; $('vd-asof').textContent = '快照基准：' + S.asOf + ' ' + S.close + ' · 打开页面自动读取';&#10; $('vd-refresh').textContent = '数据截至 ' + S.asOf + ' ' + S.close + ' · 每个交易日收盘后由 GitHub Action 更新';&#10; $('vd-trendsrc').textContent = '来源：Yahoo 日线 · ' + S.asOf + ' ' + S.close;&#10; $('vd-valsrc').textContent = 'TTM PE ' + V.ttmPE + '（' + (V.ttmPESource || '快照') + '）· 10Y ' + V.tenYearYield.toFixed(2) + '%';&#10; $('vd-fgsrc').textContent = '来源：CNN · ' + S.sentiment.asOf;&#10; $('vd-srclist').innerHTML = [&#10; ['行情', 'SPX / NDX / VIX · Yahoo 日线 · ' + S.asOf + ' ' + S.close],&#10; ['10年美债', 'Yahoo ^TNX · ' + V.tenYearYield.toFixed(2) + '%' + (V.tenYearAsOf ? ' · ' + V.tenYearAsOf : '')],&#10; ['市盈率', 'TTM PE ' + V.ttmPE + '（' + (V.ttmPESource || '快照') + ' · ' + (V.ttmPEAsOf || S.asOf) + '）· 前瞻 PE 按 ' + Math.round(V.forwardEpsGrowth * 100) + '% EPS 增长推算为 ' + fwdPE.toFixed(1)],&#10; ['恐惧贪婪', 'CNN Fear &amp; Greed · ' + FG + ' · ' + S.sentiment.asOf]&#10; ].map(function (r) {&#10; return '&lt;div class="vd-kv"&gt;&lt;span&gt;' + r[0] + '&lt;/span&gt;&lt;b&gt;' + r[1] + '&lt;/b&gt;&lt;/div&gt;';&#10; }).join('');&#10; }&#10;&#10; &#10; var current = 3;&#10; $('vd-wins').addEventListener('click', function (e) {&#10; var b = e.target.closest('button');&#10; if (!b || !b.dataset.w) return;&#10; current = +b.dataset.w;&#10; Array.prototype.forEach.call(document.querySelectorAll('#vd-wins .vd-btn'), function (x) {&#10; x.classList.toggle('on', +x.dataset.w === current);&#10; });&#10; render(current);&#10; });&#10;&#10; &#10; compute();&#10;&#10; &#10; (function validate() {&#10; var sum = Object.keys(W).reduce(function (a, k) { return a + W[k]; }, 0);&#10; console.assert(sum === 100, '权重合计应为 100，实际 ' + sum);&#10; console.assert(Math.abs(V.ttmPE / fwdPE - 1 - V.forwardEpsGrowth) &lt; 1e-9, '前瞻 PE 与增长假设不一致');&#10; Object.keys(S.windows).forEach(function (k) {&#10; ['spx', 'ndx', 'vix'].forEach(function (key) {&#10; console.assert(S.windows[k][key] &amp;&amp; S.windows[k][key].percentile &gt;= 0 &amp;&amp; S.windows[k][key].percentile &lt;= 100, '窗口 ' + k + ' 的 ' + key + ' 分位越界');&#10; });&#10; });&#10; })();&#10;&#10; renderMeta();&#10; render(current);&#10;&#10; &#10; fetch(DATA_URL, { cache: 'no-store' })&#10; .then(function (r) {&#10; if (!r.ok) throw new Error('HTTP ' + r.status);&#10; return r.json();&#10; })&#10; .then(function (d) {&#10; if (!d || !d.windows || !d.valuation || !d.sentiment) throw new Error('数据格式不对');&#10; S = d;&#10; compute();&#10; renderMeta();&#10; render(current);&#10; var when = d.generatedAt ? new Date(d.generatedAt).toLocaleString('zh-CN') : d.asOf;&#10; $('vd-refresh').textContent += ' · 已读取实时数据（生成于 ' + when + '）';&#10; })&#10; .catch(function (err) {&#10; $('vd-refresh').textContent += ' · 实时数据读取失败，使用内置快照（' + FALLBACK.asOf + '）';&#10; console.warn('valuation data:', err);&#10; });&#10;})();&#10;&lt;/script&gt;&#10;&lt;/div&gt;</description></item></channel></rss>