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,328 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ 股票池自动刷新脚本 — 从东财 push2 API 拉取板块成分股。
4
+
5
+ 用法:
6
+ python3 scripts/refresh_pool.py # 刷新全部板块
7
+ python3 scripts/refresh_pool.py --sector 机器人 # 只刷新指定板块
8
+ python3 scripts/refresh_pool.py --top 30 # 每板块取 Top 30
9
+ python3 scripts/refresh_pool.py --sort cap # 按市值排序(默认 amount)
10
+ python3 scripts/refresh_pool.py --dry-run # 只打印不写入
11
+ python3 scripts/refresh_pool.py --diff # 对比当前池显示变更
12
+
13
+ 数据源: 东财 push2.eastmoney.com 板块成分股 API
14
+ """
15
+
16
+ import argparse
17
+ import json
18
+ import os
19
+ import sys
20
+ import time
21
+ from datetime import datetime
22
+
23
+ # 复用 common.py 的 HTTP 和编码工具
24
+ sys.path.insert(0, os.path.dirname(__file__))
25
+ from common import http_get_cached, normalize_quote_code, board_type
26
+
27
+ # ---------- 常量 ----------
28
+
29
+ SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
30
+ DATA_DIR = os.path.join(SCRIPT_DIR, "data")
31
+ MAPPING_FILE = os.path.join(DATA_DIR, "sector_mapping.json")
32
+ POOL_FILE = os.path.join(DATA_DIR, "sector_stocks.json")
33
+
34
+ API_BASE = "https://push2.eastmoney.com/api/qt/clist/get"
35
+ API_TOKEN = os.environ.get("EASTMONEY_API_TOKEN", "")
36
+ if not API_TOKEN:
37
+ print("警告: 未设置 EASTMONEY_API_TOKEN 环境变量,refresh_pool 功能不可用", file=sys.stderr)
38
+ FIELDS = "f12,f14,f2,f3,f6,f8,f9,f20" # code,name,price,chg%,amount,turnover,pe,cap
39
+
40
+ # 硬过滤阈值
41
+ FILTER = {
42
+ "min_amount": {"主板": 5000, "创业板": 3500, "科创板": 3500, "北交所": 7500}, # 万元
43
+ "min_cap": {"主板": 40, "创业板": 24, "科创板": 24, "北交所": 16}, # 亿元
44
+ }
45
+
46
+
47
+ # ---------- API 调用 ----------
48
+
49
+ def fetch_board_stocks(bk_code: str, max_retries: int = 2) -> list[dict]:
50
+ """获取板块成分股,返回 [{code, name, price, change_pct, amount, turnover, pe, cap}]"""
51
+ url = (
52
+ f"{API_BASE}?pn=1&pz=500&np=1&ut={API_TOKEN}"
53
+ f"&fltt=2&invt=2&fid=f3&fs=b:{bk_code}&fields={FIELDS}"
54
+ )
55
+ for attempt in range(max_retries + 1):
56
+ try:
57
+ raw = http_get_cached(url, ttl=3600) # 缓存 1 小时
58
+ data = json.loads(raw)
59
+ if not data or "data" not in data or not data["data"]:
60
+ return []
61
+ items = data["data"].get("diff", [])
62
+ results = []
63
+ for item in items:
64
+ code6 = str(item.get("f12", ""))
65
+ if not code6 or len(code6) != 6:
66
+ continue
67
+ # 推断交易所前缀
68
+ if code6.startswith(("6",)):
69
+ full_code = f"sh{code6}"
70
+ elif code6.startswith(("0", "3")):
71
+ full_code = f"sz{code6}"
72
+ elif code6.startswith(("4", "8")):
73
+ full_code = f"bj{code6}"
74
+ else:
75
+ full_code = f"sz{code6}"
76
+ results.append({
77
+ "code": full_code,
78
+ "name": item.get("f14", ""),
79
+ "price": item.get("f2"),
80
+ "change_pct": item.get("f3"),
81
+ "amount": item.get("f6"), # 成交额(元)
82
+ "turnover": item.get("f8"), # 换手率
83
+ "pe": item.get("f9"), # PE(动)
84
+ "cap": item.get("f20"), # 总市值(元)
85
+ })
86
+ return results
87
+ except Exception as e:
88
+ if attempt < max_retries:
89
+ time.sleep(1)
90
+ continue
91
+ print(f" ⚠ API 请求失败 ({bk_code}): {e}", file=sys.stderr)
92
+ return []
93
+
94
+
95
+ def fetch_multiple_boards(bk_codes: list[str]) -> list[dict]:
96
+ """合并多个板块的成分股,去重"""
97
+ seen = {}
98
+ for bk in bk_codes:
99
+ stocks = fetch_board_stocks(bk)
100
+ for s in stocks:
101
+ if s["code"] not in seen:
102
+ seen[s["code"]] = s
103
+ time.sleep(0.5) # 限流
104
+ return list(seen.values())
105
+
106
+
107
+ # ---------- 过滤 ----------
108
+
109
+ def is_st(name: str) -> bool:
110
+ return "ST" in name.upper() or "*ST" in name
111
+
112
+
113
+ def passes_filter(stock: dict) -> tuple[bool, str]:
114
+ """硬过滤,返回 (通过, 原因)"""
115
+ name = stock.get("name", "")
116
+ code = stock.get("code", "")
117
+ bt = board_type(code)
118
+
119
+ if is_st(name):
120
+ return False, "ST"
121
+
122
+ amount = stock.get("amount")
123
+ if amount is not None:
124
+ amount_wan = amount / 10000 # 元→万元
125
+ min_amt = FILTER["min_amount"].get(bt, 5000)
126
+ if amount_wan < min_amt:
127
+ return False, f"成交额{amount_wan:.0f}万<{min_amt}万"
128
+
129
+ cap = stock.get("cap")
130
+ if cap is not None:
131
+ cap_yi = cap / 100000000 # 元→亿元
132
+ min_cap = FILTER["min_cap"].get(bt, 40)
133
+ if cap_yi < min_cap:
134
+ return False, f"市值{cap_yi:.0f}亿<{min_cap}亿"
135
+
136
+ return True, ""
137
+
138
+
139
+ # ---------- 排序与筛选 ----------
140
+
141
+ def sort_stocks(stocks: list[dict], key: str = "amount") -> list[dict]:
142
+ """排序,降序"""
143
+ keys = {
144
+ "amount": lambda s: s.get("amount") or 0,
145
+ "cap": lambda s: s.get("cap") or 0,
146
+ "pe": lambda s: s.get("pe") or 9999,
147
+ "turnover": lambda s: s.get("turnover") or 0,
148
+ }
149
+ return sorted(stocks, key=keys.get(key, keys["amount"]), reverse=True)
150
+
151
+
152
+ def build_sector_pool(stocks: list[dict], top_n: int = 20, sort_by: str = "amount") -> list[str]:
153
+ """过滤+排序+截取,返回代码列表"""
154
+ filtered = []
155
+ reasons = {}
156
+ for s in stocks:
157
+ ok, reason = passes_filter(s)
158
+ if ok:
159
+ filtered.append(s)
160
+ else:
161
+ reasons[s["code"]] = reason
162
+
163
+ sorted_stocks = sort_stocks(filtered, sort_by)
164
+ return [s["code"] for s in sorted_stocks[:top_n]]
165
+
166
+
167
+ # ---------- 高股息特殊处理 ----------
168
+
169
+ def build_dividend_pool(all_pools: dict[str, list[str]], all_stocks: dict[str, dict]) -> list[str]:
170
+ """从所有板块中筛选 PE<20 且 ROE>8% 的标的"""
171
+ candidates = []
172
+ seen = set()
173
+ for sector, codes in all_pools.items():
174
+ if sector == "高股息":
175
+ continue
176
+ for code in codes:
177
+ if code in seen:
178
+ continue
179
+ seen.add(code)
180
+ s = all_stocks.get(code, {})
181
+ pe = s.get("pe")
182
+ # ROE 需要额外查询,这里用 PE 作为第一轮筛选
183
+ if pe is not None and 0 < pe < 20:
184
+ candidates.append(s)
185
+ # 按成交额排序取 Top 15
186
+ sorted_c = sort_stocks(candidates, "amount")
187
+ return [s["code"] for s in sorted_c[:20]]
188
+
189
+
190
+ # ---------- 主流程 ----------
191
+
192
+ def load_mapping() -> dict:
193
+ with open(MAPPING_FILE, "r", encoding="utf-8") as f:
194
+ return json.load(f)
195
+
196
+
197
+ def load_current_pool() -> dict:
198
+ if not os.path.exists(POOL_FILE):
199
+ return {}
200
+ with open(POOL_FILE, "r", encoding="utf-8") as f:
201
+ data = json.load(f)
202
+ return {k: v for k, v in data.items() if not k.startswith("_")}
203
+
204
+
205
+ def refresh_pool(sectors: list[str] | None = None, top_n: int = 20,
206
+ sort_by: str = "amount", dry_run: bool = False,
207
+ show_diff: bool = False) -> dict:
208
+ """刷新股票池,返回新池"""
209
+ mapping = load_mapping()
210
+ current = load_current_pool()
211
+
212
+ target_sectors = sectors or [k for k in mapping if not k.startswith("_")]
213
+ new_pool = dict(current) # 以当前池为基础,只更新目标板块
214
+ all_stocks_raw = {} # code → stock dict,用于高股息筛选
215
+
216
+ for sector in target_sectors:
217
+ if sector not in mapping:
218
+ print(f"⚠ 板块 '{sector}' 不在映射配置中,跳过", file=sys.stderr)
219
+ continue
220
+
221
+ cfg = mapping[sector]
222
+ bk_codes = cfg.get("bk_codes", [])
223
+
224
+ if cfg.get("filter") == "dividend":
225
+ # 高股息板块延迟处理
226
+ continue
227
+
228
+ if not bk_codes:
229
+ print(f"⚠ 板块 '{sector}' 无 BK 代码,跳过", file=sys.stderr)
230
+ continue
231
+
232
+ print(f"📡 获取 {sector} ({', '.join(bk_codes)})...", end=" ", flush=True)
233
+ stocks = fetch_multiple_boards(bk_codes)
234
+ print(f"{len(stocks)} 只原始")
235
+
236
+ if stocks:
237
+ pool = build_sector_pool(stocks, top_n, sort_by)
238
+ new_pool[sector] = pool
239
+ elif sector in current:
240
+ new_pool[sector] = current[sector]
241
+ print(f" ⚠ API 失败,保留现有 {len(current[sector])} 只")
242
+
243
+ # 保存原始数据供高股息筛选
244
+ for s in stocks:
245
+ all_stocks_raw[s["code"]] = s
246
+
247
+ time.sleep(0.3)
248
+
249
+ # 高股息板块
250
+ if "高股息" in target_sectors and "高股息" in mapping:
251
+ if all_stocks_raw:
252
+ dividend_pool = build_dividend_pool(new_pool, all_stocks_raw)
253
+ new_pool["高股息"] = dividend_pool
254
+ print(f"📡 高股息: 从 {len(all_stocks_raw)} 只中筛选 {len(dividend_pool)} 只")
255
+
256
+ # 对比
257
+ if show_diff:
258
+ print_diff(current, new_pool)
259
+
260
+ # 写入
261
+ if not dry_run and new_pool:
262
+ output = {
263
+ "_meta": {
264
+ "updated": datetime.now().strftime("%Y-%m-%dT%H:%M:%S"),
265
+ "source": "eastmoney_push2",
266
+ "total_sectors": len(new_pool),
267
+ "total_stocks": sum(len(v) for v in new_pool.values()),
268
+ }
269
+ }
270
+ output.update(new_pool)
271
+ with open(POOL_FILE, "w", encoding="utf-8") as f:
272
+ json.dump(output, f, ensure_ascii=False, indent=2)
273
+ print(f"\n✅ 已写入 {POOL_FILE} ({output['_meta']['total_stocks']} 只)")
274
+ elif dry_run:
275
+ print(f"\n📋 dry-run 模式,未写入")
276
+
277
+ return new_pool
278
+
279
+
280
+ def print_diff(current: dict, new_pool: dict):
281
+ """打印新旧池对比"""
282
+ print("\n" + "=" * 60)
283
+ print("📊 股票池变更对比")
284
+ print("=" * 60)
285
+
286
+ all_sectors = sorted(set(list(current.keys()) + list(new_pool.keys())))
287
+
288
+ for sector in all_sectors:
289
+ old = set(current.get(sector, []))
290
+ new = set(new_pool.get(sector, []))
291
+ added = new - old
292
+ removed = old - new
293
+ if not added and not removed:
294
+ continue
295
+ print(f"\n【{sector}】")
296
+ if added:
297
+ print(f" + 新增 {len(added)}: {', '.join(sorted(added))}")
298
+ if removed:
299
+ print(f" - 移除 {len(removed)}: {', '.join(sorted(removed))}")
300
+
301
+ total_old = sum(len(v) for v in current.values())
302
+ total_new = sum(len(v) for v in new_pool.values())
303
+ print(f"\n总计: {total_old} → {total_new} ({total_new - total_old:+d})")
304
+
305
+
306
+ # ---------- CLI ----------
307
+
308
+ def main():
309
+ parser = argparse.ArgumentParser(description="股票池自动刷新")
310
+ parser.add_argument("--sector", "-s", nargs="+", help="只刷新指定板块")
311
+ parser.add_argument("--top", "-n", type=int, default=20, help="每板块取 Top N(默认 20)")
312
+ parser.add_argument("--sort", choices=["amount", "cap", "pe", "turnover"],
313
+ default="amount", help="排序方式(默认 amount 成交额)")
314
+ parser.add_argument("--dry-run", action="store_true", help="只打印不写入")
315
+ parser.add_argument("--diff", action="store_true", help="对比当前池显示变更")
316
+ args = parser.parse_args()
317
+
318
+ refresh_pool(
319
+ sectors=args.sector,
320
+ top_n=args.top,
321
+ sort_by=args.sort,
322
+ dry_run=args.dry_run,
323
+ show_diff=args.diff,
324
+ )
325
+
326
+
327
+ if __name__ == "__main__":
328
+ main()