← 返回排行榜
-
-
-
因子详情 · {{ factor }}
-
批次 {{ runId || '最新' }}
+
+
+
+
+
+
+
+
因子详情 · {{ detail.factor }}
+
批次 {{ route.query.run || '最新' }}
+
-
-
+
+
+
+
+ {{ detail.factor }}
+ {{ detail.category }}
+
+
+ {{ conclusionLabel }}
+
+
+
+ {{ detail.expression }}
+
+
+
+
+
+
+
+
IC 均值 ({{ period }}D)
+
{{ num(currentMetrics.ic_mean as number) }}
+
+
+
ICIR
+
{{ num(currentMetrics.icir as number, 2) }}
+
+
+
t 值
+
{{ num(currentMetrics.t_stat as number, 1) }}
+
+
+
IC 胜率
+
{{ pct(currentMetrics.win_rate as number) }}
+
+
+
多空年化
+
{{ pct(currentMetrics.ls_annual as number) }}
+
+
+
日均换手
+
{{ pct(currentMetrics.turnover as number) }}
+
参评 {{ currentMetrics.count }} 日
+
+
+
+
+
+
+
+
+
+
+
+
+
+
月度 IC 与累计 IC
+
柱=月度 RankIC · 线=累计 IC
+
+
+
+
十分组年化收益 ({{ period }}D)
+
Q1=因子值最低组 · 单调性=区分度
+
+
+
+
+
+
+
+
+
+
@@ -47,6 +332,15 @@ function goBack() {
text-underline-offset: 3px;
}
+.error-state {
+ padding: 60px;
+ text-align: center;
+ color: var(--text-3);
+ background: var(--bg-card);
+ border: 1px solid var(--border);
+ border-radius: var(--r-lg);
+}
+
.page-head {
display: flex;
align-items: flex-end;
@@ -71,12 +365,282 @@ function goBack() {
letter-spacing: 0.02em;
}
-.placeholder {
- padding: 60px;
- text-align: center;
- color: var(--text-3);
+.fcard {
background: var(--bg-card);
border: 1px solid var(--border);
border-radius: var(--r-lg);
+ padding: 16px 18px;
+ margin-bottom: var(--sp-3);
+}
+
+.fcard .hd {
+ display: flex;
+ align-items: center;
+ gap: 10px;
+ margin-bottom: 10px;
+ flex-wrap: wrap;
+}
+
+.fcard .name {
+ font-family: var(--mono);
+ font-size: 17px;
+ font-weight: 700;
+ color: var(--brand);
+ letter-spacing: 0.03em;
+}
+
+.expr {
+ font-family: var(--mono);
+ font-size: 11.5px;
+ line-height: 1.7;
+ background: var(--panel);
+ border: 1px solid var(--border-2);
+ border-left: 2px solid var(--cyan-dim);
+ border-radius: var(--r-sm);
+ padding: 11px 14px;
+ color: var(--text-2);
+ overflow-x: auto;
+ white-space: pre;
+ position: relative;
+}
+
+.expr:not(.expanded) {
+ max-height: 80px;
+ overflow: hidden;
+ mask-image: linear-gradient(to bottom, black 60%, transparent 100%);
+ -webkit-mask-image: linear-gradient(to bottom, black 60%, transparent 100%);
+}
+
+.expr.expanded {
+ mask-image: none;
+ -webkit-mask-image: none;
+}
+
+.expr-toggle {
+ position: absolute;
+ bottom: 8px;
+ right: 12px;
+ font-size: 10px;
+ color: var(--brand);
+ background: rgba(0, 229, 255, 0.1);
+ border: 1px solid rgba(0, 229, 255, 0.3);
+ border-radius: var(--r-sm);
+ padding: 2px 8px;
+ cursor: pointer;
+ transition: all 0.15s var(--ease);
+}
+
+.expr-toggle:hover {
+ background: rgba(0, 229, 255, 0.2);
+}
+
+.metric-strip {
+ display: grid;
+ grid-template-columns: repeat(6, 1fr);
+ gap: 1px;
+ background: var(--border);
+ border: 1px solid var(--border);
+ border-radius: var(--r-lg);
+ overflow: hidden;
+ margin-bottom: var(--sp-3);
+}
+
+@media (max-width: 1100px) {
+ .metric-strip {
+ grid-template-columns: repeat(3, 1fr);
+ }
+}
+
+.metric {
+ background: var(--bg-card);
+ padding: 11px 13px;
+}
+
+.metric .k {
+ color: var(--text-3);
+ font-family: var(--mono);
+ font-size: 9.5px;
+ letter-spacing: 0.12em;
+ text-transform: uppercase;
+}
+
+.metric .v {
+ font-family: var(--mono);
+ font-variant-numeric: tabular-nums;
+ font-size: 18px;
+ font-weight: 600;
+ margin-top: 2px;
+}
+
+.metric .d {
+ font-size: 10px;
+ margin-top: 2px;
+ color: var(--text-3);
+ font-family: var(--mono);
+}
+
+.period-switch {
+ display: flex;
+ border: 1px solid var(--border);
+ border-radius: var(--r-sm);
+ overflow: hidden;
+ margin-bottom: var(--sp-3);
+}
+
+.period-switch button {
+ font-family: var(--mono);
+ font-size: 11px;
+ padding: 4px 12px;
+ color: var(--text-2);
+ background: transparent;
+ border: none;
+ cursor: pointer;
+}
+
+.period-switch button.on {
+ background: rgba(0, 229, 255, 0.12);
+ color: var(--brand);
+}
+
+.charts {
+ display: grid;
+ grid-template-columns: 3fr 2fr;
+ gap: var(--sp-3);
+ margin-bottom: var(--sp-3);
+}
+
+@media (max-width: 1100px) {
+ .charts {
+ grid-template-columns: 1fr;
+ }
+}
+
+.chart-card {
+ background: var(--bg-card);
+ border: 1px solid var(--border);
+ border-radius: var(--r-lg);
+ padding: 14px 16px;
+}
+
+.chart-card h3 {
+ font-size: 12.5px;
+ font-weight: 600;
+ letter-spacing: 0.04em;
+ margin-bottom: 4px;
+}
+
+.chart-card .cs {
+ color: var(--text-3);
+ font-family: var(--mono);
+ font-size: 10.5px;
+ margin-bottom: 10px;
+}
+
+.chart-box {
+ width: 100%;
+ height: 215px;
+}
+
+.actions {
+ display: flex;
+ gap: 10px;
+}
+
+.btn {
+ font-size: 12.5px;
+ font-weight: 600;
+ border-radius: var(--r-md);
+ padding: 7px 16px;
+ border: 1px solid var(--border);
+ color: var(--text-2);
+ background: var(--bg-card);
+ transition: all 0.15s var(--ease);
+ cursor: pointer;
+}
+
+.btn:hover {
+ color: var(--text);
+ border-color: var(--text-3);
+}
+
+.btn.primary {
+ color: var(--text);
+ background: var(--brand);
+ border-color: var(--brand);
+ box-shadow: var(--glow-cyan);
+}
+
+.btn.primary:hover {
+ background: var(--cyan-dim);
+}
+
+.cat-chip {
+ display: inline-block;
+ padding: 1px 8px;
+ border-radius: var(--r-sm);
+ font-family: var(--mono);
+ font-size: 10.5px;
+ font-weight: 600;
+ line-height: 17px;
+ letter-spacing: 0.3px;
+ border: 1px solid transparent;
+}
+
+.cat-alpha101 {
+ color: var(--brand);
+ background: rgba(0, 229, 255, 0.1);
+ border-color: rgba(0, 229, 255, 0.3);
+}
+
+.cat-alpha158 {
+ color: var(--purple-dim);
+ background: rgba(180, 140, 255, 0.1);
+ border-color: rgba(180, 140, 255, 0.3);
+}
+
+.cat-builtin {
+ color: var(--amber);
+ background: rgba(255, 176, 0, 0.1);
+ border-color: rgba(255, 176, 0, 0.3);
+}
+
+.st {
+ display: inline-flex;
+ align-items: center;
+ gap: 5px;
+ font-family: var(--mono);
+ font-size: 10.5px;
+ letter-spacing: 0.08em;
+}
+
+.st-ok .lamp {
+ background: var(--lamp-ok);
+ box-shadow: 0 0 6px rgba(46, 230, 138, 0.7);
+}
+
+.st-watch .lamp {
+ background: var(--lamp-warn);
+ box-shadow: 0 0 6px rgba(255, 176, 0, 0.7);
+}
+
+.st-eliminated .lamp {
+ background: var(--lamp-idle);
+ box-shadow: none;
+}
+
+.lamp {
+ width: 7px;
+ height: 7px;
+ border-radius: 50%;
+ display: inline-block;
+ flex-shrink: 0;
+}
+
+.pos {
+ color: var(--up);
+}
+
+.neg {
+ color: var(--down);
}