dsh-stock-portfolio
对话是主要交互界面,面板只是必要时的管理入口。
在 DeepSeek Harness(DSH)里管理股票持仓:交易记录、盈亏统计、按日线保存的行情、离线代码检索与持仓复盘,全部落在本地 SQLite。覆盖 A 股(沪深京)、港股、美股,以及 ETF、指数、可转债。
三个入口,读写同一份数据:
- 侧边栏「股票持仓」(「设置」上方,右侧直接带当日盈亏)→ 管理面板。
- 对话里读数据、记交易、复盘:说「昨天买了 100 股腾讯」就写入,缺的字段当场弹一张问题卡片问;问「腾讯最近怎么样」「我在哪个动机上赚得多」时直接读本地 SQLite 回答;问「我的股票表现怎么样」会触发一次复盘(也可以直接敲
/portfolio-review)。读持仓、行情与聚合分析不用授权,读交易记录明细每次都会先弹一张授权卡片。 - 对话右侧栏「持仓提及」:对话里出现持仓标的的代码或名称时自动展开,列出它的走势与持仓统计。
界面只用 DSH 自己的主题变量(--dsw-alias-*),自动跟随浅色 / 深色主题。

截图仅为效果预览,不构成投资建议。
面板
| 分区 | 内容 |
|---|---|
| 概览 | 持仓市值、总盈亏、未实现盈亏等指标;按每日收盘价回溯的市值走势图; |
| 持仓 | 数量、成本价、最新收盘价等;表头可排序。每行可展开可查看近期股价和分析统计。 |
| 交易 | 增 / 改 / 删;表单默认折叠,动机字段旁按方向给出常用速选词,点一下即填入,也可自由输入。 |
| 分析 | 已实现盈亏记在卖出动机上、浮动盈亏按买入动机的成本占比分摊。 |
| 设置 | API Key、基准货币、自动获取的汇率、本地代码索引状态等基础设置。 |
对话里提到持仓标的
对话里出现持仓标的的代码或名称时,右侧栏的「持仓提及」自己展开,一个标的一张卡片。
提及由一个会话投影折出:用户输入与助手回复都算,从磁盘恢复的历史会话在首次读取时把整段日志折一遍;浏览器每 2 秒问一次当前会话的状态(页面不可见时不问)。
在 chat 里读数据、记交易
同一个插件还向会话注册七个 Tool,读写同一份 SQLite:
| Tool | 权限 | 回答什么 |
|---|---|---|
stock_add_trade |
直接写入 | 把一句话变成一笔交易记录 |
stock_portfolio_overview |
自动读 | 持仓明细、市值、浮动 / 已实现 / 当日盈亏、分币种小计 |
stock_symbol_detail |
自动读 | 单个标的的本地日线与指标,外加它的持仓与清仓历史 |
stock_analysis |
自动读 | 按动机、按市场的盈亏分布,标的表现排行。 |
stock_portfolio_review |
自动读 | 组合复盘:当下的盈亏等,外加未来一个月的研究清单 |
stock_search_symbols |
自动读 | 本地代码索引检索(离线、瞬时) |
stock_list_trades |
先问用户同意 | 单笔交易明细:日期、方向、数量、价格、动机、备注 |
读持仓、读行情、读聚合分析、读复盘都不打断用户;交易明细是唯一需要授权的读。
复盘
问「我的股票表现怎么样」就会做一次持仓复盘:一次给全当下的数——盈亏、波动、集中度、浮盈浮亏家数、行情陈旧度,同时给出一份未来约一个月的研究清单。
复盘分两半:数字由插件从本地日线与交易记录算出,不请求行情接口;未来一个月的走势与催化(行业竞争、券商预期 / 研报、业务进展、管理层变动、新闻)插件不抓,由对话里的模型用自己的搜索 / 抓取工具按清单逐只查,并标出信息日期与来源。
也可以走斜杠菜单的「复盘持仓」(/portfolio-review,想只看一只就直接打 /portfolio-review 腾讯控股)。
口径
- 只按日线。 每标的每交易日一行;估值用最新收盘价,「当日盈亏」对比前一日收盘价,界面上的价格永远带日期。
- 按需取数。 最新一根已是数据源能给的最后交易日时不发请求,落后的只补缺口(
start_time= 上次更新次日)。新标的(含 chat 里刚记的)写入时当场取最近 90 天。 - 成本与盈亏不含手续费:移动加权平均,卖出按摊薄成本结转并锁定已实现盈亏。
- 汇率一天取一次,基准货币默认人民币,也可在设置页手动覆盖。
- 数据源与代码索引:不填 Key 也能用(免费端点提供日线),Key 的优先级为设置 > 环境变量 >
.env> 插件行,设置页只回传「已配置 / 未配置」。
安装
插件是标准的 DSH bundle + dual-face client,按普通插件安装(插件管理器或 CLI 是同一套):
npm install && npm run build
dsh plugin --profile web add <checkout 的绝对路径>
也可以在 Web 侧边栏的 插件 页安装(插件页显示的就是本包的 logo.svg 与 description)。安装会写 profile 的 dsh.profile.bundles 并把 checkout 链接进 profile 的 node_modules,插件行由本包自带的 cordis.patch.yml 提供:Host 半边是 lib/index.js,浏览器半边由包清单里的 dsh.client 声明发现。
开发
npm run build # lib/index.js(Host)+ lib/client.js(浏览器)+ 类型
npm run watch # 监听 src/ 重建
npm run typecheck # tsc --noEmit
npm test # node --test,全部离线
npm run reload # 让运行中的 dsh 换用刚构建的 Host 半边(见下)
开发时的热重载
npm run reload 让已经在运行的 dsh 换用刚构建的 Host 半边,不用重启。它维护 profile cordis.patch.yml 里一块带哨兵的「dev 覆盖」:停用 bundle 自带的 stock-portfolio 行,再另插一行指向内容寻址的 lib/index.dev.<digest>.js。四个理由各占一环:
- 不能改成给 bundle 行改名:Loader 会跳过
name与目标行不一致的非 insert 补丁(patch: name mismatch ... skipping),所以在- id: stock-portfolio上加name:是静默无效的——行照旧加载lib/index.js,只有重启才换模块。 - 停用不等于卸载:bundle 仍留在
dsh.profile.bundles,浏览器半边照旧被发现;但那一行不能再挂载已发布的 bundle,否则插件会挂两遍(两个 store、两次路由注册)。 - 插入的行必须跟着 bundle 的开关走:profile patch 插入的行不受
dsh.profile.bundles约束,所以它带一条!!js挂载守卫,只在 bundle 那一行「存在且被停用」时才挂载。没有守卫时,插件管理器里关掉这个 bundle 只会让 bundle 那一行消失,dev 行仍把插件挂着:侧栏的「股票持仓」和当日盈亏照旧,开关看起来失灵。守卫读的是本轮组合好的 entry 列表(entry.parent.tree.root.data),而不是 Live store——同一轮里新出现的 id 会被最后创建,读 store 会在「重新开启」的那一轮看不到 bundle 行,把 dev 行卸掉之后不再重挂。 - digest 才是热重载的关键:Node 按解析后的 URL 缓存 ES 模块,只有 Loader 从没导入过的名字才会读到新构建。
npm run build 产出新 digest,npm run reload 把覆盖行指过去,profile 的 patchReload: live 让它立即生效。删掉那块覆盖(或重跑插件安装)就回到 bundle 自带的 lib/index.js。
已知边界
- 会话里能读持仓、行情、聚合分析与交易记录,但只能新增交易:改一笔、删一笔仍在面板里做。读交易明细每次都要用户点一次同意,没有明确同意就一条记录也不返回。
- 指数类裸代码有歧义(
000300既是沪深 300 的形状、也是深市股票的形状),需要后缀或搜索。 - 批量日线权限因套餐而异;没有权限时刷新会改为逐个代码请求,代码多时更慢。
- 不做汇率的历史回溯:市值走势图用当前汇率折算。
- 行情按交易日更新,美股与港股收盘时点不同,面板顶部显示行情的最新日期。
No comments yet. Be the first to write one.