韭菜盒子 LeekBox 🥬
English | 简体中文
A-share 看盘助手 —— DeepSeek Harness (DSH) Web 客户端插件。
在 DSH Web 界面的左侧边栏出现 🥬 入口,点击打开行情面板:
| Tab | 功能 |
|---|
| 📊 大盘 | 上证 / 深成 / 创业板 / 科创50 实时指数,30 秒自动刷新;顶部市场情绪温度计——半圆分段仪表盘呈现综合情绪温度 0~100°(市场宽度 40% + 涨停强度 25% + 封板率 20% + 连板高度 15%,数据缺失自动按剩余权重归一),冰点→沸腾五档弧段当前档位高亮、游标点平滑转动,右侧无框数据行:涨跌家数(红绿占比微条)/ 涨跌停 / 炸板 / 封板率 / 最高板 |
| 💹 行情 | 股票/ETF/转债/LOF 搜索(代码/名称/拼音首字母,本地索引毫秒级返回,带实时价格涨幅的下拉结果卡)+ 多池榜单(沪深A股/主板/非主板/ETF·场内基金/可转债/LOF,按涨幅/成交额/换手/主力净流入)+ 板块榜 + 龙虎榜 |
| ⭐ 自选 | 自选股实时行情(持久化在 $DSH_HOME/.leekbox-watchlist.json),支持分组、持仓成本与实时盈亏(点击持仓/成本单元格内联编辑,按现价实时计算浮动盈亏额 + 收益率 + 汇总条)、价格预警(🔔 行内按钮设置价格涨到/跌破、涨跌幅达到;交易时段自动盯盘,触发后 toast + 浏览器通知 + 蜂鸣并自动移除,持久化在 $DSH_HOME/.leekbox-alerts.json)、一键 JSON 备份 / CSV 导出(含持仓字段)、从 JSON/CSV/文本导入(合并或覆盖) |
| 🔍 选股 | 两种模式:评分选股(按价格/涨跌幅/换手率筛选 + 13 项技术信号勾选 + 加权评分排序)和 多策略交叉选股(7 个预设策略的并行交集,个股需同时命中多个策略,按命中数排序) |
| 📰 快讯 | 新浪 / 东财 / 金十 三源聚合 7×24 快讯,来源可筛选,重要资讯红色高亮,60 秒自动刷新,可点相关股票直达详情 |
| 🤖 分析 | AI 个股分析:搜索选股后由服务端汇总实时行情 + 近 60 日 K 线概览 + F10 财务摘要,调模型生成结构化中文分析(含风险提示与免责声明,支持复制 / 重新生成)。模型在面板头部 ⚙️ 全局设置里配置:多服务商下拉(DeepSeek / OpenAI / Anthropic Claude / Moonshot Kimi / 智谱 / 通义 / b.ai 等;OpenAI 兼容 + Anthropic 原生两种协议)+ 模型下拉(可一键「获取模型」拉取真实列表,也可手填),持久化在 $DSH_HOME/.leekbox-analysis.json,密钥仅服务端保存、界面只显示脱敏值 |
行情页顶部保留连板梯队(2板/3板/…及最高板数),可展开涨停池列表(点击直达个股详情)。
点击任意股票(自选里点股票名称即可)会弹出独立的个股详情窗口(类似同花顺):大字现价 + 涨跌、15 项实时指标、当日分时图(价格线 + 成交量加权均价线 + 成交量 + 昨收基准 + 相对涨跌幅纵轴,悬停浮窗)、日/周/月/5分/30分 K 线(前复权,蜡烛图 + MA5/10/20 均线 + 成交量 + 十字光标)、主力资金流向柱状图(最近 15 日,流入红/流出绿,悬停显示当日净流入额)+ 资金流分明细表、F10 财务摘要(最近 8 个报告期:营收/归母净利+同比、ROE、毛利率、负债率、EPS,东财 F10 数据源),一键加自选。详情窗口可拖动、可同时打开多个,ESC 或点击遮罩逐层关闭。
数据源
- 实时行情 / 指数 / 分时 / K线:腾讯财经(qt.gtimg.cn / web.ifzq.gtimg.cn / ifzq.gtimg.cn)
- F10 财务摘要:东方财富 F10 报表(datacenter.eastmoney.com,双主机回退)
- 榜单 / 选股:东方财富(push2.eastmoney.com,多镜像自动回退)
- 搜索:本地全市场索引(东方财富 push2 clist 快照,约 8 千只标的,缓存 6 小时)+ 腾讯 smartbox 全拼兜底 + 批量实时行情(qt.gtimg.cn);索引未就绪时自动回退东方财富 searchadapter
- 7×24 快讯:新浪财经直播流(zhibo.sina.com.cn)+ 东方财富快讯(np-listapi.eastmoney.com)+ 金十数据(jin10.com);重要资讯 = 各源官方标记(金十星标 / 新浪焦点)+ 关键词兜底(突发/重磅/重大/紧急/超预期);跨源自动去重——同一事件多家源措辞不同(截断/扩写/换措辞)也按归一化文本 + 10 分钟时间窗内相似度合并为一条,保留信息最全的副本
- AI 个股分析:模型由用户自行配置(OpenAI 兼容接口,如 OpenAI / DeepSeek 等),个股数据复用上面的行情 / K线 / F10 源汇总后送入模型;调用走服务端
/chat/completions 代理,密钥明文只在服务端落盘、绝不下发浏览器
所有数据由插件服务端(web profile 内的 cordis 插件)代理抓取并标准化,浏览器端同源调用 /api/leekbox/*,仅限本机 loopback 访问。数据仅供研究参考,不构成投资建议。
交易时段与交易日历
交易日不是"周一到周五"——国庆/春节这类工作日假期要靠真实日历才判得对。插件不从零维护节假日表,而是用指数日 K 的日期序列反推交易日(节假日没有 K 线),缓存 12 小时:
- 服务端
lib/calendar.js 提供 sessionState():preOpen / auction(9:15–9:25)/ open / lunch / closed / weekend / holiday,时刻一律按东八区判定(宿主机时区不参与)。GET /api/leekbox/calendar 下发交易日列表,/health、/sentiment 顺带回带时段摘要。首次请求不阻塞:先用"工作日"启发式回答并标注 source: weekday-fallback,后台把真日历建好后再切换,拿不到就永远如实标注是兜底。
- 客户端据此判定两件事:面板顶部标签(盘前 / 集合竞价 / 交易中 / 午间休市 / 已收盘 / 休市)与要不要轮询——非交易时段与页面不可见时都不再发请求,回到前台立刻补一次。此前国庆假期会显示"交易中"并整天重复打上游。
- 非交易时段上游数据不再变化,服务端缓存 TTL 自动放宽(
sessionTtl,默认 ×20),进一步压低节假日与盘后的无效请求。
- 日 K 的右边界:日线只包含"已经出现过"的交易日,今天那根要到集合竞价前后才出现——所以"今天不在交易日集合里"绝不能被当成"今天休市"(否则任何交易日的白天都会显示休市)。现在的判定顺序是:今天有日线 → 交易日;日期落在日线覆盖窗口
[from, to] 内却没有那根 → 确定休市;今天在窗口右侧 → 再用 5 分钟线探测"今天有没有分时",探到 → 交易日,探不到且已过 09:35 → 休市,其余(盘前 / 探测失败)→ 标 provisional 并退回工作日启发式。日历跨到新的一天会无条件重建,早盘窗口内 90 秒重探一次,拿到当天日线后立刻回到 12 小时长 TTL。
上游请求治理
榜单 / 行情 / 板块 / 快讯这些最热的路由此前每次请求都直打上游,而客户端是 15~60s 轮询、多开详情窗还会并发同码请求——重复请求不只是浪费,它会主动触发东财按出口 IP 的限流。现在统一走 lib/route-cache.js:
- TTL 缓存 + 单飞(in-flight 去重):同一 key 的并发请求共享一个上游调用,缓存挡不住的正是这一层。
- stale-if-error:上游抖动时返回上次成功的数据(有的路由保留 10 分钟、历史 K 线 30 分钟、F10 24 小时),而不是把整页 502 糊到用户脸上。前提语义不变——只在拿到真实数据后写入,绝不缓存"空快照"。
- 时段感知 TTL:配合上面的交易日历,盘后/节假日自动放宽。
- 观测出口:
GET /api/leekbox/metrics(版本 / uptime / 时段 / 索引状态 / 各缓存命中率、淘汰数、stale 服务次数),/health 也带上同一份缓存统计。
- 涨停池与涨跌家数任一不可用时,
/sentiment 按缺失渲染而不是整卡失败(响应带 partial: true)。
写接口的跨站防护
回环栅栏只看 socket 地址与 Host 头,挡不住浏览器发起的跨站请求:恶意页面用 fetch(..., {mode:"no-cors"}) 打本机端口时 Host 照样是 127.0.0.1,响应虽然读不到,但写操作已经生效。所以所有写路由额外要求:
Origin 缺失或指向本机才放行(Origin: null、其他站点一律 403);
Content-Type 必须是 application/json(否则 415)——跨站 no-cors 的字符串 body 默认是 text/plain,这一条把它彻底堵死。
龙虎榜的日期语义
GET /api/leekbox/longhu?date=YYYY-MM-DD 里的 date 是回溯起点,不是"必须是这一天":
- 当天的龙虎榜要等收盘后晚间才发布,所以盘中、周末、节假日请求当天必然为空。服务端从
date 起往前找最近一个有榜的交易日(周末直接跳过——周末不可能有榜),响应同时回带 requestedDate(你要的)和 date(实际显示的)。界面上两者不同时会写明"该日尚未发布,已回溯到最近交易日"。
- 只往过去回溯:起点之后即使有数据也不取用。往前找会把未来日期的榜单当成用户请求的那天。
- 日期格式非法(如
2026-02-30、2026-13-01、20261009)直接 400,不会悄悄换成今天——静默返回另一天的数据比报错更糟。
- 整个回溯有 15s 总预算,避免"多天 × 多轮 × 多 host"把一次请求拖到几分钟。
出错了要说得出来
这个项目里最隐蔽的一类缺陷是静默失败:不抛异常、不报错,只是悄悄给出错误结果或悄悄什么都不做。约定如下:
- 用户主动点击的操作(加/移自选、改分组、删预警等)失败必须提示,统一走
notifyFailure(what)(和价格预警同一条 toast 通道),文案形如 加入自选失败:网络连接失败,请检查网络后重试。
- 后台轮询 / 预热 / 可选增强信息(F10、资金流首次加载、情绪温度计等)保持安静:这类失败不该骚扰用户,页面上另有显式失败态——保留标题、显示原因、给一个"重试"按钮,而不是让整块消失。
- 请求失败时清掉上一次的数据,不要让旧数据留在屏幕上冒充本次结果(龙虎榜、快讯都遵循这条)。
构建产物与源码必须一致
lib/client.js 是提交进仓库的产物(宿主直接加载它,不跑构建)。CI 用"重新构建后 git diff 是否为空"判断产物是否过期。
注意一个反直觉的点:esbuild 构建失败时不会覆盖产物,所以"重建后产物哈希不变"听起来像"构建成功且幂等",实际上也可能是"构建一直在报错,产物还是上一次的旧文件"。因此除了产物新鲜度,client-bundle-test.mjs 还会直接检查 src/client/* 之间 15 个模块的导入/导出配对——漏掉一个 export 会让构建失败,而那条断言会带着文件名和符号名报错。
环境要求
- DeepSeek Harness (DSH) ≥ 0.1.1-rc.1(声明于
package.json 的 dsh.engines.dsh)
- 仅运行于 web profile(
dsh.client.platform: "web"):服务端路由随宿主进程运行,浏览器端经同源 /api/leekbox/* 访问(仅限本机 loopback)
安装
# 1. 把包链接进 web profile 的 node_modules(或 pnpm add file:...)
mklink /J "$DSH_HOME\profiles\web\node_modules\dsh-leekbox" "<本包路径>"
# 2. 在 $DSH_HOME/profiles/web/cordis.patch.yml 追加:
# - insert:
# - id: leekbox
# name: 'dsh-leekbox'
# 3. profile 配置文件 watcher 会在 ~1s 内热重组合,无需重启(服务端立即生效);
# 浏览器刷新页面后侧边栏出现 🥬 入口。
# 若修改了 lib/index.js(服务端代码),需要重启 DeepSeek Harness 进程生效。
结构
lib/index.js — 服务端 cordis 插件:/api/leekbox/* 路由 + 自选股持久化 + AI 分析(模型配置持久化与 /chat/completions 代理)
lib/calendar.js — 交易日历与交易时段(指数日 K 反推交易日,东八区时段判定)
lib/route-cache.js — 路由级 TTL 缓存 + 单飞 + stale-if-error + 观测统计
lib/search-index.js — 本地全市场搜索索引(代码/名称/拼音首字母毫秒匹配)
lib/client.js — 浏览器端 bundle:侧边栏入口 + 行情面板(React)。构建产物,勿手改——源码在 src/client/(15 个职责文件),npm run build 用 esbuild 打包生成(npm run dev 为 watch 模式);react 由宿主注入,不进 bundle
cordis.patch.yml — 插件行注册(dsh.bundle.patch)
选股模块
选股按职责拆成 5 个文件,lib/screener.js 是对外门面(runScreener / screenerProgress / screenerMeta):
lib/screener.js — 编排层:股票池快照、逐只拉日K、基础条件过滤、排序与进度快照
lib/indicators.js — 纯指标数学(EMA/MACD/RSI/KDJ/SMA/BOLL/上穿判定),无 I/O
lib/signals.js — 信号与策略的唯一定义处(权重、分组、文案、策略组成)+ 打分
lib/screener-cache.js — 结果缓存(LRU + 15 分钟 TTL)与日K缓存(自适应 TTL)
lib/screener-validate.js — 参数归一化 + 带 error.code 的校验异常
GET /api/leekbox/screener/meta 下发信号/策略元数据,前端据此渲染勾选面板,服务端加信号时界面自动跟随(客户端仅保留离线兜底副本)。
免责声明
本插件仅聚合公开免费行情接口,数据可能有延迟或缺失;所有内容仅供学习研究,不构成任何投资建议。股市有风险,入市需谨慎。