Skip to content

Commit b14c8a7

Browse files
yjwyjw
authored andcommitted
Release young-stock-cli 0.3.8
1 parent bd68b8f commit b14c8a7

7 files changed

Lines changed: 36 additions & 11 deletions

File tree

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
# Changelog
22

3+
## [0.3.8] - 2026-06-24
4+
5+
### Fixed
6+
7+
- Use Chinese expert display names in Chinese `--lens` report title and holding-advice headings, for example `巴菲特持仓建议与风险提示` instead of `Buffett持仓建议与风险提示`.
8+
39
## [0.3.7] - 2026-06-24
410

511
### Fixed

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
44

55
[project]
66
name = "young-stock-cli"
7-
version = "0.3.7"
7+
version = "0.3.8"
88
description = "A-share (China stock market) after-hours CLI — no login, no scraping tricks, just data."
99
readme = "README.md"
1010
requires-python = ">=3.9"

src/young_stock/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
"""young-stock-cli: A-share after-hours CLI."""
22

3-
__version__ = "0.3.7"
3+
__version__ = "0.3.8"

src/young_stock/_core.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2309,7 +2309,7 @@ def futu_news_search(keyword: str, size: int = 10, lang: str = "en", news_type:
23092309
})
23102310
url = f"{FUTU_NEWS_URL}?{params}"
23112311
try:
2312-
req = urllib.request.Request(url, headers={"User-Agent": "young-stock-cli/0.3.7"})
2312+
req = urllib.request.Request(url, headers={"User-Agent": "young-stock-cli/0.3.8"})
23132313
with urllib.request.urlopen(req, timeout=10) as resp:
23142314
return json.loads(resp.read().decode())
23152315
except Exception as e:
@@ -2322,7 +2322,7 @@ def futu_stock_feed(keyword: str, size: int = 30) -> dict[str, Any]:
23222322
params = urllib.parse.urlencode({"keyword": keyword, "size": size})
23232323
url = f"{FUTU_FEED_URL}?{params}"
23242324
try:
2325-
req = urllib.request.Request(url, headers={"User-Agent": "young-stock-cli/0.3.7"})
2325+
req = urllib.request.Request(url, headers={"User-Agent": "young-stock-cli/0.3.8"})
23262326
with urllib.request.urlopen(req, timeout=10) as resp:
23272327
return json.loads(resp.read().decode())
23282328
except Exception as e:

