feat: 盘面洞察第四批 — 板块相关性热力图 + 异动雷达 + 量能仪表盘

- 相关性 /hotspots 页内新增「相关性」视图:/board-mac/hotspot-correlation
  复用热点历史矩阵缓存,对窗口内活跃板块(每日前 per_day 名并集,按上榜次数
  取前 N)两两算日涨跌幅 Pearson 相关;红=同涨同跌(抱团)、绿=跷跷板(轮动),
  ECharts 热力图 + 双向色阶 visualMap;无缓存时透传 building 状态
- 异动雷达 /radar:沪深异动流时间线(封板/炸板/大笔买入/逼近涨停…),
  每分钟异动密度柱 + 类型筛选 chips(带计数),行点击直达个股弹窗,15s 轮询
- 量能仪表盘并入市场情绪页:两市(上证+深成 5 分钟线)累计成交额曲线
  vs 近 5 日同期均值(虚线),标题给出偏离百分比——放量/缩量一眼可辨
- 热点缓存判定重构为 _hotspot_history_or_build 公共入口,correlation 与
  hotspot 共用同一构建状态机;新增相关性矩阵回归单测
This commit is contained in:
Justin Gu
2026-09-05 04:09:03 +08:00
parent 37c732fb30
commit 0a205ffbf3
11 changed files with 782 additions and 26 deletions
+52
View File
@@ -327,3 +327,55 @@ def test_hotspot_missing_kline_board_excluded():
data, _ = _wait_ready(client, fake)
assert data["total_boards"] == 2
assert all(r["code"] != "881101" for r in data["rows"])
def test_hotspot_correlation_matrix_ready():
"""缓存就绪:相关矩阵直接可算,完全同向的两板块相关系数 = 1。"""
pytest.importorskip("fastapi")
from fastapi.testclient import TestClient
from easy_tdx.web.routers import board_mac
board_mac._hotspot_history_cache["HY"] = (
"2030-01-01",
{
"axis": ["2026-08-10", "2026-08-11", "2026-08-12"],
"pct": {
"881100": {"2026-08-10": 5.0, "2026-08-11": 3.0, "2026-08-12": 1.0},
"881200": {"2026-08-10": 4.0, "2026-08-11": 2.0, "2026-08-12": 0.0},
},
"names": {"881100": "甲板块", "881200": "乙板块"},
},
)
fake = _FakeHotspotMacClient()
try:
with TestClient(_hotspot_app(fake)) as client:
resp = client.get(
"/api/v1/board-mac/hotspot-correlation",
params={"board_type": "HY", "days": 5, "per_day": 2},
)
finally:
board_mac._hotspot_history_cache.clear()
assert resp.status_code == 200
data = resp.json()["data"]
assert data["status"] == "ready"
assert [b["code"] for b in data["boards"]] == ["881100", "881200"]
assert data["matrix"][0][0] == 1.0
assert data["matrix"][0][1] == pytest.approx(1.0, abs=0.01) # 完全线性同向
assert data["matrix"][1][0] == data["matrix"][0][1]
def test_hotspot_correlation_building_passthrough():
"""无缓存:与 hotspot 相同的 building 状态透传,前端轮询即可。"""
pytest.importorskip("fastapi")
from fastapi.testclient import TestClient
fake = _FakeHotspotMacClient()
with TestClient(_hotspot_app(fake)) as client:
resp = client.get("/api/v1/board-mac/hotspot-correlation", params={"board_type": "HY"})
assert resp.status_code == 200
body = resp.json()["data"]
assert body["status"] in ("building", "error", "ready") # 单机假客户端极快时可能已完成
if body["status"] == "building":
assert 0.0 <= body["progress"] <= 1.0