Financial market monitor bundle for dsh: real-time quotes, a local watchlist, threshold alerts with cooldowns, periodic polling, and in-chat ASCII/mermaid charts for A-share stocks/indices and crypto (Tencent + CoinGecko).
Install
# from GitHub (first run asks for allowBuilds approval — follow the hint, retry)
dsh plugin --profile web add github:JohnXu22786/market-watch
Any plugin you install runs third-party code with your own permissions — it can read your files, use your credentials, and reach the network, and tool approvals don’t sandbox it. GitHub-sourced plugins also run build scripts at install time — pnpm blocks those until you allow them, so an install can stop with ERR_PNPM_GIT_DEP_PREPARE_NOT_ALLOWED or ERR_PNPM_IGNORED_BUILDS; dsh prints the exact key to add under allowBuilds in your profile’s pnpm-workspace.yaml, and the install works on the next run. Allowing a build is a trust decision: only install sources you trust, and pin a commit (github:owner/repo#sha).
README
English · 简体中文
A financial market monitor bundle for DeepSeek Harness (dsh): real-time quotes, a local watchlist, threshold alerts, periodic polling, and in-chat ASCII/mermaid charts for A-share stocks/indices and cryptocurrencies — using free public data sources only. This is the first market/finance data plugin in the dsh ecosystem.
- Quote — latest quotes for stocks, indices, and crypto via free sources
(Tencent
qt.gtimg.cnfor CN securities, CoinGecko for crypto). - Watchlist — locally persisted watch items (code / name / market / kind), shared by the plugin and the CLI.
- Alerts — threshold rules (
changePercent/price,gt/gte/lt/lte) evaluated on every poll, with per-rule cooldowns. Delivery: a typed harness eventmarket-watch/alertplus optional injection into live agent sessions. - Polling — timer-based periodic refresh of the whole watchlist (overlapping ticks are dropped; free sources are rate-limit friendly).
- Charts — ASCII column charts, sparklines, and mermaid
xychart-betablocks rendered in chat. - Dual entry — six dsh tools (
quote,list,watch,unwatch,alert,chart) and a standalone CLI (dsh-market-watch) over the same data.
Data sources and latency
| Market | Source | Notes |
|---|---|---|
| Shanghai / Shenzhen / Beijing stocks & indices | Tencent qt.gtimg.cn, web.ifzq.gtimg.cn |
Free endpoints; quotes may lag the tape by seconds to minutes. Daily bars are qfq (forward-adjusted) for stocks, raw for indices. |
| Crypto | CoinGecko public API | Free tier is rate limited (calls are spaced by coingeckoDelayMs, Retry-After honored). Prices may lag; OHLC from market_chart is bucketed to UTC days. |
All quotes carry a per-source disclaimer (delayNote). Nothing here is
investment advice; never trade on delayed free data without verification.
Requirements
- Node.js
^22.19 || >=24 - dsh
>=0.1.0-rc.6with theweborheadlessprofile
Install as a dsh bundle
A bundle is an npm package whose manifest declares dsh.bundle.patch (this
package ships cordis.patch.yml plus a lib/ build). Two typical paths:
# 1. From a local checkout of this repo:
pnpm build # or: npm run build
dsh plugin --profile web add . # relative/absolute path to this directory
# 2. Git-hosted installs run the prepare script on install; pnpm >= 10 blocks
# build scripts until allowlisted — add to the profile's pnpm-workspace.yaml:
# allowBuilds:
# dsh-market-watch: true
# then:
dsh plugin --profile web add github:some-owner/dsh-market-watch
dsh plugin adds the package to the profile's dsh.profile.bundles list
because it declares dsh.bundle; the patch inserts the market-watch row and
the plugin's tools appear in every agent prompt after a restart.
Verify:
dsh config dump | grep market-watch # row present
Configuration
Every option has a default; the bundle row ships without a config section.
Override by id in your profile's cordis.patch.yml — remember a patch
replaces the whole config value, so restate every key you keep (copy
examples/cordis.patch.example.yml):
| Key | Default | Meaning |
|---|---|---|
enabled |
true |
Master switch for the plugin. |
pollIntervalSeconds |
60 |
Poll period (schema: 5..86400). |
dataDir |
$DSH_HOME/market-watch |
Directory holding watchlist.json. |
timeoutMs |
10000 |
Per-request network timeout. |
maxRetries |
2 |
Extra attempts after the first try. |
retryBackoffBaseMs |
500 |
Exponential backoff base. |
vsCurrency |
usd |
Crypto quote currency (CoinGecko id). |
coingeckoDelayMs |
1200 |
Min spacing between CoinGecko calls. |
agentNotify |
true |
Deliver alerts into live dsh agent sessions. |
agentWakeup |
false |
Wake idle agents on alert (followup) instead of quiet inject. |
Tools
Registered on ctx.tools; their schemas join the system prompt automatically.
| Tool | Purpose |
|---|---|
quote |
Latest quotes for codes (array), e.g. ["sh600000","000001","bitcoin"]. Optional days appends a sparkline per instrument (one history request each). |
list |
The local watchlist. |
watch |
Add instruments: codes (array), optional market (cn/crypto), kind (stock/index/crypto), name. |
unwatch |
Remove one instrument by code. |
alert |
Manage rules: action = list | add | remove. add needs code, field (changePercent/price), op (gt/gte/lt/lte), value, optional cooldownSeconds (default 300) and note; remove needs the rule id from list. |
chart |
code, optional days (default 30), format (ascii/mermaid), width, height. |
Accepted code forms for CN instruments: sh600000, 600000.sh, 600000.ss,
600000 (prefix inferred from the leading digit), 000001 with kind: index
for the Shanghai Composite. Everything else is treated as a CoinGecko id
(bitcoin, ethereum, …).
Tools never throw for expected failures — they return {ok:false, error} so
the model can act on the message.
Alerts
Rules live in the same file as the watchlist and are evaluated on every poll.
A rule fires when the comparison holds and the cooldown window since the last
trigger has elapsed; lastTriggeredAt is persisted.
Delivery channels (both best-effort, failures contained):
Harness event —
ctx.emit('market-watch/alert', alert). Any extension can listen:ctx.on('market-watch/alert', (alert) => { /* alert.message, alert.quote, alert.rule */ })Agent sessions — when
ctx.agentsis mounted, every live agent receives the alert as a plugin-sourceduser/message: quiet context for the next step (agent.inject) by default, or a full follow-up turn withagentWakeup: true.
CLI
dsh-market-watch runs on the same data directory as the plugin, so commands
act on the exact state the plugin polls.
dsh-market-watch quote sh600000 bitcoin --days 5
dsh-market-watch watch sh600000 bitcoin --name "BTC"
dsh-market-watch list
dsh-market-watch unwatch sh600000
dsh-market-watch alert list
dsh-market-watch alert add bitcoin --field price --op gte --value 70000 --cooldown 600
dsh-market-watch chart sh600000 --days 30 --format mermaid
dsh-market-watch poll --once # single pass (cron-friendly)
dsh-market-watch poll --interval 300 # keep polling every 5 min
Global flags: --data-dir <path> (or MARKET_WATCH_DATA_DIR), --help,
--version. Exit codes: 0 ok, 1 runtime error, 2 usage error.
Data files
<dataDir>/watchlist.json — JSON document {version, items, rules}. Writes
are atomic (temp file + rename), serialized through a promise chain, and a
corrupt file is quarantined (watchlist.json.corrupt-<ts>) instead of
wedging the plugin. Because the plugin and the CLI share one file, the engine
re-reads it on every poll/json quotation, so edits made in a second process
become visible without a restart.
FAQ
- Which data sources are used, and how fresh are quotes? A-share stocks and indices come from Tencent's public quote endpoint; crypto comes from CoinGecko. See "Data sources and latency" above for the refresh cadence and the documented staleness limits.
- Why is a symbol not recognized? Symbols are normalized case-insensitively
(e.g.
sh600000/600000for an SSE stock,bitcoin/BTCfor crypto). Rundsh-market-watch list --known(or themarket_knowntool) to see the accepted forms; symbols outside the provider's universe are rejected. - My alert did not fire. Alerts are evaluated on poll ticks; check the rule
operator (
gte/lte) and--cooldown, and that the field (e.g.price) exists in the quote shape. Alerts can be listed withdsh-market-watch alert listor themarket_alertstool. - Where is my watchlist stored? In
<dataDir>/watchlist.json(dataDirdefaults to the dsh profile data dir, orMARKET_WATCH_DATA_DIR/ the--data-dirflag). Writes are atomic and corrupt files are quarantined.
Development
npm install
npm run typecheck # tsc --noEmit
npm test # vitest (all network paths mocked)
npm run build # tsc -> lib/
npm run check # typecheck + test + build
Layout: src/core/ is framework-free (types, symbols, formatting, HTTP
client, JSON store, chart renderers, providers, engine) so the CLI and tests
share it without importing dsh; src/dsh/ adapts the core to Cordis (tools,
poller, notifier, entry point); src/cli/ is the standalone binary.
License
MIT — see LICENSE.
Links
More in this category
Tencent/WeKnora#dsh-weknora★ 32318
Four read-only tools over a WeKnora knowledge base: list knowledge bases, hybrid passage search, reassemble one document's chunks in order, and WeKnora's own cited RAG or ReAct-agent answer with a resumable session id.
superdesigndev/treg★ 4452
Tool catalog for agents: search ~2,600 external endpoints (SEO and SERP, backlinks, social, people and company enrichment, ad libraries, scraping) by the task you want done, read each one's parameters and per-call price, then call it with the credential injected server-side. Ships the skill plus an MCP row that stays disabled until TREG_TOKEN is set.
TencentCloudBase/CloudBase-AI-Toolkit#dsh-plugin★ 1132
Tencent CloudBase backend for DeepSeek Harness — scaffold and deploy full-stack apps from chat, render query results as table cards with paging, sorting and CSV export, preview a deployment on its domain, and call the CloudBase MCP toolset (`mcp__cloudbase__*`) with device-code login.
gitroomhq/postiz-agent#dsh-postiz★ 504
Connects DeepSeek Harness to Postiz over MCP: list connected social media channels, fetch per-platform posting rules, and schedule, draft, or publish posts to X, LinkedIn, Instagram, Facebook, Threads, TikTok, YouTube, Reddit, Bluesky, Mastodon, Discord, Slack, Telegram and more; adds a postiz workflow skill.
EthanYoQ/Invoice-Downloader#dsh-invoice-downloader★ 496
Local IMAP invoice download, OCR, archive, and Excel reimbursement summaries for DeepSeek Harness.
anysearch-team/anysearch-dsh★ 447
AnySearch-powered real-time web and vertical search provider for DeepSeek Harness.
Community comments
Comments are public GitHub Discussions. Loading them connects to GitHub and Giscus; a GitHub account is required to post.