scoring rules · 计分规则全景

扫描评分体系

两套独立分数:scan_score(实时市场扫描,market-scanner.ts) · fit_score(币种历史适配度,coin-analyzer.ts

看实时扫描 →

A. scan_score 主公式

实时市场扫描

scan_score = (0.60 × mScore + 0.20 × volScore + 0.20 × spreadScore + qualityAdj) × 100

三个主成分各取 [0, 1];qualityAdj 是追涨/稳健的额外加减分(±0.05~0.10);总分被 clamp 到 0~100。

动量 mScore60%

1h / 2h / 4h 涨幅打分加权

流动性 volScore20%

avg_vol log1p 后归一化

价差 spreadScore20%

cross_spread_bps 分段打分

分层 (tier) 判定

strong
scan_score ≥ 70
candidate
scan_score ≥ 50
watch
scan_score < 50
excluded
未通过筛选

B. 筛选规则(pass_filter)

未通过 → tier=excluded,scan_score=0

主流币黑名单主流币(XXX)

HFT 做满价差空间小,直接排除:BTC / ETH / BNB / SOL / XRP / ADA / DOGE / MATIC / LTC / EOS / BSV / TRX / DOT / AVAX / LINK / ATOM / UNI / SHIB / TON / SUI / APT

持续下跌持续下跌(…)

return_1h / return_2h / return_4h 至少有 2 个有效值且全部 < 0

量不足量不足(XXM)

avg_vol(24h) < thresholds.min_vol_usdt(从历史盈利样本学到,至少 10M)

⚠ 资金费筛选已移除(高频不长持,资金费成本不重要;高资金费反而代表热度)。

C. 动量 mScore(权重 60%)

1h / 2h / 4h 各打分后加权

return_Nh = (Binance 当前价 − price-recorder 中 N 小时前价) / N 小时前价
历史价取 price-recorder 离 now−Nh 最近的一条快照(cron 每 15min 写入,允许 ±30min 误差)
score1h (权重 20%)
≥ +8%1.00
≥ +3%0.75
≥ 0%0.20
< 0%0.10
score2h (权重 35%)
≥ +15%1.00
≥ +8%0.85
≥ +3%0.60
≥ 0%0.20
< 0%0.10
score4h (权重 45%)
≥ +30%1.00
≥ +15%0.90
≥ +8%0.80
≥ +3%0.55
≥ 0%0.20
< 0%0.10
mScore = (s4 × 0.45+ s2 × 0.35+ s1 × 0.20) / 实际权重和
某窗口 null 时跳过并对剩余权重归一化;三个全 null 时兜底返回 0.2。

qualityAdj — 动量质量修正

判定条件:isRecent = return_1h > return_4h × 0.6(1h 涨幅占 4h 涨幅 60% 以上 → 涨幅集中在最近,追涨风险高)

steady (稳步爬升)
三窗全正 且 ¬isRecent
+0.05
recent (最后冲高)
三窗全正 且 isRecent
−0.10
null (不连贯)
非三窗全正
0

D. 流动性 volScore(权重 20%)

log 归一化后映射到 [0, 1]

volArr[i] = log1p(avg_vol / 1e6)
volScore[i] = (volArr[i] − min(volArr)) / (max(volArr) − min(volArr))
avg_vol = (Binance 24h 成交额 + 对手所 24h 成交额) / 2; log1p 压缩量级差,再 min-max 归一化到 [0, 1]。

E. 价差 spreadScore(权重 20%)

cross_spread_bps 分段打分(不归一化)

cross_spread_bps = |Binance 价 − 对手所价| / mid × 10000
区间得分含义
5 – 500 bps1.00甜点区:覆盖手续费 + 滑点
3 – 5 bps0.60空间偏小
< 3 或 > 500 bps0.30没空间 / 价差异常

F. fit_score — 币种历史适配度

coin-analyzer.ts:基于历史 diff 聚合后排名

fit_score = (0.45 × avg_hourly_pnl + 0.25 × win_rate + 0.15 × volScore + 0.15 × spreadScore) × 100

非 win_rate 的成分先 min-max 归一化到 [0, 1] 再加权;win_rate 本身已是比例。

平均每小时 PnL45%

ΔPnL 累计 / 小时数

胜率 win_rate25%

ΔPnL>0 的小时占比

流动性 volScore15%

log1p 后归一化

价差 spreadScore15%

spread_bps 上限 20 后取负

⚠ 注意:当前 spread_bps 字段在 rawStats 里写死为 0, 所以这 15% 的价差权重对所有币种归一化后值相同、实质未发挥作用。 如需启用,需要从 price-recorder 算出真实的 spread 注入。

算例

两个虚构币种的完整打分过程

A 币:稳步上涨
  1. 1. return_1h = +2% → score1h = 0.20
  2. 2. return_2h = +5% → score2h = 0.60
  3. 3. return_4h = +12% → score4h = 0.80
  4. 4. mScore = 0.80×0.45 + 0.60×0.35 + 0.20×0.20 = 0.62
  5. 5. 1h(2%) 是否 > 4h(12%) × 0.6 = 7.2%? 否 → steady (+0.05)
  6. 6. 动量项贡献 = (0.62 + 0.05) × 0.60 = 0.402
动量项 0.402(+ vol/spread 后形成最终分)
B 币:最后一刻冲高
  1. 1. return_1h = +10% → score1h = 1.00
  2. 2. return_2h = +11% → score2h = 0.85
  3. 3. return_4h = +12% → score4h = 0.80
  4. 4. mScore = 0.80×0.45 + 0.85×0.35 + 1.00×0.20 = 0.858
  5. 5. 1h(10%) > 7.2%? 是 → recent (−0.10)
  6. 6. 动量项贡献 = 0.858 × 0.60 + (−0.10) = 0.415
动量项 0.415(被 recent 罚分压制,避免追在山顶)

可调参数索引

常见调优入口

  • · market-scanner.ts → momentumScore() · 各档涨幅阈值与得分
  • · market-scanner.ts:122-125 · 三窗权重(4h:45% / 2h:35% / 1h:20%)
  • · market-scanner.ts:scoring loop · 主公式权重(mScore 60% / vol 20% / spread 20%)
  • · market-scanner.ts:spreadArr · 价差分段(甜点区 5–500 bps)
  • · market-scanner.ts:qualityAdj · steady +0.05 / recent −0.10 / isRecent 阈值 0.6
  • · market-scanner.ts:tier · ≥70 strong / ≥50 candidate / 其余 watch
  • · market-scanner.ts:BLACKLIST_COINS · 主流币黑名单
  • · rule-extractor.ts · min_vol_usdt / strong_up_1h 等阈值的学习
  • · coin-analyzer.ts:fit_score · 45/25/15/15 权重