Files
finance-daily-site/index.html
T
2026-06-08 23:19:28 +00:00

3453 lines
174 KiB
HTML
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.
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="金融日报 — 北美华人投资者专属每日金融简报,由 Claude AI + Web Search 自动生成,每日两次更新">
<meta property="og:title" content="金融日报 | Financial Daily">
<meta property="og:description" content="北美华人投资者专属:全球指数·市场要闻·宏观数据·财报追踪·经济日历,每日自动更新">
<meta property="og:type" content="website">
<meta name="keywords" content="金融日报,北美投资,美股,A股,港股,宏观经济,财报,经济日历">
<meta name="theme-color" content="#070b14">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
<meta name="apple-mobile-web-app-title" content="金融日报">
<link rel="manifest" href="manifest.json">
<title>金融日报 | Financial Daily — 北美华人投资者日报</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&family=JetBrains+Mono:wght@400;500;600&display=swap" rel="stylesheet">
<style>
/* =========================================================
RESET & TOKENS
========================================================= */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
:root {
--bg: #070b14;
--card: #0c1525;
--card2: #0f1c30;
--border: #192840;
--border-l: #22386a;
--accent: #00d4aa;
--up: #00e676;
--down: #ff5252;
--neutral: #4fc3f7;
--warn: #ffb300;
--text: #e2e8f0;
--muted: #7a8fa8;
--dimmed: #3a4e68;
--mono: 'JetBrains Mono','Fira Code',monospace;
--sans: 'Inter',system-ui,-apple-system,sans-serif;
--r: 8px;
--rl: 14px;
}
html { font-size: 14px; scroll-behavior: smooth; }
body { font-family: var(--sans); background: var(--bg); color: var(--text); line-height: 1.6; -webkit-font-smoothing: antialiased; }
a { color: var(--accent); text-decoration: none; }
a:hover { color: #33e0be; }
/* =========================================================
READING PROGRESS
========================================================= */
#reading-progress { position: fixed; top: 0; left: 0; height: 3px; width: 0; background: linear-gradient(90deg,var(--accent),#4fc3f7); z-index: 9999; transition: width .1s; }
/* =========================================================
HEADER
========================================================= */
.site-header {
position: sticky; top: 0; z-index: 100;
background: rgba(7,11,20,.96); backdrop-filter: blur(16px);
border-bottom: 1px solid var(--border);
padding: 10px 0;
}
.header-inner { display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap; }
.logo-block { display: flex; align-items: baseline; gap: 8px; }
.site-title { font-size: 1.1rem; font-weight: 800; color: var(--accent); letter-spacing: -.02em; }
.site-sub { font-size: .65rem; color: var(--muted); font-family: var(--mono); }
.header-meta { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.header-date { font-family: var(--mono); font-size: .68rem; color: var(--muted); }
.header-badge { display: flex; align-items: center; gap: 5px; font-size: .62rem; color: var(--muted); background: rgba(0,212,170,.08); border: 1px solid rgba(0,212,170,.2); border-radius: 20px; padding: 2px 9px; }
.pulse-dot { width: 6px; height: 6px; border-radius: 50%; background: var(--accent); animation: pulse 2s ease-in-out infinite; }
@keyframes pulse { 0%,100%{opacity:1;transform:scale(1)} 50%{opacity:.4;transform:scale(.7)} }
.header-nav { display: flex; gap: 10px; }
.header-nav a { font-size: .68rem; color: var(--muted); }
.header-nav a:hover { color: var(--accent); }
.streak-badge { font-size: .62rem; font-family: var(--mono); background: rgba(255,179,0,.12); color: var(--warn); border: 1px solid rgba(255,179,0,.25); border-radius: 20px; padding: 2px 8px; }
/* =========================================================
NAV BAR
========================================================= */
.jump-nav {
position: sticky; top: 47px; z-index: 90;
background: rgba(7,11,20,.95); backdrop-filter: blur(14px);
border-bottom: 1px solid var(--border);
display: flex; overflow-x: auto; scrollbar-width: none;
}
.jump-nav::-webkit-scrollbar { display: none; }
.jump-nav a {
flex-shrink: 0; padding: 8px 14px; font-size: .72rem;
color: var(--muted); white-space: nowrap;
border-bottom: 2px solid transparent; transition: color .15s, border-color .15s;
}
.jump-nav a:hover { color: var(--text); text-decoration: none; }
.jump-nav a.active { color: var(--accent); border-bottom-color: var(--accent); }
.nav-sep { width: 1px; background: var(--border); margin: 8px 0; flex-shrink: 0; }
/* =========================================================
TICKER STRIP
========================================================= */
.indices-section { border-bottom: 1px solid var(--border); background: rgba(0,0,0,.2); }
.indices-scroll-wrapper { overflow: hidden; position: relative; }
.indices-track { display: flex; gap: 0; animation: ticker 60s linear infinite; width: max-content; }
.indices-track:hover { animation-play-state: paused; }
@keyframes ticker { from { transform: translateX(0); } to { transform: translateX(-50%); } }
.ticker-card { padding: 8px 18px; border-right: 1px solid var(--border); white-space: nowrap; cursor: default; }
.ticker-name { font-size: .62rem; color: var(--muted); font-family: var(--mono); margin-bottom: 2px; }
.ticker-value { font-size: .9rem; font-weight: 700; font-family: var(--mono); }
.ticker-change { font-size: .68rem; font-family: var(--mono); }
.ticker-change.up,.ticker-value.up { color: var(--up); }
.ticker-change.down,.ticker-value.down { color: var(--down); }
.ticker-card.up .ticker-value { color: var(--text); }
.ticker-card.down .ticker-value { color: var(--text); }
/* =========================================================
LAYOUT
========================================================= */
.container { max-width: 1360px; margin: 0 auto; padding: 0 20px; }
.page-body { padding: 20px 0 40px; }
/* Primary grid: content + sidebar */
.content-grid {
display: grid;
grid-template-columns: 1fr 380px;
gap: 20px;
align-items: start;
}
@media (max-width: 1024px) { .content-grid { grid-template-columns: 1fr; } }
/* 2-col within a column */
.two-up { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; align-items: start; }
@media (max-width: 640px) { .two-up { grid-template-columns: 1fr; } }
/* =========================================================
CARDS & SECTIONS
========================================================= */
.card {
background: var(--card); border: 1px solid var(--border);
border-radius: var(--rl); padding: 18px 20px;
transition: border-color .2s;
}
.section-label {
font-size: .65rem; font-family: var(--mono); color: var(--accent);
letter-spacing: .1em; text-transform: uppercase;
margin-bottom: 14px; padding-bottom: 10px;
border-bottom: 1px solid var(--border);
display: flex; align-items: center; gap: 8px;
}
.section-label::before { content:''; width:3px; height:12px; background:var(--accent); border-radius:2px; flex-shrink:0; }
.section-label .sec-count { margin-left:auto; color:var(--dimmed); font-size:.6rem; }
.sec-anchor { scroll-margin-top: 100px; }
.mb16 { margin-bottom: 16px; }
/* =========================================================
SUMMARY HERO
========================================================= */
.summary-section { padding: 16px 0 0; }
.summary-card {
border-radius: var(--rl); padding: 22px 26px;
border: 1px solid var(--border); margin-bottom: 16px;
}
.summary-card.bullish { background: linear-gradient(135deg,rgba(0,230,118,.07),rgba(0,212,170,.03)); border-color:rgba(0,230,118,.28); }
.summary-card.bearish { background: linear-gradient(135deg,rgba(255,82,82,.07),rgba(255,82,82,.02)); border-color:rgba(255,82,82,.28); }
.summary-card.neutral { background: linear-gradient(135deg,rgba(79,195,247,.06),rgba(0,212,170,.03)); border-color:rgba(79,195,247,.22); }
.summary-top { display:flex; align-items:center; gap:10px; margin-bottom:14px; flex-wrap:wrap; }
.sentiment-pill { font-size:.72rem; font-family:var(--mono); font-weight:700; padding:4px 14px; border-radius:20px; letter-spacing:.06em; }
.sentiment-pill.bullish { background:rgba(0,230,118,.15); color:var(--up); border:1px solid rgba(0,230,118,.3); }
.sentiment-pill.bearish { background:rgba(255,82,82,.15); color:var(--down); border:1px solid rgba(255,82,82,.3); }
.sentiment-pill.neutral { background:rgba(79,195,247,.12); color:var(--neutral);border:1px solid rgba(79,195,247,.25); }
.vix-badge { font-family:var(--mono); font-size:.72rem; color:var(--muted); }
.vix-num { color:var(--warn); font-weight:700; font-size:.9rem; }
.summary-headline { font-size:1.22rem; font-weight:800; color:var(--text); line-height:1.38; margin-bottom:14px; letter-spacing:-.02em; }
.key-points { list-style:none; display:flex; flex-direction:column; gap:7px; margin-bottom:14px; padding:0; }
.kp-item { font-size:.83rem; color:var(--text); padding:9px 14px; background:rgba(255,255,255,.04); border-radius:7px; border-left:3px solid var(--accent); display:flex; align-items:center; gap:8px; font-weight:500; line-height:1.4; }
.kp-arrow { color:var(--accent); font-size:.7rem; flex-shrink:0; }
.summary-details { margin-top:4px; }
.summary-details-toggle { font-size:.72rem; color:var(--muted); cursor:pointer; user-select:none; padding:4px 0; list-style:none; }
.summary-details-toggle:hover { color:var(--accent); }
.summary-context { font-size:.82rem; color:var(--muted); line-height:1.7; padding-top:8px; }
/* legacy hide */
.summary-icon,.summary-content,.summary-meta,.summary-label,.vix-display,.sentiment-badge { display:none !important; }
/* =========================================================
NEWS
========================================================= */
.news-item {
background: var(--card); border-radius: var(--r);
border: 1px solid var(--border); margin-bottom: 6px;
cursor: pointer; overflow: hidden; transition: border-color .18s;
}
.news-item:hover { border-color: var(--border-l); }
.news-item.expanded { border-color: var(--border-l); }
.news-header { display: flex; align-items: flex-start; gap: 10px; padding: 12px 14px 9px; }
.imp-dot { width: 7px; height: 7px; border-radius: 50%; flex-shrink:0; margin-top:5px; }
.imp-dot.breaking { background:var(--down); box-shadow:0 0 5px rgba(255,82,82,.5); }
.imp-dot.major { background:var(--warn); }
.imp-dot.normal { background:var(--neutral); opacity:.35; }
.news-title { font-size:.86rem; font-weight:600; color:var(--text); line-height:1.42; flex:1; }
.news-title a { color:var(--text); }
.news-title a:hover { color:var(--accent); }
.news-expand-icon { color:var(--dimmed); flex-shrink:0; font-size:1rem; transition:transform .2s; }
.news-item.expanded .news-expand-icon { transform:rotate(45deg); color:var(--accent); }
.news-tldr { padding:0 14px 9px 31px; font-size:.76rem; color:var(--accent); line-height:1.5; }
.tldr-label { margin-right:3px; }
.news-body-collapse { display:none; padding:9px 14px 12px 31px; font-size:.79rem; color:var(--muted); line-height:1.65; border-top:1px solid var(--border); }
.news-item.expanded .news-body-collapse { display:block; }
.news-footer { display:flex; align-items:center; gap:7px; padding:7px 14px; flex-wrap:wrap; border-top:1px solid rgba(255,255,255,.035); }
.news-item.breaking { border-left:3px solid var(--down); }
.news-item.major { border-left:3px solid var(--warn); }
.news-item.normal { border-left:3px solid transparent; }
.importance-badge { font-size:.6rem; font-family:var(--mono); padding:2px 6px; border-radius:3px; }
.importance-badge.breaking { background:rgba(255,82,82,.12); color:var(--down); }
.importance-badge.major { background:rgba(255,179,0,.12); color:var(--warn); }
.importance-badge.normal { background:rgba(79,195,247,.08); color:var(--neutral); }
.new-badge { font-size:.58rem; font-family:var(--mono); padding:1px 5px; border-radius:3px; background:rgba(0,212,170,.15); color:var(--accent); border:1px solid rgba(0,212,170,.3); }
/* =========================================================
TAGS
========================================================= */
.tag { font-size:.6rem; font-family:var(--mono); padding:2px 6px; border-radius:3px; background:rgba(255,255,255,.06); color:var(--muted); }
/* =========================================================
LEADERS
========================================================= */
.leader-card { background:var(--bg); border:1px solid var(--border); border-radius:var(--r); padding:14px; margin-bottom:8px; transition:border-color .2s; }
.leader-card:hover { border-color:var(--border-l); }
.leader-header { display:flex; align-items:center; gap:10px; margin-bottom:10px; }
.leader-avatar { width:38px; height:38px; border-radius:50%; display:flex; align-items:center; justify-content:center; font-size:.7rem; font-weight:700; font-family:var(--mono); flex-shrink:0; }
.leader-avatar.wb { background:linear-gradient(135deg,#4a3800,#8b6914); color:#ffd700; }
.leader-avatar.rd { background:linear-gradient(135deg,#1a3a5c,#2563a8); color:#60a5fa; }
.leader-avatar.jd { background:linear-gradient(135deg,#3a1a1a,#8b2525); color:#f87171; }
.leader-avatar.jp { background:linear-gradient(135deg,#1a3a2a,#256b40); color:#4ade80; }
.leader-avatar.default { background:rgba(0,212,170,.15); color:var(--accent); }
.leader-meta { flex:1; }
.leader-name { font-size:.83rem; font-weight:600; }
.leader-role { font-size:.68rem; color:var(--muted); }
.leader-date { font-size:.62rem; color:var(--dimmed); font-family:var(--mono); white-space:nowrap; }
.leader-quote { font-size:.82rem; color:var(--accent); font-style:italic; margin-bottom:8px; line-height:1.5; }
.leader-body { font-size:.78rem; color:var(--muted); line-height:1.6; margin-bottom:8px; }
/* =========================================================
MACRO
========================================================= */
.macro-grid { display:grid; grid-template-columns:repeat(auto-fill,minmax(200px,1fr)); gap:10px; }
.macro-card { background:var(--bg); border:1px solid var(--border); border-radius:var(--r); padding:12px 14px; transition:border-color .2s; }
.macro-card:hover { border-color:var(--border-l); }
.macro-card.dir-up { border-left:3px solid var(--up); }
.macro-card.dir-down{ border-left:3px solid var(--down); }
.macro-card.dir-neutral { border-left:3px solid var(--neutral); }
.macro-indicator { font-size:.65rem; font-family:var(--mono); color:var(--muted); margin-bottom:5px; text-transform:uppercase; }
.macro-value { font-size:1.1rem; font-weight:700; font-family:var(--mono); margin-bottom:4px; }
.macro-value-up { color:var(--up); }
.macro-value-down { color:var(--down); }
.macro-prev { font-size:.66rem; color:var(--dimmed); margin-bottom:5px; }
.macro-desc { font-size:.72rem; color:var(--muted); line-height:1.5; }
.arrow.up { color:var(--up); }
.arrow.down { color:var(--down); }
/* =========================================================
EARNINGS
========================================================= */
.earnings-grid { display:grid; grid-template-columns:repeat(auto-fill,minmax(200px,1fr)); gap:10px; }
.earnings-card { background:var(--bg); border:1px solid var(--border); border-radius:var(--r); padding:14px; transition:border-color .2s; }
.earnings-card:hover { border-color:var(--border-l); }
.earnings-card.beat { border-top:2px solid var(--up); }
.earnings-card.miss { border-top:2px solid var(--down); }
.earnings-card.pending{ border-top:2px solid var(--neutral); }
.e-header { display:flex; align-items:center; justify-content:space-between; margin-bottom:10px; }
.e-ticker { font-family:var(--mono); font-size:.85rem; font-weight:700; }
.e-company { font-size:.7rem; color:var(--muted); }
.e-badge { font-size:.6rem; font-family:var(--mono); padding:2px 7px; border-radius:3px; }
.e-badge.beat { background:rgba(0,230,118,.15); color:var(--up); }
.e-badge.miss { background:rgba(255,82,82,.15); color:var(--down); }
.e-badge.pending{ background:rgba(79,195,247,.1); color:var(--neutral); }
.earnings-eps { display:flex; gap:10px; margin-bottom:8px; }
.eps-item { flex:1; }
.eps-label { font-size:.6rem; font-family:var(--mono); color:var(--dimmed); margin-bottom:3px; }
.eps-value { font-size:.9rem; font-weight:700; font-family:var(--mono); }
.eps-value.actual.beat { color:var(--up); }
.eps-value.actual.miss { color:var(--down); }
.eps-value.est { color:var(--muted); }
.e-revenue { font-size:.72rem; color:var(--muted); margin-bottom:5px; }
.e-highlight { font-size:.72rem; color:var(--text); line-height:1.4; }
/* =========================================================
SECTORS
========================================================= */
.sectors-list { display:flex; flex-direction:column; gap:6px; }
.sector-row { display:grid; grid-template-columns:1fr auto 120px auto; gap:8px; align-items:center; padding:8px 10px; background:var(--bg); border-radius:var(--r); border:1px solid var(--border); font-size:.78rem; }
@media(max-width:480px){ .sector-row { grid-template-columns:1fr auto; } .sector-bar-wrap,.sector-etf{ display:none; } }
.sector-name { font-weight:500; }
.sector-name-en { font-size:.65rem; color:var(--muted); }
.sector-etf { font-family:var(--mono); font-size:.65rem; color:var(--dimmed); }
.sector-bar-wrap { height:5px; background:var(--border); border-radius:3px; overflow:hidden; }
.sector-bar { height:100%; border-radius:3px; }
.sector-bar.up { background:var(--up); }
.sector-bar.down { background:var(--down); }
.sector-pct { font-family:var(--mono); font-size:.78rem; font-weight:600; text-align:right; }
.sector-pct.up { color:var(--up); }
.sector-pct.down { color:var(--down); }
/* =========================================================
CENTRAL BANKS
========================================================= */
.cb-grid { display:grid; grid-template-columns:1fr 1fr; gap:10px; }
@media(max-width:600px){ .cb-grid { grid-template-columns:1fr; } }
.cb-card { background:var(--bg); border:1px solid var(--border); border-radius:var(--r); padding:14px; transition:border-color .2s; }
.cb-card:hover { border-color:var(--border-l); }
.cb-header { display:flex; align-items:center; justify-content:space-between; margin-bottom:8px; gap:8px; flex-wrap:wrap; }
.cb-name { font-size:.82rem; font-weight:600; }
.cb-rate { font-family:var(--mono); font-size:.78rem; color:var(--accent); }
.cb-action { font-size:.75rem; color:var(--text); margin-bottom:6px; font-weight:500; }
.cb-note { font-size:.72rem; color:var(--muted); line-height:1.5; margin-bottom:8px; }
.cb-bias { font-size:.6rem; font-family:var(--mono); padding:2px 7px; border-radius:3px; }
.cb-bias.hawkish { background:rgba(255,82,82,.12); color:var(--down); }
.cb-bias.dovish { background:rgba(0,230,118,.12); color:var(--up); }
.cb-bias.neutral { background:rgba(79,195,247,.1); color:var(--neutral); }
.cb-next { font-size:.65rem; color:var(--dimmed); font-family:var(--mono); }
/* =========================================================
CALENDAR
========================================================= */
.calendar-grid { display:flex; flex-direction:column; gap:6px; }
.cal-item { background:var(--bg); border:1px solid var(--border); border-radius:var(--r); padding:10px 12px; display:flex; gap:12px; align-items:flex-start; border-left-width:3px; transition:border-color .2s; }
.cal-item.high { border-left-color:var(--down); }
.cal-item.medium { border-left-color:var(--warn); }
.cal-item.low { border-left-color:var(--neutral); }
.cal-date { font-family:var(--mono); font-size:.62rem; color:var(--muted); min-width:54px; line-height:1.5; }
.cal-event { font-size:.78rem; color:var(--text); font-weight:500; margin-bottom:3px; }
.cal-values { font-family:var(--mono); font-size:.64rem; color:var(--muted); }
.cal-values span { color:var(--neutral); }
/* =========================================================
AI WATCHLIST
========================================================= */
.watchlist-grid { display:grid; grid-template-columns:repeat(auto-fill,minmax(220px,1fr)); gap:10px; }
.watchlist-card { background:var(--bg); border:1px solid var(--border); border-radius:var(--r); padding:14px; transition:border-color .18s,transform .18s; }
.watchlist-card:hover { border-color:var(--border-l); transform:translateY(-2px); }
.wc-header { display:flex; justify-content:space-between; align-items:flex-start; margin-bottom:8px; }
.wc-ticker { font-family:var(--mono); font-size:.9rem; font-weight:700; color:var(--accent); }
.wc-name { font-size:.65rem; color:var(--muted); margin-top:1px; }
.wc-price { text-align:right; }
.wc-price-val { font-family:var(--mono); font-size:.85rem; font-weight:600; }
.wc-price-chg { font-size:.68rem; }
.wc-price-chg.up { color:var(--up); }
.wc-price-chg.down { color:var(--down); }
.wc-signal-row { display:flex; align-items:center; gap:8px; margin-bottom:7px; }
.signal-badge { font-family:var(--mono); font-size:.65rem; font-weight:700; padding:2px 9px; border-radius:4px; }
.signal-badge.BUY { background:rgba(0,230,118,.15); color:var(--up); border:1px solid rgba(0,230,118,.3); }
.signal-badge.SELL { background:rgba(255,82,82,.15); color:var(--down);border:1px solid rgba(255,82,82,.3); }
.signal-badge.HOLD { background:rgba(255,179,0,.15); color:var(--warn);border:1px solid rgba(255,179,0,.3); }
.wc-score { font-family:var(--mono); font-size:.68rem; color:var(--muted); }
.wc-score span { color:var(--text); font-weight:600; }
.wc-conclusion { font-size:.78rem; color:var(--text); margin-bottom:3px; font-weight:500; line-height:1.4; }
.wc-driver { font-size:.68rem; color:var(--muted); margin-bottom:8px; line-height:1.4; }
.wc-targets { display:flex; gap:6px; font-size:.66rem; margin-bottom:6px; flex-wrap:wrap; }
.wc-target-up { color:var(--up); background:rgba(0,230,118,.1); padding:2px 7px; border-radius:3px; }
.wc-target-down { color:var(--down); background:rgba(255,82,82,.1); padding:2px 7px; border-radius:3px; }
.risk-badge { font-size:.58rem; font-family:var(--mono); padding:2px 6px; border-radius:3px; text-transform:uppercase; }
.risk-badge.low { background:rgba(0,230,118,.12); color:var(--up); }
.risk-badge.medium { background:rgba(255,179,0,.12); color:var(--warn); }
.risk-badge.high { background:rgba(255,82,82,.12); color:var(--down); }
.wc-action { font-size:.68rem; color:var(--muted); line-height:1.4; margin-top:5px; }
/* =========================================================
MARKET DEBATE
========================================================= */
.debate-container { display:flex; flex-direction:column; gap:12px; }
.debate-header { font-family:var(--mono); font-size:.68rem; color:var(--muted); text-transform:uppercase; letter-spacing:.08em; }
.debate-sides { display:grid; grid-template-columns:1fr 1fr; gap:10px; }
@media(max-width:600px){ .debate-sides { grid-template-columns:1fr; } }
.debate-side { background:var(--bg); border-radius:var(--r); padding:12px; }
.debate-side.bull { border-top:2px solid var(--up); }
.debate-side.bear { border-top:2px solid var(--down); }
.debate-side-title { font-size:.68rem; font-weight:600; text-transform:uppercase; letter-spacing:.08em; margin-bottom:8px; }
.debate-side.bull .debate-side-title { color:var(--up); }
.debate-side.bear .debate-side-title { color:var(--down); }
.debate-point { display:flex; align-items:flex-start; gap:7px; margin-bottom:7px; font-size:.76rem; line-height:1.4; }
.conf-badge { font-size:.57rem; font-family:var(--mono); padding:1px 4px; border-radius:3px; flex-shrink:0; margin-top:2px; }
.conf-badge.high { background:rgba(79,195,247,.15); color:var(--neutral); }
.conf-badge.medium { background:rgba(255,179,0,.12); color:var(--warn); }
.debate-verdict { background:var(--bg); border-radius:var(--r); padding:12px 14px; border-left:3px solid var(--accent); }
.verdict-label { font-size:.62rem; font-family:var(--mono); text-transform:uppercase; letter-spacing:.1em; color:var(--muted); margin-bottom:5px; }
.verdict-text { font-size:.81rem; line-height:1.5; }
.verdict-lean { display:inline-block; margin-left:7px; font-size:.62rem; font-family:var(--mono); padding:2px 6px; border-radius:3px; }
.verdict-lean.bullish { background:rgba(0,230,118,.15); color:var(--up); }
.verdict-lean.bearish { background:rgba(255,82,82,.15); color:var(--down); }
.verdict-lean.neutral { background:rgba(79,195,247,.12); color:var(--neutral); }
/* =========================================================
MARKET REPLAY
========================================================= */
.replay-grid { display:grid; grid-template-columns:1fr 1fr; gap:12px; }
@media(max-width:600px){ .replay-grid { grid-template-columns:1fr; } }
.replay-card { background:var(--bg); border:1px solid var(--border); border-radius:var(--r); padding:14px; }
.replay-card-title { font-size:.65rem; font-family:var(--mono); text-transform:uppercase; letter-spacing:.1em; color:var(--accent); margin-bottom:5px; }
.replay-summary { font-size:.82rem; font-weight:500; margin-bottom:10px; line-height:1.4; }
.ad-bar-wrap { display:flex; align-items:center; gap:6px; margin-bottom:8px; font-size:.7rem; }
.ad-bar { height:5px; border-radius:3px; }
.ad-bar.adv { background:var(--up); }
.ad-bar.dec { background:var(--down); }
.ad-label-up { color:var(--up); min-width:45px; font-family:var(--mono); font-size:.68rem; }
.ad-label-dn { color:var(--down); min-width:45px; font-family:var(--mono); font-size:.68rem; }
.replay-stats { display:grid; grid-template-columns:1fr 1fr 1fr; gap:5px; }
.replay-stat { background:rgba(255,255,255,.025); border-radius:5px; padding:6px 8px; }
.replay-stat-label { font-size:.58rem; color:var(--muted); margin-bottom:1px; }
.replay-stat-val { font-size:.76rem; font-weight:600; font-family:var(--mono); }
/* =========================================================
PERSONAL / MY DASHBOARD (collapsible drawer)
========================================================= */
.my-drawer { margin-top: 20px; }
.my-drawer-toggle {
width:100%; padding:11px 16px; background:var(--card); border:1px solid var(--border);
border-radius:var(--r); color:var(--muted); font-size:.78rem; cursor:pointer;
display:flex; align-items:center; justify-content:space-between; font-family:var(--sans);
transition:border-color .18s;
}
.my-drawer-toggle:hover { border-color:var(--border-l); color:var(--text); }
.my-drawer-toggle .drawer-icon { transition:transform .25s; }
.my-drawer-toggle.open .drawer-icon { transform:rotate(180deg); }
.my-drawer-body { display:none; margin-top:8px; }
.my-drawer-body.open { display:block; }
/* =========================================================
SUBSCRIBE STRIP (compact)
========================================================= */
.subscribe-strip {
background: rgba(0,212,170,.05); border: 1px solid rgba(0,212,170,.15);
border-radius: var(--r); padding: 12px 16px;
display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
margin-bottom: 16px;
}
.subscribe-strip-icon { font-size: 1.1rem; flex-shrink: 0; }
.subscribe-strip-body { flex: 1; min-width: 160px; }
.subscribe-strip-body strong { display:block; color:var(--accent); font-size:.82rem; }
.subscribe-strip-body span { font-size:.7rem; color:var(--muted); }
.subscribe-strip-actions { display:flex; gap:7px; flex-wrap:wrap; align-items:center; }
.btn-sub-email, .btn-sub-tg {
font-size:.72rem; padding:6px 12px; border-radius:var(--r); cursor:pointer;
display:flex; align-items:center; gap:5px; white-space:nowrap;
}
.btn-sub-email { background:rgba(0,212,170,.15); color:var(--accent); border:1px solid rgba(0,212,170,.3); }
.btn-sub-tg { background:rgba(79,195,247,.12); color:var(--neutral); border:1px solid rgba(79,195,247,.25); text-decoration:none; }
/* =========================================================
SIMPLE MODE
========================================================= */
body.simple-mode .card-secondary { display: none; }
body.simple-mode .news-item:not(.featured) { display: none; }
/* =========================================================
FAB CLUSTER
========================================================= */
.fab-cluster { position:fixed; bottom:20px; right:16px; display:flex; flex-direction:column; gap:8px; z-index:500; }
.fab { width:40px; height:40px; border-radius:50%; background:var(--card); border:1px solid var(--border); color:var(--text); font-size:1rem; cursor:pointer; display:flex; align-items:center; justify-content:center; transition:border-color .18s; box-shadow:0 4px 16px rgba(0,0,0,.4); }
.fab:hover { border-color:var(--border-l); }
#share-toast { position:fixed; bottom:70px; right:16px; background:var(--card); border:1px solid var(--border); border-radius:var(--r); padding:8px 14px; font-size:.75rem; color:var(--accent); display:none; z-index:600; }
@media(max-width:640px){ .fab-cluster { bottom:70px; } }
/* =========================================================
FOOTER
========================================================= */
.site-footer { border-top:1px solid var(--border); padding:20px 0; margin-top:20px; }
.footer-inner { display:flex; align-items:center; justify-content:space-between; gap:10px; flex-wrap:wrap; font-size:.7rem; color:var(--muted); }
/* =========================================================
ANIMATIONS
========================================================= */
.sec-anchor { animation: fadeUp .3s ease both; }
@keyframes fadeUp { from{opacity:0;transform:translateY(8px)} to{opacity:1;transform:none} }
@media (max-width: 640px) {
.jump-nav { position:fixed; bottom:0; top:auto; left:0; right:0; border-bottom:none; border-top:1px solid var(--border); justify-content:space-around; padding-bottom:env(safe-area-inset-bottom); z-index:200; }
.jump-nav a { padding:7px 3px; font-size:.58rem; flex-direction:column; gap:1px; text-align:center; }
body { padding-bottom: 60px; }
}
/* =========================================================
TRADINGVIEW OVERRIDE
========================================================= */
.tradingview-widget-container { border-radius:var(--r); overflow:hidden; }
.section-block { margin-bottom: 16px; }
/* =========================================================
INTRO OVERLAY ANIMATION
========================================================= */
#intro-overlay {
position: fixed; inset: 0; z-index: 10000;
background: #030609;
display: flex; align-items: center; justify-content: center;
flex-direction: column; overflow: hidden;
transition: opacity .7s ease;
}
#intro-overlay.fade-out { opacity: 0; pointer-events: none; }
#intro-overlay.gone { display: none; }
#intro-canvas { position: absolute; inset: 0; width: 100%; height: 100%; }
#intro-content {
position: relative; z-index: 2;
display: flex; flex-direction: column; align-items: center; gap: 18px;
text-align: center; padding: 0 20px;
}
.intro-badge {
font-size: .62rem; font-family: var(--mono); letter-spacing: .15em;
color: var(--accent); border: 1px solid rgba(0,212,170,.3);
background: rgba(0,212,170,.08); padding: 4px 14px; border-radius: 20px;
animation: fadeUp .6s .4s both;
}
.intro-logo {
display: flex; flex-direction: column; align-items: center; gap: 6px;
animation: fadeUp .7s .7s both;
}
.intro-title-zh {
font-size: clamp(2.2rem, 6vw, 4rem); font-weight: 900;
background: linear-gradient(135deg, #00d4aa, #4fc3f7, #00d4aa);
background-size: 200% 200%;
-webkit-background-clip: text; -webkit-text-fill-color: transparent;
background-clip: text; animation: shimmer 3s ease infinite;
letter-spacing: -.03em;
}
.intro-title-en {
font-size: clamp(.9rem, 2.5vw, 1.4rem); font-weight: 300;
color: rgba(226,232,240,.55); letter-spacing: .25em;
text-transform: uppercase; font-family: var(--mono);
}
@keyframes shimmer {
0% { background-position: 0% 50%; }
50% { background-position: 100% 50%; }
100% { background-position: 0% 50%; }
}
.intro-sub {
font-size: .7rem; color: var(--muted); font-family: var(--mono);
letter-spacing: .08em;
animation: fadeUp .6s 1s both;
}
.intro-ticker-row {
display: flex; gap: 18px; flex-wrap: wrap; justify-content: center;
animation: fadeUp .6s 1.2s both;
}
.intro-tick {
font-family: var(--mono); font-size: .72rem;
background: rgba(255,255,255,.04); border: 1px solid rgba(255,255,255,.08);
border-radius: 6px; padding: 5px 12px; white-space: nowrap;
}
.intro-tick .it-name { color: var(--muted); font-size: .58rem; display: block; margin-bottom: 2px; }
.intro-tick .it-val { color: var(--text); font-weight: 600; }
.intro-tick .it-chg { margin-left: 6px; font-size: .65rem; }
.intro-tick .it-chg.up { color: var(--up); }
.intro-tick .it-chg.down { color: var(--down); }
#intro-skip {
font-size: .7rem; color: var(--muted); background: rgba(255,255,255,.04);
border: 1px solid rgba(255,255,255,.1); border-radius: 20px;
padding: 6px 18px; cursor: pointer; font-family: var(--sans);
transition: color .15s, border-color .15s;
animation: fadeUp .5s 1.6s both;
}
#intro-skip:hover { color: var(--accent); border-color: rgba(0,212,170,.4); }
#intro-progress {
position: absolute; bottom: 0; left: 0; height: 2px;
background: linear-gradient(90deg, var(--accent), #4fc3f7);
width: 0%; transition: width linear;
}
/* =========================================================
LANG TOGGLE
========================================================= */
#lang-btn {
display: flex; align-items: center; gap: 0;
background: rgba(255,255,255,.04); border: 1px solid var(--border);
border-radius: 20px; overflow: hidden; cursor: pointer;
font-size: .62rem; font-family: var(--mono);
transition: border-color .15s;
flex-shrink: 0;
}
#lang-btn:hover { border-color: var(--border-l); }
.lang-opt {
padding: 3px 9px; transition: background .15s, color .15s;
color: var(--muted);
}
.lang-opt.active { background: rgba(0,212,170,.15); color: var(--accent); }
/* =========================================================
I18N: hide/show per lang
========================================================= */
body.lang-en .zh-only { display: none !important; }
body.lang-zh .en-only { display: none !important; }
/* =========================================================
HIDE GOOGLE TRANSLATE CHROME (keep translation, drop UI)
========================================================= */
.goog-te-banner-frame,
.goog-te-balloon-frame,
#goog-gt-tt,
.goog-te-balloon-frame,
.goog-tooltip,
.goog-tooltip:hover,
.goog-text-highlight { display: none !important; }
.skiptranslate { display: none !important; }
body { top: 0 !important; }
iframe.goog-te-menu-frame { display: none !important; }
/* Prevent GT from injecting font-size changes on html */
html.translated-ltr, html.translated-rtl { margin-top: 0 !important; }
</style>
<!-- Google Translate hidden widget -->
<div id="google_translate_element" style="display:none;visibility:hidden;position:absolute;width:0;height:0;"></div>
<script>
function googleTranslateElementInit() {
new google.translate.TranslateElement({
pageLanguage: 'zh-CN',
includedLanguages: 'en,zh-CN',
autoDisplay: false,
gaTrack: false
}, 'google_translate_element');
}
</script>
<script src="https://translate.google.com/translate_a/element.js?cb=googleTranslateElementInit" defer></script>
</head>
<body>
<!-- =========================================================
INTRO OVERLAY
========================================================= -->
<div id="intro-overlay">
<canvas id="intro-canvas"></canvas>
<div id="intro-content">
<div class="intro-badge">AI-POWERED · NORTH AMERICA MARKETS</div>
<div class="intro-logo">
<span class="intro-title-zh">金融日报</span>
<span class="intro-title-en">Financial Daily</span>
</div>
<div class="intro-sub" id="intro-sub">北美华人投资者 · 每日智能金融简报</div>
<div class="intro-ticker-row" id="intro-tickers">
<div class="intro-tick"><span class="it-name">S&amp;P 500</span><span class="it-val" id="it-spy"></span><span class="it-chg" id="it-spy-chg"></span></div>
<div class="intro-tick"><span class="it-name">NASDAQ</span><span class="it-val" id="it-qqq"></span><span class="it-chg" id="it-qqq-chg"></span></div>
<div class="intro-tick"><span class="it-name">BTC</span><span class="it-val" id="it-btc"></span><span class="it-chg" id="it-btc-chg"></span></div>
<div class="intro-tick"><span class="it-name">GOLD</span><span class="it-val" id="it-gld"></span><span class="it-chg" id="it-gld-chg"></span></div>
</div>
<button id="intro-skip" onclick="dismissIntro()">进入 · Enter →</button>
</div>
<div id="intro-progress"></div>
</div>
<div id="reading-progress"></div>
<!-- HEADER -->
<header class="site-header">
<div class="container">
<div class="header-inner">
<div class="logo-block">
<span class="site-title">金融日报</span>
<span class="site-sub">Financial Daily</span>
</div>
<div class="header-meta">
<span class="header-date" id="current-date">Loading...</span>
<div class="header-badge"><span class="pulse-dot"></span>Claude AI</div>
<nav class="header-nav">
<a href="archive/index.html" data-i18n="nav-archive">归档</a>
<a href="feed.xml" style="color:var(--dimmed)">RSS</a>
</nav>
<button id="lang-btn" onclick="toggleLang()" title="切换语言 / Switch Language">
<span class="lang-opt" id="lang-zh">ZH</span>
<span class="lang-opt" id="lang-en">EN</span>
</button>
</div>
</div>
</div>
</header>
<!-- NAV -->
<nav class="jump-nav" id="jump-nav">
<a href="#sec-summary" data-i18n="nav-summary">📊 大势</a>
<a href="#sec-ai-trading" data-i18n="nav-ai-trading">🤖 AI操盘</a>
<a href="#sec-news" data-i18n="nav-news">📰 要闻</a>
<a href="#sec-watchlist" data-i18n="nav-watchlist">🎯 AI分析</a>
<a href="#sec-macro" data-i18n="nav-macro">📈 宏观</a>
<a href="#sec-earnings" data-i18n="nav-earnings">💼 财报</a>
<a href="#sec-sectors" data-i18n="nav-sectors">🏭 行业</a>
<a href="#sec-debate" data-i18n="nav-debate">⚔️ 辩论</a>
<a href="#sec-calendar" data-i18n="nav-calendar">📅 日历</a>
<a href="#sec-my" data-i18n="nav-my">⭐ 我的</a>
</nav>
<!-- INDICES TICKER -->
<section class="indices-section">
<div class="indices-scroll-wrapper">
<div class="indices-track">
<!-- INDICES:START -->
<div class="ticker-card up">
<div class="ticker-name">S&P 500</div>
<div class="ticker-value">7,614.00</div>
<div class="ticker-change up">▲ +0.80%</div>
</div>
<div class="ticker-card up">
<div class="ticker-name">纳斯达克综合</div>
<div class="ticker-value">27,240.00</div>
<div class="ticker-change up">▲ +1.44%</div>
</div>
<div class="ticker-card up">
<div class="ticker-name">道琼斯工业平均</div>
<div class="ticker-value">51,156.00</div>
<div class="ticker-change up">▲ +0.58%</div>
</div>
<div class="ticker-card down">
<div class="ticker-name">上证综指</div>
<div class="ticker-value">3,959.00</div>
<div class="ticker-change down">▼ -1.71%</div>
</div>
<div class="ticker-card down">
<div class="ticker-name">恒生指数</div>
<div class="ticker-value">24,585.00</div>
<div class="ticker-change down">▼ -1.50%</div>
</div>
<div class="ticker-card up">
<div class="ticker-name">日经225</div>
<div class="ticker-value">68,402.00</div>
<div class="ticker-change up">▲ +2.50%</div>
</div>
<div class="ticker-card up">
<div class="ticker-name">德国DAX</div>
<div class="ticker-value">24,890.00</div>
<div class="ticker-change up">▲ +0.48%</div>
</div>
<div class="ticker-card down">
<div class="ticker-name">黄金现货</div>
<div class="ticker-value">4,337.00</div>
<div class="ticker-change down">▼ -0.66%</div>
</div>
<div class="ticker-card down">
<div class="ticker-name">WTI原油</div>
<div class="ticker-value">91.20</div>
<div class="ticker-change down">▼ -1.94%</div>
</div>
<div class="ticker-card up">
<div class="ticker-name">比特币</div>
<div class="ticker-value">63,192.00</div>
<div class="ticker-change up">▲ +1.36%</div>
</div>
<div class="ticker-card up">
<div class="ticker-name">美元指数</div>
<div class="ticker-value">100.25</div>
<div class="ticker-change up">▲ +0.15%</div>
</div>
<div class="ticker-card neutral">
<div class="ticker-name">离岸人民币</div>
<div class="ticker-value">6.7911</div>
<div class="ticker-change neutral"> +0.00%</div>
</div>
<!-- INDICES:END -->
<!-- INDICES:END -->
<!-- duplicate for seamless loop -->
<!-- INDICES:START -->
<div class="ticker-card up">
<div class="ticker-name">S&P 500</div>
<div class="ticker-value">7,614.00</div>
<div class="ticker-change up">▲ +0.80%</div>
</div>
<div class="ticker-card up">
<div class="ticker-name">纳斯达克综合</div>
<div class="ticker-value">27,240.00</div>
<div class="ticker-change up">▲ +1.44%</div>
</div>
<div class="ticker-card up">
<div class="ticker-name">道琼斯工业平均</div>
<div class="ticker-value">51,156.00</div>
<div class="ticker-change up">▲ +0.58%</div>
</div>
<div class="ticker-card down">
<div class="ticker-name">上证综指</div>
<div class="ticker-value">3,959.00</div>
<div class="ticker-change down">▼ -1.71%</div>
</div>
<div class="ticker-card down">
<div class="ticker-name">恒生指数</div>
<div class="ticker-value">24,585.00</div>
<div class="ticker-change down">▼ -1.50%</div>
</div>
<div class="ticker-card up">
<div class="ticker-name">日经225</div>
<div class="ticker-value">68,402.00</div>
<div class="ticker-change up">▲ +2.50%</div>
</div>
<div class="ticker-card up">
<div class="ticker-name">德国DAX</div>
<div class="ticker-value">24,890.00</div>
<div class="ticker-change up">▲ +0.48%</div>
</div>
<div class="ticker-card down">
<div class="ticker-name">黄金现货</div>
<div class="ticker-value">4,337.00</div>
<div class="ticker-change down">▼ -0.66%</div>
</div>
<div class="ticker-card down">
<div class="ticker-name">WTI原油</div>
<div class="ticker-value">91.20</div>
<div class="ticker-change down">▼ -1.94%</div>
</div>
<div class="ticker-card up">
<div class="ticker-name">比特币</div>
<div class="ticker-value">63,192.00</div>
<div class="ticker-change up">▲ +1.36%</div>
</div>
<div class="ticker-card up">
<div class="ticker-name">美元指数</div>
<div class="ticker-value">100.25</div>
<div class="ticker-change up">▲ +0.15%</div>
</div>
<div class="ticker-card neutral">
<div class="ticker-name">离岸人民币</div>
<div class="ticker-value">6.7911</div>
<div class="ticker-change neutral"> +0.00%</div>
</div>
<!-- INDICES:END -->
</div>
</div>
</section>
<!-- SUMMARY HERO -->
<section class="summary-section sec-anchor" id="sec-summary">
<div class="container">
<!-- SUMMARY:START -->
<div class="summary-card neutral">
<div class="summary-top">
<span class="sentiment-pill neutral">🟡 中性 · Neutral</span>
<span class="vix-badge">VIX <span class="vix-num">21.5</span></span>
</div>
<div class="summary-headline">芯片股反弹推动纳指涨1.4%,中东局势缓和油价回落</div>
<ul class="key-points"><li class="kp-item"><span class="kp-arrow"></span>纳指反弹1.4%芯片股领涨</li><li class="kp-item"><span class="kp-arrow"></span>伊朗宣布停火油价回落</li><li class="kp-item"><span class="kp-arrow"></span>就业强劲强化加息预期</li></ul>
<details class="summary-details">
<summary class="summary-details-toggle">深度解读 ▸</summary>
<div class="summary-context">美股周一小幅反弹,纳斯达克100涨1.5%领涨,标普500涨0.8%,投资者从上周五强劲就业报告引发的抛售中恢复。中东紧张局势有所缓和,伊朗宣布停止对以色列的军事行动,油价回落至91美元附近。对北美华人投资者而言,科技股短期反弹提供了评估AI投资价值的窗口,但美联储加息预期上升(市场预期年内加息概率达50%)和持续的地缘政治风险仍需警惕。</div>
</details>
</div>
<!-- SUMMARY:END -->
<!-- SUMMARY:END -->
</div>
</section>
<!-- PODCAST PLAYER -->
<div class="podcast-bar" id="podcast-bar">
<div class="container">
<div class="podcast-inner">
<div class="podcast-left">
<span class="podcast-icon">🎙️</span>
<div class="podcast-info">
<div class="podcast-title">金融日报早报 · 今日播客</div>
<div class="podcast-sub" id="podcast-date">欣欣 & 建国 · 约3分钟</div>
</div>
</div>
<div class="podcast-controls">
<audio id="podcast-audio" preload="none">
<source src="audio/latest.mp3" type="audio/mpeg">
</audio>
<button class="pod-btn" id="pod-play" onclick="togglePodcast()">▶ 播放</button>
<div class="pod-progress-wrap" onclick="seekPodcast(event)">
<div class="pod-progress-bar" id="pod-progress"></div>
</div>
<span class="pod-time" id="pod-time">0:00</span>
<button class="pod-btn pod-btn-sm" onclick="document.getElementById('podcast-audio').playbackRate=document.getElementById('podcast-audio').playbackRate===1?1.5:1;this.textContent=document.getElementById('podcast-audio').playbackRate+'x'">1x</button>
<a class="pod-btn pod-btn-sm" href="audio/latest.mp3" download="金融日报早报.mp3" title="下载"></a>
</div>
</div>
</div>
</div>
<style>
.podcast-bar {
background: linear-gradient(90deg, rgba(0,212,170,.08), rgba(79,195,247,.05));
border-bottom: 1px solid rgba(0,212,170,.2);
padding: 10px 0;
}
.podcast-inner { display:flex; align-items:center; justify-content:space-between; gap:14px; flex-wrap:wrap; }
.podcast-left { display:flex; align-items:center; gap:10px; }
.podcast-icon { font-size:1.4rem; animation: pulse-pod 3s ease-in-out infinite; }
@keyframes pulse-pod { 0%,100%{transform:scale(1)} 50%{transform:scale(1.1)} }
.podcast-title { font-size:.82rem; font-weight:600; color:var(--text); }
.podcast-sub { font-size:.65rem; color:var(--muted); font-family:var(--mono); margin-top:1px; }
.podcast-controls { display:flex; align-items:center; gap:10px; flex-wrap:wrap; }
.pod-btn {
background: rgba(0,212,170,.15); color:var(--accent);
border: 1px solid rgba(0,212,170,.3); border-radius:6px;
padding: 5px 14px; font-size:.75rem; cursor:pointer;
font-family:var(--sans); transition:background .15s; white-space:nowrap;
}
.pod-btn:hover { background:rgba(0,212,170,.25); }
.pod-btn.playing { background:rgba(255,82,82,.12); color:var(--down); border-color:rgba(255,82,82,.3); }
.pod-btn-sm { padding:5px 9px; font-size:.68rem; }
.pod-btn-sm[download] { color:var(--muted); background:rgba(255,255,255,.05); border-color:var(--border); text-decoration:none; }
.pod-progress-wrap { width:160px; height:4px; background:var(--border); border-radius:2px; cursor:pointer; }
@media(max-width:640px){ .pod-progress-wrap { width:80px; } }
.pod-progress-bar { height:100%; background:var(--accent); border-radius:2px; width:0%; transition:width .3s linear; }
.pod-time { font-family:var(--mono); font-size:.65rem; color:var(--muted); min-width:32px; }
</style>
<script>
(function(){
var audio = document.getElementById('podcast-audio');
var btn = document.getElementById('pod-play');
var bar = document.getElementById('pod-progress');
var time = document.getElementById('pod-time');
if (!audio) return;
// Check if audio exists
fetch('audio/latest-meta.json').then(r=>r.json()).then(m=>{
document.getElementById('podcast-date').textContent = '欣欣 & 建国 · ' + m.date + ' · 约3分钟';
}).catch(()=>{
document.getElementById('podcast-bar').style.opacity = '0.4';
btn.textContent = '暂无音频';
btn.disabled = true;
});
audio.addEventListener('timeupdate', function(){
if (!audio.duration) return;
bar.style.width = (audio.currentTime / audio.duration * 100) + '%';
var m = Math.floor(audio.currentTime/60);
var s = Math.floor(audio.currentTime%60);
time.textContent = m + ':' + (s<10?'0':'')+s;
});
audio.addEventListener('ended', function(){
btn.textContent = '▶ 播放';
btn.classList.remove('playing');
bar.style.width = '0%';
});
window.togglePodcast = function(){
if (audio.paused) {
audio.play();
btn.textContent = '⏸ 暂停';
btn.classList.add('playing');
} else {
audio.pause();
btn.textContent = '▶ 播放';
btn.classList.remove('playing');
}
};
window.seekPodcast = function(e){
if (!audio.duration) return;
var rect = e.currentTarget.getBoundingClientRect();
audio.currentTime = ((e.clientX - rect.left) / rect.width) * audio.duration;
};
})();
</script>
<!-- MAIN PAGE BODY -->
<div class="page-body">
<div class="container">
<!-- SUBSCRIBE (dismissible) -->
<div class="subscribe-strip" id="subscribe-strip">
<div class="subscribe-strip-icon">📬</div>
<div class="subscribe-strip-body">
<strong>订阅每日金融早报</strong>
<span>每个交易日自动更新,开盘前 + 收盘后各一次</span>
</div>
<div class="subscribe-strip-actions">
<form action="https://buttondown.email/api/emails/embed-subscribe/yangbai0110" method="post" target="_blank" style="display:flex;gap:6px;">
<input type="email" name="email" placeholder="your@email.com" required style="padding:6px 10px;border-radius:6px;border:1px solid var(--border);background:rgba(255,255,255,.05);color:var(--text);font-size:.73rem;width:148px;outline:none;" />
<button type="submit" class="btn-sub-email">📧 邮件</button>
</form>
<a href="https://t.me/GGmanm_bot?start=subscribe" target="_blank" class="btn-sub-tg">
<svg width="12" height="12" viewBox="0 0 24 24" fill="currentColor"><path d="M12 0C5.373 0 0 5.373 0 12s5.373 12 12 12 12-5.373 12-12S18.627 0 12 0zm5.894 8.221-1.97 9.28c-.145.658-.537.818-1.084.508l-3-2.21-1.447 1.394c-.16.16-.295.295-.605.295l.213-3.053 5.56-5.023c.242-.213-.054-.333-.373-.12L7.44 13.55l-2.955-.924c-.643-.204-.657-.643.136-.953l11.566-4.461c.537-.194 1.006.131.707.009z"/></svg>
Telegram
</a>
<button onclick="document.getElementById('subscribe-strip').style.display='none';localStorage.setItem('fd_sub_dismissed','1');" style="background:none;border:none;color:var(--dimmed);cursor:pointer;font-size:1rem;padding:2px 4px;" title="关闭">×</button>
</div>
</div>
<!-- PRIMARY GRID: main content + sidebar -->
<div class="content-grid">
<!-- ── LEFT / MAIN COLUMN ─────────────────────────────── -->
<div class="main-col">
<!-- NEWS -->
<div class="section-block sec-anchor" id="sec-news">
<div class="card">
<div class="section-label">📰 市场要闻 · Market News</div>
<!-- NEWS:START -->
<div class="news-item breaking featured" onclick="toggleNews(this)">
<div class="news-header">
<span class="imp-dot breaking"></span>
<div class="news-title"><a href="https://www.npr.org/2026/06/08/nx-s1-5847937/apple-wwdc-2026-siri-ai-tim-cook" target="_blank" rel="noopener">苹果WWDC发布全新Siri AI,库克最后一次开发者大会</a></div>
<span class="news-expand-icon"></span>
</div>
<div class="news-tldr"><span class="tldr-label">💡 新手解读</span>苹果AI升级未能说服市场,持有AAPL的投资者短期或面临压力,建议等待更清晰的收入转化信号</div>
<div class="news-body-collapse">苹果在周一WWDC上发布与谷歌合作开发的全新Siri AI,可基于屏幕内容和个人上下文回答问题,支持多步骤任务。这是库克作为CEO最后一次主持开发者大会,他将于9月交棒给硬件负责人John Ternus。但股价发布后下跌2%,分析师认为苹果AI战略仍需证明执行力。</div>
<div class="news-footer">
<span class="importance-badge breaking">🔥 BREAKING</span>
<div class="tags"><span class="tag">#苹果</span><span class="tag">#AI</span><span class="tag">#科技</span></div>
</div>
</div>
<div class="news-item breaking featured" onclick="toggleNews(this)">
<div class="news-header">
<span class="imp-dot breaking"></span>
<div class="news-title"><a href="https://www.cnbc.com/2026/06/03/spacex-ipo-stock-price-roadshow-musk.html" target="_blank" rel="noopener">SpaceX启动史上最大IPO路演,目标估值1.77万亿美元</a></div>
<span class="news-expand-icon"></span>
</div>
<div class="news-tldr"><span class="tldr-label">💡 新手解读</span>史上最大IPO来袭但估值存疑,普通投资者建议观望,等待上市后更合理的买入机会</div>
<div class="news-body-collapse">马斯克旗下SpaceX于6月4日启动IPO路演,目标融资750亿美元,IPO定价135美元/股,估值1.77万亿美元,将成为美国第七大公司,超过特斯拉。计划6月12日在纳斯达克以代码SPCX上市。但晨星分析师认为其估值过高,实际价值仅7800亿美元,较私募估值低48%,xAI部门持续亏损构成重大风险。</div>
<div class="news-footer">
<span class="importance-badge breaking">🔥 BREAKING</span>
<div class="tags"><span class="tag">#IPO</span><span class="tag">#SpaceX</span><span class="tag">#马斯克</span></div>
</div>
</div>
<div class="news-item high featured" onclick="toggleNews(this)">
<div class="news-header">
<span class="imp-dot high"></span>
<div class="news-title"><a href="https://www.schwab.com/learn/story/stock-market-update-open" target="_blank" rel="noopener">5月就业强劲超预期,美联储加息预期骤升至50%</a></div>
<span class="news-expand-icon"></span>
</div>
<div class="news-tldr"><span class="tldr-label">💡 新手解读</span>就业太强反而利空股市,持有股票ETF的投资者需警惕加息风险,可考虑增配防御性板块</div>
<div class="news-body-collapse">美国5月新增就业17.2万人,是预期的两倍,失业率维持4.3%。强劲数据推动10年期国债收益率跳升至4.54%,市场对美联储年内加息的定价从此前的零上升至50%概率。'好消息即坏消息'情绪主导,上周五纳指暴跌4.2%,标普500跌2.6%VIX飙升至21.5。</div>
<div class="news-footer">
<span class="importance-badge high">• HIGH</span>
<div class="tags"><span class="tag">#就业</span><span class="tag">#美联储</span><span class="tag">#通胀</span></div>
</div>
</div>
<div class="news-item high" onclick="toggleNews(this)">
<div class="news-header">
<span class="imp-dot high"></span>
<div class="news-title"><a href="https://tradingeconomics.com/united-states/stock-market" target="_blank" rel="noopener">伊朗宣布停止对以色列军事行动,中东局势暂时缓和</a></div>
<span class="news-expand-icon"></span>
</div>
<div class="news-tldr"><span class="tldr-label">💡 新手解读</span>中东短期停火利好风险资产,但能源危机未解,持有能源ETF可对冲通胀风险</div>
<div class="news-body-collapse">伊朗外交部周一宣布已停止对以色列的打击,但警告如果以色列继续在黎巴嫩的行动将恢复敌对。特朗普总统表示和谈取得进展接近完成。这缓解了市场对冲突升级的担忧,WTI原油从周五高点回落至91美元,能源板块领跌。但霍尔木兹海峡仍基本关闭,全球20%油气供应中断,长期能源价格压力仍存。</div>
<div class="news-footer">
<span class="importance-badge high">• HIGH</span>
<div class="tags"><span class="tag">#中东</span><span class="tag">#油价</span><span class="tag">#地缘政治</span></div>
</div>
</div>
<div class="news-item high" onclick="toggleNews(this)">
<div class="news-header">
<span class="imp-dot high"></span>
<div class="news-title"><a href="https://www.thestreet.com/stock-market-today/stock-market-today-dow-jones-sp-500-nasdaq-updates-june-08-2026" target="_blank" rel="noopener">英特尔股价暴涨10%,获谷歌300万颗AI芯片订单</a></div>
<span class="news-expand-icon"></span>
</div>
<div class="news-tldr"><span class="tldr-label">💡 新手解读</span>英特尔获AI芯片大单重振信心,看好美国半导体制造复兴,可关注INTC及相关ETF</div>
<div class="news-body-collapse">英特尔股价周一飙升10%至109美元,因报道称谷歌向其下单超过300万颗TPU芯片用于2028年交付。英伟达也在评估英特尔技术用于生产四芯片组合处理器的可行性。特斯拉CEO马斯克4月表示将使用英特尔14A制程为Terafab项目生产芯片。这显示英特尔在代工领域取得重大突破,挑战台积电主导地位。</div>
<div class="news-footer">
<span class="importance-badge high">• HIGH</span>
<div class="tags"><span class="tag">#英特尔</span><span class="tag">#AI芯片</span><span class="tag">#半导体</span></div>
</div>
</div>
<div class="news-item high" onclick="toggleNews(this)">
<div class="news-header">
<span class="imp-dot high"></span>
<div class="news-title"><a href="https://tradingeconomics.com/china/stock-market" target="_blank" rel="noopener">中国股市科技股领跌,上证跌1.7%至两月低点</a></div>
<span class="news-expand-icon"></span>
</div>
<div class="news-tldr"><span class="tldr-label">💡 新手解读</span>A股科技股补跌压力仍存,持有中概股或A股基金的投资者需谨慎,关注政策面变化</div>
<div class="news-body-collapse">上证综指周一暴跌1.7%至3959点,创两个月新低,深证成指跌3.2%至14821点。科技股受华尔街AI股抛售拖累,中际旭创跌2.1%,光迅科技跌3.1%,北方华创跌2.9%。习近平主席抵达朝鲜进行2019年以来首次访问,关注无核化和朝美关系。投资者等待本周中国贸易和通胀数据。</div>
<div class="news-footer">
<span class="importance-badge high">• HIGH</span>
<div class="tags"><span class="tag">#A股</span><span class="tag">#中国</span><span class="tag">#科技股</span></div>
</div>
</div>
<div class="news-item medium" onclick="toggleNews(this)">
<div class="news-header">
<span class="imp-dot medium"></span>
<div class="news-title"><a href="https://www.thestreet.com/stock-market-today/stock-market-today-dow-jones-sp-500-nasdaq-updates-june-08-2026" target="_blank" rel="noopener">Marvell将加入标普500,芯片股今年涨210%</a></div>
<span class="news-expand-icon"></span>
</div>
<div class="news-tldr"><span class="tldr-label">💡 新手解读</span>芯片股被动资金流入在即,已持有MRVL的投资者可继续持有,未入场者注意估值风险</div>
<div class="news-body-collapse">标普道琼斯指数公司宣布AI芯片制造商Marvell将于6月22日加入标普500指数,Marvell股价盘前飙升9%至287美元。该公司今年以来已暴涨210%,市值达2300亿美元。Flex也将同时加入标普500,股价涨4.3%至158.50美元。这反映标普对AI基础设施公司认可度提升。</div>
<div class="news-footer">
<span class="importance-badge medium">• MEDIUM</span>
<div class="tags"><span class="tag">#Marvell</span><span class="tag">#标普500</span><span class="tag">#指数调整</span></div>
</div>
</div>
<!-- NEWS:END -->
<!-- NEWS:END -->
</div>
</div>
<!-- AI 操盘实验 -->
<div class="section-block sec-anchor" id="sec-ai-trading">
<div class="card">
<div class="section-label">🤖 AI 操盘实验 · AI Trading Challenge</div>
<div id="ai-portfolio-loading" style="color:var(--muted);font-size:0.82rem;padding:8px 0;">加载中…</div>
<div id="ai-portfolio-content" style="display:none">
<!-- 排行榜 -->
<div style="font-size:0.72rem;text-transform:uppercase;letter-spacing:0.08em;color:var(--muted);margin-bottom:10px;">🏆 排行榜 · Leaderboard <span style="font-size:0.68rem;color:var(--dimmed);margin-left:6px;">初始资金 $10,000 · 基线 SPY买入持有</span></div>
<div id="ai-leaderboard" style="display:flex;flex-direction:column;gap:8px;margin-bottom:18px;"></div>
<!-- 各模型详情 Tab -->
<div style="display:flex;gap:6px;margin-bottom:12px;" id="ai-model-tabs"></div>
<div id="ai-model-detail"></div>
<!-- 历史对比表 -->
<div id="ai-history-wrap" style="margin-top:16px;">
<div style="font-size:0.72rem;text-transform:uppercase;letter-spacing:0.08em;color:var(--muted);margin-bottom:8px;">📈 历史表现对比</div>
<div id="ai-history-table" style="font-family:var(--mono);font-size:0.76rem;"></div>
</div>
</div>
</div>
</div>
<!-- AI WATCHLIST -->
<section class="section-block sec-anchor" id="sec-watchlist">
<div class="card">
<div class="section-label">🎯 AI 决策仪表盘 · AI Watchlist</div>
<!-- WATCHLIST_ANALYSIS:START -->
<div class="watchlist-grid">
<div class="watchlist-card">
<div class="wc-header">
<div><div class="wc-ticker">NVDA</div><div class="wc-name">英伟达</div></div>
<div class="wc-price"><div class="wc-price-val">208.61</div><div class="wc-price-chg up">+2.0%</div></div>
</div>
<div class="wc-signal-row">
<span class="signal-badge HOLD">HOLD</span>
<span class="wc-score">评分 <span>65</span>/100</span>
</div>
<div class="wc-conclusion">短期反弹但估值高企,观望为主</div>
<div class="wc-driver">周一反弹2%收复部分上周五失地,但今年回撤7%,AI需求持续但竞争加剧</div>
<div class="wc-targets"><span class="wc-target-up">↑ 235</span><span class="wc-target-down">↓ 199</span></div>
<div style="display:flex;align-items:center;gap:8px;margin-bottom:6px"><span class="risk-badge high">风险:high</span></div>
<div class="wc-action">已持有者继续持有,未入场者等待回调至200美元支撑位再考虑建仓,关注8月26日财报</div>
<div class="tags" style="margin-top:8px"><span class="tag">#AI</span><span class="tag">#芯片</span><span class="tag">#高估值</span></div>
</div>
<div class="watchlist-card">
<div class="wc-header">
<div><div class="wc-ticker">QQQ</div><div class="wc-name">纳斯达克100 ETF</div></div>
<div class="wc-price"><div class="wc-price-val">708.00</div><div class="wc-price-chg up">+1.5%</div></div>
</div>
<div class="wc-signal-row">
<span class="signal-badge BUY">BUY</span>
<span class="wc-score">评分 <span>72</span>/100</span>
</div>
<div class="wc-conclusion">科技反弹提供配置机会</div>
<div class="wc-driver">过去30天涨11%从637美元反弹,AI芯片股和大型科技股财报强劲推动,持仓集中度高</div>
<div class="wc-targets"><span class="wc-target-up">↑ 735</span><span class="wc-target-down">↓ 680</span></div>
<div style="display:flex;align-items:center;gap:8px;margin-bottom:6px"><span class="risk-badge medium">风险:medium</span></div>
<div class="wc-action">短期回调提供买入机会,建议分批建仓,止损设在680美元,目标735美元,关注本周CPI数据</div>
<div class="tags" style="margin-top:8px"><span class="tag">#科技</span><span class="tag">#ETF</span><span class="tag">#AI</span></div>
</div>
<div class="watchlist-card">
<div class="wc-header">
<div><div class="wc-ticker">SPY</div><div class="wc-name">标普500 ETF</div></div>
<div class="wc-price"><div class="wc-price-val">761.40</div><div class="wc-price-chg up">+0.8%</div></div>
</div>
<div class="wc-signal-row">
<span class="signal-badge HOLD">HOLD</span>
<span class="wc-score">评分 <span>68</span>/100</span>
</div>
<div class="wc-conclusion">大盘企稳但上行空间有限</div>
<div class="wc-driver">今年涨11%,估值偏高PE约21倍,加息预期和地缘风险限制上行空间</div>
<div class="wc-targets"><span class="wc-target-up">↑ 780</span><span class="wc-target-down">↓ 740</span></div>
<div style="display:flex;align-items:center;gap:8px;margin-bottom:6px"><span class="risk-badge medium">风险:medium</span></div>
<div class="wc-action">核心持仓维持不变,暂不追高,建议配置部分防御性板块对冲风险,关注VIX回落至15以下再加仓</div>
<div class="tags" style="margin-top:8px"><span class="tag">#大盘</span><span class="tag">#ETF</span><span class="tag">#防御</span></div>
</div>
<div class="watchlist-card">
<div class="wc-header">
<div><div class="wc-ticker">BTC-USD</div><div class="wc-name">比特币</div></div>
<div class="wc-price"><div class="wc-price-val">63192</div><div class="wc-price-chg up">+1.4%</div></div>
</div>
<div class="wc-signal-row">
<span class="signal-badge SELL">SELL</span>
<span class="wc-score">评分 <span>42</span>/100</span>
</div>
<div class="wc-conclusion">短期反弹难改下行趋势</div>
<div class="wc-driver">周一小幅反弹但本周跌势创2月以来最差,ETF连续净流出,投机资金转向AI股</div>
<div class="wc-targets"><span class="wc-target-up">↑ 65000</span><span class="wc-target-down">↓ 60000</span></div>
<div style="display:flex;align-items:center;gap:8px;margin-bottom:6px"><span class="risk-badge high">风险:high</span></div>
<div class="wc-action">建议减仓或止损离场,技术面显示可能跌向49000美元甚至更低,等待更清晰的底部信号</div>
<div class="tags" style="margin-top:8px"><span class="tag">#加密货币</span><span class="tag">#高风险</span><span class="tag">#下跌趋势</span></div>
</div>
<div class="watchlist-card">
<div class="wc-header">
<div><div class="wc-ticker">510300.SS</div><div class="wc-name">沪深300 ETF</div></div>
<div class="wc-price"><div class="wc-price-val">4707.00</div><div class="wc-price-chg down">-1.2%</div></div>
</div>
<div class="wc-signal-row">
<span class="signal-badge HOLD">HOLD</span>
<span class="wc-score">评分 <span>55</span>/100</span>
</div>
<div class="wc-conclusion">政策底显现但市场底未明</div>
<div class="wc-driver">A股周一科技股补跌,CSI 300指数跌至4月以来低点,四周跌3.6%但全年仍涨21%</div>
<div class="wc-targets"><span class="wc-target-up">↑ 4850</span><span class="wc-target-down">↓ 4600</span></div>
<div style="display:flex;align-items:center;gap:8px;margin-bottom:6px"><span class="risk-badge medium">风险:medium</span></div>
<div class="wc-action">长期配置可分批建仓,短期观望本周贸易和通胀数据,等待政策面进一步宽松信号</div>
<div class="tags" style="margin-top:8px"><span class="tag">#A股</span><span class="tag">#中国</span><span class="tag">#政策底</span></div>
</div>
<div class="watchlist-card">
<div class="wc-header">
<div><div class="wc-ticker">GC=F</div><div class="wc-name">黄金期货</div></div>
<div class="wc-price"><div class="wc-price-val">4337</div><div class="wc-price-chg down">-0.7%</div></div>
</div>
<div class="wc-signal-row">
<span class="signal-badge BUY">BUY</span>
<span class="wc-score">评分 <span>78</span>/100</span>
</div>
<div class="wc-conclusion">避险资产回调提供买入良机</div>
<div class="wc-driver">中东局势缓和引发获利回吐,但今年仍涨30%,央行购金需求强劲,长期上行趋势不变</div>
<div class="wc-targets"><span class="wc-target-up">↑ 4500</span><span class="wc-target-down">↓ 4250</span></div>
<div style="display:flex;align-items:center;gap:8px;margin-bottom:6px"><span class="risk-badge low">风险:low</span></div>
<div class="wc-action">回调至4250-4300美元区间积极买入,长期持有对冲通胀和地缘风险,目标4500-4600美元</div>
<div class="tags" style="margin-top:8px"><span class="tag">#避险</span><span class="tag">#通胀对冲</span><span class="tag">#央行购金</span></div>
</div>
<div class="watchlist-card">
<div class="wc-header">
<div><div class="wc-ticker">CL=F</div><div class="wc-name">WTI原油</div></div>
<div class="wc-price"><div class="wc-price-val">91.20</div><div class="wc-price-chg down">-1.9%</div></div>
</div>
<div class="wc-signal-row">
<span class="signal-badge HOLD">HOLD</span>
<span class="wc-score">评分 <span>62</span>/100</span>
</div>
<div class="wc-conclusion">短期回调但供应风险仍存</div>
<div class="wc-driver">伊朗停火消息引发回落,但霍尔木兹海峡关闭令全球20%油供中断,IEA称史上最大供应中断</div>
<div class="wc-targets"><span class="wc-target-up">↑ 100</span><span class="wc-target-down">↓ 85</span></div>
<div style="display:flex;align-items:center;gap:8px;margin-bottom:6px"><span class="risk-badge high">风险:high</span></div>
<div class="wc-action">持有能源ETF对冲通胀风险,90美元上方减仓获利,80-85美元支撑位考虑重新建仓</div>
<div class="tags" style="margin-top:8px"><span class="tag">#能源</span><span class="tag">#中东</span><span class="tag">#供应中断</span></div>
</div>
<div class="watchlist-card">
<div class="wc-header">
<div><div class="wc-ticker">TSLA</div><div class="wc-name">特斯拉</div></div>
<div class="wc-price"><div class="wc-price-val">440.00</div><div class="wc-price-chg up">+1.8%</div></div>
</div>
<div class="wc-signal-row">
<span class="signal-badge HOLD">HOLD</span>
<span class="wc-score">评分 <span>58</span>/100</span>
</div>
<div class="wc-conclusion">波动剧烈需谨慎应对</div>
<div class="wc-driver">周一温和反弹但投机性强,与SpaceX合作关系受关注,马斯克讨论合并两公司可能性</div>
<div class="wc-targets"><span class="wc-target-up">↑ 467</span><span class="wc-target-down">↓ 423</span></div>
<div style="display:flex;align-items:center;gap:8px;margin-bottom:6px"><span class="risk-badge high">风险:high</span></div>
<div class="wc-action">短线交易者可在440支撑位上方持有,跌破431美元果断止损,长期投资者建议观望至更清晰催化剂</div>
<div class="tags" style="margin-top:8px"><span class="tag">#电动车</span><span class="tag">#马斯克</span><span class="tag">#高波动</span></div>
</div>
</div>
<!-- WATCHLIST_ANALYSIS:END -->
<!-- WATCHLIST_ANALYSIS:END -->
</div>
</section>
<!-- MACRO + DEBATE (2-up) -->
<div class="two-up">
<div class="section-block sec-anchor" id="sec-macro">
<div class="card" style="height:100%">
<div class="section-label">📈 宏观指标 · Macro</div>
<!-- MACRO:START -->
<div class="macro-grid">
<div class="macro-card dir-down">
<div class="macro-indicator">Nonfarm Payrolls (5月)</div>
<div class="macro-value macro-value-down">172,000</div>
<div class="macro-prev"><span class="arrow down"></span> 前值: 179,000 (修正后)</div>
<div class="macro-desc">5月新增就业17.2万,大幅超过预期的8.5万,显示劳动力市场韧性强于预期,推高加息预期</div>
</div>
<div class="macro-card dir-neutral">
<div class="macro-indicator">Unemployment Rate (5月)</div>
<div class="macro-value ">4.3%</div>
<div class="macro-prev"><span class="arrow "></span> 前值: 4.3%</div>
<div class="macro-desc">失业率维持4.3%不变,劳动力参与率稳定,平均时薪月增0.3%符合预期</div>
</div>
<div class="macro-card dir-up">
<div class="macro-indicator">CPI YoY (4月)</div>
<div class="macro-value macro-value-down">3.8%</div>
<div class="macro-prev"><span class="arrow up"></span> 前值: 3.3%</div>
<div class="macro-desc">4月CPI同比3.8%,为2023年5月以来最高,核心CPI 2.8%,通胀压力重新抬头</div>
</div>
<div class="macro-card dir-up">
<div class="macro-indicator">Core PCE (4月)</div>
<div class="macro-value macro-value-down">3.3%</div>
<div class="macro-prev"><span class="arrow up"></span> 前值: 3.2%</div>
<div class="macro-desc">美联储首选通胀指标核心PCE 4月同比3.3%,连续两月上升,年化增速6.02%</div>
</div>
<div class="macro-card dir-up">
<div class="macro-indicator">10-Year Treasury Yield</div>
<div class="macro-value macro-value-up">4.54%</div>
<div class="macro-prev"><span class="arrow up"></span> 前值: 4.51%</div>
<div class="macro-desc">10年期国债收益率因强劲就业数据跳升至4.54%,20年和30年期收益率重回5%以上</div>
</div>
<div class="macro-card dir-down">
<div class="macro-indicator">WTI Crude Oil</div>
<div class="macro-value macro-value-down">$91.20</div>
<div class="macro-prev"><span class="arrow down"></span> 前值: $93.00</div>
<div class="macro-desc">WTI原油从周五高点回落至91美元,伊朗停火缓解供应担忧,但霍尔木兹海峡关闭持续</div>
</div>
<div class="macro-card dir-up">
<div class="macro-indicator">Q1 GDP (二次估计)</div>
<div class="macro-value macro-value-up">2.0%</div>
<div class="macro-prev"><span class="arrow up"></span> 前值: 0.5% (Q4 2025)</div>
<div class="macro-desc">美国一季度GDP年化增速2.0%,较去年四季度0.5%大幅回升,但Q1 PCE价格指数飙升4.5%</div>
</div>
<div class="macro-card dir-up">
<div class="macro-indicator">ISM Manufacturing PMI (5月预期)</div>
<div class="macro-value macro-value-up">预期 49.5</div>
<div class="macro-prev"><span class="arrow up"></span> 前值: 48.7</div>
<div class="macro-desc">5月制造业PMI预计小幅回升但仍处收缩区间,制造业活动持续疲软</div>
</div>
</div>
<!-- MACRO:END -->
<!-- MACRO:END -->
</div>
</div>
<div class="section-block sec-anchor" id="sec-debate">
<div class="card" style="height:100%">
<div class="section-label">⚔️ 多空辩论 · Bull vs Bear</div>
<!-- MARKET_DEBATE:START -->
<div class="debate-container">
<div class="debate-header">标普500 本周展望</div>
<div class="debate-sides">
<div class="debate-side bull">
<div class="debate-side-title">🐂 多方看涨</div>
<div class="debate-point"><span class="conf-badge high">high</span>科技股反弹动能强劲,AI投资持续</div>
<div class="debate-point"><span class="conf-badge medium">medium</span>中东局势缓和降低地缘风险溢价</div>
<div class="debate-point"><span class="conf-badge high">high</span>企业盈利增长29%支撑估值</div>
</div>
<div class="debate-side bear">
<div class="debate-side-title">🐻 空方看跌</div>
<div class="debate-point"><span class="conf-badge high">high</span>就业强劲推高加息预期至50%</div>
<div class="debate-point"><span class="conf-badge high">high</span>CPI周三公布或显示通胀粘性</div>
<div class="debate-point"><span class="conf-badge medium">medium</span>标普500估值PE 21倍处历史高位</div>
</div>
</div>
<div class="debate-verdict">
<div class="verdict-label">裁判结论 <span class="verdict-lean neutral">NEUTRAL</span></div>
<div class="verdict-text">短期震荡为主,方向取决于周三CPI数据。若CPI低于预期,市场将延续反弹;若符合或高于预期,加息预期将压制指数。SpaceX IPO可能分流科技股资金。建议防御性配置,等待更清晰信号</div>
</div>
</div>
<!-- MARKET_DEBATE:END -->
<!-- MARKET_DEBATE:END -->
</div>
</div>
</div>
<!-- EARNINGS + SECTORS (2-up) -->
<div class="two-up">
<div class="section-block sec-anchor" id="sec-earnings">
<div class="card">
<div class="section-label">💼 财报追踪 · Earnings</div>
<!-- EARNINGS:START -->
<div class="earnings-grid">
<div class="earnings-card pending">
<div class="earnings-ticker">ORCL</div>
<div class="earnings-company">Oracle</div>
<span class="earnings-beat-badge pending">UPCOMING</span>
<div class="earnings-eps">
<div class="eps-item">
<div class="eps-label">EPS EST.</div>
<div class="eps-value est">$1.35</div>
</div>
<div class="eps-item">
<div class="eps-label">REPORT DATE</div>
<div class="eps-value est" style="font-size:0.75rem;">2026-06-10</div>
</div>
</div>
<div class="earnings-revenue">收入: <span>预期 $15.8B</span></div>
<div class="earnings-highlight">AI数据中心需求关键测试,市场预期资本支出达500亿美元,股价近月上涨16%</div>
</div>
<div class="earnings-card pending">
<div class="earnings-ticker">ADBE</div>
<div class="earnings-company">Adobe</div>
<span class="earnings-beat-badge pending">UPCOMING</span>
<div class="earnings-eps">
<div class="eps-item">
<div class="eps-label">EPS EST.</div>
<div class="eps-value est">$4.38</div>
</div>
<div class="eps-item">
<div class="eps-label">REPORT DATE</div>
<div class="eps-value est" style="font-size:0.75rem;">2026-06-11</div>
</div>
</div>
<div class="earnings-revenue">收入: <span>预期 $5.3B</span></div>
<div class="earnings-highlight">Q2财报聚焦AI创意工具采用率,分析师预计营收增长率达37%五年CAGR</div>
</div>
<div class="earnings-card pending">
<div class="earnings-ticker">CPB</div>
<div class="earnings-company">Campbell's</div>
<span class="earnings-beat-badge pending">UPCOMING</span>
<div class="earnings-eps">
<div class="eps-item">
<div class="eps-label">EPS EST.</div>
<div class="eps-value est">$0.70</div>
</div>
<div class="eps-item">
<div class="eps-label">REPORT DATE</div>
<div class="eps-value est" style="font-size:0.75rem;">2026-06-09</div>
</div>
</div>
<div class="earnings-revenue">收入: <span>预期 $2.1B</span></div>
<div class="earnings-highlight">消费品公司财报测试消费者支出韧性,通胀环境下定价权成关注焦点</div>
</div>
<div class="earnings-card pending">
<div class="earnings-ticker">CHWY</div>
<div class="earnings-company">Chewy</div>
<span class="earnings-beat-badge pending">UPCOMING</span>
<div class="earnings-eps">
<div class="eps-item">
<div class="eps-label">EPS EST.</div>
<div class="eps-value est">$0.28</div>
</div>
<div class="eps-item">
<div class="eps-label">REPORT DATE</div>
<div class="eps-value est" style="font-size:0.75rem;">2026-06-10</div>
</div>
</div>
<div class="earnings-revenue">收入: <span>预期 $3.37B</span></div>
<div class="earnings-highlight">宠物电商Q1财报,股价今年暴跌38%至52周低点,自动订阅占销售额84%</div>
</div>
<div class="earnings-card beat">
<div class="earnings-ticker">AVGO</div>
<div class="earnings-company">Broadcom</div>
<span class="earnings-beat-badge beat">BEAT ✓</span>
<div class="earnings-eps">
<div class="eps-item">
<div class="eps-label">EPS ACTUAL</div>
<div class="eps-value actual beat">$6.25</div>
</div>
<div class="eps-item">
<div class="eps-label">EPS EST.</div>
<div class="eps-value est">$6.12</div>
</div>
</div>
<div class="earnings-revenue">收入: <span>$15.8B</span></div>
<div class="earnings-highlight">AI芯片巨头Q1超预期但未上调全年指引,引发芯片股上周五暴跌,拖累纳指跌4.2%</div>
</div>
<div class="earnings-card beat">
<div class="earnings-ticker">LULU</div>
<div class="earnings-company">Lululemon</div>
<span class="earnings-beat-badge beat">BEAT ✓</span>
<div class="earnings-eps">
<div class="eps-item">
<div class="eps-label">EPS ACTUAL</div>
<div class="eps-value actual beat">$2.84</div>
</div>
<div class="eps-item">
<div class="eps-label">EPS EST.</div>
<div class="eps-value est">$2.69</div>
</div>
</div>
<div class="earnings-revenue">收入: <span>$2.21B</span></div>
<div class="earnings-highlight">运动服饰公司大幅下调全年指引,Q2营收预期24.5-24.8亿低于预期26亿,股价暴跌</div>
</div>
<div class="earnings-card beat">
<div class="earnings-ticker">GME</div>
<div class="earnings-company">GameStop</div>
<span class="earnings-beat-badge beat">BEAT ✓</span>
<div class="earnings-eps">
<div class="eps-item">
<div class="eps-label">EPS ACTUAL</div>
<div class="eps-value actual beat">$0.30</div>
</div>
<div class="eps-item">
<div class="eps-label">EPS EST.</div>
<div class="eps-value est">$0.22</div>
</div>
</div>
<div class="earnings-revenue">收入: <span>$835.3M</span></div>
<div class="earnings-highlight">游戏零售商Q1超预期,营收增长14%,董事会批准20亿美元股票回购计划,股价盘前涨9%</div>
</div>
<div class="earnings-card pending">
<div class="earnings-ticker">LEN</div>
<div class="earnings-company">Lennar</div>
<span class="earnings-beat-badge pending">UPCOMING</span>
<div class="earnings-eps">
<div class="eps-item">
<div class="eps-label">EPS EST.</div>
<div class="eps-value est">$3.85</div>
</div>
<div class="eps-item">
<div class="eps-label">REPORT DATE</div>
<div class="eps-value est" style="font-size:0.75rem;">2026-06-11</div>
</div>
</div>
<div class="earnings-revenue">收入: <span>预期 $9.2B</span></div>
<div class="earnings-highlight">美国最大住宅建筑商之一,财报将反映高利率环境对房地产市场影响</div>
</div>
</div>
<!-- EARNINGS:END -->
<!-- EARNINGS:END -->
</div>
</div>
<div class="section-block sec-anchor" id="sec-sectors">
<div class="card">
<div class="section-label">🏭 板块表现 · Sectors</div>
<!-- SECTORS:START -->
<div class="sectors-list">
<div class="sector-row">
<div><div class="sector-name">科技</div><div class="sector-name-en">Technology</div></div>
<div class="sector-etf">XLK</div>
<div class="sector-bar-wrap"><div class="sector-bar up" style="width:98%"></div></div>
<div class="sector-pct up">+1.82%</div>
</div>
<div class="sector-row">
<div><div class="sector-name">通信服务</div><div class="sector-name-en">Communication Services</div></div>
<div class="sector-etf">XLC</div>
<div class="sector-bar-wrap"><div class="sector-bar up" style="width:75%"></div></div>
<div class="sector-pct up">+1.35%</div>
</div>
<div class="sector-row">
<div><div class="sector-name">非必需消费品</div><div class="sector-name-en">Consumer Discretionary</div></div>
<div class="sector-etf">XLY</div>
<div class="sector-bar-wrap"><div class="sector-bar up" style="width:54%"></div></div>
<div class="sector-pct up">+0.92%</div>
</div>
<div class="sector-row">
<div><div class="sector-name">工业</div><div class="sector-name-en">Industrials</div></div>
<div class="sector-etf">XLI</div>
<div class="sector-bar-wrap"><div class="sector-bar up" style="width:43%"></div></div>
<div class="sector-pct up">+0.68%</div>
</div>
<div class="sector-row">
<div><div class="sector-name">金融</div><div class="sector-name-en">Financials</div></div>
<div class="sector-etf">XLF</div>
<div class="sector-bar-wrap"><div class="sector-bar up" style="width:31%"></div></div>
<div class="sector-pct up">+0.45%</div>
</div>
<div class="sector-row">
<div><div class="sector-name">医疗保健</div><div class="sector-name-en">Health Care</div></div>
<div class="sector-etf">XLV</div>
<div class="sector-bar-wrap"><div class="sector-bar up" style="width:28%"></div></div>
<div class="sector-pct up">+0.38%</div>
</div>
<div class="sector-row">
<div><div class="sector-name">必需消费品</div><div class="sector-name-en">Consumer Staples</div></div>
<div class="sector-etf">XLP</div>
<div class="sector-bar-wrap"><div class="sector-bar up" style="width:17%"></div></div>
<div class="sector-pct up">+0.15%</div>
</div>
<div class="sector-row">
<div><div class="sector-name">材料</div><div class="sector-name-en">Materials</div></div>
<div class="sector-etf">XLB</div>
<div class="sector-bar-wrap"><div class="sector-bar up" style="width:15%"></div></div>
<div class="sector-pct up">+0.12%</div>
</div>
<div class="sector-row">
<div><div class="sector-name">公用事业</div><div class="sector-name-en">Utilities</div></div>
<div class="sector-etf">XLU</div>
<div class="sector-bar-wrap"><div class="sector-bar down" style="width:22%"></div></div>
<div class="sector-pct down">-0.25%</div>
</div>
<div class="sector-row">
<div><div class="sector-name">房地产</div><div class="sector-name-en">Real Estate</div></div>
<div class="sector-etf">XLRE</div>
<div class="sector-bar-wrap"><div class="sector-bar down" style="width:30%"></div></div>
<div class="sector-pct down">-0.42%</div>
</div>
<div class="sector-row">
<div><div class="sector-name">能源</div><div class="sector-name-en">Energy</div></div>
<div class="sector-etf">XLE</div>
<div class="sector-bar-wrap"><div class="sector-bar down" style="width:100%"></div></div>
<div class="sector-pct down">-1.85%</div>
</div>
</div>
<!-- SECTORS:END -->
<!-- SECTORS:END -->
</div>
</div>
</div>
<!-- REPLAY + CALENDAR (2-up) -->
<div class="two-up">
<div class="section-block sec-anchor" id="sec-replay">
<div class="card">
<div class="section-label">📽️ 大盘复盘 · Replay</div>
<!-- MARKET_REPLAY:START -->
<div class="replay-grid"><div class="replay-card">
<div class="replay-card-title">🇺🇸 美股</div>
<div class="replay-summary">芯片股强劲反弹推动科技领涨,但能源板块拖累大盘涨幅有限</div>
<div class="ad-bar-wrap">
<span class="ad-label-up">↑1890</span>
<div class="ad-bar adv" style="width:59px;max-width:80px"></div>
<div class="ad-bar dec" style="width:41px;max-width:80px"></div>
<span class="ad-label-dn">↓1320</span>
</div>
<div class="replay-stats">
<div class="replay-stat"><div class="replay-stat-label">热门板块</div><div class="replay-stat-val">科技</div></div>
<div class="replay-stat"><div class="replay-stat-label">领涨标的</div><div class="replay-stat-val">英特尔 (INTC) +10.0%</div></div>
<div class="replay-stat"><div class="replay-stat-label">创52周新高</div><div class="replay-stat-val">42</div></div>
</div>
</div><div class="replay-card">
<div class="replay-card-title">🇨🇳 A股</div>
<div class="replay-summary">A股科技股补跌拖累指数创两月新低,北向资金净流出82亿</div>
<div class="ad-bar-wrap">
<span class="ad-label-up">↑950</span>
<div class="ad-bar adv" style="width:21px;max-width:80px"></div>
<div class="ad-bar dec" style="width:79px;max-width:80px"></div>
<span class="ad-label-dn">↓3640</span>
</div>
<div class="replay-stats">
<div class="replay-stat"><div class="replay-stat-label">热门板块</div><div class="replay-stat-val">航空航天(习近平访朝)</div></div>
<div class="replay-stat"><div class="replay-stat-label">领涨标的</div><div class="replay-stat-val">中国国航 (601111) +3.2%</div></div>
<div class="replay-stat"><div class="replay-stat-label">北向资金</div><div class="replay-stat-val">-82亿</div></div>
</div>
</div></div>
<!-- MARKET_REPLAY:END -->
<!-- MARKET_REPLAY:END -->
</div>
</div>
<div class="section-block sec-anchor" id="sec-calendar">
<div class="card">
<div class="section-label">📅 本周日程 · Calendar</div>
<!-- CALENDAR:START -->
<div class="calendar-grid">
<div class="cal-item high">
<div class="cal-date">周一 6/8<br><span style="font-size:0.6rem;color:var(--dimmed)">全天</span></div>
<div>
<div class="cal-event">Apple WWDC开发者大会</div>
<div class="cal-values">预期: <span>Siri AI重大升级</span> &nbsp;&middot;&nbsp; 前值: -</div>
</div>
</div>
<div class="cal-item medium">
<div class="cal-date">周二 6/9<br><span style="font-size:0.6rem;color:var(--dimmed)">10:00 AM ET</span></div>
<div>
<div class="cal-event">5月成屋销售</div>
<div class="cal-values">预期: <span>415万套</span> &nbsp;&middot;&nbsp; 前值: 410万套</div>
</div>
</div>
<div class="cal-item low">
<div class="cal-date">周二 6/9<br><span style="font-size:0.6rem;color:var(--dimmed)">盘前</span></div>
<div>
<div class="cal-event">Campbell's、J.M. Smucker财报</div>
<div class="cal-values">预期: <span>测试消费支出</span> &nbsp;&middot;&nbsp; 前值: -</div>
</div>
</div>
<div class="cal-item high">
<div class="cal-date">周三 6/10<br><span style="font-size:0.6rem;color:var(--dimmed)">8:30 AM ET</span></div>
<div>
<div class="cal-event">5月CPI通胀数据</div>
<div class="cal-values">预期: <span>3.7% YoY (核心2.8%)</span> &nbsp;&middot;&nbsp; 前值: 3.8% YoY</div>
</div>
</div>
<div class="cal-item high">
<div class="cal-date">周三 6/10<br><span style="font-size:0.6rem;color:var(--dimmed)">盘后</span></div>
<div>
<div class="cal-event">Oracle、Chewy财报</div>
<div class="cal-values">预期: <span>AI基础设施支出关键测试</span> &nbsp;&middot;&nbsp; 前值: -</div>
</div>
</div>
<div class="cal-item medium">
<div class="cal-date">周三 6/10<br><span style="font-size:0.6rem;color:var(--dimmed)">9:45 AM ET</span></div>
<div>
<div class="cal-event">加拿大央行利率决定</div>
<div class="cal-values">预期: <span>维持4.25%</span> &nbsp;&middot;&nbsp; 前值: 4.25%</div>
</div>
</div>
<div class="cal-item medium">
<div class="cal-date">周四 6/11<br><span style="font-size:0.6rem;color:var(--dimmed)">8:30 AM ET</span></div>
<div>
<div class="cal-event">5月PPI生产者物价指数</div>
<div class="cal-values">预期: <span>2.5% YoY</span> &nbsp;&middot;&nbsp; 前值: 2.4% YoY</div>
</div>
</div>
<div class="cal-item medium">
<div class="cal-date">周四 6/11<br><span style="font-size:0.6rem;color:var(--dimmed)">盘后</span></div>
<div>
<div class="cal-event">Adobe、Lennar财报</div>
<div class="cal-values">预期: <span>软件和房地产需求</span> &nbsp;&middot;&nbsp; 前值: -</div>
</div>
</div>
<div class="cal-item high">
<div class="cal-date">周四 6/11<br><span style="font-size:0.6rem;color:var(--dimmed)">盘后</span></div>
<div>
<div class="cal-event">SpaceX IPO定价</div>
<div class="cal-values">预期: <span>目标价$135/股</span> &nbsp;&middot;&nbsp; 前值: -</div>
</div>
</div>
<div class="cal-item high">
<div class="cal-date">周五 6/12<br><span style="font-size:0.6rem;color:var(--dimmed)">开盘</span></div>
<div>
<div class="cal-event">SpaceX (SPCX) 纳斯达克首日交易</div>
<div class="cal-values">预期: <span>史上最大IPO $1.77T估值</span> &nbsp;&middot;&nbsp; 前值: -</div>
</div>
</div>
<div class="cal-item medium">
<div class="cal-date">周五 6/13<br><span style="font-size:0.6rem;color:var(--dimmed)">10:00 AM ET</span></div>
<div>
<div class="cal-event">6月密歇根消费者信心指数初值</div>
<div class="cal-values">预期: <span>68.5</span> &nbsp;&middot;&nbsp; 前值: 69.1</div>
</div>
</div>
</div>
<!-- CALENDAR:END -->
<!-- CALENDAR:END -->
</div>
</div>
</div>
</div><!-- end main-col -->
<!-- ── RIGHT / SIDEBAR ────────────────────────────────── -->
<div class="sidebar-col">
<!-- LEADERS -->
<div class="section-block sec-anchor mb16" id="sec-leaders">
<div class="card">
<div class="section-label">👔 领袖观点 · Leaders</div>
<!-- LEADERS:START -->
<div class="leader-card">
<div class="leader-header">
<div class="leader-avatar jd">JD</div>
<div class="leader-meta">
<div class="leader-name">杰米·戴蒙 <span style="color:var(--muted);font-weight:400;font-size:0.78rem;">Jamie Dimon</span></div>
<div class="leader-role">摩根大通CEO</div>
</div>
<div class="leader-date">4月11日</div>
</div>
<div class="leader-quote">"利率就像所有资产价格的引力"</div>
<div class="leader-body">戴蒙在4月致股东信中警告,当前市场存在过度乐观情绪,类似1972、1986、2000和2007年泡沫前夕。他强调通胀上升将推高利率,而高利率会像引力一样压低所有资产价格。戴蒙还指出信贷周期脆弱性正在积累,包括契约条款放松、EBITDA被拉伸、再融资风险增加,预计信贷周期到来时将比预期更严重。</div>
<div class="tags"><span class="tag">#利率</span><span class="tag">#美股估值</span></div>
</div>
<div class="leader-card">
<div class="leader-header">
<div class="leader-avatar wb">WB</div>
<div class="leader-meta">
<div class="leader-name">沃伦·巴菲特 <span style="color:var(--muted);font-weight:400;font-size:0.78rem;">Warren Buffett</span></div>
<div class="leader-role">伯克希尔哈撒韦CEO</div>
</div>
<div class="leader-date">4月</div>
</div>
<div class="leader-quote">"当市值与GDP比率接近200%时,你是在玩火"</div>
<div class="leader-body">巴菲特指标(美国股市总市值/GDP比率)最近达到230%,远超巴菲特自己设定的200%警戒线。这一指标在2000年互联网泡沫时达到200%。巴菲特近期保持谨慎,伯克希尔持有创纪录的现金储备。他在最近的股东信中呼应了戴蒙关于利率对资产价格影响的观点。</div>
<div class="tags"><span class="tag">#价值投资</span><span class="tag">#估值警告</span></div>
</div>
<div class="leader-card">
<div class="leader-header">
<div class="leader-avatar jp">JP</div>
<div class="leader-meta">
<div class="leader-name">杰罗姆·鲍威尔 <span style="color:var(--muted);font-weight:400;font-size:0.78rem;">Jerome Powell</span></div>
<div class="leader-role">美联储主席</div>
</div>
<div class="leader-date">5月</div>
</div>
<div class="leader-quote">"通胀预期今年已经上升"</div>
<div class="leader-body">鲍威尔在5月FOMC会议上指出,2026年通胀预期中值已升至2.7%,进一步降息前景显著恶化。期货交易员目前预期利率将在年底前维持不变,甚至有小概率加息。强于预期的5月就业报告(新增17.2万就业)进一步强化了美联储可能需要收紧政策以应对过热经济的担忧,市场现在预期年内至少加息一次的概率达到50%。</div>
<div class="tags"><span class="tag">#美联储</span><span class="tag">#利率政策</span></div>
</div>
<div class="leader-card">
<div class="leader-header">
<div class="leader-avatar default">TC</div>
<div class="leader-meta">
<div class="leader-name">蒂姆·库克 <span style="color:var(--muted);font-weight:400;font-size:0.78rem;">Tim Cook</span></div>
<div class="leader-role">苹果CEO</div>
</div>
<div class="leader-date">6月8日</div>
</div>
<div class="leader-quote">"今天我们在AI和Siri上迈出了一大步"</div>
<div class="leader-body">库克在6月8日WWDC上宣布重大AI升级,推出全新Siri AI助手,这是他作为CEO的最后一次开发者大会。苹果与谷歌深度合作开发新一代AI模型,Siri现在可以基于设备屏幕内容回答问题并参考个人上下文。但苹果股价在发布后下跌近2%,分析师认为投资者对苹果AI执行力仍持怀疑态度。库克将于9月卸任CEO,由硬件工程主管John Ternus接任。</div>
<div class="tags"><span class="tag">#苹果</span><span class="tag">#AI</span></div>
</div>
<!-- LEADERS:END -->
<!-- LEADERS:END -->
</div>
</div>
<!-- CENTRAL BANKS -->
<div class="section-block sec-anchor mb16" id="sec-banks">
<div class="card">
<div class="section-label">🏦 央行动态 · Central Banks</div>
<!-- CENTRAL_BANKS:START -->
<div class="cb-grid">
<div class="cb-card">
<div class="cb-header">
<div>
<div class="cb-name">美联储</div>
<div class="cb-name-en">Federal Reserve</div>
</div>
<span class="bias-badge hawkish">Hawkish</span>
</div>
<div class="cb-rate">4.25-4.50%</div>
<div class="cb-action">维持利率4.25-4.50%</div>
<div class="cb-next">下次会议: <span class="font-mono" style="color:var(--neutral)">2026-06-16</span></div>
<div class="cb-note">强劲就业报告后市场预期年内至少加息一次概率达50%,鲍威尔强调通胀预期上升至2.7%</div>
</div>
<div class="cb-card">
<div class="cb-header">
<div>
<div class="cb-name">欧洲央行</div>
<div class="cb-name-en">European Central Bank</div>
</div>
<span class="bias-badge neutral">Neutral</span>
</div>
<div class="cb-rate">2.0%</div>
<div class="cb-action">维持存款便利利率2.0%</div>
<div class="cb-next">下次会议: <span class="font-mono" style="color:var(--neutral)">2026-06-11</span></div>
<div class="cb-note">ECB已结束降息周期,拉加德称目前既不讨论加息也不讨论降息,通胀预期未来两年低于2%目标</div>
</div>
<div class="cb-card">
<div class="cb-header">
<div>
<div class="cb-name">中国人民银行</div>
<div class="cb-name-en">People's Bank of China</div>
</div>
<span class="bias-badge dovish">Dovish</span>
</div>
<div class="cb-rate">3.45%</div>
<div class="cb-action">维持1年期LPR 3.45%</div>
<div class="cb-next">下次会议: <span class="font-mono" style="color:var(--neutral)">2026-06-20</span></div>
<div class="cb-note">预计2026年全年降息20基点、降准100基点,支持经济稳定增长,但需平衡银行净息差和股市泡沫风险</div>
</div>
<div class="cb-card">
<div class="cb-header">
<div>
<div class="cb-name">日本银行</div>
<div class="cb-name-en">Bank of Japan</div>
</div>
<span class="bias-badge hawkish">Hawkish</span>
</div>
<div class="cb-rate">0.75%</div>
<div class="cb-action">维持政策利率0.75%</div>
<div class="cb-next">下次会议: <span class="font-mono" style="color:var(--neutral)">2026-06-18</span></div>
<div class="cb-note">多位委员支持近期加息,实际利率仍处极低水平,但中东局势令央行保持谨慎,预计年底前加息至1.0%</div>
</div>
<div class="cb-card">
<div class="cb-header">
<div>
<div class="cb-name">英格兰银行</div>
<div class="cb-name-en">Bank of England</div>
</div>
<span class="bias-badge neutral">Neutral</span>
</div>
<div class="cb-rate">3.75%</div>
<div class="cb-action">维持基准利率3.75%</div>
<div class="cb-next">下次会议: <span class="font-mono" style="color:var(--neutral)">2026-06-20</span></div>
<div class="cb-note">12月降息25基点至3.75%,投票5-4分裂,通胀接近目标但增长疲软,预计暂停进一步行动</div>
</div>
<div class="cb-card">
<div class="cb-header">
<div>
<div class="cb-name">加拿大央行</div>
<div class="cb-name-en">Bank of Canada</div>
</div>
<span class="bias-badge neutral">Neutral</span>
</div>
<div class="cb-rate">4.25%</div>
<div class="cb-action">待6月9日决定</div>
<div class="cb-next">下次会议: <span class="font-mono" style="color:var(--neutral)">2026-06-09</span></div>
<div class="cb-note">本周三10:30 AM ET公布利率决定并召开新闻发布会,市场预期维持4.25%不变</div>
</div>
</div>
<!-- CENTRAL_BANKS:END -->
<!-- CENTRAL_BANKS:END -->
</div>
</div>
<!-- TRADINGVIEW CHARTS -->
<div class="section-block mb16">
<div class="card" style="padding:14px 16px">
<div class="section-label">📈 行情图表 · Live Charts</div>
<div class="tradingview-widget-container">
<div class="tradingview-widget-container__widget"></div>
<script type="text/javascript" src="https://s3.tradingview.com/external-embedding/embed-widget-market-overview.js" async>
{
"colorTheme": "dark",
"dateRange": "1D",
"showChart": true,
"locale": "zh_CN",
"isTransparent": true,
"showSymbolLogo": true,
"showFloatingTooltip": false,
"width": "100%",
"height": "480",
"tabs": [
{
"title": "🇺🇸 美股",
"symbols": [
{"s":"FOREXCOM:SPXUSD","d":"S&P 500"},
{"s":"FOREXCOM:NSXUSD","d":"Nasdaq 100"},
{"s":"FOREXCOM:DJI","d":"道琼斯"},
{"s":"CBOE:VIX","d":"VIX 恐慌指数"},
{"s":"TVC:US10Y","d":"美10年债"}
],
"originalTitle": "US"
},
{
"title": "🇨🇳 中国",
"symbols": [
{"s":"SSE:000001","d":"上证指数"},
{"s":"SZSE:399006","d":"创业板指"},
{"s":"HKEX:HSI","d":"恒生指数"},
{"s":"FX:USDCNH","d":"离岸人民币"},
{"s":"HKEX:2318","d":"中国平安"}
],
"originalTitle": "China"
},
{
"title": "🛢️ 大宗",
"symbols": [
{"s":"TVC:GOLD","d":"黄金"},
{"s":"NYMEX:CL1!","d":"原油 WTI"},
{"s":"COMEX:SI1!","d":"白银"},
{"s":"TVC:DXY","d":"美元指数"}
],
"originalTitle": "Commodities"
},
{
"title": "₿ 加密",
"symbols": [
{"s":"BINANCE:BTCUSDT","d":"Bitcoin"},
{"s":"BINANCE:ETHUSDT","d":"Ethereum"},
{"s":"BINANCE:SOLUSDT","d":"Solana"}
],
"originalTitle": "Crypto"
}
]
}
</script>
</div>
</div>
</div>
</div><!-- end sidebar-col -->
</div><!-- end content-grid -->
<!-- MY DASHBOARD (collapsed drawer) -->
<div class="my-drawer sec-anchor" id="sec-my">
<button class="my-drawer-toggle" onclick="this.classList.toggle('open');this.nextElementSibling.classList.toggle('open')">
<span>⭐ 我的工作台 · My Dashboard</span>
<span class="drawer-icon"></span>
</button>
<div class="my-drawer-body">
<div class="card">
<div class="profile-bar">
<span class="profile-label">👤 用户:</span>
<select id="profile-select" onchange="profileSwitch()"></select>
<button onclick="profileNew()"> 新建</button>
<button onclick="profileDelete()">删除</button>
</div>
<div class="personal-header">
<div class="section-label">⭐ 我的工作台 · My Dashboard</div>
<span class="personal-privacy">🔒 数据存本地 · 不上传服务器</span>
</div>
<div class="ptabs">
<button class="ptab active" id="ptab-wl" onclick="switchTab(event,'wl')">📋 自选股</button>
<button class="ptab" id="ptab-pf" onclick="switchTab(event,'pf')">💼 持仓盈亏</button>
<button class="ptab" id="ptab-sim" onclick="switchTab(event,'sim')">📊 模拟器</button>
</div>
<div id="panel-wl">
<div class="add-row">
<input id="wl-sym" placeholder="代码,如 AAPL / 000001.SS / BTC-USD" />
<input id="wl-name" placeholder="备注名(可选)" />
<button onclick="wlAdd()"> 添加</button>
</div>
<div id="wl-empty" class="p-empty">还没有自选股,输入代码开始追踪 →</div>
<div id="wl-list" class="wl-list"></div>
</div>
<div id="panel-pf" style="display:none">
<div class="add-row">
<input id="pf-sym" placeholder="代码,如 AAPL / TSLA" />
<input id="pf-shares" type="number" min="0.0001" step="0.0001" placeholder="数量" />
<input id="pf-cost" type="number" min="0" step="0.01" placeholder="买入均价 ($)" />
<button onclick="pfAdd()"> 添加持仓</button>
</div>
<div id="pf-empty" class="p-empty">还没有持仓记录,输入持仓开始计算浮盈浮亏 →</div>
<div id="pf-summary" class="pf-summary" style="display:none">
<div class="pf-sum-item">总成本<span id="sum-cost"></span></div>
<div class="pf-sum-item">总市值<span id="sum-value"></span></div>
<div class="pf-sum-item">总盈亏<span id="sum-pnl"></span></div>
<div class="pf-sum-item">盈亏率<span id="sum-pct"></span></div>
</div>
<div id="pf-list" class="pf-list"></div>
</div>
<div id="panel-sim" style="display:none">
<div class="sim-section">
<div>
<div class="sim-label">总投资金额</div>
<div class="sim-capital-row">
<input type="number" id="sim-capital" min="0" step="100" value="10000" oninput="simUpdate()" />
<select id="sim-currency" onchange="simUpdate()">
<option value="USD">USD $</option>
<option value="CAD">CAD $</option>
<option value="CNY">CNY ¥</option>
</select>
</div>
</div>
<div>
<div class="sim-label">资产配置</div>
<div class="sim-add-row">
<input id="sim-sym" placeholder="代码,如 AAPL" style="width:100px" />
<input id="sim-alias" placeholder="备注名" style="width:85px" />
<input type="number" id="sim-pct" placeholder="分配%" min="0" max="100" step="1" style="width:65px" />
<input type="number" id="sim-entry" placeholder="买入价(选填)" min="0" step="0.01" style="width:110px" />
<button onclick="simAddAsset()"> 添加</button>
<span style="font-size:0.68rem;color:var(--dimmed)">不填则自动记录当前价</span>
</div>
<div id="sim-pct-total" class="sim-pct-total" style="margin-top:4px">已分配:0%</div>
</div>
<div id="sim-alloc-bar" class="sim-alloc-bar" style="display:none"></div>
<div id="sim-assets-wrap" style="display:none">
<table class="sim-assets-table">
<thead><tr><th>代码</th><th>备注</th><th>分配%</th><th>投入金额</th><th>买入价</th><th>操作</th></tr></thead>
<tbody id="sim-assets-tbody"></tbody>
</table>
</div>
<div id="sim-scenario-section" style="display:none">
<div class="sim-label">收益情景(年化%</div>
<div class="sim-scenario-row">
<label>😨 悲观 <input type="number" id="sim-bear" value="-20" step="1" oninput="simUpdate()" /></label>
<label>📊 中性 <input type="number" id="sim-base" value="8" step="1" oninput="simUpdate()" /></label>
<label>🚀 乐观 <input type="number" id="sim-bull" value="25" step="1" oninput="simUpdate()" /></label>
</div>
<div class="sim-horizon-row">
<span>时间跨度:</span>
<button class="sim-hbtn" data-h="1m" onclick="simSetHorizon(this,'1m')">1月</button>
<button class="sim-hbtn" data-h="3m" onclick="simSetHorizon(this,'3m')">3月</button>
<button class="sim-hbtn" data-h="6m" onclick="simSetHorizon(this,'6m')">6月</button>
<button class="sim-hbtn active" data-h="1y" onclick="simSetHorizon(this,'1y')">1年</button>
<button class="sim-hbtn" data-h="3y" onclick="simSetHorizon(this,'3y')">3年</button>
<button class="sim-hbtn" data-h="5y" onclick="simSetHorizon(this,'5y')">5年</button>
</div>
</div>
<div id="sim-returns-wrap" style="display:none">
<div class="sim-label">预期收益预测</div>
<table class="sim-returns-table">
<thead>
<tr>
<th style="text-align:left">资产</th>
<th>投入</th>
<th>📈 实际</th>
<th>😨 悲观</th>
<th>📊 中性</th>
<th>🚀 乐观</th>
</tr>
</thead>
<tbody id="sim-returns-tbody"></tbody>
</table>
</div>
<div class="sim-actions">
<button class="sim-btn sim-btn-secondary" onclick="simReset()">🗑 重置</button>
</div>
</div>
</div>
</div>
</div>
</div>
</div><!-- end container -->
</div><!-- end page-body -->
<!-- =========================================================
FOOTER
========================================================= -->
<footer class="site-footer">
<div class="container">
<div class="footer-inner">
<span>© 2025 金融日报 · Financial Daily &nbsp;|&nbsp; Powered by <a href="https://www.anthropic.com" target="_blank">Claude AI</a></span>
<span>内容由AI自动生成,仅供参考,不构成投资建议</span>
<a href="feed.xml">RSS Feed</a>
</div>
<div style="display:flex;gap:24px;justify-content:center;margin-top:12px;font-size:0.75rem;color:var(--muted);">
<span>👁 访客 <strong id="footer-visitors" style="color:var(--accent)"></strong></span>
<span>📄 浏览 <strong id="footer-pageviews" style="color:var(--accent)"></strong></span>
</div>
</div>
</footer>
<script>
// Set current date
(function() {
const el = document.getElementById('current-date');
if (!el) return;
const now = new Date();
const opts = { year: 'numeric', month: 'long', day: 'numeric', weekday: 'short' };
el.textContent = now.toLocaleDateString('zh-CN', opts);
})();
// Data age indicator
(function() {
const metaEl = document.querySelector('meta[name="last-updated"]');
if (!metaEl) return;
const updated = new Date(metaEl.content);
const ageH = (Date.now() - updated) / 3600000;
const badge = document.querySelector('.header-badge');
if (!badge) return;
const ageMin = Math.round(ageH * 60);
const ageStr = ageH < 1 ? ageMin + '分钟前更新' : Math.round(ageH) + '小时前更新';
badge.title = ageStr;
if (ageH > 14) badge.classList.add('data-stale');
})();
// Simple / Advanced mode toggle
(function() {
const btn = document.getElementById('mode-btn');
if (!btn) return;
const stored = localStorage.getItem('fd-mode') || 'advanced';
applyMode(stored);
btn.addEventListener('click', function() {
const isSimple = document.body.classList.contains('simple-mode');
const next = isSimple ? 'advanced' : 'simple';
localStorage.setItem('fd-mode', next);
applyMode(next);
});
function applyMode(mode) {
const label = btn.querySelector('.mode-label');
const icon = btn.querySelector('.mode-icon');
if (mode === 'simple') {
document.body.classList.add('simple-mode');
label.textContent = '专业模式';
icon.textContent = '📊';
} else {
document.body.classList.remove('simple-mode');
label.textContent = '新手模式';
icon.textContent = '📖';
}
}
})();
// Live quotes from data/quotes.json (populated by live-quotes workflow)
(function() {
fetch('data/quotes.json?' + Date.now())
.then(r => r.ok ? r.json() : null)
.then(data => {
if (!data || !data.quotes) return;
const track = document.querySelector('.indices-track');
if (!track) return;
data.quotes.forEach(q => {
track.querySelectorAll('.ticker-card').forEach(card => {
const nameEl = card.querySelector('.ticker-name');
if (nameEl && nameEl.textContent.trim() === q.name) {
card.className = 'ticker-card ' + q.direction;
card.querySelector('.ticker-value').textContent = q.value;
const chgEl = card.querySelector('.ticker-change');
const arrow = q.direction === 'up' ? '▲' : '▼';
chgEl.textContent = arrow + ' ' + q.change_pct;
chgEl.className = 'ticker-change ' + q.direction;
}
});
});
// Show live badge
const badge = document.querySelector('.header-badge');
if (badge) {
const updated = new Date(data.updated);
const mins = Math.round((Date.now() - updated) / 60000);
badge.title = '行情数据: ' + (mins < 60 ? mins + '分钟前' : Math.round(mins/60) + '小时前');
badge.classList.remove('data-stale');
}
})
.catch(() => {});
})();
// Auto-tooltip for financial jargon
const FIN_TERMS = {
'VIX': 'VIX = 标普期权隐含波动率,越高越恐慌',
'PCE': 'PCE = 个人消费支出物价指数,美联储首选通胀指标',
'NFP': 'NFP = 非农就业人数,衡量美国就业市场健康度',
'CPI': 'CPI = 消费者物价指数,最常见通胀衡量指标',
'PMI': 'PMI > 50 = 经济扩张;PMI < 50 = 经济收缩',
'QE': 'QE = 量化宽松,央行购买债券向市场注入流动性',
'鹰派': '鹰派 = 倾向加息/收紧货币政策,对抗通胀',
'鸽派': '鸽派 = 倾向降息/宽松货币政策,刺激经济',
'EPS': 'EPS = 每股收益,公司盈利能力的核心指标',
'DXY': 'DXY = 美元指数,衡量美元对六大货币的强弱',
};
document.addEventListener('DOMContentLoaded', function() {
const walker = document.createTreeWalker(
document.querySelector('.macro-section') || document.body,
NodeFilter.SHOW_TEXT
);
// Only apply to macro + news sections to avoid performance issues
['macro-section','news-section','cb-grid'].forEach(cls => {
const sec = document.querySelector('.' + cls);
if (!sec) return;
Object.entries(FIN_TERMS).forEach(([term, tip]) => {
sec.querySelectorAll('.macro-indicator, .cb-action, .news-body').forEach(el => {
if (el.innerHTML.includes(term) && !el.innerHTML.includes('fin-term')) {
el.innerHTML = el.innerHTML.replace(
new RegExp('(' + term.replace(/[.*+?^${}()|[\]\\]/g,'\\$&') + ')', 'g'),
`<span class="fin-term" data-tip="${tip}">$1</span>`
);
}
});
});
});
});
function copyRSS(e) {
e.preventDefault();
const url = 'https://yang1bai.github.io/finance-daily-site/feed.xml';
navigator.clipboard.writeText(url).then(() => {
const btn = document.getElementById('copy-rss');
btn.textContent = '✅ 已复制';
setTimeout(() => { btn.textContent = '📋 复制链接'; }, 2000);
}).catch(() => {
prompt('RSS 链接:', url);
});
}
// ═══════════════════════════════════════════════════════════
// PERSONAL DASHBOARD — Watchlist + Portfolio
// ═══════════════════════════════════════════════════════════
// ── Multi-user Profiles ──────────────────────────────────────
function profileLoad() {
return JSON.parse(localStorage.getItem('fd-profiles-v1') || 'null') || [{ id: 'default', name: '默认用户' }];
}
function profileSave(list) { localStorage.setItem('fd-profiles-v1', JSON.stringify(list)); }
function profileActive() { return localStorage.getItem('fd-active-profile-v1') || 'default'; }
function profileSetActive(id) { localStorage.setItem('fd-active-profile-v1', id); }
function profileRenderSelect() {
const list = profileLoad();
const active = profileActive();
const sel = document.getElementById('profile-select');
if (!sel) return;
sel.innerHTML = list.map(p => `<option value="${p.id}" ${p.id === active ? 'selected' : ''}>${p.name}</option>`).join('');
}
function profileSwitch() {
const sel = document.getElementById('profile-select');
if (!sel) return;
profileSetActive(sel.value);
wlRender(); pfRender(); simRender();
}
function profileNew() {
const name = prompt('输入用户名:', '用户' + (profileLoad().length + 1));
if (!name || !name.trim()) return;
const id = 'user_' + Date.now();
const list = profileLoad();
list.push({ id, name: name.trim() });
profileSave(list);
profileSetActive(id);
profileRenderSelect();
wlRender(); pfRender(); simRender();
}
function profileDelete() {
const list = profileLoad();
if (list.length <= 1) { alert('至少保留一个用户'); return; }
const active = profileActive();
const idx = list.findIndex(p => p.id === active);
if (idx === -1) return;
if (!confirm(`确认删除用户"${list[idx].name}"的所有数据?`)) return;
['watchlist-v1','portfolio-v1','sim-v1'].forEach(k => {
localStorage.removeItem(`fd-${active}-${k}`);
});
list.splice(idx, 1);
profileSave(list);
profileSetActive(list[0].id);
profileRenderSelect();
wlRender(); pfRender(); simRender();
}
// ── Dynamic localStorage keys ──────────────────────────
function lsWL() { return `fd-${profileActive()}-watchlist-v1`; }
function lsPF() { return `fd-${profileActive()}-portfolio-v1`; }
function lsSIM() { return `fd-${profileActive()}-sim-v1`; }
const priceCache = {};
function wlLoad() { return JSON.parse(localStorage.getItem(lsWL()) || '[]'); }
function wlSave(d) { localStorage.setItem(lsWL(), JSON.stringify(d)); }
function pfLoad() { return JSON.parse(localStorage.getItem(lsPF()) || '[]'); }
function pfSave(d) { localStorage.setItem(lsPF(), JSON.stringify(d)); }
function switchTab(e, tab) {
['wl','pf','sim'].forEach(t => {
document.getElementById('panel-' + t).style.display = t === tab ? 'block' : 'none';
document.getElementById('ptab-' + t).classList.toggle('active', t === tab);
});
}
// ── Price fetching (Yahoo Finance → CORS proxy fallback) ───
function toYahooSym(raw) {
if (!raw.includes(':')) return raw;
const [exch, ticker] = raw.split(':');
const map = { SSE:'', SZSE:'', HKEX:'.HK', TSX:'.TO', LSE:'.L', FWB:'.DE' };
if (exch === 'SSE') return ticker + '.SS';
if (exch === 'SZSE') return ticker + '.SZ';
return ticker + (map[exch] || '');
}
async function fetchPrice(rawSym) {
const key = rawSym;
if (priceCache[key] && Date.now() - priceCache[key].ts < 300000) return priceCache[key];
const ySym = toYahooSym(rawSym);
const yUrl = `https://query1.finance.yahoo.com/v8/finance/chart/${encodeURIComponent(ySym)}?range=1d&interval=1m&includePrePost=false`;
const proxies = [
yUrl,
`https://corsproxy.io/?${encodeURIComponent(yUrl)}`,
`https://api.allorigins.win/get?url=${encodeURIComponent(yUrl)}`
];
for (const url of proxies) {
try {
const resp = await fetch(url, { signal: AbortSignal.timeout(7000) });
if (!resp.ok) continue;
let json = await resp.json();
// allorigins wraps in {contents: '...'}
if (json.contents) json = JSON.parse(json.contents);
const result = json.chart?.result?.[0];
if (!result) continue;
const meta = result.meta;
const price = meta.regularMarketPrice;
const prev = meta.chartPreviousClose || meta.previousClose || price;
const chgPct = prev ? (price - prev) / prev * 100 : 0;
const chgAbs = price - prev;
const info = { price, prev, chgPct, chgAbs, currency: meta.currency || 'USD', ts: Date.now() };
priceCache[key] = info;
return info;
} catch(e) {}
}
return null;
}
function fmtNum(n, dec=2) {
return n.toLocaleString('en-US', { minimumFractionDigits: dec, maximumFractionDigits: dec });
}
// ── Watchlist ───────────────────────────────────────────────
function wlAdd() {
const sym = (document.getElementById('wl-sym').value || '').trim().toUpperCase();
const name = (document.getElementById('wl-name').value || '').trim();
if (!sym) return;
const list = wlLoad();
if (list.find(i => i.symbol === sym)) { alert('已在自选列表'); return; }
list.push({ symbol: sym, alias: name });
wlSave(list);
document.getElementById('wl-sym').value = '';
document.getElementById('wl-name').value = '';
wlRender();
}
function wlRemove(sym) {
wlSave(wlLoad().filter(i => i.symbol !== sym));
wlRender();
}
function wlRender() {
const list = wlLoad();
const grid = document.getElementById('wl-list');
const empty = document.getElementById('wl-empty');
if (!list.length) { empty.style.display = 'block'; grid.innerHTML = ''; return; }
empty.style.display = 'none';
grid.innerHTML = list.map(item => {
const id = 'wlp-' + item.symbol.replace(/[^a-z0-9]/gi, '_');
return `<div class="wl-card">
<div class="wl-card-top">
<div>
<div class="wl-sym">${item.symbol}</div>
${item.alias ? `<div class="wl-alias">${item.alias}</div>` : ''}
</div>
<button class="wl-rm" onclick="wlRemove('${item.symbol.replace(/'/g,"\'")}')">×</button>
</div>
<div id="${id}"><span class="wl-loading">加载中…</span></div>
</div>`;
}).join('');
list.forEach(item => {
const id = 'wlp-' + item.symbol.replace(/[^a-z0-9]/gi, '_');
fetchPrice(item.symbol).then(info => {
const el = document.getElementById(id);
if (!el) return;
if (!info) { el.innerHTML = '<span class="wl-loading">获取失败</span>'; return; }
const dir = info.chgPct >= 0 ? 'up' : 'down';
const arrow = info.chgPct >= 0 ? '▲' : '▼';
el.innerHTML = `
<div class="wl-price-block">
<span class="wl-cur">${info.currency}</span>
<span class="wl-price">${fmtNum(info.price)}</span>
<span class="ticker-change ${dir}" style="font-size:0.72rem;">${arrow} ${Math.abs(info.chgPct).toFixed(2)}%</span>
</div>
<div class="wl-prev">昨收 ${fmtNum(info.prev)}</div>
`;
});
});
}
// ── Portfolio ───────────────────────────────────────────────
function pfAdd() {
const sym = (document.getElementById('pf-sym').value || '').trim().toUpperCase();
const shares = parseFloat(document.getElementById('pf-shares').value);
const cost = parseFloat(document.getElementById('pf-cost').value);
if (!sym || !shares || !cost || isNaN(shares) || isNaN(cost)) {
alert('请完整填写代码、数量和买入均价');
return;
}
const list = pfLoad();
list.push({ symbol: sym, shares, costBasis: cost, addedAt: Date.now() });
pfSave(list);
['pf-sym','pf-shares','pf-cost'].forEach(id => document.getElementById(id).value = '');
pfRender();
}
function pfRemove(idx) {
const list = pfLoad(); list.splice(idx, 1); pfSave(list); pfRender();
}
function pfRender() {
const list = pfLoad();
const grid = document.getElementById('pf-list');
const empty = document.getElementById('pf-empty');
const sumEl = document.getElementById('pf-summary');
if (!list.length) { empty.style.display='block'; grid.innerHTML=''; sumEl.style.display='none'; return; }
empty.style.display = 'none';
sumEl.style.display = 'flex';
const totalCost = list.reduce((s, i) => s + i.shares * i.costBasis, 0);
document.getElementById('sum-cost').textContent = '$' + fmtNum(totalCost);
grid.innerHTML = list.map((item, idx) => {
const id = 'pfp-' + idx;
const itemCost = item.shares * item.costBasis;
return `<div class="pf-card">
<div class="pf-card-top">
<span class="pf-sym">${item.symbol}</span>
<button class="wl-rm" onclick="pfRemove(${idx})">×</button>
</div>
<div class="pf-meta">
${fmtNum(item.shares, 4)} 股 &nbsp;×&nbsp; $${fmtNum(item.costBasis)} 成本<br>
持仓成本 <strong>$${fmtNum(itemCost)}</strong>
</div>
<div class="pf-pnl-row" id="${id}"><span class="wl-loading">计算盈亏中…</span></div>
</div>`;
}).join('');
let fetchedCount = 0, totalValue = 0;
list.forEach((item, idx) => {
fetchPrice(item.symbol).then(info => {
fetchedCount++;
const el = document.getElementById('pfp-' + idx);
if (!el) return;
if (!info) { el.innerHTML = '<span class="wl-loading">价格获取失败</span>'; return; }
const curVal = item.shares * info.price;
const pnlAbs = curVal - item.shares * item.costBasis;
const pnlPct = pnlAbs / (item.shares * item.costBasis) * 100;
const dir = pnlAbs >= 0 ? 'pos' : 'neg';
const sign = pnlAbs >= 0 ? '+' : '';
totalValue += curVal;
el.innerHTML = `
<span class="pf-cur-price">${info.currency} ${fmtNum(info.price)}</span>
<span class="pf-gain ${dir}">${sign}$${fmtNum(pnlAbs)} (${sign}${pnlPct.toFixed(2)}%)</span>
`;
if (fetchedCount === list.length) {
document.getElementById('sum-value').textContent = '$' + fmtNum(totalValue);
const totPnl = totalValue - totalCost;
const totPct = totPnl / totalCost * 100;
const sign2 = totPnl >= 0 ? '+' : '';
const cls = totPnl >= 0 ? 'pf-pnl-pos' : 'pf-pnl-neg';
document.getElementById('sum-pnl').innerHTML = `<span class="${cls}">${sign2}$${fmtNum(totPnl)}</span>`;
document.getElementById('sum-pct').innerHTML = `<span class="${cls}">${sign2}${totPct.toFixed(2)}%</span>`;
}
});
});
}
// ── Investment Simulator ─────────────────────────────────
function simLoad() {
return JSON.parse(localStorage.getItem(lsSIM()) || 'null') || {
capital: 10000, currency: 'USD',
assets: [],
scenarios: { bear: -20, base: 8, bull: 25 },
horizon: '1y'
};
}
function simSave(d) { localStorage.setItem(lsSIM(), JSON.stringify(d)); }
function simRender() {
const d = simLoad();
const capEl = document.getElementById('sim-capital');
const curEl = document.getElementById('sim-currency');
const bearEl = document.getElementById('sim-bear');
const baseEl = document.getElementById('sim-base');
const bullEl = document.getElementById('sim-bull');
if (capEl) capEl.value = d.capital;
if (curEl) curEl.value = d.currency;
if (bearEl) bearEl.value = d.scenarios.bear;
if (baseEl) baseEl.value = d.scenarios.base;
if (bullEl) bullEl.value = d.scenarios.bull;
document.querySelectorAll('.sim-hbtn').forEach(b => {
b.classList.toggle('active', b.dataset.h === d.horizon);
});
simRenderAssets(d);
simCalcReturns(d);
}
function simRenderAssets(d) {
const capital = parseFloat(d.capital) || 0;
const totalPct = d.assets.reduce((s, a) => s + (parseFloat(a.pct)||0), 0);
const pctEl = document.getElementById('sim-pct-total');
if (pctEl) {
pctEl.textContent = `已分配:${totalPct.toFixed(1)}%`;
pctEl.className = 'sim-pct-total' + (totalPct > 100 ? ' over' : '');
}
if (!d.assets.length) {
['sim-assets-wrap','sim-alloc-bar','sim-scenario-section','sim-returns-wrap'].forEach(id => {
const el = document.getElementById(id);
if (el) el.style.display = 'none';
});
return;
}
['sim-assets-wrap','sim-scenario-section','sim-returns-wrap'].forEach(id => {
const el = document.getElementById(id);
if (el) el.style.display = 'block';
});
const bar = document.getElementById('sim-alloc-bar');
if (bar) {
bar.style.display = 'flex';
bar.innerHTML = d.assets.map((a, i) => {
const w = Math.min(parseFloat(a.pct)||0, 100);
return `<div class="sim-alloc-seg" title="${a.symbol} ${a.pct}%" style="width:${w}%;background:hsl(${i*47},65%,50%);"></div>`;
}).join('');
}
const tbody = document.getElementById('sim-assets-tbody');
if (tbody) {
const cur = d.currency === 'CNY' ? '¥' : '$';
tbody.innerHTML = d.assets.map((a, idx) => {
const invest = capital * (parseFloat(a.pct)||0) / 100;
return `<tr>
<td><strong>${a.symbol}</strong></td>
<td>${a.alias || '—'}</td>
<td><input type="number" min="0" max="100" step="1" value="${a.pct}" onchange="simUpdatePct(${idx},this.value)" style="width:55px;background:transparent;border:1px solid var(--border);color:var(--text);border-radius:3px;padding:2px 5px;" /></td>
<td>${cur}${fmtNum(invest)}</td>
<td style="font-size:0.72rem;color:var(--dimmed)">${a.entryPrice ? cur + fmtNum(a.entryPrice) : '—'}</td>
<td><button class="wl-rm" onclick="simRemoveAsset(${idx})">×</button></td>
</tr>`;
}).join('');
}
}
async function simCalcReturns(d) {
const tbody = document.getElementById('sim-returns-tbody');
if (!tbody || !d.assets.length) return;
const capital = parseFloat(d.capital) || 0;
const horizonMap = { '1m': 1/12, '3m': 0.25, '6m': 0.5, '1y': 1, '3y': 3, '5y': 5 };
const years = horizonMap[d.horizon] || 1;
const bear = parseFloat(d.scenarios.bear) / 100;
const base = parseFloat(d.scenarios.base) / 100;
const bull = parseFloat(d.scenarios.bull) / 100;
const cur = d.currency === 'CNY' ? '¥' : '$';
function calcProfit(invest, rate, yrs) { return invest * Math.pow(1 + rate, yrs) - invest; }
function sCell(v, invest) {
const p = invest ? (v / invest * 100).toFixed(1) : '0.0';
const sign = v >= 0 ? '+' : '';
const cls = v >= 0 ? 'sim-ret-pos' : 'sim-ret-neg';
return `<span class="${cls}">${sign}${cur}${fmtNum(Math.abs(v))}<br><small>${sign}${p}%</small></span>`;
}
let totBear = 0, totBase = 0, totBull = 0, totInvest = 0;
// Render scenario columns immediately
tbody.innerHTML = d.assets.map(a => {
const invest = capital * (parseFloat(a.pct)||0) / 100;
const pb = calcProfit(invest, bear, years);
const pn = calcProfit(invest, base, years);
const pu = calcProfit(invest, bull, years);
totBear += pb; totBase += pn; totBull += pu; totInvest += invest;
const rid = 'simreal-' + a.symbol.replace(/[^a-z0-9]/gi,'_');
const realCell = a.entryPrice
? `<td id="${rid}"><span style="color:var(--dimmed);font-size:0.72rem">拉取中…</span></td>`
: `<td style="color:var(--dimmed);font-size:0.72rem">无买入价</td>`;
return `<tr>
<td><strong>${a.symbol}</strong>${a.alias ? `<br><small style="color:var(--muted)">${a.alias}</small>` : ''}</td>
<td>${cur}${fmtNum(invest)}</td>
${realCell}
<td>${sCell(pb, invest)}</td>
<td>${sCell(pn, invest)}</td>
<td>${sCell(pu, invest)}</td>
</tr>`;
}).join('');
tbody.innerHTML += `<tr class="total-row">
<td>合计</td>
<td>${cur}${fmtNum(totInvest)}</td>
<td id="simreal-total">—</td>
<td>${sCell(totBear, totInvest)}</td>
<td>${sCell(totBase, totInvest)}</td>
<td>${sCell(totBull, totInvest)}</td>
</tr>`;
// Async: fetch live prices for real P&L column
const realResults = new Array(d.assets.length).fill(null);
let fetched = 0;
d.assets.forEach(async (a, idx) => {
if (!a.entryPrice) { fetched++; return; }
const rid = 'simreal-' + a.symbol.replace(/[^a-z0-9]/gi,'_');
const el = document.getElementById(rid);
const info = await fetchPrice(a.symbol).catch(() => null);
fetched++;
if (!el) return;
if (!info) { el.innerHTML = '<span style="color:var(--dimmed);font-size:0.72rem">获取失败</span>'; return; }
const invest = capital * (parseFloat(a.pct)||0) / 100;
const realPnl = invest * (info.price - a.entryPrice) / a.entryPrice;
realResults[idx] = realPnl;
el.innerHTML = sCell(realPnl, invest);
// Update total row when all fetched
if (fetched === d.assets.length) {
const totEl = document.getElementById('simreal-total');
if (totEl) {
const validResults = realResults.filter(r => r !== null);
if (validResults.length) {
const totReal = validResults.reduce((s,v) => s+v, 0);
totEl.innerHTML = sCell(totReal, totInvest);
}
}
}
});
}
function simUpdate() {
const d = simLoad();
d.capital = parseFloat(document.getElementById('sim-capital').value) || 10000;
d.currency = document.getElementById('sim-currency').value;
d.scenarios.bear = parseFloat(document.getElementById('sim-bear').value) || -20;
d.scenarios.base = parseFloat(document.getElementById('sim-base').value) || 8;
d.scenarios.bull = parseFloat(document.getElementById('sim-bull').value) || 25;
simSave(d);
simRenderAssets(d);
simCalcReturns(d);
}
function simSetHorizon(btn, h) {
const d = simLoad();
d.horizon = h;
simSave(d);
document.querySelectorAll('.sim-hbtn').forEach(b => b.classList.toggle('active', b.dataset.h === h));
simCalcReturns(d);
}
async function simAddAsset() {
const sym = (document.getElementById('sim-sym').value || '').trim().toUpperCase();
const alias = (document.getElementById('sim-alias').value || '').trim();
const pct = parseFloat(document.getElementById('sim-pct').value) || 0;
const manualEntry = parseFloat(document.getElementById('sim-entry').value) || null;
if (!sym) return;
const d = simLoad();
if (d.assets.find(a => a.symbol === sym)) { alert('该资产已在列表中'); return; }
let entryPrice = manualEntry;
if (!entryPrice) {
const btn = document.querySelector('#panel-sim .sim-add-row button');
if (btn) { btn.textContent = '抓取中…'; btn.disabled = true; }
const info = await fetchPrice(sym).catch(() => null);
if (btn) { btn.textContent = ' 添加'; btn.disabled = false; }
entryPrice = info ? info.price : null;
if (!entryPrice) { alert(`无法获取 ${sym} 当前价格,请手动填入买入价`); return; }
}
d.assets.push({ symbol: sym, alias, pct, entryPrice, entryDate: new Date().toISOString().slice(0,10) });
simSave(d);
document.getElementById('sim-sym').value = '';
document.getElementById('sim-alias').value = '';
document.getElementById('sim-pct').value = '';
document.getElementById('sim-entry').value = '';
simRender();
}
function simRemoveAsset(idx) {
const d = simLoad();
d.assets.splice(idx, 1);
simSave(d);
simRender();
}
function simUpdatePct(idx, val) {
const d = simLoad();
d.assets[idx].pct = parseFloat(val) || 0;
simSave(d);
simRenderAssets(d);
simCalcReturns(d);
}
function simReset() {
if (!confirm('确认重置模拟器数据?')) return;
localStorage.removeItem(lsSIM());
simRender();
}
// Init personal dashboard on load
document.addEventListener('DOMContentLoaded', function() {
profileRenderSelect();
wlRender();
pfRender();
simRender();
// Enter key triggers add
document.getElementById('wl-name').addEventListener('keydown', e => { if(e.key==='Enter') wlAdd(); });
document.getElementById('pf-cost').addEventListener('keydown', e => { if(e.key==='Enter') pfAdd(); });
});
// ── Reading progress bar ──────────────────────────────────────────────────────────
(function() {
const bar = document.getElementById('reading-progress');
if (!bar) return;
window.addEventListener('scroll', function() {
const scrolled = window.scrollY;
const total = document.documentElement.scrollHeight - window.innerHeight;
bar.style.width = (total > 0 ? (scrolled / total * 100) : 0) + '%';
}, { passive: true });
})();
// ── Back-to-top FAB visibility ───────────────────────────────────────────────────
(function() {
const btn = document.getElementById('fab-top');
if (!btn) return;
window.addEventListener('scroll', function() {
btn.classList.toggle('visible', window.scrollY > 400);
}, { passive: true });
})();
// ── Share / copy URL ────────────────────────────────────────────────────────────
function shareOrCopy() {
const url = window.location.href;
const toast = document.getElementById('share-toast');
if (navigator.share) {
navigator.share({ title: '金融日报 | Financial Daily', url });
} else {
navigator.clipboard.writeText(url).then(function() {
toast.classList.add('show');
setTimeout(function() { toast.classList.remove('show'); }, 2000);
});
}
}
// ── Jump nav active highlight on scroll ────────────────────────────────────────
(function() {
const sections = document.querySelectorAll('.sec-anchor[id]');
const links = document.querySelectorAll('.jump-nav a');
if (!sections.length || !links.length) return;
const obs = new IntersectionObserver(function(entries) {
entries.forEach(function(entry) {
if (entry.isIntersecting) {
links.forEach(function(l) { l.classList.remove('active'); });
const a = document.querySelector('.jump-nav a[href="#' + entry.target.id + '"]');
if (a) a.classList.add('active');
}
});
}, { rootMargin: '-20% 0px -70% 0px' });
sections.forEach(function(s) { obs.observe(s); });
})();
// ── Dismiss subscribe strip if already dismissed ────────────────────────────
(function() {
if (localStorage.getItem('fd_sub_dismissed')) {
var el = document.getElementById('subscribe-strip');
if (el) el.style.display = 'none';
}
})();
// ── Subscriber count (Telegram) ───────────────────────────────────────
(function loadSubCount() {
const el = document.getElementById('subscriber-count');
if (!el) return;
fetch('data/investment-subscribers.json')
.then(r => r.json())
.then(d => {
const count = Object.values(d.subscribers || {}).filter(s => s.active).length;
if (count > 0) el.textContent = `📱 ${count} 人已订阅Telegram早报`;
})
.catch(() => {});
})();
// ── AI 操盘实验(多模型对比)─────────────────────────────────────────
(function loadAIPortfolio() {
const fmt$ = v => '$' + v.toLocaleString('en-US', {minimumFractionDigits:2, maximumFractionDigits:2});
const fmtPct = v => (v >= 0 ? '+' : '') + v.toFixed(2) + '%';
function renderModelDetail(modelId, pf, contest) {
const history = pf.history || [];
const latest = history[history.length - 1] || {};
const holdings = pf.holdings || [];
const startCap = contest.start_capital || 10000;
const pv = latest.portfolio_value || 0;
const bv = latest.baseline_value || 0;
const cash = latest.cash || 0;
const positions = latest.positions || {};
const trades = latest.trades || [];
let html = '';
// 持仓明细
html += `<div style="font-size:0.72rem;text-transform:uppercase;letter-spacing:0.08em;color:var(--muted);margin-bottom:8px;">📊 当前持仓</div>`;
html += `<div style="display:flex;flex-direction:column;gap:5px;margin-bottom:14px;">`;
Object.entries(positions).forEach(([t, pos]) => {
const h = holdings.find(x => x.ticker === t);
const avg = h ? h.avg_cost : pos.price;
const pl = pos.price - avg;
const plP = avg > 0 ? pl / avg * 100 : 0;
const pct = pv > 0 ? pos.value / pv * 100 : 0;
const c = pl >= 0 ? 'var(--up)' : 'var(--down)';
html += `<div style="display:flex;align-items:center;gap:8px;padding:5px 8px;background:rgba(255,255,255,0.03);border-radius:6px;font-size:0.79rem;">
<span style="font-family:var(--mono);font-weight:600;min-width:44px;color:var(--accent);">${t}</span>
<span style="color:var(--muted);min-width:46px;">${pos.shares}股</span>
<span style="font-family:var(--mono);min-width:66px;">$${pos.price.toFixed(2)}</span>
<span style="font-family:var(--mono);min-width:72px;">${fmt$(pos.value)}</span>
<span style="color:${c};min-width:62px;">${(pl>=0?'+':'')}${fmtPct(plP)}</span>
<div style="flex:1;height:3px;background:rgba(255,255,255,0.06);border-radius:2px;"><div style="width:${Math.min(pct,100).toFixed(1)}%;height:100%;background:var(--accent);border-radius:2px;"></div></div>
<span style="color:var(--muted);min-width:34px;text-align:right;">${pct.toFixed(1)}%</span>
</div>`;
});
if (cash > 0) {
const cp = pv > 0 ? cash / pv * 100 : 0;
html += `<div style="display:flex;align-items:center;gap:8px;padding:5px 8px;background:rgba(255,255,255,0.03);border-radius:6px;font-size:0.79rem;">
<span style="font-family:var(--mono);font-weight:600;min-width:44px;color:#ffb300;">CASH</span>
<span style="color:var(--muted);min-width:46px;">—</span>
<span style="font-family:var(--mono);min-width:66px;">—</span>
<span style="font-family:var(--mono);min-width:72px;">${fmt$(cash)}</span>
<span style="color:var(--muted);min-width:62px;">现金</span>
<div style="flex:1;height:3px;background:rgba(255,255,255,0.06);border-radius:2px;"><div style="width:${Math.min(cp,100).toFixed(1)}%;height:100%;background:#ffb300;border-radius:2px;"></div></div>
<span style="color:var(--muted);min-width:34px;text-align:right;">${cp.toFixed(1)}%</span>
</div>`;
}
html += '</div>';
// 交易记录
if (trades.length) {
html += `<div style="font-size:0.72rem;text-transform:uppercase;letter-spacing:0.08em;color:var(--muted);margin-bottom:8px;">📋 今日交易</div>`;
html += trades.map(t => {
const ic = t.action==='BUY'?'🟢':t.action==='SELL'?'🔴':'🟡';
const c2 = t.action==='BUY'?'var(--up)':t.action==='SELL'?'var(--down)':'var(--warn)';
return `<div style="padding:5px 0;border-bottom:1px solid var(--border);font-size:0.8rem;">${ic} <strong style="color:${c2};">${t.action} ${t.ticker}</strong> ${t.shares}股 @ $${(t.price||0).toFixed(2)} <span style="color:var(--muted);">${t.reason||''}</span></div>`;
}).join('');
html += '<div style="margin-bottom:12px;"></div>';
}
// 备注
if (latest.note) {
html += `<div style="font-size:0.8rem;color:var(--muted);padding:8px 10px;background:rgba(0,212,170,0.04);border-left:2px solid var(--accent);border-radius:4px;">${latest.note}</div>`;
}
document.getElementById('ai-model-detail').innerHTML = html;
}
fetch('data/ai-portfolio.json?v=' + Date.now())
.then(r => r.json())
.then(data => {
const contest = data.contest || {};
const portfolios = data.portfolios || {};
const startCap = contest.start_capital || 10000;
const startDate = new Date(contest.start_date || '2026-05-13');
// 计算排名
const ranked = Object.entries(portfolios).map(([id, pf]) => {
const hist = pf.history || [];
const latest = hist[hist.length - 1] || {};
const pv = latest.portfolio_value || startCap;
const bv = latest.baseline_value || startCap;
const d = new Date(latest.date || contest.start_date);
const days = Math.round((d - startDate) / 86400000) + 1;
return { id, pf, pv, bv, days, latest };
}).sort((a, b) => b.pv - a.pv);
// 排行榜
const lbEl = document.getElementById('ai-leaderboard');
// 标题行:说明这是累计净值
lbEl.innerHTML = `<div style="font-size:0.72rem;color:var(--muted);margin-bottom:8px;">📅 累计净值 — 初始资金 ${fmt$(startCap)},自 ${contest.start_date} 起</div>`;
lbEl.innerHTML += ranked.map((r, i) => {
const pv = r.pv;
const bv = r.bv;
const pnl = pv - startCap;
const ret = pnl / startCap * 100;
const alpha = pv - bv;
const alphaP = bv > 0 ? alpha / bv * 100 : 0;
const retC = ret >= 0 ? 'var(--up)' : 'var(--down)';
const alpC = alpha >= 0 ? 'var(--up)' : 'var(--down)';
const medal = i===0 ? '🥇' : i===1 ? '🥈' : '🥉';
const pf = r.pf;
return `<div style="display:flex;align-items:center;gap:10px;padding:10px 12px;background:rgba(255,255,255,0.04);border:1px solid var(--border);border-radius:8px;">
<span style="font-size:1.2rem;min-width:28px;">${medal}</span>
<span style="font-size:1.1rem;">${pf.emoji||'🤖'}</span>
<div style="flex:1;">
<div style="font-weight:600;font-size:0.9rem;">${pf.display_name||r.id}</div>
<div style="font-size:0.75rem;color:var(--muted);">${r.latest.note||''}</div>
</div>
<div style="text-align:right;min-width:90px;">
<div style="font-family:var(--mono);font-weight:600;font-size:0.95rem;">${fmt$(pv)}</div>
<div style="font-size:0.72rem;color:var(--muted);">累计净值</div>
</div>
<div style="text-align:right;min-width:90px;">
<div style="font-family:var(--mono);font-size:0.9rem;font-weight:600;color:${retC};">${(pnl>=0?'+':'')}${fmt$(pnl)}</div>
<div style="font-size:0.72rem;color:${retC};">${(ret>=0?'+':'')}${ret.toFixed(2)}% 累计</div>
</div>
<div style="text-align:right;min-width:80px;">
<div style="font-family:var(--mono);font-size:0.85rem;color:${alpC};">${(alpha>=0?'+':'')}${fmt$(alpha)}</div>
<div style="font-size:0.75rem;color:var(--muted);">vs SPY</div>
</div>
</div>`;
}).join('');
// SPY 基线行
const anyLatest = ranked[0]?.latest || {};
const spyVal = anyLatest.baseline_value || startCap;
const spyPnl = spyVal - startCap;
const spyRet = spyPnl / startCap * 100;
const spyC = spyRet >= 0 ? 'var(--up)' : 'var(--down)';
lbEl.innerHTML += `<div style="display:flex;align-items:center;gap:10px;padding:10px 12px;background:rgba(255,255,255,0.02);border:1px solid var(--border);border-radius:8px;opacity:0.7;">
<span style="font-size:1.2rem;min-width:28px;">📊</span>
<span style="font-size:1.1rem;">—</span>
<div style="flex:1;"><div style="font-weight:600;font-size:0.9rem;">SPY 基线(买入持有)</div><div style="font-size:0.75rem;color:var(--muted);">S&amp;P 500 ETF · ${contest.baseline?.shares||13.5296} 股</div></div>
<div style="text-align:right;min-width:90px;">
<div style="font-family:var(--mono);font-weight:600;font-size:0.95rem;">${fmt$(spyVal)}</div>
<div style="font-size:0.72rem;color:var(--muted);">累计净值</div>
</div>
<div style="text-align:right;min-width:90px;">
<div style="font-family:var(--mono);font-size:0.9rem;font-weight:600;color:${spyC};">${(spyPnl>=0?'+':'')}${fmt$(spyPnl)}</div>
<div style="font-size:0.72rem;color:${spyC};">${(spyRet>=0?'+':'')}${spyRet.toFixed(2)}% 累计</div>
</div>
<div style="text-align:right;min-width:80px;">
<div style="font-family:var(--mono);font-size:0.85rem;color:var(--muted);">—</div>
<div style="font-size:0.75rem;color:var(--muted);">基准</div>
</div>
</div>`;
// 模型 Tab
const tabsEl = document.getElementById('ai-model-tabs');
let activeModel = ranked[0]?.id;
function setActiveTab(id) {
activeModel = id;
tabsEl.querySelectorAll('button').forEach(b => {
b.style.background = b.dataset.id === id ? 'rgba(0,212,170,0.15)' : 'rgba(255,255,255,0.04)';
b.style.borderColor = b.dataset.id === id ? 'var(--accent)' : 'var(--border)';
b.style.color = b.dataset.id === id ? 'var(--accent)' : 'var(--text)';
});
const pf = portfolios[id];
if (pf) renderModelDetail(id, pf, contest);
}
tabsEl.innerHTML = ranked.map(r => {
const pf = r.pf;
return `<button data-id="${r.id}" onclick="(function(id){window._aiSetTab&&window._aiSetTab(id)})('${r.id}')" style="padding:6px 12px;border-radius:6px;border:1px solid var(--border);background:rgba(255,255,255,0.04);color:var(--text);cursor:pointer;font-size:0.8rem;">${pf.emoji||'🤖'} ${pf.display_name||r.id}</button>`;
}).join('');
window._aiSetTab = setActiveTab;
setActiveTab(activeModel);
// 历史对比表
const histEl = document.getElementById('ai-history-table');
const allDates = [...new Set(ranked.flatMap(r => (r.pf.history||[]).map(h => h.date)))].sort().reverse();
if (allDates.length > 1) {
const headers = ['<th style="text-align:left;padding:4px 6px;font-size:0.72rem;">日期</th>',
...ranked.map(r => `<th style="text-align:right;padding:4px 6px;font-size:0.72rem;">${r.pf.emoji||'📊'} ${r.pf.display_name||r.id}</th>`),
'<th style="text-align:right;padding:4px 6px;font-size:0.72rem;">SPY 基线</th>'
].join('');
const subHeaders = ['<th style="text-align:left;padding:2px 6px;font-size:0.65rem;color:var(--muted);">日期</th>',
...ranked.map(() => '<th style="text-align:right;padding:2px 6px;font-size:0.65rem;color:var(--muted);">净值 / 今日盈亏</th>'),
'<th style="text-align:right;padding:2px 6px;font-size:0.65rem;color:var(--muted);">净值 / 今日盈亏</th>'
].join('');
const rows = allDates.map((date, dateIndex) => {
const prevDate = allDates[dateIndex + 1]; // previous trading day (sorted descending)
const cells = ranked.map(r => {
const rec = (r.pf.history||[]).find(h => h.date === date);
if (!rec) return '<td style="text-align:right;padding:4px 6px;color:var(--muted);">—</td>';
const pv = rec.portfolio_value;
const prevRec = prevDate ? (r.pf.history||[]).find(h => h.date === prevDate) : null;
const prevVal = prevRec ? prevRec.portfolio_value : startCap;
const dailyPnl = pv - prevVal;
const dailyRet = dailyPnl / prevVal * 100;
const c = dailyRet >= 0 ? 'var(--up)' : 'var(--down)';
return `<td style="text-align:right;padding:4px 6px;"><div style="font-family:var(--mono);font-size:0.8rem;font-weight:600;">${fmt$(pv)}</div><div style="font-size:0.72rem;color:${c};">${(dailyPnl>=0?'+':'')}${fmt$(dailyPnl)} (${(dailyRet>=0?'+':'')}${dailyRet.toFixed(2)}% 今日)</div></td>`;
}).join('');
const spyRec = (ranked[0]?.pf.history||[]).find(h => h.date === date);
const spyV = spyRec ? spyRec.baseline_value : startCap;
const spyPrevRec = prevDate ? (ranked[0]?.pf.history||[]).find(h => h.date === prevDate) : null;
const spyPrevV = spyPrevRec ? spyPrevRec.baseline_value : startCap;
const spyDailyPnl = spyV - spyPrevV;
const spyDailyR = spyDailyPnl / spyPrevV * 100;
const sc = spyDailyR >= 0 ? 'var(--up)' : 'var(--down)';
return `<tr style="border-top:1px solid var(--border);"><td style="padding:4px 6px;color:var(--muted);font-size:0.8rem;">${date}</td>${cells}<td style="text-align:right;padding:4px 6px;"><div style="font-family:var(--mono);font-size:0.8rem;font-weight:600;">${fmt$(spyV)}</div><div style="font-size:0.72rem;color:${sc};">${(spyDailyPnl>=0?'+':'')}${fmt$(spyDailyPnl)} (${(spyDailyR>=0?'+':'')}${spyDailyR.toFixed(2)}% 今日)</div></td></tr>`;
}).join('');
histEl.innerHTML = `<div style="font-size:0.72rem;color:var(--muted);margin-bottom:6px;">📈 净值走势(自 ${contest.start_date} 起,初始 ${fmt$(startCap)}</div><table style="width:100%;border-collapse:collapse;"><thead><tr style="color:var(--text);border-bottom:1px solid var(--border);">${headers}</tr></thead><tbody>${rows}</tbody></table>`;
} else {
histEl.innerHTML = '<span style="color:var(--muted);font-size:0.8rem;">天数超过1天后显示对比曲线…</span>';
}
document.getElementById('ai-portfolio-loading').style.display='none';
document.getElementById('ai-portfolio-content').style.display='';
})
.catch(()=>{ const el=document.getElementById('ai-portfolio-loading'); if(el) el.textContent='数据加载失败'; });
})();
// ── Visitor counter (Cloudflare Worker + KV) ──────────────────────────
document.addEventListener('DOMContentLoaded', function () {
const WORKER = 'https://finance-daily-counter.yangbai0110.workers.dev';
const LS_KEY = 'fd_visited';
const visEl = document.getElementById('footer-visitors');
const pvEl = document.getElementById('footer-pageviews');
function fmt(n) { return Number(n).toLocaleString('en-US'); }
function animate(el, target) {
if (!el) return;
if (target === 0) { el.textContent = '0'; return; }
const dur = 900; let t0 = null;
const step = ts => {
if (!t0) t0 = ts;
const p = Math.min((ts - t0) / dur, 1);
el.textContent = fmt(Math.round((1 - Math.pow(1 - p, 3)) * target));
if (p < 1) requestAnimationFrame(step);
};
requestAnimationFrame(step);
}
const isNew = !localStorage.getItem(LS_KEY);
fetch(WORKER + (isNew ? '?newVisitor=1' : '?newVisitor=0'))
.then(r => r.json())
.then(data => {
localStorage.setItem(LS_KEY, '1');
animate(visEl, data.visitors || 0);
animate(pvEl, data.pageViews || 0);
})
.catch(() => {
if (visEl) visEl.textContent = '--';
if (pvEl) pvEl.textContent = '--';
});
});
</script>
<script>
// ─── Streak counter ────────────────────────────────────────────────────────
(function() {
var today = new Date().toISOString().slice(0,10);
var last = localStorage.getItem('fd_last_visit') || '';
var streak = parseInt(localStorage.getItem('fd_streak') || '0');
if (last !== today) {
var yesterday = new Date(Date.now() - 86400000).toISOString().slice(0,10);
streak = (last === yesterday) ? streak + 1 : 1;
localStorage.setItem('fd_last_visit', today);
localStorage.setItem('fd_streak', streak);
}
if (streak >= 2) {
var meta = document.querySelector('.header-meta');
if (meta) {
var sb = document.createElement('span');
sb.className = 'streak-badge';
sb.title = '连续访问天数';
sb.innerHTML = '🔥 ' + streak + ' 天';
meta.appendChild(sb);
}
}
})();
// ─── Mark first breaking news as NEW ────────────────────────────────────────
document.querySelectorAll('.news-item.breaking, .news-item.major').forEach(function(n, i) {
if (i < 2) {
var title = n.querySelector('.news-title');
if (title) {
var badge = document.createElement('span');
badge.className = 'new-badge';
badge.textContent = '新';
badge.style.cssText = 'display:inline-block;font-size:.58rem;font-family:var(--mono);padding:1px 5px;border-radius:3px;background:rgba(0,212,170,.15);color:var(--accent);border:1px solid rgba(0,212,170,.3);margin-right:6px;vertical-align:middle;';
title.insertBefore(badge, title.firstChild);
}
}
});
// ─── News toggle ────────────────────────────────────────────────────────────
function toggleNews(el) { el.classList.toggle('expanded'); }
</script>
<!-- Floating action cluster -->
<div class="fab-cluster">
<button class="fab" id="fab-share" title="分享此页" onclick="shareOrCopy()">🔗</button>
<button class="fab" id="fab-top" title="回到顶部" onclick="window.scrollTo({top:0,behavior:'smooth'})"></button>
</div>
<div id="share-toast">✅ 链接已复制</div>
<!-- =======================================================
INTRO ANIMATION
======================================================= -->
<script>
(function() {
'use strict';
// Skip if user already visited this session
if (sessionStorage.getItem('fd-intro-done')) {
var ov = document.getElementById('intro-overlay');
if (ov) ov.classList.add('gone');
return;
}
var canvas = document.getElementById('intro-canvas');
var overlay = document.getElementById('intro-overlay');
if (!canvas || !overlay) return;
var ctx = canvas.getContext('2d');
var W, H;
function resize() {
W = canvas.width = window.innerWidth;
H = canvas.height = window.innerHeight;
}
resize();
window.addEventListener('resize', resize);
// --- Candlestick data (simulated) ---
var candles = [];
for (var i = 0; i < 60; i++) {
var base = 400 + Math.sin(i * 0.18) * 40 + Math.random() * 20;
var o = base + (Math.random() - 0.5) * 15;
var c = base + (Math.random() - 0.5) * 15;
var h = Math.max(o, c) + Math.random() * 12;
var l = Math.min(o, c) - Math.random() * 12;
candles.push({ o: o, c: c, h: h, l: l });
}
// --- Streaming ticker lines ---
var tickers = [
'NVDA +2.47%', 'SPY +0.31%', 'QQQ +0.19%', 'AAPL -0.12%', 'TSLA +1.04%',
'META +0.88%', 'MSFT +0.55%', 'BTC +0.24%', 'GLD -0.42%', 'AMD +3.21%',
'GOOGL +0.37%', 'AMZN +0.62%', 'TLT -0.35%', 'INTC +4.60%', 'AVGO +1.14%',
'VIX 16.76', 'DXY 99.25', 'WTI $98.05', 'AU $4524', 'ETH +1.18%'
];
var streamLines = [];
for (var j = 0; j < 18; j++) {
streamLines.push({
x: Math.random() * W,
y: Math.random() * H,
speed: 0.3 + Math.random() * 0.5,
text: tickers[j % tickers.length],
opacity: 0.04 + Math.random() * 0.12,
size: 10 + Math.floor(Math.random() * 4)
});
}
var progress = document.getElementById('intro-progress');
var startTime = performance.now();
var DURATION = 3500; // ms total
var animDone = false;
var rafId;
function draw(now) {
if (animDone) return;
var elapsed = now - startTime;
var t = Math.min(elapsed / DURATION, 1);
ctx.clearRect(0, 0, W, H);
// -- Background gradient --
var grad = ctx.createRadialGradient(W/2, H/2, 0, W/2, H/2, Math.max(W,H) * 0.7);
grad.addColorStop(0, 'rgba(7,20,35,.85)');
grad.addColorStop(1, 'rgba(3,6,9,1)');
ctx.fillStyle = grad;
ctx.fillRect(0, 0, W, H);
// -- Grid lines --
ctx.strokeStyle = 'rgba(0,212,170,0.04)';
ctx.lineWidth = 1;
var step = 60;
for (var gx = 0; gx < W; gx += step) {
ctx.beginPath(); ctx.moveTo(gx, 0); ctx.lineTo(gx, H); ctx.stroke();
}
for (var gy = 0; gy < H; gy += step) {
ctx.beginPath(); ctx.moveTo(0, gy); ctx.lineTo(W, gy); ctx.stroke();
}
// -- Streaming tickers --
ctx.font = '11px JetBrains Mono, monospace';
streamLines.forEach(function(l) {
l.y -= l.speed;
if (l.y < -20) { l.y = H + 20; l.x = Math.random() * W; l.text = tickers[Math.floor(Math.random()*tickers.length)]; }
var isUp = l.text.indexOf('-') === -1 || l.text.indexOf('+') !== -1;
ctx.fillStyle = isUp
? 'rgba(0,230,118,' + l.opacity + ')'
: 'rgba(255,82,82,' + l.opacity + ')';
ctx.fillText(l.text, l.x, l.y);
});
// -- Candlestick chart (bottom area) --
var revealCandles = Math.floor(t * candles.length);
var cW = Math.min(W * 0.7, 600);
var cH = 90;
var cX = (W - cW) / 2;
var cY = H * 0.72;
var maxP = Math.max.apply(null, candles.map(function(c){return c.h;}));
var minP = Math.min.apply(null, candles.map(function(c){return c.l;}));
var range = maxP - minP || 1;
var barW = cW / candles.length * 0.7;
ctx.globalAlpha = Math.min(t * 3, 1) * 0.7;
for (var ci = 0; ci < revealCandles; ci++) {
var cd = candles[ci];
var cx = cX + (ci + 0.5) * (cW / candles.length);
var cy_o = cY + (1 - (cd.o - minP) / range) * cH;
var cy_c = cY + (1 - (cd.c - minP) / range) * cH;
var cy_h = cY + (1 - (cd.h - minP) / range) * cH;
var cy_l = cY + (1 - (cd.l - minP) / range) * cH;
var isGreen = cd.c >= cd.o;
ctx.strokeStyle = isGreen ? '#00e676' : '#ff5252';
ctx.lineWidth = 1;
ctx.beginPath(); ctx.moveTo(cx, cy_h); ctx.lineTo(cx, cy_l); ctx.stroke();
ctx.fillStyle = isGreen ? '#00e676' : '#ff5252';
var bh = Math.abs(cy_c - cy_o);
ctx.fillRect(cx - barW/2, Math.min(cy_o, cy_c), barW, Math.max(bh, 1.5));
}
ctx.globalAlpha = 1;
// -- Progress bar --
if (progress) progress.style.width = (t * 100) + '%';
if (elapsed >= DURATION) {
dismissIntro();
return;
}
rafId = requestAnimationFrame(draw);
}
rafId = requestAnimationFrame(draw);
// -- Populate intro tickers from quotes.json --
fetch('data/quotes.json?' + Date.now())
.then(function(r){ return r.ok ? r.json() : null; })
.then(function(data) {
if (!data || !data.quotes) return;
var map = {};
data.quotes.forEach(function(q){ map[q.name] = q; });
var bindings = [
['it-spy', 'it-spy-chg', '标晥00'],
['it-qqq', 'it-qqq-chg', '纳斯达克'],
['it-btc', 'it-btc-chg', '比特币'],
['it-gld', 'it-gld-chg', '黄金现货'],
];
bindings.forEach(function(b){
var q = map[b[2]];
var el = document.getElementById(b[0]);
var chgEl = document.getElementById(b[1]);
if (!el || !q) return;
el.textContent = q.value || '—';
if (chgEl && q.change_pct) {
chgEl.textContent = (q.direction === 'up' ? '▲ ' : '▼ ') + q.change_pct;
chgEl.className = 'it-chg ' + q.direction;
}
});
}).catch(function(){});
window.dismissIntro = function() {
if (animDone) return;
animDone = true;
cancelAnimationFrame(rafId);
overlay.classList.add('fade-out');
sessionStorage.setItem('fd-intro-done', '1');
setTimeout(function(){ overlay.classList.add('gone'); }, 750);
};
// Keyboard shortcut: any key skips intro
document.addEventListener('keydown', function handler(e) {
dismissIntro();
document.removeEventListener('keydown', handler);
}, { once: true });
})();
</script>
<!-- =======================================================
I18N / LANGUAGE TOGGLE
======================================================= -->
<script>
(function() {
'use strict';
var LANG = {
zh: {
'nav-archive': '归档',
'nav-summary': '📊 大势',
'nav-ai-trading': '🤖 AI操盘',
'nav-news': '📰 要闻',
'nav-watchlist': '🎯 AI分析',
'nav-macro': '📈 宏观',
'nav-earnings': '💼 财报',
'nav-sectors': '🏭 行业',
'nav-debate': '⚔️ 辩论',
'nav-calendar': '📅 日历',
'nav-my': '⭐ 我的',
},
en: {
'nav-archive': 'Archive',
'nav-summary': '📊 Market',
'nav-ai-trading': '🤖 AI Trade',
'nav-news': '📰 News',
'nav-watchlist': '🎯 Watchlist',
'nav-macro': '📈 Macro',
'nav-earnings': '💼 Earnings',
'nav-sectors': '🏭 Sectors',
'nav-debate': '⚔️ Bull/Bear',
'nav-calendar': '📅 Calendar',
'nav-my': '⭐ My Dashboard',
}
};
// Section label maps (by section id + .section-label text)
var SECTION_LABELS = {
zh: {
'sec-news': '📰 市场要闻 · Market News',
'sec-ai-trading': '🤖 AI 操盘实验 · AI Trading Challenge',
'sec-watchlist': '🎯 AI 决策仪表盘 · AI Watchlist',
'sec-macro': '📈 宏观指标 · Macro',
'sec-debate': '⚔️ 多空辩论 · Bull vs Bear',
'sec-earnings': '💼 财报追踪 · Earnings',
'sec-sectors': '🏭 板块表现 · Sectors',
'sec-replay': '🎥 大盘复盘 · Replay',
'sec-calendar': '📅 本周日程 · Calendar',
'sec-leaders': '👔 领袖观点 · Leaders',
'sec-banks': '🏦 幂行动态 · Central Banks',
},
en: {
'sec-news': '📰 Market News',
'sec-ai-trading': '🤖 AI Trading Challenge',
'sec-watchlist': '🎯 AI Watchlist',
'sec-macro': '📈 Macro Indicators',
'sec-debate': '⚔️ Bull vs Bear',
'sec-earnings': '💼 Earnings Tracker',
'sec-sectors': '🏭 Sector Performance',
'sec-replay': '🎥 Market Replay',
'sec-calendar': '📅 Economic Calendar',
'sec-leaders': '👔 Market Leaders',
'sec-banks': '🏦 Central Banks',
}
};
// Static UI strings (selectors → text)
var STATIC_EN = [
['.site-title', 'Financial Daily'],
['.site-sub', 'AI-Powered · Daily Briefing'],
['.subscribe-strip-body strong', 'Subscribe to Daily Briefing'],
['.subscribe-strip-body span', 'Updated twice daily, every trading day'],
['.btn-sub-email', '📧 Email'],
['#pod-play', '▶ Play'],
['.podcast-title', 'Financial Daily · Today\'s Podcast'],
['.my-drawer-toggle span:first-child', '⭐ My Dashboard'],
['#ptab-wl', '📋 Watchlist'],
['#ptab-pf', '💼 Portfolio P&L'],
['#ptab-sim', '📊 Simulator'],
['#wl-empty', 'No stocks yet. Enter a symbol to start tracking →'],
['#pf-empty', 'No positions yet. Add holdings to track P&L →'],
['.footer-inner span:nth-child(2)', 'AI-generated content for informational purposes only. Not investment advice.'],
];
var STATIC_ZH = [
['.site-title', '金融日报'],
['.site-sub', 'Financial Daily'],
['.subscribe-strip-body strong', '订阅每日金融早报'],
['.subscribe-strip-body span', '每个交易日自动更新,开盘前 + 收盘后各一次'],
['.btn-sub-email', '📧 邮件'],
['#pod-play', '▶ 播放'],
['.podcast-title', '金融日报早报 · 今日播客'],
['.my-drawer-toggle span:first-child', '⭐ 我的工作台 · My Dashboard'],
['#ptab-wl', '📋 自选股'],
['#ptab-pf', '💼 持仓盈亏'],
['#ptab-sim', '📊 模拟器'],
['#wl-empty', '还没有自选股,输入代码开始追踪 →'],
['#pf-empty', '还没有持仓记录,输入持仓开始计算浮盈浮亏 →'],
['.footer-inner span:nth-child(2)', '内容由AI自动生成,仅供参考,不构成投资建议'],
];
function applyLang(lang) {
// Toggle body class
document.body.classList.remove('lang-zh', 'lang-en');
document.body.classList.add('lang-' + lang);
// Update toggle button active state
var elZH = document.getElementById('lang-zh');
var elEN = document.getElementById('lang-en');
if (elZH) elZH.classList.toggle('active', lang === 'zh');
if (elEN) elEN.classList.toggle('active', lang === 'en');
// data-i18n nav items
var map = LANG[lang];
document.querySelectorAll('[data-i18n]').forEach(function(el) {
var key = el.getAttribute('data-i18n');
if (map[key]) el.textContent = map[key];
});
// Section labels
var slMap = SECTION_LABELS[lang];
Object.entries(slMap).forEach(function(entry) {
var secId = entry[0], text = entry[1];
var sec = document.getElementById(secId);
if (!sec) return;
var lbl = sec.querySelector('.section-label');
if (lbl) lbl.childNodes.forEach(function(n){ if (n.nodeType === 3 && n.textContent.trim()) n.textContent = ' ' + text; });
});
// Static UI strings
var statics = lang === 'en' ? STATIC_EN : STATIC_ZH;
statics.forEach(function(pair) {
try {
var el = document.querySelector(pair[0]);
if (el) el.textContent = pair[1];
} catch(e) {}
});
// date format
var dateEl = document.getElementById('current-date');
if (dateEl) {
var now = new Date();
var opts = lang === 'en'
? { year: 'numeric', month: 'short', day: 'numeric', weekday: 'short' }
: { year: 'numeric', month: 'long', day: 'numeric', weekday: 'short' };
dateEl.textContent = now.toLocaleDateString(lang === 'en' ? 'en-US' : 'zh-CN', opts);
}
// AI portfolio section heading (dynamic)
var lbHdr = document.querySelector('#ai-portfolio-content > div:first-child');
if (lbHdr) lbHdr.innerHTML = lang === 'en'
? '🏆 Leaderboard <span style="font-size:.68rem;color:var(--dimmed);margin-left:6px;">Starting capital $10,000 · Baseline: SPY buy &amp; hold</span>'
: '🏆 排行榜 · Leaderboard <span style="font-size:.68rem;color:var(--dimmed);margin-left:6px;">初始资金 $10,000 · 基线 SPY买入持有</span>';
localStorage.setItem('fd-lang', lang);
// ── Google Translate for dynamic content ───────────────────
triggerGoogleTranslate(lang);
}
// ── Google Translate helper ─────────────────────────────────
var _gtRetries = 0;
function triggerGoogleTranslate(lang) {
var targetLang = lang === 'en' ? 'en' : 'zh-CN';
// Method 1: drive the hidden <select> that GT injects
function driveSelect() {
var sel = document.querySelector('.goog-te-combo');
if (sel) {
sel.value = targetLang;
sel.dispatchEvent(new Event('change', { bubbles: true }));
return true;
}
return false;
}
// Method 2: cookie + reload fallback
function cookieFallback() {
var exp = new Date();
exp.setTime(exp.getTime() + 30 * 24 * 60 * 60 * 1000);
var expStr = '; expires=' + exp.toUTCString() + '; path=/';
if (lang === 'en') {
document.cookie = 'googtrans=/zh-CN/en' + expStr;
document.cookie = 'googtrans=/zh-CN/en' + expStr + '; domain=.' + window.location.hostname;
} else {
document.cookie = 'googtrans=; path=/; expires=Thu, 01 Jan 1970 00:00:00 UTC';
document.cookie = 'googtrans=; path=/; expires=Thu, 01 Jan 1970 00:00:00 UTC; domain=.' + window.location.hostname;
}
// Small delay then reload so cookie takes effect
setTimeout(function() { window.location.reload(); }, 150);
}
// Try select-drive first; retry up to 8 times while GT loads
if (driveSelect()) { _gtRetries = 0; return; }
if (_gtRetries < 8) {
_gtRetries++;
setTimeout(function() { triggerGoogleTranslate(lang); }, 400);
} else {
// GT never loaded (e.g. blocked) — use cookie+reload
_gtRetries = 0;
cookieFallback();
}
}
window.toggleLang = function() {
var current = localStorage.getItem('fd-lang') || 'zh';
applyLang(current === 'zh' ? 'en' : 'zh');
};
// Apply saved lang on load (after DOM ready)
var savedLang = localStorage.getItem('fd-lang') || 'zh';
document.addEventListener('DOMContentLoaded', function() {
applyLang(savedLang);
});
// Also expose for external call after dynamic content loads
window.applyCurrentLang = function() {
applyLang(localStorage.getItem('fd-lang') || 'zh');
};
})();
</script>
</body>
</html>