stock-analyzer-skill 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (154) hide show
  1. package/.claude-plugin/marketplace.json +19 -0
  2. package/.claude-plugin/plugin.json +21 -0
  3. package/CHANGELOG.md +93 -0
  4. package/CONTRIBUTING.md +331 -0
  5. package/README.md +259 -0
  6. package/experts/README.md +119 -0
  7. package/experts/buffett.md +91 -0
  8. package/experts/chaogu_yangjia.md +125 -0
  9. package/experts/decide.md +212 -0
  10. package/experts/duan_yongping.md +106 -0
  11. package/experts/lynch.md +127 -0
  12. package/experts/soros.md +89 -0
  13. package/experts/xu_xiang.md +107 -0
  14. package/experts/zhao_laoge.md +143 -0
  15. package/experts/zuoshou_xinyi.md +144 -0
  16. package/install-plugin.js +69 -0
  17. package/methodology.md +455 -0
  18. package/package.json +43 -0
  19. package/scripts/__pycache__/announcements.cpython-314.pyc +0 -0
  20. package/scripts/__pycache__/backtest.cpython-314.pyc +0 -0
  21. package/scripts/__pycache__/chan.cpython-314.pyc +0 -0
  22. package/scripts/__pycache__/classifier.cpython-314.pyc +0 -0
  23. package/scripts/__pycache__/common.cpython-314.pyc +0 -0
  24. package/scripts/__pycache__/finance.cpython-314.pyc +0 -0
  25. package/scripts/__pycache__/init_pool.cpython-314.pyc +0 -0
  26. package/scripts/__pycache__/kline.cpython-314.pyc +0 -0
  27. package/scripts/__pycache__/patterns_local.cpython-314.pyc +0 -0
  28. package/scripts/__pycache__/quote.cpython-314.pyc +0 -0
  29. package/scripts/__pycache__/refresh_pool.cpython-314.pyc +0 -0
  30. package/scripts/__pycache__/screener.cpython-314.pyc +0 -0
  31. package/scripts/__pycache__/technical.cpython-314.pyc +0 -0
  32. package/scripts/announcements.py +118 -0
  33. package/scripts/backtest.py +528 -0
  34. package/scripts/chan.py +591 -0
  35. package/scripts/classifier.py +302 -0
  36. package/scripts/common.py +507 -0
  37. package/scripts/data/__init__.py +208 -0
  38. package/scripts/data/__pycache__/__init__.cpython-314.pyc +0 -0
  39. package/scripts/data/__pycache__/cache.cpython-314.pyc +0 -0
  40. package/scripts/data/__pycache__/config.cpython-314.pyc +0 -0
  41. package/scripts/data/__pycache__/types.cpython-314.pyc +0 -0
  42. package/scripts/data/cache.py +99 -0
  43. package/scripts/data/config.py +49 -0
  44. package/scripts/data/industry_thresholds.json +199 -0
  45. package/scripts/data/portfolio_example.json +14 -0
  46. package/scripts/data/sector_etf.csv +14 -0
  47. package/scripts/data/sector_mapping.json +64 -0
  48. package/scripts/data/sector_stocks.json +135 -0
  49. package/scripts/data/types.py +66 -0
  50. package/scripts/fetchers/__init__.py +130 -0
  51. package/scripts/fetchers/__pycache__/__init__.cpython-314.pyc +0 -0
  52. package/scripts/fetchers/__pycache__/akshare_finance.cpython-314.pyc +0 -0
  53. package/scripts/fetchers/__pycache__/akshare_kline.cpython-314.pyc +0 -0
  54. package/scripts/fetchers/__pycache__/akshare_quote.cpython-314.pyc +0 -0
  55. package/scripts/fetchers/__pycache__/baostock_kline.cpython-314.pyc +0 -0
  56. package/scripts/fetchers/__pycache__/eastmoney_finance.cpython-314.pyc +0 -0
  57. package/scripts/fetchers/__pycache__/eastmoney_kline.cpython-314.pyc +0 -0
  58. package/scripts/fetchers/__pycache__/eastmoney_quote.cpython-314.pyc +0 -0
  59. package/scripts/fetchers/__pycache__/efinance_finance.cpython-314.pyc +0 -0
  60. package/scripts/fetchers/__pycache__/efinance_kline.cpython-314.pyc +0 -0
  61. package/scripts/fetchers/__pycache__/efinance_quote.cpython-314.pyc +0 -0
  62. package/scripts/fetchers/__pycache__/pytdx_quote.cpython-314.pyc +0 -0
  63. package/scripts/fetchers/__pycache__/sina_kline.cpython-314.pyc +0 -0
  64. package/scripts/fetchers/__pycache__/sina_quote.cpython-314.pyc +0 -0
  65. package/scripts/fetchers/__pycache__/tencent_kline.cpython-314.pyc +0 -0
  66. package/scripts/fetchers/__pycache__/tencent_quote.cpython-314.pyc +0 -0
  67. package/scripts/fetchers/__pycache__/tushare_kline.cpython-314.pyc +0 -0
  68. package/scripts/fetchers/__pycache__/tushare_quote.cpython-314.pyc +0 -0
  69. package/scripts/fetchers/__pycache__/yfinance_kline.cpython-314.pyc +0 -0
  70. package/scripts/fetchers/akshare_finance.py +35 -0
  71. package/scripts/fetchers/akshare_kline.py +59 -0
  72. package/scripts/fetchers/akshare_quote.py +52 -0
  73. package/scripts/fetchers/baostock_kline.py +64 -0
  74. package/scripts/fetchers/eastmoney_finance.py +29 -0
  75. package/scripts/fetchers/eastmoney_kline.py +48 -0
  76. package/scripts/fetchers/eastmoney_quote.py +68 -0
  77. package/scripts/fetchers/efinance_finance.py +32 -0
  78. package/scripts/fetchers/efinance_kline.py +46 -0
  79. package/scripts/fetchers/efinance_quote.py +53 -0
  80. package/scripts/fetchers/pytdx_kline.py +70 -0
  81. package/scripts/fetchers/pytdx_quote.py +78 -0
  82. package/scripts/fetchers/sina_kline.py +30 -0
  83. package/scripts/fetchers/sina_quote.py +35 -0
  84. package/scripts/fetchers/tencent_kline.py +52 -0
  85. package/scripts/fetchers/tencent_quote.py +29 -0
  86. package/scripts/fetchers/tushare_kline.py +62 -0
  87. package/scripts/fetchers/tushare_quote.py +62 -0
  88. package/scripts/fetchers/yfinance_kline.py +66 -0
  89. package/scripts/finance.py +92 -0
  90. package/scripts/init_pool.py +105 -0
  91. package/scripts/kline.py +62 -0
  92. package/scripts/monitor.py +107 -0
  93. package/scripts/patterns_local.py +599 -0
  94. package/scripts/quote.py +69 -0
  95. package/scripts/refresh_pool.py +328 -0
  96. package/scripts/screener.py +434 -0
  97. package/scripts/strategies/__init__.py +11 -0
  98. package/scripts/strategies/__pycache__/__init__.cpython-314.pyc +0 -0
  99. package/scripts/strategies/__pycache__/registry.cpython-314.pyc +0 -0
  100. package/scripts/strategies/__pycache__/thresholds.cpython-314.pyc +0 -0
  101. package/scripts/strategies/factors/__init__.py +8 -0
  102. package/scripts/strategies/factors/__pycache__/__init__.cpython-314.pyc +0 -0
  103. package/scripts/strategies/factors/__pycache__/liquidity.cpython-314.pyc +0 -0
  104. package/scripts/strategies/factors/__pycache__/momentum.cpython-314.pyc +0 -0
  105. package/scripts/strategies/factors/__pycache__/quality.cpython-314.pyc +0 -0
  106. package/scripts/strategies/factors/__pycache__/valuation.cpython-314.pyc +0 -0
  107. package/scripts/strategies/factors/__pycache__/volatility.cpython-314.pyc +0 -0
  108. package/scripts/strategies/factors/liquidity.py +49 -0
  109. package/scripts/strategies/factors/momentum.py +45 -0
  110. package/scripts/strategies/factors/quality.py +54 -0
  111. package/scripts/strategies/factors/valuation.py +76 -0
  112. package/scripts/strategies/factors/volatility.py +89 -0
  113. package/scripts/strategies/registry.py +87 -0
  114. package/scripts/strategies/thresholds.py +28 -0
  115. package/scripts/technical/__init__.py +116 -0
  116. package/scripts/technical/__pycache__/__init__.cpython-314.pyc +0 -0
  117. package/scripts/technical/__pycache__/astock.cpython-314.pyc +0 -0
  118. package/scripts/technical/__pycache__/boll.cpython-314.pyc +0 -0
  119. package/scripts/technical/__pycache__/candlestick.cpython-314.pyc +0 -0
  120. package/scripts/technical/__pycache__/core.cpython-314.pyc +0 -0
  121. package/scripts/technical/__pycache__/kdj.cpython-314.pyc +0 -0
  122. package/scripts/technical/__pycache__/macd.cpython-314.pyc +0 -0
  123. package/scripts/technical/__pycache__/moving_average.cpython-314.pyc +0 -0
  124. package/scripts/technical/__pycache__/report.cpython-314.pyc +0 -0
  125. package/scripts/technical/__pycache__/rsi.cpython-314.pyc +0 -0
  126. package/scripts/technical/__pycache__/scoring.cpython-314.pyc +0 -0
  127. package/scripts/technical/__pycache__/signals.cpython-314.pyc +0 -0
  128. package/scripts/technical/__pycache__/trend.cpython-314.pyc +0 -0
  129. package/scripts/technical/__pycache__/volume.cpython-314.pyc +0 -0
  130. package/scripts/technical/astock.py +98 -0
  131. package/scripts/technical/boll.py +49 -0
  132. package/scripts/technical/candlestick.py +151 -0
  133. package/scripts/technical/core.py +92 -0
  134. package/scripts/technical/kdj.py +68 -0
  135. package/scripts/technical/macd.py +97 -0
  136. package/scripts/technical/moving_average.py +59 -0
  137. package/scripts/technical/report.py +221 -0
  138. package/scripts/technical/rsi.py +37 -0
  139. package/scripts/technical/scoring.py +392 -0
  140. package/scripts/technical/signals.py +70 -0
  141. package/scripts/technical/trend.py +143 -0
  142. package/scripts/technical/volume.py +113 -0
  143. package/scripts/technical.py +215 -0
  144. package/skills/financial-analyst/SKILL.md +141 -0
  145. package/skills/help/SKILL.md +188 -0
  146. package/skills/init/SKILL.md +66 -0
  147. package/skills/investment-researcher/SKILL.md +152 -0
  148. package/skills/market/SKILL.md +99 -0
  149. package/skills/portfolio/SKILL.md +96 -0
  150. package/skills/screener/SKILL.md +128 -0
  151. package/skills/sector/SKILL.md +102 -0
  152. package/skills/stock/SKILL.md +148 -0
  153. package/skills/technical/SKILL.md +168 -0
  154. package/workflow.md +91 -0
