寰镜 MarketLens(@suifei/dsh-market-lens)
A 股 / 港股 / 美股的只读行情看板 DSH Web 插件。定位一句话:Web 面板形态覆盖 PC 与移动端的延迟行情看板,不接任何交易端能力。
- 数据性质:公开免费接口的延迟行情,非 Level-2,UI 常驻标注。
- 市场:A 股(沪/深/北)、港股、美股;指数、个股(板块视图在后续版本)。
- 不做:下单、撤单、持仓盈亏、量化执行、任何写操作(连配置写回都没有)。
架构
浏览器(DSH Web GUI) Node(DSH Host)
┌─────────────────────────┐ 同源 HTTP ┌──────────────────────────┐
│ client.js React 面板 │ ───────────→ │ index.js │
│ · sidebar.panellist 图标 │ /market-lens│ · /market-lens/* routes │
│ · main keyed 主面板 │ /* │ · market_search/quotes/ │
│ · Canvas 自绘 K 线(零 CDN)│ │ kline 三个只读工具 │
│ · localStorage 自选/偏好 │ │ lib/service.js │
└─────────────────────────┘ │ 归一化 · TTL 缓存 · 在途去重 │
UI 永不直连外部行情接口 │ 多源降级(按市场分链) │
│ sources/{eastmoney, │
│ tencent,yahoo}.js │
└──────────────────────────┘
行情抓取只发生在宿主侧。 UI 与模型工具共用同一个 createMarketService,一个操作、两个调用方。
符号规范
内部规范格式(与腾讯公开接口词表一致):
| 市场 | 规范 | 接受输入 |
|---|---|---|
| 沪/深/北 | sh600519 sz000001 bj830799 |
600519、SH600519、sh.600519(裸 6 位按代码段推断:5/6/9→sh,0/3/1→sz,4/8→bj) |
| 港股 | hk00700(5 位)、指数别名 hkHSI hkHSTECH |
700、00700、HK00700 |
| 美股 | usAAPL、指数别名 usDJI usIXIC usINX |
AAPL、us.aapl、US.AAPL |
搜索支持代码、中文名、拼音全拼与拼音首字母(gzmt → 贵州茅台):拼音匹配委托给上游 suggest 接口(smartbox / 东方财富),宿主侧只做归一化、合并与去重。
多源降级
| 市场 | 主源 | 备源 |
|---|---|---|
| A 股(含北交所)/ 指数 | 东方财富 | 腾讯 |
| 港股 | 东方财富 | 腾讯 |
| 美股 / 美指数 | Yahoo chart | 腾讯(美股 K 线自动解析 .OQ/.N 后缀码) |
- 东方财富 TLS 在部分网络被重置:适配器带 https 失败→http 重试(仅公开只读 GET)。
- 单源失败自动切换;全链失败时 quotes 返回
failed[](UI 显示「数据暂不可用」),有缓存旧值时以stale: true供出延迟值而非假数据。
面板接口(同源,宿主实现)
| Route | 参数 | 返回 |
|---|---|---|
GET /market-lens/meta |
— | { pollIntervalMs, defaultWatchlist, indexBar, limits, disclaimer } |
GET /market-lens/quotes |
symbols(逗号分隔,≤200) |
{ quotes: QuoteRow[], failed: [{symbol, reason}] } |
GET /market-lens/kline |
`symbol, period=day | week |
GET /market-lens/search |
q(1–50), limit≤30 |
{ items: [{symbol, name, market, kind}] } |
QuoteRow = { symbol, name, price, prevClose, open, high, low, change, changePct, volume(股), amount(元), turnoverRate, pe, marketCap, floatMarketCap, currency?, updatedAt, source, stale? }。字段可得性因市场与源而异:缺失为 null,UI 显示 —,绝不补 0。K 线前复权固定在宿主侧,UI 与工具都不暴露复权参数。
路由带同源护栏:Sec-Fetch-Site: cross-site 或 Origin/Referer 与 Host 不一致一律 403;全部 cache-control: no-store。
模型工具(只读)
| 工具 | 参数 | 说明 |
|---|---|---|
market_search |
query(1–50), limit?≤30 |
代码/名称/拼音检索 |
market_quotes |
symbols: string[](≤200) |
批量报价,含 source 与 stale 标注 |
market_kline |
symbol, `period: day |
week |
工具描述内写明「只读行情、不涉及交易」;上限同时写在参数描述与宿主校验(越界报 BAD_INPUT)。没有 market_order 之类的写工具。
可靠性实现点
- 轮询:
setTimeout链式调度,上一次完成后才排下一次;document.hidden暂停,回前台立即刷新(面板卸载即整链拆除)。 - 收回:样式、监听、AbortController、定时器全部挂在
ctx.effect/ 组件 cleanup。 - 指数条与自选行按 key 原地更新文本,不重建列表 DOM,滚动位置与手动顺序不被轮询重置。
- K 线:Canvas 自绘;PC 滚轮缩放 + 拖拽平移 + hover tooltip;移动端双指缩放、单指平移、长按出 tooltip(不依赖 hover)。
- 搜索带序号防竞态,慢的旧响应不覆盖新输入。
配置(cordis.patch.yml 行内 config)
pollIntervalMs 5000 · quoteTtlMs 5000 · klineTtlMs 60000 · searchTtlMs 300000 · upstreamTimeoutMs 6000 · maxQuoteSymbols ≤200 · maxKlineCount ≤320 · routePath /market-lens
开发
node --test # 离线单测(fetch 全桩)
node scripts/live-probe.mjs # 真网络冒烟(不在测试里跑,避免 CI 依赖外网)
发布自检(社区市场流程)
- 仓库
github.com/suifei/dsh-market-lens,public;本目录即包根(package.json声明dsh.bundle.patch→./cordis.patch.yml)。 dsh-plugintopic;meta.title/description在locale/zh.json、locale/en.json。✓- 建仓满 1 天后再提收录 PR。
- 向
awesome-dsh-plugin/awesome-dsh-plugin的data/plugins/提交单文件条目suifei__dsh-market-lens.yml(category 以当时 contributing.md 为准),不动自动生成的 README。 - npm 发布(可选但推荐):
npm view @suifei/dsh-market-lens确认包名可用后发布。 - 带 UI 包自查:
dsh.bundle.patch存在 ✓;dsh.client.platform: web✓;客户端侧无额外运行时依赖(peerDependencies只列宿主侧 cordis/dsh 面)✓。
首版范围与后续
首版必做:自选列表(过滤/排序/批量导入)+ 三市场报价 + 日/周/月 K(MA5/10/20/60 可开关、量副图)+ 指数条 + 搜索 + 移动端布局模式切换 + 宿主缓存与多源降级 + 三个只读工具。
已明确不做:交易、持仓、选股、AI 投研、新闻、L2 盘口。
后续(按数据源稳定性排序):分时图 → 板块/行业视图 → 热力图 → 新闻/快讯 → 自定义布局保存。原则不变:新数据源先落在宿主侧,UI 只消费归一化结构。
已知边界
- 裸 6 位代码按号段猜测交易所(
92xxxx北交所新代码段会被猜成 sh);带前缀输入永远正确。 - Yahoo 在部分区域返回 403:美股自动落到腾讯,K 线历史长度可能缩短。
- 分时图未进首版;详情页暂以 K 线为主视图。
License
MIT · 图标为本仓库原创绘制。
No comments yet. Be the first to write one.