stock-analyzer-skill 1.1.0 → 1.2.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.
- package/CHANGELOG.md +36 -0
- package/README.md +110 -39
- package/data/reports/202506_Stock_Analysis_Summary.md +271 -0
- package/experts/README.md +23 -2
- package/experts/buffett.md +44 -1
- package/experts/chaogu_yangjia.md +50 -0
- package/experts/decide.md +54 -2
- package/experts/duan_yongping.md +45 -0
- package/experts/lynch.md +48 -1
- package/experts/soros.md +43 -0
- package/experts/xu_xiang.md +44 -0
- package/experts/zhao_laoge.md +53 -0
- package/experts/zuoshou_xinyi.md +66 -0
- package/methodology.md +313 -13
- package/package.json +1 -1
- package/scripts/__pycache__/screener.cpython-314.pyc +0 -0
- package/scripts/api/__init__.py +22 -0
- package/scripts/api/__pycache__/__init__.cpython-314.pyc +0 -0
- package/scripts/api/__pycache__/quote_cli.cpython-314.pyc +0 -0
- package/scripts/api/__pycache__/screener_cli.cpython-314.pyc +0 -0
- package/scripts/api/quote_cli.py +106 -0
- package/scripts/api/screener_cli.py +149 -0
- package/scripts/business/__init__.py +15 -0
- package/scripts/business/__pycache__/__init__.cpython-314.pyc +0 -0
- package/scripts/business/__pycache__/screening_service.cpython-314.pyc +0 -0
- package/scripts/business/__pycache__/stock_analysis.cpython-314.pyc +0 -0
- package/scripts/business/screening_service.py +267 -0
- package/scripts/business/stock_analysis.py +183 -0
- package/scripts/common/__init__.py +334 -0
- package/scripts/common/__pycache__/__init__.cpython-314.pyc +0 -0
- package/scripts/common/__pycache__/http.cpython-314.pyc +0 -0
- package/scripts/common/__pycache__/parsers.cpython-314.pyc +0 -0
- package/scripts/common/__pycache__/utils.cpython-314.pyc +0 -0
- package/scripts/common/__pycache__/validators.cpython-314.pyc +0 -0
- package/scripts/common/exceptions/__init__.py +172 -0
- package/scripts/common/exceptions/__pycache__/__init__.cpython-314.pyc +0 -0
- package/scripts/common/http.py +79 -0
- package/scripts/common/metrics.py +92 -0
- package/scripts/common/parsers.py +125 -0
- package/scripts/common/utils.py +195 -0
- package/scripts/common/validators.py +219 -0
- package/scripts/config/__init__.py +24 -0
- package/scripts/config/__pycache__/__init__.cpython-314.pyc +0 -0
- package/scripts/config/__pycache__/loader.cpython-314.pyc +0 -0
- package/scripts/config/data_source.yaml +126 -0
- package/scripts/config/industry_thresholds.yaml +158 -0
- package/scripts/config/limits.yaml +48 -0
- package/scripts/config/loader.py +141 -0
- package/scripts/config/notification.yaml +57 -0
- package/scripts/config/scoring.yaml +159 -0
- package/scripts/data/__pycache__/config.cpython-314.pyc +0 -0
- package/scripts/data/__pycache__/types.cpython-314.pyc +0 -0
- package/scripts/data/config.py +56 -4
- package/scripts/data/portfolio.json +100 -0
- package/scripts/data/portfolio_example.json +66 -11
- package/scripts/data/sector_stocks.json +244 -80
- package/scripts/data/types.py +3 -3
- package/scripts/fetchers/__init__.py +54 -0
- package/scripts/fetchers/__pycache__/__init__.cpython-314.pyc +0 -0
- package/scripts/fetchers/__pycache__/akshare_quote.cpython-314.pyc +0 -0
- package/scripts/fetchers/__pycache__/eastmoney_event.cpython-314.pyc +0 -0
- package/scripts/fetchers/__pycache__/eastmoney_flow.cpython-314.pyc +0 -0
- package/scripts/fetchers/__pycache__/eastmoney_lhb.cpython-314.pyc +0 -0
- package/scripts/fetchers/__pycache__/eastmoney_quote.cpython-314.pyc +0 -0
- package/scripts/fetchers/__pycache__/efinance_quote.cpython-314.pyc +0 -0
- package/scripts/fetchers/__pycache__/sina_quote.cpython-314.pyc +0 -0
- package/scripts/fetchers/__pycache__/tencent_quote.cpython-314.pyc +0 -0
- package/scripts/fetchers/akshare_quote.py +17 -3
- package/scripts/fetchers/eastmoney_event.py +148 -0
- package/scripts/fetchers/eastmoney_flow.py +118 -0
- package/scripts/fetchers/eastmoney_lhb.py +134 -0
- package/scripts/fetchers/eastmoney_quote.py +3 -3
- package/scripts/fetchers/efinance_quote.py +17 -3
- package/scripts/fetchers/sina_quote.py +5 -9
- package/scripts/fetchers/tencent_quote.py +3 -1
- package/scripts/monitor/__init__.py +13 -0
- package/scripts/monitor/__pycache__/__init__.cpython-314.pyc +0 -0
- package/scripts/monitor/__pycache__/manager.cpython-314.pyc +0 -0
- package/scripts/monitor/channels/__init__.py +6 -0
- package/scripts/monitor/channels/__pycache__/__init__.cpython-314.pyc +0 -0
- package/scripts/monitor/channels/__pycache__/bark.cpython-314.pyc +0 -0
- package/scripts/monitor/channels/__pycache__/base.cpython-314.pyc +0 -0
- package/scripts/monitor/channels/bark.py +75 -0
- package/scripts/monitor/channels/base.py +36 -0
- package/scripts/monitor/health.py +148 -0
- package/scripts/monitor/manager.py +229 -0
- package/scripts/portfolio/__init__.py +13 -0
- package/scripts/portfolio/__pycache__/__init__.cpython-314.pyc +0 -0
- package/scripts/portfolio/__pycache__/manager.cpython-314.pyc +0 -0
- package/scripts/portfolio/manager.py +329 -0
- package/scripts/portfolio/performance.py +209 -0
- package/scripts/screener.py +78 -23
- package/scripts/strategies/factors/__pycache__/liquidity.cpython-314.pyc +0 -0
- package/scripts/strategies/factors/liquidity.py +1 -1
- package/skills/backtest/SKILL.md +57 -0
- package/skills/help/SKILL.md +69 -5
- package/skills/monitor/SKILL.md +98 -0
- package/skills/portfolio/SKILL.md +135 -40
- package/skills/stock/SKILL.md +99 -1
- package/skills/{init → stock-init}/SKILL.md +5 -5
- package/workflow.md +36 -2
- package/scripts/common.py +0 -507
|
@@ -123,3 +123,53 @@
|
|
|
123
123
|
### 调用方式
|
|
124
124
|
|
|
125
125
|
debate 模式中重点关注:情绪周期阶段——用全市场涨停家数/跌停家数/炸板率/昨涨停今日溢价四条数据定位(主升/震荡/退潮/冰点)。养家的核心判断不在个股,而在"此刻市场情绪处于什么阶段"。
|
|
126
|
+
|
|
127
|
+
**代码示例:**
|
|
128
|
+
|
|
129
|
+
```python
|
|
130
|
+
from data import get_quote
|
|
131
|
+
from common import to_float
|
|
132
|
+
|
|
133
|
+
# 基础数据
|
|
134
|
+
quote = get_quote("sh600989")
|
|
135
|
+
|
|
136
|
+
# 情绪维度:情绪周期判断(需结合市场整体数据)
|
|
137
|
+
# 示例市场数据(实际需从市场接口获取)
|
|
138
|
+
market_up_count = 65 # 全市场涨停家数
|
|
139
|
+
market_down_count = 15 # 全市场跌停家数
|
|
140
|
+
break_rate = 0.25 # 炸板率
|
|
141
|
+
|
|
142
|
+
# 判断情绪周期阶段
|
|
143
|
+
if market_down_count > 50 and break_rate > 0.6:
|
|
144
|
+
# 冰点期:绝望中蕴含机会
|
|
145
|
+
phase = "冰点"
|
|
146
|
+
sentiment_score = 100
|
|
147
|
+
elif market_up_count > 80:
|
|
148
|
+
# 主升期:赚钱效应扩散
|
|
149
|
+
phase = "主升"
|
|
150
|
+
sentiment_score = 80
|
|
151
|
+
elif 40 <= market_up_count <= 60:
|
|
152
|
+
# 震荡期:分化
|
|
153
|
+
phase = "震荡"
|
|
154
|
+
sentiment_score = 50
|
|
155
|
+
else:
|
|
156
|
+
# 退潮期
|
|
157
|
+
phase = "退潮"
|
|
158
|
+
sentiment_score = 0
|
|
159
|
+
|
|
160
|
+
# 技术面维度:市场温度计
|
|
161
|
+
if market_up_count > 80:
|
|
162
|
+
tech_score = 100
|
|
163
|
+
elif market_up_count >= 40:
|
|
164
|
+
tech_score = 50
|
|
165
|
+
else:
|
|
166
|
+
tech_score = 0
|
|
167
|
+
|
|
168
|
+
# 风险维度
|
|
169
|
+
if market_down_count < 10:
|
|
170
|
+
risk_score = 100
|
|
171
|
+
elif market_down_count <= 30:
|
|
172
|
+
risk_score = 30
|
|
173
|
+
else:
|
|
174
|
+
risk_score = 0
|
|
175
|
+
```
|
package/experts/decide.md
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
# 专家圆桌决策引擎
|
|
2
2
|
|
|
3
|
+
> 版本:v1.1.0(2026-06-08)
|
|
4
|
+
> 更新:适配新的 `scripts/data/` 和 `scripts/common/` 模块
|
|
5
|
+
|
|
3
6
|
> 整合 8 位专家的独立评分,生成加权投票结果。用于 stock skill debate 模式。
|
|
4
7
|
|
|
5
8
|
## 一、投票机制
|
|
@@ -122,13 +125,62 @@
|
|
|
122
125
|
|
|
123
126
|
## 五、使用流程(stock skill debate 模式)
|
|
124
127
|
|
|
125
|
-
1.
|
|
126
|
-
2.
|
|
128
|
+
1. **获取数据**:使用 `scripts/data/` 获取目标股票完整数据
|
|
129
|
+
2. **获取大盘数据**:使用 `get_quote("sh000001")` 或 `get_quote("sh510300")` 判断市场环境
|
|
127
130
|
3. **专家打分**:每位专家按各自 `§九 评分矩阵` 对目标股票独立打分(使用步骤1的数据)
|
|
128
131
|
4. **应用调整**:根据市场环境(步骤2)调整长线/短线权重
|
|
129
132
|
5. **冲突解决**:按 §三 规则处理分歧,特别注意巴菲特否决权和养家情绪周期
|
|
130
133
|
6. **输出结果**:按 §四 格式输出,含评分表、方向、风险、仓位
|
|
131
134
|
|
|
135
|
+
**代码示例:**
|
|
136
|
+
|
|
137
|
+
```python
|
|
138
|
+
from data import get_quote, get_finance, get_kline
|
|
139
|
+
import statistics
|
|
140
|
+
|
|
141
|
+
# 1. 获取股票数据
|
|
142
|
+
quote = get_quote("sh600989")
|
|
143
|
+
fin = get_finance("sh600989")[0]
|
|
144
|
+
bars = get_kline("sh600989", scale=240, datalen=30)
|
|
145
|
+
|
|
146
|
+
# 2. 获取大盘数据判断市场环境
|
|
147
|
+
index_quote = get_quote("sh000001")
|
|
148
|
+
prev_close = index_quote.get("prev_close", 0)
|
|
149
|
+
current_price = index_quote.get("price", 0)
|
|
150
|
+
|
|
151
|
+
# 判断市场状态
|
|
152
|
+
if prev_close > 0:
|
|
153
|
+
change_pct = (current_price / prev_close - 1) * 100
|
|
154
|
+
if change_pct > 3:
|
|
155
|
+
market_state = "牛市"
|
|
156
|
+
long_weight = 0.40
|
|
157
|
+
short_weight = 0.60
|
|
158
|
+
elif change_pct < -3:
|
|
159
|
+
market_state = "熊市"
|
|
160
|
+
long_weight = 0.65
|
|
161
|
+
short_weight = 0.35
|
|
162
|
+
else:
|
|
163
|
+
market_state = "震荡"
|
|
164
|
+
long_weight = 0.55
|
|
165
|
+
short_weight = 0.45
|
|
166
|
+
|
|
167
|
+
# 3. 计算专家评分(以巴菲特为例)
|
|
168
|
+
roe = float(fin.get("ROEJQ", 0))
|
|
169
|
+
pe = float(quote.get("pe", 0))
|
|
170
|
+
|
|
171
|
+
# 巴菲特评分矩阵
|
|
172
|
+
buffett_scores = {
|
|
173
|
+
"基本面": 100 if roe >= 20 else (75 if roe >= 15 else (40 if roe >= 10 else 0)),
|
|
174
|
+
"估值": 100 if pe <= 15 else (60 if pe <= 25 else (25 if pe <= 40 else 0)),
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
# 4. 计算综合分
|
|
178
|
+
# ... (按 decide.md 规则计算)
|
|
179
|
+
|
|
180
|
+
# 5. 输出结果
|
|
181
|
+
print(f"市场状态: {market_state} | 长线权重: {long_weight} | 短线权重: {short_weight}")
|
|
182
|
+
```
|
|
183
|
+
|
|
132
184
|
---
|
|
133
185
|
|
|
134
186
|
## 六、信心指数计算
|
package/experts/duan_yongping.md
CHANGED
|
@@ -104,3 +104,48 @@
|
|
|
104
104
|
### 调用方式
|
|
105
105
|
|
|
106
106
|
debate 模式中,先判断"生意模式"—商业模式好→所有维度分不减;一般→总分×0.8。估值用 PE 绝对值+PE 历史分位综合判断。A 股需对管理层可信度单独折扣 10-20%。
|
|
107
|
+
|
|
108
|
+
**代码示例:**
|
|
109
|
+
|
|
110
|
+
```python
|
|
111
|
+
from data import get_quote, get_finance
|
|
112
|
+
from common import to_float
|
|
113
|
+
|
|
114
|
+
# 获取数据
|
|
115
|
+
quote = get_quote("sh600989")
|
|
116
|
+
fin = get_finance("sh600989")[0]
|
|
117
|
+
|
|
118
|
+
# 估值维度:PE
|
|
119
|
+
pe = to_float(quote.get("pe", 0))
|
|
120
|
+
risk_free_rate = 0.03 # 无风险利率
|
|
121
|
+
pe_threshold = 1 / risk_free_rate # 约 33 倍
|
|
122
|
+
|
|
123
|
+
if pe < pe_threshold * 0.75: # < 25 倍
|
|
124
|
+
pe_score = 100
|
|
125
|
+
elif pe < pe_threshold: # < 33 倍
|
|
126
|
+
pe_score = 70
|
|
127
|
+
elif pe < pe_threshold * 1.2: # < 40 倍
|
|
128
|
+
pe_score = 40
|
|
129
|
+
else:
|
|
130
|
+
pe_score = 0
|
|
131
|
+
|
|
132
|
+
# 安全边际维度:自由现金流
|
|
133
|
+
eps = to_float(fin.get("EPSJB", 0))
|
|
134
|
+
ocf_per_share = to_float(fin.get("MGJYXJJE", 0))
|
|
135
|
+
if eps > 0 and ocf_per_share > eps * 0.8:
|
|
136
|
+
fcf_score = 100 # FCF 持续为正
|
|
137
|
+
elif eps > 0:
|
|
138
|
+
fcf_score = 50
|
|
139
|
+
else:
|
|
140
|
+
fcf_score = 0
|
|
141
|
+
|
|
142
|
+
# 商业模式判断(简化版:基于行业和ROE)
|
|
143
|
+
industry = infer_industry(quote.get("name", ""), quote.get("code", ""))
|
|
144
|
+
roe = to_float(fin.get("ROEJQ", 0))
|
|
145
|
+
if roe >= 20:
|
|
146
|
+
business_score = 100 # 优秀商业模式
|
|
147
|
+
elif roe >= 15:
|
|
148
|
+
business_score = 60
|
|
149
|
+
else:
|
|
150
|
+
business_score = 20
|
|
151
|
+
```
|
package/experts/lynch.md
CHANGED
|
@@ -124,4 +124,51 @@
|
|
|
124
124
|
|
|
125
125
|
### 调用方式
|
|
126
126
|
|
|
127
|
-
debate 模式中,用 scripts/ 获取 PE 和净利增速计算 PEG,对照上表打分。增速取近 3 年 CAGR,若数据不足则用最新季度年化。
|
|
127
|
+
debate 模式中,用 `scripts/data/` 获取 PE 和净利增速计算 PEG,对照上表打分。增速取近 3 年 CAGR,若数据不足则用最新季度年化。
|
|
128
|
+
|
|
129
|
+
**代码示例:**
|
|
130
|
+
|
|
131
|
+
```python
|
|
132
|
+
from data import get_quote, get_finance
|
|
133
|
+
from common import to_float
|
|
134
|
+
|
|
135
|
+
# 获取数据
|
|
136
|
+
quote = get_quote("sh600989")
|
|
137
|
+
fin = get_finance("sh600989")[0]
|
|
138
|
+
|
|
139
|
+
# 基本面维度:净利增速
|
|
140
|
+
profit_growth = to_float(fin.get("PARENTNETPROFITTZ", 0)) # 净利润同比增长%
|
|
141
|
+
if profit_growth >= 25:
|
|
142
|
+
base_score = 100
|
|
143
|
+
elif profit_growth >= 20:
|
|
144
|
+
base_score = 80
|
|
145
|
+
elif profit_growth >= 15:
|
|
146
|
+
base_score = 50
|
|
147
|
+
else:
|
|
148
|
+
base_score = 20
|
|
149
|
+
|
|
150
|
+
# 估值维度:PEG
|
|
151
|
+
pe = to_float(quote.get("pe", 0))
|
|
152
|
+
growth = to_float(fin.get("PARENTNETPROFITTZ", 0))
|
|
153
|
+
peg = pe / max(growth, 1) # 避免除零
|
|
154
|
+
|
|
155
|
+
if peg <= 0.5:
|
|
156
|
+
peg_score = 100
|
|
157
|
+
elif peg <= 1.0:
|
|
158
|
+
peg_score = 80
|
|
159
|
+
elif peg <= 1.5:
|
|
160
|
+
peg_score = 50
|
|
161
|
+
elif peg <= 2.0:
|
|
162
|
+
peg_score = 30
|
|
163
|
+
else:
|
|
164
|
+
peg_score = 0
|
|
165
|
+
|
|
166
|
+
# 风险维度:负债率
|
|
167
|
+
debt_ratio = to_float(fin.get("ZCFZL", 0))
|
|
168
|
+
if debt_ratio < 60:
|
|
169
|
+
risk_score = 100
|
|
170
|
+
elif debt_ratio < 100:
|
|
171
|
+
risk_score = 60
|
|
172
|
+
else:
|
|
173
|
+
risk_score = 0
|
|
174
|
+
```
|
package/experts/soros.md
CHANGED
|
@@ -87,3 +87,46 @@ _简化案例_:某银行 PB 0.5 倍,市场担忧不良资产→股价跌至
|
|
|
87
87
|
### 调用方式
|
|
88
88
|
|
|
89
89
|
debate 模式中,重点关注:趋势是否明确(从 kline.py 20日均线判断)、市场情绪是否一致(从涨停家数/炸板率判断)、是否有反身性强化信号。个股基本面只作参考背景。
|
|
90
|
+
|
|
91
|
+
**代码示例:**
|
|
92
|
+
|
|
93
|
+
```python
|
|
94
|
+
from data import get_quote, get_kline
|
|
95
|
+
from common import to_float
|
|
96
|
+
import statistics
|
|
97
|
+
|
|
98
|
+
# 获取K线数据判断趋势
|
|
99
|
+
bars = get_kline("sh600989", scale=240, datalen=30)
|
|
100
|
+
closes = [to_float(b["close"]) for b in bars if to_float(b.get("close", 0)) > 0]
|
|
101
|
+
|
|
102
|
+
if len(closes) >= 20:
|
|
103
|
+
ma20 = statistics.mean(closes[-20:])
|
|
104
|
+
current_price = closes[-1]
|
|
105
|
+
|
|
106
|
+
if current_price > ma20:
|
|
107
|
+
trend_score = 100 # 上升趋势
|
|
108
|
+
else:
|
|
109
|
+
trend_score = 0 # 下降趋势
|
|
110
|
+
|
|
111
|
+
# 技术面维度:趋势强度
|
|
112
|
+
if len(closes) >= 10:
|
|
113
|
+
recent = closes[-10:]
|
|
114
|
+
if all(recent[i] < recent[i+1] for i in range(len(recent)-1)):
|
|
115
|
+
tech_score = 100 # 明确上升趋势
|
|
116
|
+
elif all(recent[i] > recent[i+1] for i in range(len(recent)-1)):
|
|
117
|
+
tech_score = 0 # 明确下降趋势
|
|
118
|
+
else:
|
|
119
|
+
tech_score = 40 # 震荡
|
|
120
|
+
else:
|
|
121
|
+
tech_score = 40
|
|
122
|
+
|
|
123
|
+
# 情绪/反身性维度(需结合市场数据)
|
|
124
|
+
# 实际使用时从市场情绪接口获取涨停家数、炸板率等
|
|
125
|
+
market_up_count = 80 # 示例:涨停家数
|
|
126
|
+
if market_up_count > 80:
|
|
127
|
+
sentiment_score = 40 # 亢奋期,一致性过高
|
|
128
|
+
elif market_up_count > 40:
|
|
129
|
+
sentiment_score = 60 # 正常
|
|
130
|
+
else:
|
|
131
|
+
sentiment_score = 100 # 冰点,反向机会
|
|
132
|
+
```
|
package/experts/xu_xiang.md
CHANGED
|
@@ -105,3 +105,47 @@
|
|
|
105
105
|
### 调用方式
|
|
106
106
|
|
|
107
107
|
debate 模式中重点关注:涨停板基因(kline.py 近30日是否有9.5%+涨幅日)、板块联动(同板涨停数)、大盘趋势(所在指数是否站上20日线)。基本面只看EPS排雷,不深度分析。
|
|
108
|
+
|
|
109
|
+
**代码示例:**
|
|
110
|
+
|
|
111
|
+
```python
|
|
112
|
+
from data import get_quote, get_kline
|
|
113
|
+
from common import to_float
|
|
114
|
+
import statistics
|
|
115
|
+
|
|
116
|
+
# 基础数据
|
|
117
|
+
quote = get_quote("sh600989")
|
|
118
|
+
|
|
119
|
+
# 技术面维度:涨停板基因
|
|
120
|
+
# 获取近30日K线,检查是否有接近涨停的交易日
|
|
121
|
+
bars = get_kline("sh600989", scale=240, datalen=30)
|
|
122
|
+
high_prices = [to_float(b.get("high", 0)) for b in bars]
|
|
123
|
+
prev_close = to_float(quote.get("prev_close", 0))
|
|
124
|
+
|
|
125
|
+
if prev_close > 0:
|
|
126
|
+
# 计算每日涨跌幅
|
|
127
|
+
limit_up_pct = 0.095 if "30" in quote.get("code", "") or "68" in quote.get("code", "") else 0.095
|
|
128
|
+
limit_up_count = sum(1 for hp in high_prices if hp / prev_close - 1 >= limit_up_pct * 0.9)
|
|
129
|
+
|
|
130
|
+
if limit_up_count >= 2:
|
|
131
|
+
tech_score = 100
|
|
132
|
+
elif limit_up_count >= 1:
|
|
133
|
+
tech_score = 50
|
|
134
|
+
else:
|
|
135
|
+
tech_score = 0
|
|
136
|
+
|
|
137
|
+
# 情绪/题材维度:板块联动(需外部市场数据)
|
|
138
|
+
# 示例:同板块涨停数量
|
|
139
|
+
sector_limit_up_count = 3 # 实际从市场数据获取
|
|
140
|
+
|
|
141
|
+
if sector_limit_up_count >= 3:
|
|
142
|
+
sentiment_score = 100
|
|
143
|
+
elif sector_limit_up_count >= 2:
|
|
144
|
+
sentiment_score = 60
|
|
145
|
+
else:
|
|
146
|
+
sentiment_score = 20
|
|
147
|
+
|
|
148
|
+
# 基本面维度:仅排雷
|
|
149
|
+
eps = to_float(quote.get("pe")) # 这里用PE作为占位,实际不深入分析
|
|
150
|
+
base_score = 60 if eps and eps > 0 else 0
|
|
151
|
+
```
|
package/experts/zhao_laoge.md
CHANGED
|
@@ -141,3 +141,56 @@
|
|
|
141
141
|
### 调用方式
|
|
142
142
|
|
|
143
143
|
debate 模式中重点关注:kline.py 30日K线判断均线排列形态(MA5/MA10/MA20是否多头)、题材在生命周期中位置(启动→高潮→加速→分歧→退潮)、量价是否健康(放量上涨+缩量回踩=最佳)。流通市值取 quote.py 的 circulating_cap 字段。
|
|
144
|
+
|
|
145
|
+
**代码示例:**
|
|
146
|
+
|
|
147
|
+
```python
|
|
148
|
+
from data import get_quote, get_kline
|
|
149
|
+
from common import to_float
|
|
150
|
+
import statistics
|
|
151
|
+
|
|
152
|
+
# 基础数据
|
|
153
|
+
quote = get_quote("sh600989")
|
|
154
|
+
circulating_cap = to_float(quote.get("circulating_cap", 0))
|
|
155
|
+
|
|
156
|
+
# 估值维度:流通市值
|
|
157
|
+
if 50 <= circulating_cap <= 300:
|
|
158
|
+
cap_score = 100
|
|
159
|
+
elif 30 <= circulating_cap <= 500:
|
|
160
|
+
cap_score = 60
|
|
161
|
+
else:
|
|
162
|
+
cap_score = 20
|
|
163
|
+
|
|
164
|
+
# 技术面维度:均线系统
|
|
165
|
+
bars = get_kline("sh600989", scale=240, datalen=30)
|
|
166
|
+
closes = [to_float(b["close"]) for b in bars if to_float(b.get("close", 0)) > 0]
|
|
167
|
+
|
|
168
|
+
if len(closes) >= 20:
|
|
169
|
+
ma5 = statistics.mean(closes[-5:])
|
|
170
|
+
ma10 = statistics.mean(closes[-10:])
|
|
171
|
+
ma20 = statistics.mean(closes[-20:])
|
|
172
|
+
|
|
173
|
+
if ma5 > ma10 > ma20:
|
|
174
|
+
tech_score = 100 # 多头排列
|
|
175
|
+
elif ma5 < ma10 < ma20:
|
|
176
|
+
tech_score = 0 # 空头排列
|
|
177
|
+
else:
|
|
178
|
+
tech_score = 70 # 均线粘合
|
|
179
|
+
else:
|
|
180
|
+
tech_score = 40
|
|
181
|
+
|
|
182
|
+
# 情绪/题材维度:量价配合
|
|
183
|
+
volumes = [to_float(b.get("volume", 0)) for b in bars]
|
|
184
|
+
if len(closes) >= 10 and len(volumes) >= 10:
|
|
185
|
+
recent_vol = statistics.mean(volumes[-5:])
|
|
186
|
+
prev_vol = statistics.mean(volumes[-10:-5])
|
|
187
|
+
|
|
188
|
+
if recent_vol > prev_vol * 1.2 and closes[-1] > statistics.mean(closes[-5:-1]):
|
|
189
|
+
sentiment_score = 100 # 放量上涨
|
|
190
|
+
elif recent_vol < prev_vol * 0.8:
|
|
191
|
+
sentiment_score = 60 # 缩量回调(健康)
|
|
192
|
+
else:
|
|
193
|
+
sentiment_score = 40
|
|
194
|
+
else:
|
|
195
|
+
sentiment_score = 50
|
|
196
|
+
```
|
package/experts/zuoshou_xinyi.md
CHANGED
|
@@ -142,3 +142,69 @@
|
|
|
142
142
|
### 调用方式
|
|
143
143
|
|
|
144
144
|
debate 模式中重点关注:kline.py 30日K线判断是否强势股(有≥4板记录)、当前是否缩量调整(量能<主升期50%)、关键K线反转信号(锤子线/早晨之星/阳包阴/缩量十字星)。流通市值取 quote.py circulating_cap,止损位取前低或20日线。
|
|
145
|
+
|
|
146
|
+
**代码示例:**
|
|
147
|
+
|
|
148
|
+
```python
|
|
149
|
+
from data import get_quote, get_kline
|
|
150
|
+
from common import to_float
|
|
151
|
+
import statistics
|
|
152
|
+
|
|
153
|
+
# 基础数据
|
|
154
|
+
quote = get_quote("sh600989")
|
|
155
|
+
circulating_cap = to_float(quote.get("circulating_cap", 0))
|
|
156
|
+
|
|
157
|
+
# 估值维度:流通市值 + 回调深度
|
|
158
|
+
if 30 <= circulating_cap <= 200:
|
|
159
|
+
cap_score = 100
|
|
160
|
+
elif 10 <= circulating_cap <= 300:
|
|
161
|
+
cap_score = 50
|
|
162
|
+
else:
|
|
163
|
+
cap_score = 0
|
|
164
|
+
|
|
165
|
+
# 技术面维度:K线反转形态 + 缩量程度
|
|
166
|
+
bars = get_kline("sh600989", scale=240, datalen=30)
|
|
167
|
+
closes = [to_float(b["close"]) for b in bars if to_float(b.get("close", 0)) > 0]
|
|
168
|
+
volumes = [to_float(b.get("volume", 0)) for b in bars if to_float(b.get("volume", 0)) > 0]
|
|
169
|
+
|
|
170
|
+
if len(closes) >= 10 and len(volumes) >= 10:
|
|
171
|
+
# 计算缩量程度
|
|
172
|
+
peak_vol = max(volumes[-10:]) if volumes else 1
|
|
173
|
+
recent_vol = statistics.mean(volumes[-3:]) if len(volumes) >= 3 else 1
|
|
174
|
+
vol_ratio = recent_vol / peak_vol if peak_vol > 0 else 1
|
|
175
|
+
|
|
176
|
+
# K线反转形态识别(简化版)
|
|
177
|
+
last3 = closes[-3:]
|
|
178
|
+
if len(closes) >= 4:
|
|
179
|
+
prev3 = closes[-4:-1]
|
|
180
|
+
else:
|
|
181
|
+
prev3 = closes[:-1] if len(closes) > 1 else [closes[0]] * 3
|
|
182
|
+
|
|
183
|
+
# 锤子线/早晨之星形态
|
|
184
|
+
is_hammer = last3[-1] < last3[-2] and closes[-1] < statistics.mean(last3)
|
|
185
|
+
is_engulfing = last3[-1] > last3[-2] and last3[-2] < last3[-3] and last3[-1] > last3[-3]
|
|
186
|
+
|
|
187
|
+
if vol_ratio <= 0.5 and (is_hammer or is_engulfing):
|
|
188
|
+
tech_score = 100
|
|
189
|
+
elif vol_ratio <= 0.5:
|
|
190
|
+
tech_score = 60
|
|
191
|
+
else:
|
|
192
|
+
tech_score = 20
|
|
193
|
+
else:
|
|
194
|
+
tech_score = 40
|
|
195
|
+
|
|
196
|
+
# 情绪维度:调整阶段
|
|
197
|
+
if len(closes) >= 10:
|
|
198
|
+
# 计算调整天数(从最高点回调)
|
|
199
|
+
peak_idx = closes.index(max(closes))
|
|
200
|
+
adjust_days = len(closes) - peak_idx - 1
|
|
201
|
+
|
|
202
|
+
if 3 <= adjust_days <= 7:
|
|
203
|
+
sentiment_score = 100 # ���佳调整期
|
|
204
|
+
elif adjust_days < 3:
|
|
205
|
+
sentiment_score = 40 # 调整不足
|
|
206
|
+
else:
|
|
207
|
+
sentiment_score = 30 # 调整过长
|
|
208
|
+
else:
|
|
209
|
+
sentiment_score = 50
|
|
210
|
+
```
|