@@ -0,0 +1,19 @@
1
+ {
2
+ "name": "stock-analyzer-marketplace",
3
+ "description": "A 股分析 skills marketplace",
4
+ "owner": {
5
+ "name": "curtis",
6
+ "email": "curtis@example.com"
7
+ },
8
+ "plugins": [
9
+ {
10
+ "name": "stock-analyzer",
11
+ "description": "A 股分析 skill 包,包含 8 个专业分析工具:单股分析、大盘复盘、板块分析、持仓检查、选股策略、技术分析、财务分析、投资研究",
12
+ "version": "1.0.0",
13
+ "source": "./",
14
+ "author": {
15
+ "name": "curtis"
16
+ }
17
+ }
18
+ ]
19
+ }
@@ -0,0 +1,21 @@
1
+ {
2
+ "name": "stock-analyzer",
3
+ "description": "A 股分析 skill 包,包含 8 个专业分析工具:单股分析、大盘复盘、板块分析、持仓检查、选股策略、技术分析、财务分析、投资研究",
4
+ "version": "1.1.0",
5
+ "author": {
6
+ "name": "curtis"
7
+ },
8
+ "homepage": "https://github.com/curtis/stock-analyzer-skill",
9
+ "repository": "https://github.com/curtis/stock-analyzer-skill",
10
+ "license": "MIT",
11
+ "keywords": [
12
+ "stock",
13
+ "a-share",
14
+ "analysis",
15
+ "claude-code",
16
+ "skills",
17
+ "investing",
18
+ "technical-analysis",
19
+ "fundamental-analysis"
20
+ ]
21
+ }
package/CHANGELOG.md ADDED
@@ -0,0 +1,93 @@
1
+ # Changelog
2
+
3
+ 本文件记录 stock-analyzer-skill 的所有重要变更。
4
+
5
+ 格式基于 [Keep a Changelog](https://keepachangelog.com/zh-CN/1.0.0/),
6
+ 版本号遵循 [语义化版本](https://semver.org/lang/zh-CN/)。
7
+
8
+ ## [1.1.0] - 2026-06-08
9
+
10
+ ### Added
11
+
12
+ - 新增 `/help` skill,显示所有可用 skills 和使用说明
13
+ - 支持 `/stocks` 和 `/skills` 作为 `/help` 的别名
14
+ - 在 help 中包含工作流建议和使用示例
15
+
16
+ ### Changed
17
+
18
+ - 将项目重构为 Claude Code plugin 格式
19
+ - 创建 `.claude-plugin/plugin.json` 和 `marketplace.json`
20
+ - 将 `.claude/skills/` 移动到 `skills/` 目录
21
+ - 更新 README.md 安装说明,支持 plugin 方式安装
22
+
23
+ ### Fixed
24
+
25
+ - 优化 skill description 提高触发准确率
26
+
27
+ ## [1.0.0] - 2026-06-05
28
+
29
+ ### Added
30
+
31
+ - 初始版本发布
32
+ - 8 个股票分析 skills:
33
+ - `/stock` - 单股分析(quick/full/debate 模式)
34
+ - `/market` - 大盘复盘(full/quick/intraday 模式)
35
+ - `/sector` - 板块分析(overview/compare/stock 模式)
36
+ - `/portfolio` - 持仓健康检查(health/rebalance/compare 模式)
37
+ - `/screener` - 多因子选股策略系统
38
+ - `/technical` - 纯技术分析(quick/full 模式)
39
+ - `/financial-analyst` - 财务分析 agent
40
+ - `/investment-researcher` - 投资研究 agent
41
+ - 完整投资方法论(methodology.md)
42
+ - 8 人专家圆桌系统(巴菲特/林奇/索罗斯/段永平 + 徐翔/赵老哥/炒股养家/作手新一)
43
+ - 5 种选股策略(均衡精选/质量价值/成长动量/防守低波/拐点修复)
44
+ - 行业差异化阈值(金融/消费/科技/周期/医药/制造/能源/地产)
45
+ - 工具脚本(Python stdlib only):
46
+ - quote.py - 腾讯实时行情
47
+ - finance.py - 东财财务数据
48
+ - kline.py - 新浪 K 线
49
+ - announcements.py - 东财公告/研报
50
+ - screener.py - A 股多因子选股器
51
+ - technical.py - 纯技术分析
52
+ - classifier.py - 个股类型分类
53
+ - chan.py - 缠论结构
54
+ - patterns_local.py - A 股本土战法形态
55
+ - 静态参考数据:
56
+ - sector_etf.csv - 板块 ETF 清单
57
+ - sector_stocks.json - 板块核心标的库
58
+ - portfolio_example.json - 持仓配置示例
59
+ - 端到端冒烟测试(tests/smoke_test.sh)
60
+ - 贡献指南(CONTRIBUTING.md)
61
+ - 工作流编排(workflow.md)
62
+
63
+ ### Technical Details
64
+
65
+ - 零项目依赖:不引用任何业务项目内文件
66
+ - 零外部 Python 库:只用 stdlib(urllib + json + pathlib)
67
+ - 支持 Codex(.agents/skills/)和 Claude Code(.claude/skills/)两套入口
68
+ - 所有数据 API 在国内直连,无须代理
69
+
70
+ ## [Unreleased]
71
+
72
+ ### Planned
73
+
74
+ - 支持更多数据源(如雪球、同花顺)
75
+ - 添加历史回测功能
76
+ - 支持港股和美股分析
77
+ - 添加更多本土战法形态
78
+ - 优化缠论算法
79
+ - 添加自动化测试
80
+
81
+ ---
82
+
83
+ ## 版本说明
84
+
85
+ - **主版本号**:不兼容的 API 变更
86
+ - **次版本号**:向下兼容的功能性新增
87
+ - **修订号**:向下兼容的问题修正
88
+
89
+ ## 链接
90
+
91
+ - [GitHub 仓库](https://github.com/curtis/stock-analyzer-skill)
92
+ - [问题反馈](https://github.com/curtis/stock-analyzer-skill/issues)
93
+ - [发布页面](https://github.com/curtis/stock-analyzer-skill/releases)
@@ -0,0 +1,331 @@
1
+ # 贡献指南
2
+
3
+ 本项目所有协作流程(提交、分支、Tag)须遵守本文规范。规范仅约束**协作行为**,不限制代码风格与功能设计。
4
+
5
+ > 一句话原则:**一次提交只做一件事,标题一句话说清,必要时正文给理由。**
6
+
7
+ ---
8
+
9
+ ## 1. 提交信息规范(Commit Message)
10
+
11
+ 采用 [Conventional Commits](https://www.conventionalcommits.org/) 1.0.0 的结构,但**标题与正文均使用中文**。结构如下:
12
+
13
+ ```
14
+ <type>(<scope>): <中文标题>
15
+
16
+ <中文正文:说明"为什么"而不是"做了什么">
17
+
18
+ <可选脚注>
19
+ ```
20
+
21
+ ### 1.1 标题行(必须)
22
+
23
+ - **type**:必须小写英文,取自下表。
24
+ - **scope**:可选,表示影响范围,建议小写英文或简写。本项目常用值:
25
+ - `*` 或省略:跨多个模块的通用变更(与项目历史风格一致)
26
+ - `stock` / `market` / `sector` / `portfolio` / `financial-analyst` / `investment-researcher`:对应 skill
27
+ - `scripts`:底层 Python 工具
28
+ - `data`:示例数据、配置
29
+ - `docs`:文档(README、方法论、CHANGELOG)
30
+ - `ci` / `deps`:工作流、依赖
31
+ - **中文标题**:
32
+ - 不加句号、不加末尾标点
33
+ - 长度 ≤ 50 个字符(不含 type 与 scope)
34
+ - 用动词开头("新增"、"修复"、"重构"、"调整"、"移除"、"升级"……)
35
+ - 避免空泛词("优化"、"完善"、"update")
36
+
37
+ ### 1.2 常用 type
38
+
39
+ | type | 含义 | 是否更新 CHANGELOG |
40
+ |------------|------------------------------------|--------------------|
41
+ | `feat` | 新增功能 | 是 |
42
+ | `fix` | 修复 Bug | 是 |
43
+ | `docs` | 仅文档变更(注释、README、方法论) | 否 |
44
+ | `style` | 不影响逻辑的格式调整(空格、缩进) | 否 |
45
+ | `refactor` | 既不修 Bug 也不加功能的代码重构 | 否 |
46
+ | `perf` | 性能优化 | 是 |
47
+ | `test` | 新增/修改测试 | 否 |
48
+ | `build` | 构建系统、依赖、脚本目录调整 | 否 |
49
+ | `ci` | CI 配置变更 | 否 |
50
+ | `chore` | 杂项(如 .gitignore、目录调整) | 否 |
51
+ | `revert` | 回滚某次提交 | 是 |
52
+
53
+ ### 1.3 正文(强烈建议)
54
+
55
+ - 与标题之间空一行。
56
+ - 回答"**为什么**这样改":解释动机、取舍、限制、副作用。
57
+ - 多段落用空行分隔;每行建议 ≤ 72 个字符。
58
+ - 若有非显而易见的设计权衡("为什么用 A 而不用 B"),必须写出来。
59
+
60
+ ### 1.4 脚注(可选)
61
+
62
+ 格式 `Token: 值`,常用:
63
+
64
+ - `Refs: #123` —— 关联 Issue / PR
65
+ - `Closes: #123` —— 关闭 Issue
66
+ - `BREAKING CHANGE: <说明>` —— 破坏性变更,必须单独成段
67
+
68
+ ### 1.5 示例
69
+
70
+ #### ✅ 好的提交
71
+
72
+ ```
73
+ feat(stock): 新增 8 人专家圆桌多空辩论模式
74
+
75
+ 原五层框架只能产出单边结论,长线持有者无法验证
76
+ 持仓股是否被市场主流逻辑证伪。新增 debate 模式调用
77
+ 4 名看多 + 4 名看空专家独立打分,最终按加权一致性
78
+ 输出结论,便于人工复核。
79
+
80
+ Refs: #42
81
+ ```
82
+
83
+ ```
84
+ fix(quote): 修复腾讯接口字段缺失导致 0 报价
85
+
86
+ 请求返回中"昨收"字段为空时旧代码抛 KeyError。改为
87
+ 容错取实时价作为兜底,并在日志中标记降级。
88
+
89
+ BREAKING CHANGE: 当 data['last_close'] 为空时,
90
+ 返回的 change_pct 字段不再抛异常,但会标注为"估算"。
91
+ ```
92
+
93
+ ```
94
+ docs(*): 在 README 中补充 install.sh 的使用说明
95
+ ```
96
+
97
+ #### ❌ 不合格的提交
98
+
99
+ ```
100
+ fix: 改了点东西
101
+ ```
102
+ → 没说清改了什么、为什么改。
103
+
104
+ ```
105
+ feat(stock): 新增功能、优化体验、完善细节
106
+ ```
107
+ → 一句话塞了三件事;"优化"、"完善"是空泛词。
108
+
109
+ ```
110
+ Update README
111
+ ```
112
+ → 不是 Conventional 格式;中文环境下标题未使用中文。
113
+
114
+ ---
115
+
116
+ ## 2. 分支命名规范
117
+
118
+ 所有非个人分支须遵循 `<type>/<短描述>` 格式,**全部使用小写英文 + 连字符**,避免中文路径在不同工具下出现转义问题。
119
+
120
+ | 用途 | 分支模式 | 示例 |
121
+ |--------------|--------------------------------|---------------------------------|
122
+ | 新功能 | `feat/<短描述>` | `feat/stock-debate-mode` |
123
+ | 修复 | `fix/<短描述>` | `fix/quote-keyerror` |
124
+ | 紧急热修 | `hotfix/<短描述>` | `hotfix/install-permission` |
125
+ | 重构 | `refactor/<短描述>` | `refactor/finance-cache` |
126
+ | 文档 | `docs/<短描述>` | `docs/methodology-update` |
127
+ | 个人探索 | `exp/<作者>/<短描述>` | `exp/curtis/try-new-render` |
128
+ | 长期集成 | `release/<版本号>` | `release/v1.2.0` |
129
+
130
+ - 主干分支固定为 `main`,受保护:仅允许 PR 合入,禁止直推。
131
+ - 短描述使用 2~4 个英文单词,必要时加版本号或日期。
132
+ - 分支完成后删除(`git push origin --delete <branch>`),保持仓库整洁。
133
+
134
+ ---
135
+
136
+ ## 3. Tag 与版本号
137
+
138
+ - 触发正式发布时打 Tag,命名 `v<MAJOR>.<MINOR>.<PATCH>`,遵循 [SemVer 2.0](https://semver.org/)。
139
+ - Tag 须用 `git tag -s v1.2.0 -m "..."` 签名(GPG 可用时)。
140
+ - 预发布版本加后缀:`v1.2.0-rc.1`、`v1.2.0-beta.2`。
141
+ - Tag 一经推送不允许修改或删除,需变更则打新 Tag。
142
+
143
+ ---
144
+
145
+ ## 4. 提交粒度与频率
146
+
147
+ - **一个提交 = 一个原子变更**。不要把功能开发与顺手重构混在一起。
148
+ - WIP 状态请留在本地或自己的 `exp/` 分支,不要污染主干。
149
+ - 推送前自查:
150
+ - `git diff --staged` 是否包含无关文件
151
+ - 是否引入了调试代码、注释掉的死代码
152
+ - 是否需要拆成多个提交
153
+ - 提 PR 前本地 rebase 到 `main`,避免历史分叉。
154
+
155
+ ---
156
+
157
+ ## 5. 工具辅助
158
+
159
+ ### 5.1 提交模板
160
+
161
+ `git config commit.template .gitmessage` 后,新建 `.gitmessage`:
162
+
163
+ ```
164
+ <type>(<scope>): <中文标题>
165
+
166
+ # 正文:解释"为什么"而不是"做了什么"
167
+ # 多段落用空行分隔
168
+ #
169
+ # 脚注(可选):
170
+ # Refs: #123
171
+ # BREAKING CHANGE: 说明
172
+ ```
173
+
174
+ ### 5.2 commitlint(可选)
175
+
176
+ 若团队启用 CI 检查,可在 `package.json` 旁维护一份 `commitlint.config.js`:
177
+
178
+ ```js
179
+ module.exports = {
180
+ extends: ['@commitlint/config-conventional'],
181
+ rules: {
182
+ 'subject-max-length': [2, 'always', 50],
183
+ 'type-enum': [2, 'always', [
184
+ 'feat','fix','docs','style','refactor',
185
+ 'perf','test','build','ci','chore','revert'
186
+ ]],
187
+ },
188
+ };
189
+ ```
190
+
191
+ ### 5.3 推荐的本地工作流
192
+
193
+ ```bash
194
+ # 1. 拉取最新主干
195
+ git checkout main && git pull --rebase
196
+
197
+ # 2. 新建功能分支
198
+ git checkout -b feat/<short-desc>
199
+
200
+ # 3. 多次小提交(写好中文 commit message)
201
+ git add -p
202
+ git commit # 弹出模板,照填即可
203
+
204
+ # 4. 推送分支并开 PR
205
+ git push -u origin feat/<short-desc>
206
+
207
+ # 5. PR 通过并合并后,删除远端与本地分支
208
+ git push origin --delete feat/<short-desc>
209
+ git branch -d feat/<short-desc>
210
+ ```
211
+
212
+ ---
213
+
214
+ ## 6. 例外与豁免
215
+
216
+ 以下场景允许偏离规范,请在 PR 描述中明确说明:
217
+
218
+ - **首次提交(init)**:`first commit`、`chore: 初始化项目骨架` 等历史性 commit。
219
+ - **自动化脚本产生的提交**(如 `release-please`、Dependabot):保持工具默认输出即可。
220
+ - **临时回滚**:`revert:` 提交可仅含 commit 引用,正文写自动生成说明。
221
+
222
+ ---
223
+
224
+ ## 7. 自检清单(提交前过一遍)
225
+
226
+ - [ ] type 在合法枚举内,小写
227
+ - [ ] 标题中文,≤ 50 字,无句号
228
+ - [ ] 正文解释了"为什么",不只是"做了什么"
229
+ - [ ] 破坏性变更用 `BREAKING CHANGE:` 标注
230
+ - [ ] 一个提交只改一件事;无关文件已 `git reset`
231
+ - [ ] 分支命名符合 `<type>/<短描述>` 规范
232
+ - [ ] 已 rebase 到最新 `main`,历史线性
233
+
234
+ ---
235
+
236
+ ## 8. Claude Code Skill 开发规范
237
+
238
+ 本项目的 skill 位于 `.claude/skills/<name>/SKILL.md`,供 Claude Code 使用。以下是开发规范:
239
+
240
+ ### 8.1 路径规范
241
+
242
+ **核心原则**:Claude Code 运行 Bash 时,工作目录**自动是项目根目录**,不是 skill 文件所在目录。
243
+
244
+ ```bash
245
+ # ❌ 错误:使用相对路径 cd ../../..
246
+ cd ../../..
247
+ python3 scripts/quote.py sh600989
248
+
249
+ # ✅ 正确:直接运行脚本
250
+ python3 scripts/quote.py sh600989
251
+ python3 scripts/finance.py SH600989
252
+ python3 scripts/kline.py sh600989 240 30
253
+ ```
254
+
255
+ 如果 SKILL.md 中需要说明项目根目录,使用通用描述而非硬编码路径:
256
+
257
+ ```markdown
258
+ # ❌ 错误:硬编码用户路径
259
+ 项目根目录为 `/Users/curtis/Documents/curtis/stock-analyzer-skill`
260
+
261
+ # ✅ 正确:通用描述
262
+ Claude Code 运行时工作目录即为项目根目录
263
+ ```
264
+
265
+ ### 8.2 避免循环导入
266
+
267
+ Python 模块级导入顺序很重要。以下模式会导致循环导入错误:
268
+
269
+ ```
270
+ common.py (line 32) → from data.cache import ...
271
+ → 触发加载 data/__init__.py (line 21)
272
+ → from common import to_float, to_int ← 此时 common.py 还没执行完!
273
+ → ImportError
274
+ ```
275
+
276
+ **解决方案**:使用延迟导入(在函数内部导入):
277
+
278
+ ```python
279
+ # ❌ 错误:模块顶层导入
280
+ from common import to_float, to_int
281
+
282
+ # ✅ 正确:延迟导入
283
+ def _get_common_helpers():
284
+ """延迟导入 common,避免循环导入。"""
285
+ from common import to_float, to_int
286
+ return to_float, to_int
287
+
288
+ def _dict_to_quote(d: dict) -> Quote:
289
+ to_float, to_int = _get_common_helpers()
290
+ return Quote(price=to_float(d.get("price")), ...)
291
+ ```
292
+
293
+ ### 8.3 权限配置
294
+
295
+ 项目级权限配置放在 `.claude/settings.json`(注意不是 `settings.local.json`)。
296
+
297
+ 权限规则应使用通配符匹配脚本名,而非硬编码具体股票代码:
298
+
299
+ ```json
300
+ {
301
+ "permissions": {
302
+ "allow": [
303
+ "Bash(python3 scripts/quote.py *)",
304
+ "Bash(python3 scripts/finance.py *)",
305
+ "Bash(python3 scripts/kline.py *)",
306
+ "Bash(python3 scripts/technical.py *)",
307
+ "Bash(python3 scripts/screener.py *)"
308
+ ]
309
+ }
310
+ }
311
+ ```
312
+
313
+ ### 8.4 测试验证
314
+
315
+ 修改 SKILL.md 或权限配置后,必须验证:
316
+
317
+ ```bash
318
+ # 1. 脚本直接运行正常
319
+ python3 scripts/quote.py sh600989
320
+
321
+ # 2. 测试套件通过
322
+ python3 -m pytest tests/ -x -q
323
+ ```
324
+
325
+ ### 8.5 本地调试
326
+
327
+ 在 Claude Code 中调试 skill 时:
328
+
329
+ 1. 先在终端验证脚本可以正常运行
330
+ 2. 检查 Claude Code 的工作目录:`pwd`
331
+ 3. 查看权限是否匹配:权限规则需要精确匹配命令格式