npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

dsh-us-stocks

v0.3.0

Published

DSH US stock market data plugin, powered by yahoo-finance2

Readme

dsh-us-stocks

English | 中文

DeepSeek Harness 用的美股行情数据插件,基于 yahoo-finance2

提供行情、历史 K 线、财务报表、分析师共识、新闻、股东结构六个专用工具,无需模型自行解析网页。

效果对比

下表为同一任务在装载与未装载本插件两种条件下的实测结果,模型与运行环境一致。任务内容:AAPL 的现价、近三个月走势、最近几个季度财务、分析师评级和近期新闻。

| | 未装载本插件 | 装载本插件 | | ---- | ----------------------------- | ------- | | 步骤 | 14 步 | 2 步 | | 工具调用 | 31 次 | 5 次 | | 整体耗时 | 213.5 秒 | 33.2 秒 | | 调用构成 | 16 次 web_search、15 次 bash | 任务需要的每个工具各一次 |

在缺少行情数据工具的情况下,模型只能依靠网页搜索与 shell 命令,逐个页面抓取并解析。其余 33 秒主要为模型推理耗时,不在本插件的作用范围内;数据获取本身占 2.6 秒。

Acceptance benchmark — AAPL

  ✅ get_quote           2016ms  305.93 USD (+0.2195%), mcap 4464.80B
  ✅ get_history          446ms  62 bars 2026-05-18..2026-08-14
  ✅ get_financials      2181ms  4 income / 4 balance / 4 cash-flow periods
  ✅ get_analyst_view    2492ms  buy from 41 analysts, target 322.2844
  ✅ get_news             632ms  8 headlines, latest "Google is using a $29 gadget to tighten its gri…"
  ✅ get_ownership       3135ms  66.48% institutional across 7709 filers, insiders net 35206 shares over 6m

  tool calls        6
  wall clock        3.14s (concurrent)
  payload           26.2 KiB across 6 results

可用 npm run benchmark 自行复现,亦可指定其他标的:npm run benchmark -- TTMI

安装

懒人版

直接对你的 DeepSeek Harness 说:

安装一下这个插件:https://github.com/Realyujie/dsh-us-stocks

它会读这份 README 并自行执行安装命令。过程中会请求文件系统权限,因为 profile 目录在会话工作区之外。

手动安装

dsh 已在 PATH 中:

dsh plugin --profile web add dsh-us-stocks

若不在——通过 npx 启动 Harness 时即属此种情况,因为可执行文件只存在于 npx 缓存中——改用 npx 调用:

npx @deepseek-ai/dsh plugin --profile web add dsh-us-stocks

下文所有命令同理:把 dsh 换成 npx @deepseek-ai/dsh 前缀即可;或用 npm install -g @deepseek-ai/dsh 全局安装一次,之后统一使用简写形式。

后续更新:

dsh plugin --profile web update dsh-us-stocks

更新后需重启 profile——插件是在启动时组装插件树的过程中解析的。

本地开发则让 profile 指向检出目录,改动在 npm run build 并重启后生效:

dsh plugin --profile web add link:/absolute/path/to/dsh-us-stocks

dsh plugin 是转发给 profile 目录下的 pnpm,并会同步维护 profile 的 dsh.profile.bundles 列表,不需要手动注册。

本插件注册服务端的 agent 工具,同时附带一个很小的浏览器半边,用于绘制 get_history 一节所述的 K 线图;在 TUI 或 headless profile 下该半边不存在,六个工具照常可用。

工具

| 工具 | 返回内容 | | ------------------ | -------------------------------------------------------- | | get_quote | 最新价、涨跌、日内区间、成交量、市值、市盈率、每股收益、每股净资产、股息率、52 周区间、均线、上次和下次财报日。ETF 与共同基金另有费率、规模、分类、资产配置、滚动收益与前十大持仓 | | get_history | 日/周/月 K 线 OHLCV 及复权收盘价,附窗口内的分红与拆股,纯结构化数据 | | get_financials | 利润表、资产负债表、现金流量表科目,季度或年度,含报表货币与 TTM 比率 | | get_analyst_view | 共识评级、逐月买入/持有/卖出家数、目标价、EPS 与营收预期、近期券商评级变动、EPS 超预期记录 | | get_news | 近期新闻标题,含发布方、时间和链接 | | get_ownership | 内部人与机构持股比例、最大机构与基金股东(含季度仓位变动)、内部人近六个月买卖汇总 |

get_quote

