/* === Manager Analysis pages === */ /* global React, LineChart, HBars, Icons */ const { useState: useMgrState } = React; const safeNum = (n, defaultVal = 0) => (typeof n === "number" ? n : defaultVal); const safeArr = (arr, defaultVal = []) => (Array.isArray(arr) ? arr : defaultVal); const safeStr = (s, defaultVal = "") => (typeof s === "string" ? s : defaultVal); function MgrHero({ mgr, products }) { return (
{mgr.name}
类型:{mgr.type} 在管产品:{mgr.productCount}
); } function MgrSelector({ mgrId, setMgrId }) { const { managers } = window.IRDATA; return (
{managers.map((m) => )}
); } function PageMgrStrategy({ mgrId, setMgrId, openDrawer }) { const { managers, DATES, products } = window.IRDATA; const mgr = managers.find((m) => m.id === mgrId) || managers[0]; return (
策略配置能力 · 战略基准对照
基于年度战略权重 × 资产指数收益合成
{/* Chart 1 - Benchmark NAV */}
图 1 · 基准净值曲线
长期收益贡献
{managers.map((m) =>
{m.name}
)}
({ name: m.name, color: m.stratColor, data: safeArr(m.benchmarkNav), strokeWidth: m.id === mgr.id ? 1.9 : 1.1 }))} dates={DATES} height={200} format="nav" onPointClick={(idx) => openDrawer({ kind: "info", payload: { title: `基准净值 · ${DATES[idx]}`, kvs: managers.map((m) => ({ k: m.name, v: {safeArr(m.benchmarkNav)[idx]?.toFixed(4) || "0.0000"} })), body: "战略基准 = Σ(年度中枢权重 × 对应资产指数收益)。" } })} />
{/* Chart 2 - Benchmark Drawdown */}
图 2 · 基准回撤曲线
压力阶段防守
{managers.map((m) =>
{m.name}
)}
({ name: m.name, color: m.stratColor, data: safeArr(m.benchmarkDD), strokeWidth: m.id === mgr.id ? 1.9 : 1.1 }))} dates={DATES} height={200} format="percent" maxY={0.01} threshold={[{ y: -0.06, color: "#97a3b8", label: "阈值 -6%" }]} />
{/* Chart 3 - Rolling Sharpe */}
图 3 · 滚动夏普 (60D)
风险收益效率稳定性
{managers.map((m) =>
{m.name}
)}
({ name: m.name, color: m.stratColor, data: safeArr(m.rollingSharpe), strokeWidth: m.id === mgr.id ? 1.9 : 1.1 }))} dates={DATES} height={200} format="raw" threshold={[{ y: 0, color: "#97a3b8" }, { y: 1, color: "#97a3b8", label: "1.0" }]} />
{/* Qualitative analysis */}
定性分析 · 战略配置基准
战略配置基准用于回答"年度中枢本身是否有效"
· 净值曲线看长期收益贡献——验证中枢权重是否在多年维度上跑赢现金/无风险参照。
· 回撤曲线看中枢在压力阶段的防守能力——衡量结构性下跌时的损失上限。
· 滚动夏普看风险收益效率是否稳定——剔除单一区间偶然性,识别中枢的稳健性。
结论:{mgr.conclusion}
); } function PageMgrTactical({ mgrId, setMgrId, openDrawer }) { const { managers, products } = window.IRDATA; const mgr = managers.find((m) => m.id === mgrId) || managers[0]; // 安全地获取 capabilities - 兼容不同数据结构 const cap = mgr.capabilities || {}; // 创建默认的 env 和 evt 结构 const env = { match: safeNum(cap.tactical, 0.65), winRate: safeNum(cap.selection, 0.55), alpha: safeNum(cap.strategic, 0.45) }; const evt = { response: safeNum(cap.tactical, 0.6), winRate: safeNum(cap.selection, 0.5), alpha: safeNum(cap.strategic, 0.4) }; const c = { env, evt }; const renderMetric = (label, val, format, color, sub) =>
openDrawer({ kind: "info", payload: { title: label, sub: mgr.name, kvs: managers.map((m) => { const mCap = m.capabilities || {}; const mEnvMatch = safeNum(mCap.tactical, 0.65); const mEvtResponse = safeNum(mCap.tactical, 0.6); let v = null; if (safeStr(label).includes("匹配")) { v = mEnvMatch; } else if (safeStr(label).includes("响应")) { v = mEvtResponse; } if (v !== null) { return { k: m.name, v: {(v * 100).toFixed(1)}% }; } return null; }).filter(Boolean), body: "点击其它管理人卡片可对比同一指标,所有口径基于过去 24 个月滚动窗口。" } })}>
{label}
{format === "pct" ? (safeNum(val) * 100).toFixed(1) : safeNum(val).toFixed(2)} {format === "pct" ? "%" : ""}
{sub &&
{sub}
}
; return (
战术配置能力 · 环境模块
日常市场中的表现
{renderMetric("环境匹配度", c.env.match, "pct", "#0f5cff", "")} {renderMetric("环境胜率", c.env.winRate, "pct", "#00a99d", "")} {renderMetric("环境超额收益", c.env.alpha, "pct", "#14a065", "")}
战术配置能力 · 事件模块
重大事件后的处理质量
{renderMetric("事件响应度", c.evt.response, "pct", "#ff7a1a", "")} {renderMetric("事件胜率", c.evt.winRate, "pct", "#6b4ce6", "")} {renderMetric("事件超额收益", c.evt.alpha, "pct", "#ef3f3f", "")}
定性分析 · 战术配置
战术配置评价重点从单纯调仓频率转向"是否看对环境、是否及时响应事件、响应后是否产生胜率和超额收益"
· 环境模块适合观察市场状态判断——通过比较战术权重与彼时市场实际状态,识别管理人对宏观和风格的前瞻性。
· 事件模块适合观察回撤、风格漂移、开放赎回或业绩突变后的处理质量——衡量真实压力情境下的决策效率。
主要风险:{safeStr(mgr.risk, "暂无")}
); } function PageMgrSelection({ mgrId, setMgrId }) { const { managers, products } = window.IRDATA; const mgr = managers.find((m) => m.id === mgrId) || managers[0]; return (
选基能力
{Icons.empty}
选基能力待接入底层基金数据后展示
预计 Q3 接入 Wind / 朝阳永续底基库
); } function PageMgrOverview({ mgrId, setMgrId, onNav, openDrawer }) { const { managers, products, DATES } = window.IRDATA; const mgr = managers.find((m) => m.id === mgrId) || managers[0]; const mgrProducts = products.filter((p) => p.managerId === mgr.id); const cap = mgr.capabilities || { tactical: 0, selection: 0, strategic: 0 }; // Aggregate capability scores const navArr = safeArr(mgr.benchmarkNav); const ddArr = safeArr(mgr.benchmarkDD); const stratScore = (navArr.length > 0 ? (navArr[navArr.length - 1] - 1) * 100 : 0); const stratDD = (ddArr.length > 0 ? Math.min(...ddArr.map(safeNum)) * 100 : 0); const tactEnv = (safeNum(cap.tactical) + safeNum(cap.selection)) / 2; const tactEvt = (safeNum(cap.strategic) + safeNum(cap.tactical)) / 2; // Radar-style data const radarItems = [ { label: "战略中枢", val: 0.62 + (mgr.id === "M01" ? 0.18 : mgr.id === "M02" ? 0.08 : 0.04), color: "#0f5cff" }, { label: "压力防守", val: 0.50 + (mgr.id === "M01" ? 0.18 : mgr.id === "M02" ? 0.15 : 0.02), color: "#ef3f3f" }, { label: "效率稳定", val: 0.55 + (mgr.id === "M01" ? 0.18 : mgr.id === "M02" ? 0.05 : 0.10), color: "#00a99d" }, { label: "环境判断", val: safeNum(cap.tactical), color: "#6b4ce6" }, { label: "事件响应", val: safeNum(cap.selection), color: "#ff7a1a" }, { label: "事件胜率", val: safeNum(cap.strategic), color: "#f5a623" }]; const Capability = ({ title, badge, kpis, route, gradient }) =>
onNav(route)}>
{badge}
{title}
{kpis.map((k, i) =>
{k.label}
{k.val}
)}
进入详情 → {badge}
; return ( {/* Three capabilities overview */}
能力总览 · 三大维度
0 ? mgr.fundCount : "10") + " 支" }, { label: "管理人集中度", val: mgr.id === "M03" ? "高" : "中" }] } />
{/* Compact comparison: benchmark NAV across all 3 managers */}
战略基准对照 · 全部管理人
{managers.map((m) =>
{m.name}
)}
({ name: m.name, color: m.stratColor, data: safeArr(m.benchmarkNav), strokeWidth: m.id === mgr.id ? 1.9 : 1.1 }))} dates={DATES} height={220} format="nav" />
{/* Conclusion / risk strip */}
系统结论
{safeStr(mgr.conclusion, "暂无")}
主要风险
{safeStr(mgr.risk, "暂无")}
); } Object.assign(window, { PageMgrStrategy, PageMgrTactical, PageMgrSelection, PageMgrOverview });