Files
finance-daily-site/archive/2026-07-07.html
T
2026-07-07 23:09:52 +00:00

3385 lines
168 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="../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 down">
<div class="ticker-name">S&P 500</div>
<div class="ticker-value">7,503.85</div>
<div class="ticker-change down">▼ -0.45%</div>
</div>
<div class="ticker-card down">
<div class="ticker-name">Nasdaq Composite</div>
<div class="ticker-value">25,818.69</div>
<div class="ticker-change down">▼ -1.16%</div>
</div>
<div class="ticker-card down">
<div class="ticker-name">Dow Jones</div>
<div class="ticker-value">52,925.15</div>
<div class="ticker-change down">▼ -0.25%</div>
</div>
<div class="ticker-card down">
<div class="ticker-name">上证综指</div>
<div class="ticker-value">3,990.24</div>
<div class="ticker-change down">▼ -1.26%</div>
</div>
<div class="ticker-card down">
<div class="ticker-name">恒生指数</div>
<div class="ticker-value">23,497</div>
<div class="ticker-change down">▼ -0.51%</div>
</div>
<div class="ticker-card down">
<div class="ticker-name">日经225</div>
<div class="ticker-value">68,256.96</div>
<div class="ticker-change down">▼ -2.12%</div>
</div>
<div class="ticker-card down">
<div class="ticker-name">德国DAX</div>
<div class="ticker-value">25,465</div>
<div class="ticker-change down">▼ -1.37%</div>
</div>
<div class="ticker-card up">
<div class="ticker-name">黄金现货</div>
<div class="ticker-value">4,165</div>
<div class="ticker-change up">▲ +0.19%</div>
</div>
<div class="ticker-card up">
<div class="ticker-name">WTI原油</div>
<div class="ticker-value">72.00</div>
<div class="ticker-change up">▲ +5.29%</div>
</div>
<div class="ticker-card up">
<div class="ticker-name">比特币</div>
<div class="ticker-value">64,000</div>
<div class="ticker-change up">▲ +0.79%</div>
</div>
<div class="ticker-card up">
<div class="ticker-name">美元指数</div>
<div class="ticker-value">100.85</div>
<div class="ticker-change up">▲ +0.22%</div>
</div>
<div class="ticker-card down">
<div class="ticker-name">离岸人民币</div>
<div class="ticker-value">7.2450</div>
<div class="ticker-change down">▼ +0.21%</div>
</div>
<!-- INDICES:END -->
<!-- INDICES:END -->
<!-- duplicate for seamless loop -->
<!-- INDICES:START -->
<div class="ticker-card down">
<div class="ticker-name">S&P 500</div>
<div class="ticker-value">7,503.85</div>
<div class="ticker-change down">▼ -0.45%</div>
</div>
<div class="ticker-card down">
<div class="ticker-name">Nasdaq Composite</div>
<div class="ticker-value">25,818.69</div>
<div class="ticker-change down">▼ -1.16%</div>
</div>
<div class="ticker-card down">
<div class="ticker-name">Dow Jones</div>
<div class="ticker-value">52,925.15</div>
<div class="ticker-change down">▼ -0.25%</div>
</div>
<div class="ticker-card down">
<div class="ticker-name">上证综指</div>
<div class="ticker-value">3,990.24</div>
<div class="ticker-change down">▼ -1.26%</div>
</div>
<div class="ticker-card down">
<div class="ticker-name">恒生指数</div>
<div class="ticker-value">23,497</div>
<div class="ticker-change down">▼ -0.51%</div>
</div>
<div class="ticker-card down">
<div class="ticker-name">日经225</div>
<div class="ticker-value">68,256.96</div>
<div class="ticker-change down">▼ -2.12%</div>
</div>
<div class="ticker-card down">
<div class="ticker-name">德国DAX</div>
<div class="ticker-value">25,465</div>
<div class="ticker-change down">▼ -1.37%</div>
</div>
<div class="ticker-card up">
<div class="ticker-name">黄金现货</div>
<div class="ticker-value">4,165</div>
<div class="ticker-change up">▲ +0.19%</div>
</div>
<div class="ticker-card up">
<div class="ticker-name">WTI原油</div>
<div class="ticker-value">72.00</div>
<div class="ticker-change up">▲ +5.29%</div>
</div>
<div class="ticker-card up">
<div class="ticker-name">比特币</div>
<div class="ticker-value">64,000</div>
<div class="ticker-change up">▲ +0.79%</div>
</div>
<div class="ticker-card up">
<div class="ticker-name">美元指数</div>
<div class="ticker-value">100.85</div>
<div class="ticker-change up">▲ +0.22%</div>
</div>
<div class="ticker-card down">
<div class="ticker-name">离岸人民币</div>
<div class="ticker-value">7.2450</div>
<div class="ticker-change down">▼ +0.21%</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 bearish">
<div class="summary-top">
<span class="sentiment-pill bearish">🔴 看空 · Bearish</span>
<span class="vix-badge">VIX <span class="vix-num">15.88</span></span>
</div>
<div class="summary-headline">芯片股暴跌拖累纳指,油价飙升推高通胀预期</div>
<ul class="key-points"><li class="kp-item"><span class="kp-arrow"></span>芯片股集体重挫,半导体ETF跌超3%</li><li class="kp-item"><span class="kp-arrow"></span>油价因地缘冲突飙升5%以上</li><li class="kp-item"><span class="kp-arrow"></span>VIX维持低位15.88,市场仍相对平静</li></ul>
<details class="summary-details">
<summary class="summary-details-toggle">深度解读 ▸</summary>
<div class="summary-context">美股周二(7月7日)遭遇芯片股大幅抛售,纳指跌1.16%,道指小跌0.25%。三星财报未能提振市场,DeepSeek自研AI芯片消息引发对英伟达的担忧,半导体ETF重挫超3%。同时,伊朗袭击霍尔木兹海峡油轮推升原油价格超5%,加剧通胀压力。对于北美华人投资者,短期建议关注科技股回撤带来的买入机会,但需警惕美联储可能因通胀反弹而加息的风险。</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">芯片股遭遇大规模抛售,DeepSeek自研芯片引发担忧</div>
<span class="news-expand-icon"></span>
</div>
<div class="news-tldr"><span class="tldr-label">💡 新手解读</span>持有芯片股的投资者需警惕估值回调风险,可考虑逢低分批建仓</div>
<div class="news-body-collapse">周二芯片股集体暴跌,VanEck半导体ETF(SMH)下跌超3%,美光科技跌4.7%。路透报道中国AI初创公司DeepSeek正在开发自有AI芯片,与英伟达竞争,引发市场对AI芯片需求集中度的担忧。三星电子虽公布创纪录季度利润,但投资者对其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></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">伊朗袭击霍尔木兹海峡油轮,原油价格飙升超5%</div>
<span class="news-expand-icon"></span>
</div>
<div class="news-tldr"><span class="tldr-label">💡 新手解读</span>油价上涨将推高生活成本,美联储降息预期进一步推迟</div>
<div class="news-body-collapse">美国官员向CNBC透露,财政部正撤销允许伊朗石油销售的许可证。布伦特原油期货飙升超5%至76美元以上,WTI原油涨至72美元以上。霍尔木兹海峡威胁等级升至"严重",可能进一步推高能源价格,加剧通胀压力。</div>
<div class="news-footer">
<span class="importance-badge breaking">🔥 BREAKING</span>
<div class="tags"><span class="tag">#能源</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.bls.gov/news.release/empsit.nr0.htm" target="_blank" rel="noopener">美国6月新增就业仅5.7万,远低于预期</a></div>
<span class="news-expand-icon"></span>
</div>
<div class="news-tldr"><span class="tldr-label">💡 新手解读</span>就业放缓未能改变加息预期,通胀成为美联储首要关注点</div>
<div class="news-body-collapse">美国6月非农就业仅增加5.7万,大幅低于预期的11万和修正后的5月数据12.9万。失业率维持4.2%。尽管数据疲弱,但市场仍预期美联储可能在2026年晚些时候加息,因通胀担忧超过就业疲软。平均时薪同比增长3.5%,显示工资压力仍存。</div>
<div class="news-footer">
<span class="importance-badge high">• HIGH</span>
<div class="tags"><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">SpaceX正式加入纳斯达克100指数,首日下跌5%</div>
<span class="news-expand-icon"></span>
</div>
<div class="news-tldr"><span class="tldr-label">💡 新手解读</span>指数纳入不一定带来短期涨幅,需关注估值合理性</div>
<div class="news-body-collapse">埃隆·马斯克旗下SpaceX今日正式纳入纳斯达克100指数,成为该指数历史上最快入选的公司之一。尽管获得大量被动资金流入,SpaceX股价首日下跌超5%,反映出投资者对高估值的担忧。</div>
<div class="news-footer">
<span class="importance-badge medium">• MEDIUM</span>
<div class="tags"><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">特朗普关税政策持续影响企业利润</div>
<span class="news-expand-icon"></span>
</div>
<div class="news-tldr"><span class="tldr-label">💡 新手解读</span>关税转嫁给消费者,生活成本上升压力加大</div>
<div class="news-body-collapse">尽管最高法院推翻部分IEEPA关税,贸易不确定性仍困扰企业。宝洁公司称关税每年影响利润10亿美元,已对25%产品提价。通用汽车2025年关税成本达31亿美元。多家企业警告2026年关税影响仍将持续,拖累消费者支出和企业投资。</div>
<div class="news-footer">
<span class="importance-badge high">• HIGH</span>
<div class="tags"><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">中国Q1出口增长14%,但对美出口下降16%</div>
<span class="news-expand-icon"></span>
</div>
<div class="news-tldr"><span class="tldr-label">💡 新手解读</span>中国贸易转向发展中国家,对全球供应链影响深远</div>
<div class="news-body-collapse">中国海关数据显示,2026年一季度出口同比增长14%至9,776亿美元,但对美出口下降16%。中国加大向东南亚、非洲和欧盟的出口,分别增长20%、32%和21%。贸易顺差因AI芯片进口激增而收窄,一季度半导体进口达创纪录的1,350亿美元。</div>
<div class="news-footer">
<span class="importance-badge medium">• MEDIUM</span>
<div class="tags"><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">Vertex宣布100亿美元收购Crinetics制药</div>
<span class="news-expand-icon"></span>
</div>
<div class="news-tldr"><span class="tldr-label">💡 新手解读</span>生物医药并购活跃,板块或迎来新一轮整合潮</div>
<div class="news-body-collapse">生物制药公司Vertex宣布以约100亿美元收购Crinetics PharmaceuticalsCrinetics股价盘后暴涨近99%。这是2026年迄今最大的生物制药并购交易,预计第三季度完成。</div>
<div class="news-footer">
<span class="importance-badge medium">• MEDIUM</span>
<div class="tags"><span class="tag">#生物医药</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">195.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>62</span>/100</span>
</div>
<div class="wc-conclusion">短期承压,等待AI需求验证</div>
<div class="wc-driver">DeepSeek自研芯片引发竞争担忧,但AI数据中心投资仍强劲</div>
<div class="wc-targets"><span class="wc-target-up">↑ 236</span><span class="wc-target-down">↓ 180</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">建议持有现有仓位观望,等待Q2财报(8月26日)验证AI需求是否持续。回调至180美元附近可考虑加仓,但需控制仓位在10%以内。</div>
<div class="tags" style="margin-top:8px"><span class="tag">#AI</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">465.80</div><div class="wc-price-chg down">-1.5%</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">芯片股拖累指数,但七巨头中Meta、谷歌等仍相对抗跌</div>
<div class="wc-targets"><span class="wc-target-up">↑ 490</span><span class="wc-target-down">↓ 445</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">短期波动加大,建议定投策略,回调5%以上可分批买入。科技股长期受益于AI投资,但估值需消化。</div>
<div class="tags" style="margin-top:8px"><span class="tag">#科技</span><span class="tag">#ETF</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">565.20</div><div class="wc-price-chg down">-0.4%</div></div>
</div>
<div class="wc-signal-row">
<span class="signal-badge BUY">BUY</span>
<span class="wc-score">评分 <span>70</span>/100</span>
</div>
<div class="wc-conclusion">大盘相对抗跌,分散配置首选</div>
<div class="wc-driver">板块轮动明显,能源、防御性板块表现强劲抵消科技股跌幅</div>
<div class="wc-targets"><span class="wc-target-up">↑ 590</span><span class="wc-target-down">↓ 550</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">标普500估值相对纳指更合理,板块分散度高。建议作为核心持仓,回调至560以下逢低买入,目标仓位30-40%。</div>
<div class="tags" style="margin-top:8px"><span class="tag">#大盘</span><span class="tag">#ETF</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">64,000</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>55</span>/100</span>
</div>
<div class="wc-conclusion">震荡整理,突破65K才有上行空间</div>
<div class="wc-driver">风险资产属性明显,与纳斯达克相关性高达85%,缺乏独立行情</div>
<div class="wc-targets"><span class="wc-target-up">↑ 75,000</span><span class="wc-target-down">↓ 58,000</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">比特币仍受流动性和风险偏好主导,突破65,000美元后才能看向75,000。跌破60,000则可能测试55,000支撑。仅适合风险承受力高的投资者,建议仓位不超过5%。</div>
<div class="tags" style="margin-top:8px"><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">3.82</div><div class="wc-price-chg down">-1.3%</div></div>
</div>
<div class="wc-signal-row">
<span class="signal-badge BUY">BUY</span>
<span class="wc-score">评分 <span>68</span>/100</span>
</div>
<div class="wc-conclusion">估值底部,政策宽松支撑</div>
<div class="wc-driver">A股估值处历史低位,人民币升值预期和政策支持构成底部支撑</div>
<div class="wc-targets"><span class="wc-target-up">↑ 4.20</span><span class="wc-target-down">↓ 3.65</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">沪深300估值极具吸引力,中国政策底已现。建议北美华人配置5-10%作为分散化投资,长期定投策略。关注7月中旬经济数据。</div>
<div class="tags" style="margin-top:8px"><span class="tag">#A股</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">4,165</div><div class="wc-price-chg up">+0.2%</div></div>
</div>
<div class="wc-signal-row">
<span class="signal-badge BUY">BUY</span>
<span class="wc-score">评分 <span>75</span>/100</span>
</div>
<div class="wc-conclusion">通胀对冲首选,突破4200即可追涨</div>
<div class="wc-driver">地缘冲突和通胀反弹推升避险需求,各国央行持续增持黄金</div>
<div class="wc-targets"><span class="wc-target-up">↑ 4,900</span><span class="wc-target-down">↓ 4,050</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">黄金是当前环境下最佳通胀对冲工具。高盛预计年底达4,900美元。建议配置10-15%作为组合保护,回调至4,100以下加仓。</div>
<div class="tags" style="margin-top:8px"><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">72.00</div><div class="wc-price-chg up">+5.3%</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">伊朗冲突升级推升油价,但全球经济放缓抑制需求增长</div>
<div class="wc-targets"><span class="wc-target-up">↑ 85</span><span class="wc-target-down">↓ 65</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(XLE)间接参与,仓位控制在5%以内。</div>
<div class="tags" style="margin-top:8px"><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">425.00</div><div class="wc-price-chg up">+1.5%</div></div>
</div>
<div class="wc-signal-row">
<span class="signal-badge HOLD">HOLD</span>
<span class="wc-score">评分 <span>52</span>/100</span>
</div>
<div class="wc-conclusion">Q2交付数据将决定短期走向</div>
<div class="wc-driver">华尔街上调Q2交付预期,但估值仍偏高(P/E超200倍)</div>
<div class="wc-targets"><span class="wc-target-up">↑ 480</span><span class="wc-target-down">↓ 375</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">特斯拉波动性极高,等待Q2交付报告(7月初)和财报(7月22日)。基本面改善需要交付量和利润率双双超预期。投机性仓位可参与,但长期投资者建议观望。</div>
<div class="tags" style="margin-top:8px"><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">非农就业(6月)</div>
<div class="macro-value macro-value-down">5.7万</div>
<div class="macro-prev"><span class="arrow down"></span> 前值: 12.9万(修正)</div>
<div class="macro-desc">6月新增就业大幅低于预期11万,为四个月最低,显示劳动力市场降温</div>
</div>
<div class="macro-card dir-down">
<div class="macro-indicator">失业率(6月)</div>
<div class="macro-value macro-value-up">4.2%</div>
<div class="macro-prev"><span class="arrow down"></span> 前值: 4.3%</div>
<div class="macro-desc">失业率小幅下降,但就业参与率仍偏低</div>
</div>
<div class="macro-card dir-up">
<div class="macro-indicator">CPI YoY(5月)</div>
<div class="macro-value macro-value-down">4.2%</div>
<div class="macro-prev"><span class="arrow up"></span> 前值: 3.8%</div>
<div class="macro-desc">通胀意外反弹至4.2%,能源价格上涨是主要推手,超60%的月度涨幅来自能源</div>
</div>
<div class="macro-card dir-up">
<div class="macro-indicator">核心CPI YoY(5月)</div>
<div class="macro-value macro-value-down">2.9%</div>
<div class="macro-prev"><span class="arrow up"></span> 前值: 2.6%</div>
<div class="macro-desc">核心通胀升至2.9%,剔除食品和能源后仍显示价格压力</div>
</div>
<div class="macro-card dir-up">
<div class="macro-indicator">平均时薪YoY(6月)</div>
<div class="macro-value macro-value-up">3.5%</div>
<div class="macro-prev"><span class="arrow up"></span> 前值: 3.4%</div>
<div class="macro-desc">工资增速小幅加快,暗示工资-通胀螺旋风险</div>
</div>
<div class="macro-card dir-down">
<div class="macro-indicator">ISM服务业PMI(6月)</div>
<div class="macro-value macro-value-down">54.0%</div>
<div class="macro-prev"><span class="arrow down"></span> 前值: 54.5%</div>
<div class="macro-desc">服务业PMI略低于前值但仍处扩张区间,高于市场预期53.9%</div>
</div>
<div class="macro-card dir-down">
<div class="macro-indicator">美国GDP增速Q1(年化)</div>
<div class="macro-value macro-value-down">2.0%</div>
<div class="macro-prev"><span class="arrow down"></span> 前值: 2.5%</div>
<div class="macro-desc">一季度GDP增速放缓至2.0%,低于去年同期,消费支出疲软</div>
</div>
<div class="macro-card dir-down">
<div class="macro-indicator">中国GDP增速Q1</div>
<div class="macro-value macro-value-down">5.0%</div>
<div class="macro-prev"><span class="arrow down"></span> 前值: 5.4%(Q4 2025)</div>
<div class="macro-desc">中国一季度GDP增长5.0%,符合官方目标,但消费仍显疲弱</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 medium">medium</span>财报季开启,科技巨头盈利有望超预期</div>
<div class="debate-point"><span class="conf-badge high">high</span>板块轮动健康,能源金融接力科技</div>
<div class="debate-point"><span class="conf-badge high">high</span>VIX维持低位15.88,市场恐慌情绪可控</div>
</div>
<div class="debate-side bear">
<div class="debate-side-title">🐻 空方看跌</div>
<div class="debate-point"><span class="conf-badge high">high</span>芯片股暴跌可能引发科技股连锁反应</div>
<div class="debate-point"><span class="conf-badge high">high</span>油价飙升推高通胀,美联储加息预期升温</div>
<div class="debate-point"><span class="conf-badge medium">medium</span>就业数据疲弱暗示经济放缓滞胀风险</div>
</div>
</div>
<div class="debate-verdict">
<div class="verdict-label">裁判结论 <span class="verdict-lean neutral">NEUTRAL</span></div>
<div class="verdict-text">短期谨慎,7500点有支撑但上行空间有限。芯片股技术性调整叠加通胀反弹,令市场面临双重压力。建议降低科技股仓位,增配能源、金融等板块。等待7月14日CPI数据和财报季验证盈利成长性。</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">PEP</div>
<div class="earnings-company">PepsiCo</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.82</div>
</div>
<div class="eps-item">
<div class="eps-label">REPORT DATE</div>
<div class="eps-value est" style="font-size:0.75rem;">2026-07-10</div>
</div>
</div>
<div class="earnings-revenue">收入: <span>预期$19.8B</span></div>
<div class="earnings-highlight">第二季度财报季开启,关注食品饮料行业定价能力</div>
</div>
<div class="earnings-card pending">
<div class="earnings-ticker">DAL</div>
<div class="earnings-company">Delta Air Lines</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">$2.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-07-11</div>
</div>
</div>
<div class="earnings-revenue">收入: <span>预期$15.6B</span></div>
<div class="earnings-highlight">夏季旅游旺季需求及油价上涨对利润率的影响</div>
</div>
<div class="earnings-card pending">
<div class="earnings-ticker">JPM</div>
<div class="earnings-company">JPMorgan Chase</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.25</div>
</div>
<div class="eps-item">
<div class="eps-label">REPORT DATE</div>
<div class="eps-value est" style="font-size:0.75rem;">2026-07-14</div>
</div>
</div>
<div class="earnings-revenue">收入: <span>预期$41.2B</span></div>
<div class="earnings-highlight">大行Q2业绩将显示利率高位对交易和投行业务的影响</div>
</div>
<div class="earnings-card pending">
<div class="earnings-ticker">GS</div>
<div class="earnings-company">Goldman Sachs</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">$8.60</div>
</div>
<div class="eps-item">
<div class="eps-label">REPORT DATE</div>
<div class="eps-value est" style="font-size:0.75rem;">2026-07-14</div>
</div>
</div>
<div class="earnings-revenue">收入: <span>预期$12.8B</span></div>
<div class="earnings-highlight">Q1超预期9%,Q2关注交易收入和并购业务</div>
</div>
<div class="earnings-card pending">
<div class="earnings-ticker">TSLA</div>
<div class="earnings-company">Tesla</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.47</div>
</div>
<div class="eps-item">
<div class="eps-label">REPORT DATE</div>
<div class="eps-value est" style="font-size:0.75rem;">2026-07-22</div>
</div>
</div>
<div class="earnings-revenue">收入: <span>预期$25.1B</span></div>
<div class="earnings-highlight">Q2交付数据即将公布,华尔街上调交付预期</div>
</div>
<div class="earnings-card pending">
<div class="earnings-ticker">NVDA</div>
<div class="earnings-company">NVIDIA</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">$待定</div>
</div>
<div class="eps-item">
<div class="eps-label">REPORT DATE</div>
<div class="eps-value est" style="font-size:0.75rem;">2026-08-26</div>
</div>
</div>
<div class="earnings-revenue">收入: <span>市场高度关注</span></div>
<div class="earnings-highlight">AI芯片需求能否持续是全球市场焦点,DeepSeek竞争引发担忧</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">Energy</div></div>
<div class="sector-etf">XLE</div>
<div class="sector-bar-wrap"><div class="sector-bar up" style="width:61%"></div></div>
<div class="sector-pct up">+1.97%</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:66%"></div></div>
<div class="sector-pct up">+2.15%</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 up" style="width:54%"></div></div>
<div class="sector-pct up">+1.69%</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:50%"></div></div>
<div class="sector-pct up">+1.55%</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 up" style="width:48%"></div></div>
<div class="sector-pct up">+1.47%</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:31%"></div></div>
<div class="sector-pct up">+0.80%</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:17%"></div></div>
<div class="sector-pct up">+0.30%</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 down" style="width:12%"></div></div>
<div class="sector-pct down">-0.10%</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 down" style="width:66%"></div></div>
<div class="sector-pct down">-2.13%</div>
</div>
<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 down" style="width:84%"></div></div>
<div class="sector-pct down">-2.84%</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 down" style="width:100%"></div></div>
<div class="sector-pct down">-3.41%</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">↑1,850</span>
<div class="ad-bar adv" style="width:36px;max-width:80px"></div>
<div class="ad-bar dec" style="width:64px;max-width:80px"></div>
<span class="ad-label-dn">↓3,240</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">Crinetics制药(CRNX) +98.8%</div></div>
<div class="replay-stat"><div class="replay-stat-label">创52周新高</div><div class="replay-stat-val">52</div></div>
</div>
</div><div class="replay-card">
<div class="replay-card-title">🇨🇳 A股</div>
<div class="replay-summary">A股再破4000点,近4800只个股下跌成交量萎缩至2.6万亿</div>
<div class="ad-bar-wrap">
<span class="ad-label-up">↑1,200</span>
<div class="ad-bar adv" style="width:20px;max-width:80px"></div>
<div class="ad-bar dec" style="width:80px;max-width:80px"></div>
<span class="ad-label-dn">↓4,800</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">龙芯中科等国产芯片股逆势抗跌</div></div>
<div class="replay-stat"><div class="replay-stat-label">北向资金</div><div class="replay-stat-val">-180亿</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">周三 7/8<br><span style="font-size:0.6rem;color:var(--dimmed)">2:00 PM ET</span></div>
<div>
<div class="cal-event">FOMC会议纪要(6月)</div>
<div class="cal-values">预期: <span>市场高度关注新任主席Warsh首次会议细节</span> &nbsp;&middot;&nbsp; 前值: N/A</div>
</div>
</div>
<div class="cal-item high">
<div class="cal-date">周一 7/14<br><span style="font-size:0.6rem;color:var(--dimmed)">8:30 AM ET</span></div>
<div>
<div class="cal-event">6月CPI</div>
<div class="cal-values">预期: <span>4.0% YoY</span> &nbsp;&middot;&nbsp; 前值: 4.2% YoY</div>
</div>
</div>
<div class="cal-item medium">
<div class="cal-date">周二 7/15<br><span style="font-size:0.6rem;color:var(--dimmed)">8:30 AM ET</span></div>
<div>
<div class="cal-event">6月PPI</div>
<div class="cal-values">预期: <span>3.1% YoY</span> &nbsp;&middot;&nbsp; 前值: 3.2% YoY</div>
</div>
</div>
<div class="cal-item medium">
<div class="cal-date">周二 7/15<br><span style="font-size:0.6rem;color:var(--dimmed)">4:15 PM ET</span></div>
<div>
<div class="cal-event">美联储褐皮书</div>
<div class="cal-values">预期: <span>7月FOMC会议前最新经济状况</span> &nbsp;&middot;&nbsp; 前值: N/A</div>
</div>
</div>
<div class="cal-item high">
<div class="cal-date">周二 7/29<br><span style="font-size:0.6rem;color:var(--dimmed)">2:00 PM ET</span></div>
<div>
<div class="cal-event">FOMC利率决议</div>
<div class="cal-values">预期: <span>维持不变,但声明措辞至关重要</span> &nbsp;&middot;&nbsp; 前值: 3.50-3.75%</div>
</div>
</div>
<div class="cal-item high">
<div class="cal-date">周二 7/29<br><span style="font-size:0.6rem;color:var(--dimmed)">2:30 PM ET</span></div>
<div>
<div class="cal-event">美联储主席记者会</div>
<div class="cal-values">预期: <span>Warsh将阐述政策框架和加息条件</span> &nbsp;&middot;&nbsp; 前值: N/A</div>
</div>
</div>
<div class="cal-item high">
<div class="cal-date">周三 7/30<br><span style="font-size:0.6rem;color:var(--dimmed)">8:30 AM ET</span></div>
<div>
<div class="cal-event">Q2 GDP初值</div>
<div class="cal-values">预期: <span>2.2%</span> &nbsp;&middot;&nbsp; 前值: 2.0%(Q1)</div>
</div>
</div>
<div class="cal-item high">
<div class="cal-date">周三 7/30<br><span style="font-size:0.6rem;color:var(--dimmed)">8:30 AM ET</span></div>
<div>
<div class="cal-event">6月PCE物价指数</div>
<div class="cal-values">预期: <span>2.9% YoY(核心)</span> &nbsp;&middot;&nbsp; 前值: 3.0% YoY(5月核心)</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">戴蒙在2026年致股东信中警告,当前经济环境下通胀上升是最大担忧,这将导致利率走高。他引用巴菲特26年前的观点强调,利率对所有资产价格都具有引力般的影响。通胀若持续反弹,将迫使投资者重新定价资产,股票估值面临下行压力。</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">美联储主席(至2026年5月)</div>
</div>
<div class="leader-date">1月11日</div>
</div>
<div class="leader-quote">"我们将谨慎评估经济数据"</div>
<div class="leader-body">鲍威尔在卸任前强调美联储政策将基于数据而非政治压力做出决定。面对特朗普政府司法部调查威胁,鲍威尔坚持央行独立性。市场普遍预期新任主席Kevin Warsh将采取更鹰派立场,2026年加息概率上升。</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">"利率是资产估值的根本"</div>
<div class="leader-body">巴菲特在其股东信中重申利率对资产价格的决定性影响。他警告当前市场估值偏高,类似2000年互联网泡沫时期。尽管AI驱动科技股上涨,但若通胀推升利率,高估值股票将面临显著回撤风险。</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">KW</div>
<div class="leader-meta">
<div class="leader-name">凯文·沃什 <span style="color:var(--muted);font-weight:400;font-size:0.78rem;">Kevin Warsh</span></div>
<div class="leader-role">美联储新任主席候选人</div>
</div>
<div class="leader-date">6月</div>
</div>
<div class="leader-quote">"政策将完全依赖数据"</div>
<div class="leader-body">作为特朗普提名的美联储主席接班人选,沃什在6月会议后取消传统前瞻指引,转向纯数据依赖模式。他暗示若通胀持续升温,2026年下半年可能加息。这标志着美联储政策框架的重大转变,市场对降息预期大幅降温。</div>
<div class="tags"><span class="tag">#美联储</span><span class="tag">#鹰派</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">3.50-3.75%</div>
<div class="cb-action">维持利率3.50-3.75%不变</div>
<div class="cb-next">下次会议: <span class="font-mono" style="color:var(--neutral)">2026-07-29</span></div>
<div class="cb-note">新任主席Warsh取消前瞻指引,转向纯数据依赖,通胀反弹令市场预期年内可能加息</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">3.25%</div>
<div class="cb-action">维持存款利率3.25%</div>
<div class="cb-next">下次会议: <span class="font-mono" style="color:var(--neutral)">2026-07-18</span></div>
<div class="cb-note">经济增长疲弱但通胀仍高于目标,政策陷入两难</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">1年期LPR 3.45%</div>
<div class="cb-action">维持LPR不变</div>
<div class="cb-next">下次会议: <span class="font-mono" style="color:var(--neutral)">2026-07-20</span></div>
<div class="cb-note">人民币升值压力加大,贸易顺差持续扩大,央行可能允许汇率缓慢升值</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.10%</div>
<div class="cb-action">维持利率0.10%</div>
<div class="cb-next">下次会议: <span class="font-mono" style="color:var(--neutral)">2026-07-30</span></div>
<div class="cb-note">日元贬值压力仍存,可能进一步加息或干预汇市</div>
</div>
<div class="cb-card">
<div class="cb-header">
<div>
<div class="cb-name">澳洲联储</div>
<div class="cb-name-en">Reserve Bank of Australia</div>
</div>
<span class="bias-badge neutral">Neutral</span>
</div>
<div class="cb-rate">4.35%</div>
<div class="cb-action">维持利率4.35%</div>
<div class="cb-next">下次会议: <span class="font-mono" style="color:var(--neutral)">2026-08-11</span></div>
<div class="cb-note">通胀粘性令降息预期消退,澳元可能走强</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>