| 参数 | 类型 | 说明 | | -------- | --------- | ----------------- | | ticker | string,必填 | 例如 AAPLBRK-B |

财报日期拆成 last_earnings_datenext_earnings_date 两个字段返回,因为上游将二者合并在同一字段中。next_earnings_date_is_estimate 用于标记该日期为按财报节奏推算所得,而非公司正式确认。在十个标的的抽样中约有一半为预估值,建议读取该字段确认,不宜直接假定。

currency 是股票的交易货币,financial_currency 是公司的报表货币。ADR 的这两者不一致,而 get_financials 中的数字仅以后者计价。

上游虽然返回了分析师评级,本工具有意不包含该字段。共识评级与目标价统一由 get_analyst_view 提供,使仅需行情数据的调用方不会一并收到投资建议。

ETF 与共同基金会额外返回 fund_expense_ratio_percent(并附同类均值)、fund_total_assetsfund_categoryfund_familyfund_asset_allocation_percentfund_trailing_returns_percentfund_top_holdings。这些来自第二次上游请求,仅在行情确认该标的为基金后才发出,个股不承担任何额外开销;基金的一次查询耗时约为个股的三倍。该请求失败时仍返回行情本体,并附一条 warning。

关于基金字段有三点写在响应内的 fund_notes 里,而不只写在这里——因为读这些数字的对象读的是响应:

  • 对基金而言,trailing_peprice_to_bookbook_value_per_shareeps_trailing_twelve_months 是成分股的加权聚合值,不是某一家公司的数据。不加标注时会被当成对该基金的估值判断。
  • 费率按上游原样透传,偶有错误——实测 FXAIX 报 0.42%,实际为 0.015%。
  • fund_trailing_returns_percent 沿用上游的混合口径:ytdone_year 是区间收益,而 three_year_annualizedfive_year_annualizedten_year_annualized 是年化值。字段名直接标明口径 —— 五年期这两种口径能差出四倍。
  • fund_top_holdings 受上游限制最多 10 条,因此以 fund_top_holdings_coverage_percent 说明这些持仓合计占基金的比例。实测该比例从 VXUS 的 14% 到 XLE 的 73% 不等,无法据此计算两只基金之间的重叠度。债券、商品与反向基金完全不返回持仓,此时该字段直接缺失而非为空。

get_history

| 参数 | 类型 | 说明 | | ------------------------- | --------- | ----------------------------------------------------------------------------------- | | ticker | string,必填 | | | range | 枚举 | 5d 1mo 3mo 6mo 1y 2y 5y 10y max,默认 1y | | start_date / end_date | string | yyyy-MM-dd,指定 start_date 时覆盖 range | | interval | 枚举 | 1h 1d 1wk 1mo,默认 1d。单次调用 1h 约覆盖 5 周,1d 约 2 年,1wk 约 8 年,1mo 约 35 年 | | limit | 整数 | 保留最近 N 根,1–500。默认返回窗口内全部 |

K 线按时间从旧到新排列。1d/1wk/1modateyyyy-MM-dd1h 则是完整 ISO 时间戳——这个粒度下同一天会有多根 K 线,若只保留日期会让它们的标签全部相同。

interval: "1h" 另受上游限制,历史最多回溯约 730 天,与请求窗口大小无关。rangestart_date 超出这个范围会直接返回 invalid_argument,而不是其他档位那种"已裁剪"的警告——因为 Yahoo 对此是直接拒绝整个请求,而非退而求其次给一部分数据。

在 Web UI 中,该调用会渲染成 K 线图——蜡烛实体、上下影线、成交量副图、价格网格线,鼠标悬停显示当根 OHLC——所用数据与模型收到的完全是同一份,因此图与数字不会出现分歧。配色跟随宿主主题,绿涨红跌。图表文案跟随宿主语言(中文或英文);来自数据源的消息按原文显示,因为那些文字同时也是写给模型看的。在其他客户端则显示宿主的通用结果卡片,工具输出本身没有区别。

每次响应都带一条 chart_note 说明这件事——因为模型决定下一步做什么时读的是返回的数据,而不是调用时读过的工具描述。没有这条提示时,实测出现过模型在 Web UI 里已经拿到图表、却毫不知情,转身花了一分钟装 matplotlib、建虚拟环境,想再画一张。

落在返回窗口内的分红和拆股以 dividendssplits 返回;从未分红或拆股的标的不会出现这两个键。

