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
package/methodology.md ADDED
@@ -0,0 +1,455 @@
1
+ ---
2
+ name: stock-analyzer-methodology
3
+ description: 投资分析完整方法论——五层框架、专家讨论模式、数据源、仓位管理、决策流程
4
+ source: 抽离自 ~/.claude/memory/investment-methodology.md
5
+ version: 1.0
6
+ ---
7
+
8
+ # 投资分析方法论
9
+
10
+ ## 一、数据源
11
+
12
+ ### 实时行情(腾讯)
13
+ ```
14
+ curl -s "https://qt.gtimg.cn/q=sh600989" | iconv -f GBK -t UTF-8
15
+ ```
16
+ 字段: 3=名称, 4=现价, 33=涨跌幅, 40=PE, 37=成交量, 39=换手率
17
+
18
+ ### 财务数据(东方财富)
19
+ ```
20
+ curl -s "https://emweb.securities.eastmoney.com/PC_HSF10/NewFinanceAnalysis/ZYZBAjaxNew?type=0&code=SH600989"
21
+ ```
22
+ JSON结构: `response['data'][0]`
23
+ 关键字段: EPSJB(每股收益), ROEJQ(加权ROE), TOTALOPERATEREVETZ(营收增速), PARENTNETPROFITTZ(净利增速), XSMLL(毛利率), XSJLL(净利率), ZCFZL(负债率), BPS(每股净资产), MGJYXJJE(每股经营现金流)
24
+
25
+ ### K线数据(新浪财经)
26
+ 日K: `scale=240`, 5分钟: `scale=5`, 15分钟: `scale=15`
27
+ ```
28
+ curl -s "https://money.finance.sina.com.cn/quotes_service/api/json_v2.php/CN_MarketData.getKLineData?symbol=sh600989&scale=240&ma=no&datalen=30"
29
+ ```
30
+
31
+ ### 板块ETF
32
+ 510050(上证50), 510300(沪深300), 510500(中证500), 512010(医药), 512480(半导体), 512690(白酒), 512800(银行), 513120(港股创新药), 518880(黄金), 515030(新能源车)
33
+
34
+ ## 二、五层分析框架
35
+
36
+ ### 第1层:基本面筛选
37
+ - ROE > 15%(优秀), > 20%(顶级)
38
+ - 净利增速 > 20%(成长), > 50%(高速)
39
+ - 毛利率 > 30%(有壁垒)
40
+ - 负债率 < 60%(健康)
41
+ - 经营现金流/EPS > 1(利润含金量高)
42
+
43
+ ### 第2层:估值评估
44
+ - PE绝对值 vs 行业对比
45
+ - PEG = PE / 净利增速(<1低估, 1-2合理, >2偏贵)
46
+ - PE/ROE(<3为好)
47
+ - 历史估值分位
48
+
49
+ ### 第3层:技术面确认
50
+ - 30日K线趋势(上升/横盘/下降)
51
+ - 关键支撑/阻力位
52
+ - 成交量变化(放量/缩量)
53
+ - 5分钟分时形态(出货/吸筹/震荡)
54
+
55
+ ### 第4层:板块与风格分析
56
+ - 板块轮动节奏
57
+ - 大小盘分化程度
58
+ - 市场风格(成长vs价值、进攻vs防御)
59
+ - 资金流向
60
+
61
+ ### 第5层:风险收益比计算
62
+ - 情景分析(牛市/基准/震荡/悲观/极端)
63
+ - 概率加权期望收益
64
+ - 凯利公式:f = p - (1-p)/b(p=胜率, b=赔率)
65
+ - 止损/止盈位设定
66
+
67
+ ## 三、专家讨论模式(8人圆桌)
68
+
69
+ > 完整档案见 [experts/README.md](experts/README.md),每位专家独立成文(1200-1500 字深度档)。
70
+
71
+ ### 长线4人(价值发现)
72
+ | 专家 | 风格 | 核心逻辑 | 档案 |
73
+ |------|------|---------|------|
74
+ | 巴菲特 | 价值投资 | 好生意+好价格+长期持有,偏好高ROE低PE | [buffett.md](experts/buffett.md) |
75
+ | 彼得·林奇 | 成长投资 | PEG<1增速消化估值,偏好高增速合理PE | [lynch.md](experts/lynch.md) |
76
+ | 索罗斯 | 宏观/趋势 | 趋势确认+反身性,技术面+资金面 | [soros.md](experts/soros.md) |
77
+ | 段永平 | 逆向投资 | 好公司+安全边际,低估值+护城河 | [duan_yongping.md](experts/duan_yongping.md) |
78
+
79
+ ### 短线4人(时机把握)
80
+ | 专家 | 风格 | 核心逻辑 | 档案 |
81
+ |------|------|---------|------|
82
+ | 徐翔 | 涨停板战法 | 龙头+量价配合,打板追涨 | [xu_xiang.md](experts/xu_xiang.md) |
83
+ | 赵老哥 | 趋势龙头 | 趋势确认+持仓周期,波段操作 | [zhao_laoge.md](experts/zhao_laoge.md) |
84
+ | 炒股养家 | 情绪流 | 情绪周期+板块轮动,情绪拐点买卖 | [chaogu_yangjia.md](experts/chaogu_yangjia.md) |
85
+ | 作手新一 | 强势股低吸 | 回调到支撑位低吸,分批建仓 | [zuoshou_xinyi.md](experts/zuoshou_xinyi.md) |
86
+
87
+ ### 讨论流程
88
+ 1. 基本面数据呈现 → 共识
89
+ 2. 多空辩论 → 正方vs反方
90
+ 3. 操作方案对比 → 不同风格方案
91
+ 4. 投票汇总 → 多数决+少数保留
92
+ 5. 最终建议 → 折中方案+风险预案
93
+
94
+ ## 四、仓位管理
95
+
96
+ ### 凯利公式
97
+ ```
98
+ 最优仓位 f = p - (1-p)/b
99
+ p = 胜率, b = 赔率(期望收益/最大风险)
100
+ 调整后最优仓位 ≈ f × 0.5(安全系数)
101
+ ```
102
+
103
+ ### 仓位分级
104
+ | 仓位 | 含义 | 适用场景 |
105
+ |------|------|---------|
106
+ | 0% | 不碰 | 基本面差/估值过高 |
107
+ | 3% | 试探仓 | 等回调/方向不明 |
108
+ | 5% | 标准仓 | 确认买入信号 |
109
+ | 8% | 重仓 | 强烈看好+低位 |
110
+ | 10-15% | 核心仓 | 最强标的+安全边际充足 |
111
+
112
+ ### 集中度控制
113
+
114
+ | 约束项 | 上限 | 理由 |
115
+ | ------ | ---- | ---- |
116
+ | 单只个股 | 15% | 避免单一标的黑天鹅 |
117
+ | 单一行业 | 30% | 避免行业系统性风险 |
118
+ | 前 3 大持仓 | 45% | 保持适度分散 |
119
+ | 总仓位(牛市) | 90% | 保留 10% 现金应对波动 |
120
+ | 总仓位(震荡) | 70% | 保留 30% 现金 |
121
+ | 总仓位(熊市) | 50% | 保留 50% 现金 |
122
+
123
+ ### 止损铁律
124
+ - 个股:跌破关键支撑位收盘确认即止损
125
+ - 组合:单日亏损>3%减仓
126
+ - 板块:板块趋势转空减仓
127
+ - 时间止损:短线 5 个交易日无预期表现减仓 50%,中线 20 个交易日重新评估
128
+
129
+ ### 加仓规则
130
+ - 浮盈 > 10% 且趋势确认(MA 多头 + 量价配合):可加仓
131
+ - 每次加仓不超过原仓位的 50%
132
+ - 单只总仓位不超过 30%(含加仓)
133
+ - 加仓必须有新资金来源或减持其他标的
134
+
135
+ ### 极端情景预案
136
+ - 个股连续 2 个跌停:次日集合竞价挂跌停价卖出
137
+ - 组合单周亏损 > 10%:强制减仓至 50% 以下
138
+ - 全市场跌停 > 1000 家:暂停所有新开仓,等待流动性恢复
139
+
140
+ ## 五、决策流程
141
+
142
+ ```
143
+ 研究标的 → 基本面筛选(ROE/增速/毛利)
144
+ → 估值评估(PE/PEG)
145
+ → 技术面确认(支撑/趋势)
146
+ → 板块分析(轮动/风格)
147
+ → 专家讨论(多空辩论)
148
+ → 风险收益比计算
149
+ → 仓位决策(凯利公式)
150
+ → 建仓节奏(分批)
151
+ → 持续跟踪(止损/止盈)
152
+ ```
153
+
154
+ ### Skill 协作流程
155
+
156
+ 完整协作关系见 `workflow.md`。常用路径:
157
+
158
+ | 场景 | 推荐链路 |
159
+ |------|----------|
160
+ | 自上而下找机会 | `market` → `sector` → `screener` → `stock` → `technical` → `portfolio` |
161
+ | 已有个股做验证 | `stock` → `financial-analyst` → `sector` → `technical` → `portfolio` |
162
+ | 持仓再平衡 | `portfolio` → `market` → `technical` → `screener` → `stock` |
163
+ | 深度研究报告 | `investment-researcher` 总控,按需调用其他 skill |
164
+
165
+ 交接时至少保留:市场状态、板块观点、候选池、基本面评级、技术触发、仓位计划、置信度。
166
+
167
+ ## 六、选股策略系统
168
+
169
+ 选股系统不是“找一只马上买的股票”,而是生成可跟踪候选池。流程必须固定:股票池 → 硬过滤 → 多因子评分 → 策略权重 → 市场适配 → 买点触发。
170
+
171
+ ### 1. A 股市场约束
172
+
173
+ - 先识别市场板块:主板、创业板、科创板、北交所、ETF。不同板块波动制度不同,不能用同一套追涨风险假设。
174
+ - 普通 A 股交易以 T+1 为主,短线策略必须考虑隔夜风险和次日无法立即卖出的限制。
175
+ - 涨跌停附近的标的只进入观察池,不做机械追入;高分但流动性不足同样剔除。
176
+ - ST、退市风险、长期停牌、成交额过低、市值过小、财务亏损标的优先硬过滤。
177
+
178
+ ### 2. 股票池构建
179
+
180
+ | 股票池 | 用途 | 数据来源 |
181
+ |--------|------|----------|
182
+ | 内置板块池 | 快速筛主题/行业 | `data/sector_stocks.json` |
183
+ | ETF 映射池 | 判断板块强弱 | `data/sector_etf.csv` |
184
+ | 用户自定义池 | 精筛自选或持仓 | `--codes` 或持仓 JSON |
185
+ | 全市场池 | 后续扩展 | 需接入完整 A 股列表 |
186
+
187
+ ### 3. 硬过滤
188
+
189
+ | 过滤项 | 默认规则 | 理由 |
190
+ |--------|----------|------|
191
+ | ST/退市风险 | 名称含 ST 剔除 | 风险收益结构失真 |
192
+ | 成交额 | 低于 5000 万剔除 | 避免冲击成本和流动性陷阱 |
193
+ | 总市值 | 低于 40 亿剔除 | 避免壳、小票极端波动 |
194
+ | 盈利 | 可选剔除 EPS<=0 | 质量/价值策略必须盈利约束 |
195
+ | 涨跌停 | 降低动量分 | 当日可交易性差 |
196
+
197
+ ### 4. 多因子评分
198
+
199
+ | 因子 | 权重桶 | 指标 | 解释 |
200
+ |------|--------|------|------|
201
+ | 质量 | quality | ROE、净利增速、营收增速、毛利率、负债率、经营现金流/EPS | 好公司与盈利质量 |
202
+ | 估值 | valuation | PE、PB、PEG、PE/ROE | 安全边际和估值消化能力 |
203
+ | 动量 | momentum | 20 日收益、MA10/MA20、量能比、换手率 | 市场是否开始认可 |
204
+ | 流动性 | liquidity | 成交额、总市值、换手适中程度 | 能否交易、能否退出 |
205
+
206
+ ### 5. 策略权重
207
+
208
+ | 策略 | 市场环境 | 质量 | 估值 | 动量 | 流动性 |
209
+ |------|----------|------|------|------|--------|
210
+ | balanced | 震荡/方向不明 | 32% | 25% | 23% | 20% |
211
+ | quality_value | 价值修复/防守 | 42% | 32% | 10% | 16% |
212
+ | growth_momentum | 进攻行情/主线题材 | 26% | 12% | 42% | 20% |
213
+ | defensive | 缩量弱市/避险 | 38% | 34% | 8% | 20% |
214
+ | turning_point | 超跌修复/拐点 | 24% | 24% | 36% | 16% |
215
+
216
+ ### 6. 输出标准
217
+
218
+ 选股结果必须同时给出:
219
+
220
+ - 候选排名:总分 + 四因子分。
221
+ - 剔除原因:让“为什么没选”可审计。
222
+ - 市场适配:当前更适合进攻、均衡还是防守。
223
+ - 交易计划:买入触发、失效条件、止损/降仓、仓位上限。
224
+ - 后续跟踪:需要复核的财报、公告、板块 ETF、关键均线或支撑位。
225
+
226
+ ### 7. 脚本入口
227
+
228
+ ```bash
229
+ python3 scripts/screener.py --strategy balanced --top 10
230
+ python3 scripts/screener.py --sector 资源 --strategy quality_value --top 5
231
+ python3 scripts/screener.py --codes sh600989,sz000807,300476 --strategy growth_momentum
232
+ python3 scripts/screener.py --strategy defensive --exclude-loss --json
233
+ ```
234
+
235
+ ## 七、数据获取工具详解
236
+
237
+ ### 1. 腾讯实时行情 — 批量查询
238
+
239
+ **单只查询:**
240
+ ```bash
241
+ curl -s "https://qt.gtimg.cn/q=sh600989" | iconv -f GBK -t UTF-8
242
+ ```
243
+
244
+ **批量查询(最多约15只/次):**
245
+ ```bash
246
+ curl -s "https://qt.gtimg.cn/q=sh600989,sz000807,sh518880,sh603993" | iconv -f GBK -t UTF-8
247
+ ```
248
+
249
+ **编码注意:** 返回GBK编码,必须用 `iconv -f GBK -t UTF-8` 转码。
250
+
251
+ **代码前缀规则:**
252
+ - `sh` = 上海(60xxxx, 68xxxx)
253
+ - `sz` = 深圳(00xxxx, 30xxxx)
254
+
255
+ **字段解析(按~分隔,从0开始):**
256
+ | 字段位 | 含义 | 示例 |
257
+ |--------|------|------|
258
+ | 1 | 市场代码 | 1=沪, 51=深 |
259
+ | 2 | 代码 | 600989 |
260
+ | 3 | 名称 | 宝丰能源 |
261
+ | 4 | 当前价 | 24.59 |
262
+ | 5 | 昨收 | 24.92 |
263
+ | 33 | 涨跌幅% | -0.49 |
264
+ | 37 | 成交量(手) | 547985 |
265
+ | 38 | 成交额(万) | 134521 |
266
+ | 39 | 换手率% | 0.75 |
267
+ | 40 | PE(动) | 14.34 |
268
+
269
+ **提取脚本模式:**
270
+ ```bash
271
+ curl -s "https://qt.gtimg.cn/q=sh600989" | iconv -f GBK -t UTF-8 | tr ';' '\n' | while read line; do
272
+ name=$(echo "$line" | cut -d'~' -f3)
273
+ price=$(echo "$line" | cut -d'~' -f4)
274
+ change=$(echo "$line" | cut -d'~' -f33)
275
+ pe=$(echo "$line" | cut -d'~' -f40)
276
+ echo "$name | $price | 涨跌:${change}% | PE:$pe"
277
+ done
278
+ ```
279
+
280
+ ### 2. 东方财富财务数据 — JSON解析
281
+
282
+ **请求:**
283
+ ```bash
284
+ curl -s "https://emweb.securities.eastmoney.com/PC_HSF10/NewFinanceAnalysis/ZYZBAjaxNew?type=0&code=SH600989"
285
+ ```
286
+
287
+ **注意:** `code` 参数必须大写 `SH`/`SZ`。
288
+
289
+ **JSON结构:**
290
+ ```json
291
+ {
292
+ "data": [
293
+ {"EPSJB": 0.5, "ROEJQ": 7.28, "TOTALOPERATEREVETZ": 22.9, ...},
294
+ {"EPSJB": 1.56, "ROEJQ": 24.84, ...},
295
+ ...
296
+ ]
297
+ }
298
+ ```
299
+
300
+ **关键字段名(必须用这些,不是WEIGHTAVG_ROE等):**
301
+ | 字段 | 含义 | 示例值 |
302
+ |------|------|--------|
303
+ | EPSJB | 每股收益 | 0.5 |
304
+ | ROEJQ | ROE(加权) | 7.28 |
305
+ | TOTALOPERATEREVETZ | 营收同比增长% | 22.9 |
306
+ | PARENTNETPROFITTZ | 净利润同比增长% | 50.2 |
307
+ | XSMLL | 毛利率% | 37.4 |
308
+ | XSJLL | 净利率% | 27.7 |
309
+ | ZCFZL | 资产负债率% | 44.9 |
310
+ | BPS | 每股净资产 | 7.11 |
311
+ | MGJYXJJE | 每股经营现金流 | 0.76 |
312
+
313
+ **解析脚本(多季度):**
314
+ ```bash
315
+ curl -s "https://emweb.securities.eastmoney.com/PC_HSF10/NewFinanceAnalysis/ZYZBAjaxNew?type=0&code=SH600989" | python3 -c "
316
+ import json,sys
317
+ d=json.load(sys.stdin)
318
+ if d and 'data' in d and d['data']:
319
+ for r in d['data'][:4]:
320
+ print(f\"EPS: {r.get('EPSJB')}, ROE: {r.get('ROEJQ')}, 营收增长: {r.get('TOTALOPERATEREVETZ')}, 净利增长: {r.get('PARENTNETPROFITTZ')}\")
321
+ print(f\"毛利率: {r.get('XSMLL')}, 净利率: {r.get('XSJLL')}, 负债率: {r.get('ZCFZL')}\")
322
+ print()
323
+ " 2>/dev/null
324
+ ```
325
+
326
+ **已知坑:**
327
+ - `WEIGHTAVG_ROE`、`GROSSPROFITINRATIO`、`NETPROFITRATIO` 返回 None — 不要用
328
+ - 正确字段是 `ROEJQ`、`XSMLL`、`XSJLL`
329
+ - `data` 是数组,取 `[0]` 是最新一期,`[:4]` 是最近4期
330
+
331
+ ### 3. 新浪K线数据 — 多周期
332
+
333
+ **请求:**
334
+ ```bash
335
+ curl -s "https://money.finance.sina.com.cn/quotes_service/api/json_v2.php/CN_MarketData.getKLineData?symbol=sh600989&scale=240&ma=no&datalen=30"
336
+ ```
337
+
338
+ **参数:**
339
+ | 参数 | 含义 | 取值 |
340
+ |------|------|------|
341
+ | symbol | 股票代码 | sh600989 / sz000807 |
342
+ | scale | 周期(分钟) | 5=5分钟, 15=15分钟, 30=30分钟, 240=日K |
343
+ | ma | 均线 | no=不显示 |
344
+ | datalen | 数据条数 | 10/15/30/48 |
345
+
346
+ **JSON结构:**
347
+ ```json
348
+ [
349
+ {"day": "2026-05-29", "open": "24.60", "high": "24.70", "low": "24.00", "close": "24.00", "volume": "69178677"},
350
+ ...
351
+ ]
352
+ ```
353
+
354
+ **解析脚本:**
355
+ ```bash
356
+ curl -s "https://money.finance.sina.com.cn/quotes_service/api/json_v2.php/CN_MarketData.getKLineData?symbol=sh600989&scale=240&ma=no&datalen=30" | python3 -c "
357
+ import json,sys
358
+ data=json.load(sys.stdin)
359
+ for d in data[-10:]:
360
+ print(f\"{d['day']} | O:{d['open']} H:{d['high']} L:{d['low']} C:{d['close']} V:{d['volume']}\")
361
+ " 2>/dev/null
362
+ ```
363
+
364
+ **5分钟分时用途:**
365
+ - 分析日内走势(出货/吸筹/震荡)
366
+ - 识别支撑/阻力位
367
+ - 判断资金行为(放量杀跌/缩量横盘)
368
+
369
+ **日K用途:**
370
+ - 判断中期趋势
371
+ - 识别支撑/阻力位
372
+ - 成交量分析
373
+
374
+ ### 4. 批量操作模板
375
+
376
+ **批量获取财务数据:**
377
+ ```bash
378
+ for code in "SH600989" "SZ000807" "SH603993"; do
379
+ echo "=== $code ==="
380
+ curl -s "https://emweb.securities.eastmoney.com/PC_HSF10/NewFinanceAnalysis/ZYZBAjaxNew?type=0&code=$code" | python3 -c "
381
+ import json,sys
382
+ d=json.load(sys.stdin)
383
+ if d and 'data' in d and d['data']:
384
+ r=d['data'][0]
385
+ print(f\"EPS: {r.get('EPSJB')}, ROE: {r.get('ROEJQ')}, 营收增长: {r.get('TOTALOPERATEREVETZ')}, 净利增长: {r.get('PARENTNETPROFITTZ')}\")
386
+ " 2>/dev/null
387
+ done
388
+ ```
389
+
390
+ **批量K线对比:**
391
+ ```bash
392
+ for sym in "sh600989" "sz000807" "sh603993"; do
393
+ echo "=== $sym ==="
394
+ curl -s "https://money.finance.sina.com.cn/quotes_service/api/json_v2.php/CN_MarketData.getKLineData?symbol=$sym&scale=240&ma=no&datalen=10" | python3 -c "
395
+ import json,sys
396
+ data=json.load(sys.stdin)
397
+ for d in data[-5:]:
398
+ print(f\"{d['day']} | O:{d['open']} H:{d['high']} L:{d['low']} C:{d['close']} V:{d['volume']}\")
399
+ " 2>/dev/null
400
+ done
401
+ ```
402
+
403
+ **行情+解析一步到位:**
404
+ ```bash
405
+ curl -s "https://qt.gtimg.cn/q=sh600989,sz000807" | iconv -f GBK -t UTF-8 | tr ';' '\n' | while read line; do
406
+ if [ -n "$line" ]; then
407
+ name=$(echo "$line" | cut -d'~' -f3)
408
+ price=$(echo "$line" | cut -d'~' -f4)
409
+ change=$(echo "$line" | cut -d'~' -f33)
410
+ pe=$(echo "$line" | cut -d'~' -f40)
411
+ echo "$name | $price | 涨跌:${change}% | PE:$pe"
412
+ fi
413
+ done
414
+ ```
415
+
416
+ ### 5. 工具选择决策树
417
+
418
+ ```
419
+ 需要什么数据?
420
+ ├─ 实时行情/PE/涨跌 → 腾讯API(最快,支持批量)
421
+ ├─ 财务指标(ROE/增速/毛利) → 东方财富API(JSON,需解析)
422
+ ├─ K线走势/分时图 → 新浪API(支持多周期)
423
+ ├─ 板块对比 → 腾讯API + ETF代码
424
+ └─ 综合分析 → 三种API组合使用
425
+ ```
426
+
427
+ ### 6. 常见错误与解决
428
+
429
+ | 错误 | 原因 | 解决 |
430
+ |------|------|------|
431
+ | 中文乱码 | GBK编码未转换 | 加 `iconv -f GBK -t UTF-8` |
432
+ | 财务字段返回None | 字段名错误 | 用 ROEJQ 不用 WEIGHTAVG_ROE |
433
+ | JSON解析失败 | 返回空或格式错误 | 加 `2>/dev/null` + 判断 `d['data']` |
434
+ | K线数据为空 | symbol格式错误 | 检查 sh/sz 前缀 |
435
+ | 批量查询部分失败 | 超过API限制 | 分批查询,每批≤15只 |
436
+
437
+ ## 八、快捷启动命令
438
+
439
+ | 命令 | 用途 | 模式 |
440
+ |------|------|------|
441
+ | `/stock <标的> [quick\|full\|debate]` | 个股分析 | quick=3分钟, full=五层, debate=专家辩论 |
442
+ | `/portfolio [health\|rebalance\|compare]` | 持仓检查 | health=健康检查, rebalance=调仓, compare=对比 |
443
+ | `/market [full\|quick\|intraday]` | 大盘复盘 | full=完整, quick=快评, intraday=分时 |
444
+ | `/sector <板块> [overview\|compare\|stock]` | 板块分析 | overview=全景, compare=对比, stock=个股 |
445
+
446
+ ## 九、关键经验
447
+
448
+ 1. 不追高:PE>100时风险极大
449
+ 2. 板块轮动极快:不追轮动,持有核心仓位
450
+ 3. 关键支撑位需多次测试确认,不赌单次
451
+ 4. 仓位管理比选股重要
452
+ 5. 现金是最好的期权:震荡市中30%现金是优势
453
+ 6. 高赔率≠无风险:仍需止损纪律
454
+ 7. 防御仓位(黄金/低估值金融)是组合压舱石
455
+ 8. 科技仓位不能为零,至少5-8%
package/package.json ADDED
@@ -0,0 +1,43 @@
1
+ {
2
+ "name": "stock-analyzer-skill",
3
+ "version": "1.1.0",
4
+ "description": "A 股分析 skill 包,包含 8 个专业分析工具:单股分析、大盘复盘、板块分析、持仓检查、选股策略、技术分析、财务分析、投资研究",
5
+ "main": "index.js",
6
+ "scripts": {
7
+ "test": "./tests/smoke_test.sh",
8
+ "postinstall": "node install-plugin.js"
9
+ },
10
+ "keywords": [
11
+ "claude-code",
12
+ "stock",
13
+ "a-share",
14
+ "analysis",
15
+ "skills",
16
+ "investing",
17
+ "technical-analysis",
18
+ "fundamental-analysis"
19
+ ],
20
+ "author": {
21
+ "name": "curtis",
22
+ "email": "curtis@example.com"
23
+ },
24
+ "license": "MIT",
25
+ "repository": {
26
+ "type": "git",
27
+ "url": "https://github.com/curtis/stock-analyzer-skill.git"
28
+ },
29
+ "homepage": "https://github.com/curtis/stock-analyzer-skill",
30
+ "files": [
31
+ ".claude-plugin/",
32
+ "skills/",
33
+ "scripts/",
34
+ "data/",
35
+ "experts/",
36
+ "install-plugin.js",
37
+ "README.md",
38
+ "CONTRIBUTING.md",
39
+ "workflow.md",
40
+ "methodology.md",
41
+ "CHANGELOG.md"
42
+ ]
43
+ }
@@ -0,0 +1,118 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ 东方财富公告 + 研报。
4
+ 用法:
5
+ announcements.py 600989 # 最新公告
6
+ announcements.py 600989 reports # 券商研报
7
+ announcements.py 600989 -j # JSON
8
+ """
9
+ import sys
10
+ import json
11
+ from datetime import datetime, timedelta
12
+ from common import http_get, err, DataError, cache_key_for_stock, cache_get, cache_set
13
+
14
+ ANN_URL = "https://np-anotice-stock.eastmoney.com/api/security/ann?page_size=10&page_index=1&ann_type=A&stock_list={code}&f_node=0"
15
+ # 东方财富研报 API 需要 pageNo, beginTime, qType 参数
16
+ REPORT_URL = "https://reportapi.eastmoney.com/report/list?pageSize=10&pageNo=1&code={code}&beginTime={begin_time}&endTime={end_time}&qType=0"
17
+
18
+ def fetch_announcements(code: str, use_cache: bool = True) -> list:
19
+ """获取公告数据,支持缓存(TTL 30 分钟)。"""
20
+ key = cache_key_for_stock("ann", code)
21
+ if use_cache:
22
+ cached = cache_get(key, ttl_seconds=1800) # 30 分钟
23
+ if cached is not None:
24
+ try:
25
+ return json.loads(cached)
26
+ except json.JSONDecodeError:
27
+ pass
28
+
29
+ raw = http_get(ANN_URL.format(code=code))
30
+ try:
31
+ data = json.loads(raw)
32
+ result = data.get("data", {}).get("list", [])
33
+ if use_cache and result:
34
+ cache_set(key, json.dumps(result, ensure_ascii=False).encode())
35
+ return result
36
+ except json.JSONDecodeError:
37
+ return []
38
+
39
+ def fetch_reports(code: str, use_cache: bool = True) -> list:
40
+ """获取研报数据,支持缓存(TTL 1 小时)。"""
41
+ key = cache_key_for_stock("report", code)
42
+ if use_cache:
43
+ cached = cache_get(key, ttl_seconds=3600) # 1 小时
44
+ if cached is not None:
45
+ try:
46
+ return json.loads(cached)
47
+ except json.JSONDecodeError:
48
+ pass
49
+
50
+ # 计算时间范围:最近 1 年
51
+ end_date = datetime.now()
52
+ begin_date = end_date - timedelta(days=365)
53
+ begin_time = begin_date.strftime("%Y-%m-%d")
54
+ end_time = end_date.strftime("%Y-%m-%d")
55
+
56
+ url = REPORT_URL.format(code=code, begin_time=begin_time, end_time=end_time)
57
+ raw = http_get(url)
58
+ try:
59
+ data = json.loads(raw)
60
+ # API 返回 {"hits": N, "data": [...], ...} 结构
61
+ result = data.get("data", []) if isinstance(data, dict) else []
62
+ if use_cache and result:
63
+ cache_set(key, json.dumps(result, ensure_ascii=False).encode())
64
+ return result
65
+ except json.JSONDecodeError:
66
+ return []
67
+
68
+ def render_announcements(items: list) -> str:
69
+ if not items:
70
+ return "(无公告)"
71
+ lines = []
72
+ for it in items[:10]:
73
+ title = it.get("title", "").strip()
74
+ date = it.get("notice_date", "")[:10] or it.get("notice_time", "")[:10]
75
+ lines.append(f"{date} | {title}")
76
+ return "\n".join(lines)
77
+
78
+ def render_reports(items: list) -> str:
79
+ if not items:
80
+ return "(无研报)"
81
+ lines = []
82
+ for it in items[:10]:
83
+ title = it.get("title", "").strip()
84
+ org = it.get("orgSName", "")
85
+ date = it.get("publishDate", "")[:10]
86
+ rating = it.get("infoCode", "") # 简化
87
+ lines.append(f"{date} | {org} | {title}")
88
+ return "\n".join(lines)
89
+
90
+ def main():
91
+ if len(sys.argv) < 2:
92
+ err("用法: announcements.py <代码> [reports] [-j]")
93
+ args = sys.argv[1:]
94
+ json_mode = "-j" in args
95
+ args = [a for a in args if a != "-j"]
96
+ code = args[0]
97
+ mode = args[1] if len(args) > 1 else "announcements"
98
+
99
+ if mode == "reports":
100
+ data = fetch_reports(code)
101
+ if json_mode:
102
+ print(json.dumps(data, ensure_ascii=False, indent=2))
103
+ else:
104
+ print(f"\n=== 研报 {code} ===")
105
+ print(render_reports(data))
106
+ else:
107
+ data = fetch_announcements(code)
108
+ if json_mode:
109
+ print(json.dumps(data, ensure_ascii=False, indent=2))
110
+ else:
111
+ print(f"\n=== 公告 {code} ===")
112
+ print(render_announcements(data))
113
+
114
+ if __name__ == "__main__":
115
+ try:
116
+ main()
117
+ except DataError as e:
118
+ sys.exit(1)