src/young_stock/lens/registry.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
class LensDefinition:
1010
id: str
1111
name: str
12+
zh_name: str
1213
school: str
1314
summary: str
1415
voice: str
@@ -33,6 +34,7 @@ def chat_profile(self) -> dict[str, str]:
3334
LensDefinition(
3435
"buffett",
3536
"Buffett",
37+
"巴菲特",
3638
"价值",
3739
"重商业质量、护城河、管理层、资本配置与安全边际。",
3840
"长期主义、朴素直接、少术语,像在和股东通信",
@@ -42,6 +44,7 @@ def chat_profile(self) -> dict[str, str]:
4244
LensDefinition(
4345
"munger",
4446
"Munger",
47+
"芒格",
4548
"价值",
4649
"用多元思维模型、反向思考、激励与错配检查。",
4750
"犀利、直白、强调思维模型",
@@ -51,6 +54,7 @@ def chat_profile(self) -> dict[str, str]:
5154
LensDefinition(
5255
"graham",
5356
"Graham",
57+
"格雷厄姆",
5458
"价值",
5559
"重资产负债表、盈利稳定性、估值纪律与下行保护。",
5660
"审慎、克制、偏教科书式",
@@ -60,6 +64,7 @@ def chat_profile(self) -> dict[str, str]:
6064
LensDefinition(
6165
"klarman",
6266
"Klarman",
67+
"卡拉曼",
6368
"价值",
6469
"重绝对回报、复杂性折价、催化剂和永久损失风险。",
6570
"耐心、逆向、强调风险先于收益",
@@ -69,6 +74,7 @@ def chat_profile(self) -> dict[str, str]:
6974
LensDefinition(
7075
"lynch",
7176
"Lynch",
77+
"彼得·林奇",
7278
"成长",
7379
"从可理解的增长故事出发,用盈利兑现检验叙事。",
7480
"生动、务实、贴近普通投资者观察",
@@ -78,6 +84,7 @@ def chat_profile(self) -> dict[str, str]:
7884
LensDefinition(
7985
"o_neil",
8086
"O'Neil",
87+
"欧奈尔",
8188
"成长",
8289
"关注盈利加速、行业龙头、机构需求与价格强度。",
8390
"果断、规则化、尊重市场确认",
@@ -87,6 +94,7 @@ def chat_profile(self) -> dict[str, str]:
8794
LensDefinition(
8895
"wood",
8996
"Wood",
97+
"伍德",
9098
"成长",
9199
"关注颠覆式创新、长期渗透率和技术成本曲线。",
92100
"前瞻、主题驱动、明确承认高波动",
@@ -96,6 +104,7 @@ def chat_profile(self) -> dict[str, str]:
96104
LensDefinition(
97105
"dalio",
98106
"Dalio",
107+
"达利欧",
99108
"宏观",
100109
"重宏观周期、情景分析、分散化与风险平衡。",
101110
"原则导向、结构化、偏桥水备忘录式",
@@ -105,6 +114,7 @@ def chat_profile(self) -> dict[str, str]:
105114
LensDefinition(
106115
"soros",
107116
"Soros",
117+
"索罗斯",
108118
"宏观",
109119
"关注反身性、预期差、政策拐点和仓位非对称性。",
110120
"敏锐、假设驱动、随证据快速修正",
@@ -114,6 +124,7 @@ def chat_profile(self) -> dict[str, str]:
114124
LensDefinition(
115125
"livermore",
116126
"Livermore",
127+
"利弗莫尔",
117128
"技术/交易",
118129
"顺势而为,等待关键点确认并把风险控制放在第一位。",
119130
"简洁、纪律化、少预测多确认",
@@ -123,6 +134,7 @@ def chat_profile(self) -> dict[str, str]:
123134
LensDefinition(
124135
"minervini",
125136
"Minervini",
137+
"米勒维尼",
126138
"技术/交易",
127139
"用趋势模板、盈利加速和风险收益比筛选强势股。",
128140
"精确、规则化、强调入场质量",
@@ -132,6 +144,7 @@ def chat_profile(self) -> dict[str, str]:
132144
LensDefinition(
133145
"simons",
134146
"Simons",
147+
"西蒙斯",
135148
"量化",
136149
"关注数据定义、可重复信号、样本外稳健性和交易成本。",
137150
"冷静、概率化、避免故事替代统计",
@@ -141,6 +154,7 @@ def chat_profile(self) -> dict[str, str]:
141154
LensDefinition(
142155
"duan_yongping",
143156
"段永平",
157+
"段永平",
144158
"中国视角",
145159
"重本分、商业模式、企业文化、长期现金创造与合理价格。",
146160
"朴实、耐心、从消费者与经营者角度思考",
@@ -150,6 +164,7 @@ def chat_profile(self) -> dict[str, str]:
150164
LensDefinition(
151165
"zhang_kun",
152166
"张坤",
167+
"张坤",
153168
"中国视角",
154169
"关注高质量商业模式、长期自由现金流和组合机会成本。",
155170
"克制、长期、重定性与定量互证",
@@ -159,6 +174,7 @@ def chat_profile(self) -> dict[str, str]:
159174
LensDefinition(
160175
"feng_liu",
161176
"冯柳",
177+
"冯柳",
162178
"中国视角",
163179
"从市场认知、赔率、困境反转和可验证变化寻找机会。",
164180
"逆向、重赔率、尊重市场已有认知",

src/young_stock/reports.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -112,11 +112,13 @@
112112
def _llm_report_structure_prompt(lens: str | None) -> str:
113113
if not lens or lens in {"balanced", "all"}:
114114
return LLM_REPORT_STRUCTURE_PROMPT
115-
lens_name = get_lens(lens).name
115+
lens_def = get_lens(lens)
116+
lens_name = lens_def.zh_name
116117
return (
117118
LLM_REPORT_STRUCTURE_PROMPT
118119
+ "\n"
119-
+ f"本次指定专家视角为 {lens_name}:一级标题必须包含“{lens_name}”;"
120+
+ f"本次指定专家视角为 {lens_def.name};中文报告使用“{lens_name}”。"
121+
+ f"一级标题必须包含“{lens_name}”;"
120122
+ f"最后一个二级标题必须写成“## {lens_name}持仓建议与风险提示”,"
121123
+ "不要再使用“## 综合持仓建议与风险提示”。"
122124
)

tests/test_llm_reports.py

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -170,23 +170,24 @@ def test_llm_report_with_explicit_balanced_lens_uses_institutional_prompt(monkey
170170
assert metadata["debate_rounds"] == 0
171171

172172

173-
def test_llm_report_with_specific_lens_names_expert_in_title_and_advice_heading():
173+
def test_llm_report_with_specific_lens_uses_chinese_expert_name_for_chinese_reports():
174174
client = RecordingClient(
175-
"# Buffett复盘\n\n"
175+
"# 巴菲特复盘\n\n"
176176
"投资评级:持有观察。\n"
177177
"详细结论:据公开市场数据,仍以震荡观察为主。\n"
178178
"证据:证据暂缺。\n"
179179
"风险:量能不足。\n"
180180
"行动建议:等待确认,不追高。\n"
181181
"观察清单:跟踪下一交易日成交额。\n\n"
182-
"## Buffett持仓建议与风险提示\n"
182+
"## 巴菲特持仓建议与风险提示\n"
183183
)
184184

185185
generate_llm_daily_report({"modules": {}, "_meta": {}}, client, lens="buffett")
186186

187187
system_text = "\n".join(message["content"] for message in client.messages if message["role"] == "system")
188-
assert "一级标题必须包含“Buffett”" in system_text
189-
assert "## Buffett持仓建议与风险提示" in system_text
188+
assert "中文报告使用“巴菲特”" in system_text
189+
assert "一级标题必须包含“巴菲特”" in system_text
190+
assert "## 巴菲特持仓建议与风险提示" in system_text
190191
assert "不要再使用“## 综合持仓建议与风险提示”" in system_text
191192

192193

0 commit comments

Comments
 (0)