两套价格基准不可混用。 open/high/low/close 只做了拆股复权,adj_close 则同时做了拆股和分红复权。2019–2026 年间 AAPL 的 93 根月线里有 91 根 close ≠ adj_close,在同一计算中混用会得出错误结果且不会报错。每次响应均在 price_adjustment 中标明这一区别。

K 线是按输出预算实测裁剪的,而不是按固定根数——单根成本随价格量级和 interval 在 117–127 字符间浮动。实际请求 max 会返回 266–489 根。发生裁剪时,警告中会指明应改用的下一档 interval。

get_financials

| 参数 | 类型 | 说明 | | ------------ | --------- | ------------------------------------------ | | ticker | string,必填 | | | period | 枚举 | quarterly(默认)或 annual | | statements | 数组 | income balance cash_flow 任意组合,默认返回三张 | | limit | 整数 | 最近 N 期,1–8,默认 4 | | detail | 枚举 | summary(默认,核心科目)或 full(全部上报字段) |

上游可提供的期数是固定的,将起始日期前移也无法增加:利润表和现金流约 5 期,资产负债表 7 期,季度年度皆然。

每次响应均包含 reporting_currency它不一定是美元。 ADR 用本国货币编制报表却以美元交易——台积电用 TWD、SAP 用 EUR、阿里用 CNY、诺和诺德用 DKK——因此台积电的原始营收数字与以美元编制报表的公司相比,量级相差约 32 倍。若无法确定货币,报表仍照常返回,并附警告提示不应默认为美元。

完整的 TTM 报表不可用:上游 trailing 周期返回 periodType: "TTM",无法通过 yahoo-finance2 的 schema 校验,读取它需要整体关闭结果校验。但 TTM 聚合值——营收、毛利、EBITDA、自由现金流,以及各项利润率、回报率、增速和杠杆比率——仍可获取,见 ratios 块。

ratios 中的利润率、回报率和增速都是无量纲小数(0.27 表示 27%)。debt_to_equity_percent 是例外:Yahoo 对该字段乘了 100,AAPL 的 0.784 倍在这里是 78.445。该字段保留上游数值,并将单位体现在字段名中,而非隐式换算。

get_analyst_view

| 参数 | 类型 | 说明 | | -------- | --------- | --- | | ticker | string,必填 | |

recommendation_mean 的刻度是 1 到 5,1 为强烈买入、5 为强烈卖出——数字越小越看好;若按五分制得分理解,方向恰好相反。每次响应均在 recommendation_mean_scale 中重述该刻度,不依赖调用方预先了解这一约定。

两组 period 代码的计数方向相反:recommendation_trend0m 表示本月、-1m 表示上月;estimates0q/+1q 表示本季和下季、0y/+1y 表示本财年和下财年。earnings_surprises-1q 表示最近已公布的季度。

rating_changes 保留最近 10 条券商评级动作,最新在前;上游共存有数百条。action 取值为 updownmain(维持)或 init(首次覆盖)。

本工具中的价格以交易货币计价(美股即美元),即使公司以其他货币编制报表亦然——这一点与 get_financials 的报表数字不同。

ETF 与基金返回 no_data:分析师覆盖的是具体公司,基金不会有评级、目标价或 EPS 预期。基金数据请用 get_quote

get_news

| 参数 | 类型 | 说明 | | -------- | --------- | ---------- | | ticker | string,必填 | | | limit | 整数 | 1–10,默认 10 |

只返回标题元数据,不抓取正文。上游无论请求多少最多返回 10 条,所以 10 既是默认值也是上限。

只返回确实提及该代码的新闻。 上游的新闻检索是文本匹配,当代码本身为常用词时会返回无关内容——搜 ALL 返回了芬兰某银行的要约收购和一则矿产资源公告,搜 KEY 返回了英国房地产的申报文件,没有一条提到 Allstate 或 KeyCorp。本工具依据每条新闻自带的关联代码列表进行过滤;当按代码匹配的结果不足时,再以公司全称检索一次。经此处理,ALL 的相关比例由 0/6 提升至 6/6,KEY 同样如此。被丢弃的条数以警告形式返回;若全部匹配均为噪音,则返回 no_data 并说明原因,而非返回表面合理、实为其他公司的报道。

get_ownership

| 参数 | 类型 | 说明 | | -------- | --------- | -------------------- | | ticker | string,必填 | | | detail | 枚举 | summary(默认)或 full | | limit | 整数 | 每个列表的条数,1–50,默认 10 |

