/* === 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 */}
{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 */}
{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 }) =>
;
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 });