summary 返回内部人/机构持股拆分、最大的机构与基金股东、以及内部人近六个月的买卖汇总。insider_activityinstitutional_activity 是并列的两块:上游把两者放在同一个模块里返回,但 insider_activity.net_institutional_shares 这样的路径会字段名说一回事、值是另一回事。只有内部人那一块带 period —— 上游从未说明机构净额对应的时间窗口。full 额外返回内部人逐笔申报和具名内部人的持股——逐笔申报占了绝大部分体积,因此设为按需获取。

股东数据来自季度 13F 申报,口径是每一行自己的 report_date,不是当天。insider_activity 汇总的是期间内所有内部人,因此完全可能在某位知名内部人大额减持的同时呈现净买入——这一点在 ownership_note 中重申,因为模型拿它和新闻报道对照时,需要知道两者是不同的测量口径,而非互相矛盾。

机构与内部人申报针对的是经营实体,因此 ETF 和基金返回 no_data。基金自身的持仓在 get_quote 中。

响应结构

所有工具都返回结构一致的 JSON 字符串。

成功:

{
  "ok": true,
  "market": "us",
  "ticker": "AAPL",
  "as_of": "2026-08-14T09:28:31.204Z",
  "data": { "…": "…" },
  "warnings": ["Returned the most recent 455 of 11509 bars, the most that fits the tool output budget. …"]
}

失败时返回结构化错误,不向外抛出异常:

{
  "ok": false,
  "market": "us",
  "ticker": "ZZZZ",
  "error": {
    "kind": "unknown_symbol",
    "retryable": false,
    "message": "No quote data for symbol \"ZZZZ\"."
  }
}

其中对模型最关键的字段是 retryable,它用于区分两类情形:该标的确实不存在此项数据,无需重试;以及上游出现临时故障,相同调用稍后可能成功。

| kind | retryable | 含义 | | ---------------------- | ----------- | ------------------------ | | unknown_symbol | 否 | 代码解析不到任何标的 | | no_data | 否 | 代码有效但该数据集不存在(ETF 不编制利润表) | | invalid_argument | 否 | 工具无法接受的参数 | | upstream_unavailable | 是 | 上游拒绝或临时报错 | | rate_limited | 是 | 上游限流 | | timeout | 是 | 触发超时或调用方取消 | | response_too_large | 是 | 剥掉信封后仍超出输出预算 | | internal | 否 | 未分类 |

超过 64,000 字符的结果会被截断:data 被丢弃、信封保留,并通过 output_truncatedoriginal_characters 提示模型缩小查询范围后重试。get_history 的体积随请求窗口线性增长,它会先按实测大小自行裁剪 K 线,因此仅在极端情况下才会触发该兜底。

配置

enabled: true          # 是否注册这些工具
market: us             # 目前仅支持 "us"
quoteTtlMs: 10000      # 实时行情缓存时长
referenceTtlMs: 300000 # 报表、K 线、评级和新闻的缓存时长

缓存为进程内内存缓存。并发的相同请求会合并为一次上游调用,因此模型对同一代码并发调用六个工具时,不会产生六次冗余请求。失败结果不进入缓存。

开发

npm install
npm run typecheck
npm test            # 单元测试,不访问网络
npm run build
npm run test:live   # 针对 Yahoo 的真实调用冒烟测试,需要联网
npm run benchmark   # AAPL 验收基准

需要 Node >= 22.19.0。

目录结构

src/
├── index.ts                    apply(ctx, config) 入口
├── config.ts                   schemastery 配置,含 market 枚举
├── datasource/us/
│   └── yahoo-client.ts         yahoo-finance2 封装:缓存、取消、错误定型
├── tools/                      每个工具一个文件,另有共用的数据整形辅助函数
├── client/                     浏览器半边:get_history 的 K 线卡片
└── util/
    ├── cache.ts                短 TTL 缓存,含并发请求合并
    ├── errors.ts               失败分类与信封
    └── stringify.ts            输出预算控制

目前仅支持美股。datasource/<market>/ 的分层、market 配置枚举,以及将 ticker 作为不透明字符串处理,均是为将来接入其他市场预留的空间;除此之外未实现任何其他市场。

关于数据源

财务报表取自 Yahoo 的 fundamentalsTimeSeries 接口,而非 quoteSummary 的三表模块。后者自 2024 年底起只返回少量利润表字段,且落后一个报告期;以 AAPL 为例,旧接口给出 9 个有值字段、截至 2026-03-31,而这里使用的接口给出 35 个、截至 2026-06-30。

该 API 为非官方接口,无公开文档,可能随时变更,并存在访问频率限制。数据按现状提供,仅供研究参考,不构成投资建议。

许可

MIT