-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathstock_detail_analysis.py
More file actions
204 lines (174 loc) · 8.71 KB
/
Copy pathstock_detail_analysis.py
File metadata and controls
204 lines (174 loc) · 8.71 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
"""Check daily capital flow for Loongson & Hygon, and find similar AIoT chip stocks"""
import baostock as bs
import pandas as pd
import numpy as np
lg = bs.login()
# ============================================================
# Part 1: Loongson & Hygon daily capital flow (recent 10 days)
# ============================================================
print("=" * 90)
print("PART 1: DAILY CAPITAL FLOW - LOONGSON & HYGON (Recent 10 Days)")
print("=" * 90)
for code, name in [("sh.688047", "龙芯中科"), ("sh.688041", "海光信息")]:
rs = bs.query_history_k_data_plus(code,
"date,close,open,high,low,volume,amount,pctChg",
start_date="2026-05-06", end_date="2026-05-19",
frequency="d", adjustflag="3")
data_list = []
while (rs.error_code == "0") & rs.next():
data_list.append(rs.get_row_data())
if data_list:
df = pd.DataFrame(data_list, columns=rs.fields)
df["date"] = pd.to_datetime(df["date"])
df = df.sort_values("date")
for col in ["close", "open", "high", "low", "volume", "amount", "pctChg"]:
df[col] = df[col].astype(float)
df["inflow"] = df.apply(lambda r: r["amount"] if r["pctChg"] > 0 else 0, axis=1)
df["outflow"] = df.apply(lambda r: r["amount"] if r["pctChg"] < 0 else 0, axis=1)
df["net_flow"] = (df["inflow"] - df["outflow"]) / 1e8
df["total_flow"] = (df["inflow"] + df["outflow"]) / 1e8
df["net_ratio"] = (df["net_flow"] / df["total_flow"] * 100)
# RSI6
delta = df["close"].diff()
gain6 = delta.where(delta > 0, 0).rolling(6).mean()
loss6 = (-delta.where(delta < 0, 0)).rolling(6).mean()
rs6 = gain6 / loss6.replace(0, 0.001)
df["RSI6"] = 100 - (100 / (1 + rs6))
print(f"\n {name} ({code}) - Daily Capital Flow")
print(f" {'Date':<12} {'Close':>8} {'Chg%':>7} {'Vol(万)':>10} {'NetFlow(亿)':>12} {'NetRatio':>10} {'RSI6':>6} {'Signal'}")
print(f" {'-'*12} {'-'*8} {'-'*7} {'-'*10} {'-'*12} {'-'*10} {'-'*6} {'-'*20}")
for _, row in df.iterrows():
signal = "INFLOW" if row["net_ratio"] > 10 else "INFLOW+" if row["net_ratio"] > 0 else "OUTFLOW" if row["net_ratio"] < -10 else "OUTFLOW-" if row["net_ratio"] < 0 else "FLAT"
rsi6 = row.get("RSI6", 0)
print(f" {row['date'].strftime('%Y-%m-%d'):<12} {row['close']:>8.2f} {row['pctChg']:>+6.2f}% {row['volume']/1e4:>10.0f} {row['net_flow']:>+10.2f} {row['net_ratio']:>+8.1f}% {rsi6:>6.1f} {signal}")
# Check last 2 days
last2 = df.tail(2)
both_inflow = all(last2["net_ratio"] > 0)
print(f"\n Last 2 days both positive inflow: {'YES' if both_inflow else 'NO'}")
print(f" 5/18: NetFlow={last2.iloc[0]['net_flow']:+.2f}亿 ({last2.iloc[0]['net_ratio']:+.1f}%)")
print(f" 5/19: NetFlow={last2.iloc[1]['net_flow']:+.2f}亿 ({last2.iloc[1]['net_ratio']:+.1f}%)")
# Volume trend: compare 5/18-19 vs 5/14-15
recent2_vol = df.tail(2)["volume"].mean()
prev2_vol = df.iloc[-6:-4]["volume"].mean() if len(df) >= 6 else recent2_vol
vol_change = (recent2_vol / prev2_vol - 1) * 100 if prev2_vol > 0 else 0
print(f" Volume trend: Recent 2d avg vs Previous 2d avg: {vol_change:+.1f}% ({'缩量' if vol_change < -20 else '放量' if vol_change > 20 else '持平'})")
# Price stabilization check
recent2_range = (df.tail(2)["high"].max() - df.tail(2)["low"].min()) / df.tail(2)["close"].mean() * 100
prev2_range = (df.iloc[-6:-4]["high"].max() - df.iloc[-6:-4]["low"].min()) / df.iloc[-6:-4]["close"].mean() * 100 if len(df) >= 6 else recent2_range
print(f" Price volatility: Recent 2d={recent2_range:.1f}% vs Previous 2d={prev2_range:.1f}% ({'波动收窄=企稳' if recent2_range < prev2_range else '波动扩大'})")
# ============================================================
# Part 2: Edge-side AI Chip Stocks (similar to Rockchip)
# ============================================================
print(f"\n{'='*90}")
print("PART 2: EDGE-SIDE AI CHIP STOCKS (Similar to Rockchip)")
print("=" * 90)
# Key edge-side AI / AIoT chip stocks
edge_ai_stocks = [
("sh.603893", "瑞芯微", "AIoT SoC"),
("sz.300782", "卓胜微", "射频芯片"),
("sh.688396", "华润微", "功率半导体"),
("sz.300458", "全志科技", "智能应用处理器SoC"),
("sh.688521", "芯原股份", "芯片IP"),
("sz.300474", "景嘉微", "GPU芯片"),
("sh.688012", "中微半导", "MCU芯片"),
("sh.688256", "寒武纪", "AI芯片"),
("sz.002371", "北方华创", "半导体设备"),
("sh.688981", "中芯国际", "晶圆代工"),
("sz.300223", "北京君正", "存储+处理器"),
("sh.688049", "晶晨股份", "智能机顶盒SoC"),
("sz.300613", "富瀚微", "安防芯片"),
("sh.688008", "澜起科技", "内存接口芯片"),
("sz.300053", "欧比特", "宇航芯片+AI"),
]
print(f"\n {'Stock':<10} {'Sector':<16} {'Price':>8} {'5d%':>7} {'20d%':>7} {'RSI14':>6} {'NetFlow5d':>12} {'MACD':>10} {'Score'}")
print(f" {'-'*10} {'-'*16} {'-'*8} {'-'*7} {'-'*7} {'-'*6} {'-'*12} {'-'*10} {'-'*6}")
results = []
for code, name, sector in edge_ai_stocks:
rs = bs.query_history_k_data_plus(code,
"date,close,pctChg,amount",
start_date="2026-03-01", end_date="2026-05-19",
frequency="d", adjustflag="3")
data_list = []
while (rs.error_code == "0") & rs.next():
data_list.append(rs.get_row_data())
if not data_list:
print(f" {name:<10} {sector:<16} {'N/A':>8}")
continue
df = pd.DataFrame(data_list, columns=rs.fields)
df["date"] = pd.to_datetime(df["date"])
df = df.sort_values("date")
df["close"] = df["close"].astype(float)
df["pctChg"] = df["pctChg"].astype(float)
df["amount"] = df["amount"].astype(float)
last_close = df["close"].iloc[-1]
ret_5d = (df["close"].iloc[-1] / df["close"].iloc[-5] - 1) * 100 if len(df) >= 5 else 0
ret_20d = (df["close"].iloc[-1] / df["close"].iloc[-20] - 1) * 100 if len(df) >= 20 else 0
# RSI14
delta = df["close"].diff()
gain = delta.where(delta > 0, 0).rolling(14).mean()
loss_val = (-delta.where(delta < 0, 0)).rolling(14).mean()
rs_val = gain / loss_val.replace(0, 0.001)
df["RSI14"] = 100 - (100 / (1 + rs_val))
last_rsi = df["RSI14"].iloc[-1]
# MACD
df["EMA12"] = df["close"].ewm(span=12).mean()
df["EMA26"] = df["close"].ewm(span=26).mean()
df["DIF"] = df["EMA12"] - df["EMA26"]
df["DEA"] = df["DIF"].ewm(span=9).mean()
last_dif = df["DIF"].iloc[-1]
last_dea = df["DEA"].iloc[-1]
prev_dif = df["DIF"].iloc[-2]
prev_dea = df["DEA"].iloc[-2]
if last_dif > last_dea and prev_dif <= prev_dea:
macd_signal = "GOLDEN"
elif last_dif > last_dea:
macd_signal = "BULL"
elif last_dif < last_dea and prev_dif >= prev_dea:
macd_signal = "DEAD"
else:
macd_signal = "BEAR"
# Capital flow
df["inflow"] = df.apply(lambda r: r["amount"] if r["pctChg"] > 0 else 0, axis=1)
df["outflow"] = df.apply(lambda r: r["amount"] if r["pctChg"] < 0 else 0, axis=1)
net_5d = (df["inflow"].tail(5).sum() - df["outflow"].tail(5).sum()) / 1e8
total_5d = (df["inflow"].tail(5).sum() + df["outflow"].tail(5).sum()) / 1e8
net_ratio = (net_5d / total_5d * 100) if total_5d > 0 else 0
# Quick score
score = 0
if ret_5d > 5: score += 2
elif ret_5d > 0: score += 1
elif ret_5d < -5: score -= 2
else: score -= 1
if 40 <= last_rsi <= 65: score += 2
elif 30 <= last_rsi <= 70: score += 1
elif last_rsi > 80: score -= 1
if net_ratio > 20: score += 2
elif net_ratio > 0: score += 1
elif net_ratio < -20: score -= 2
else: score -= 1
if macd_signal in ("GOLDEN", "BULL"): score += 2
elif macd_signal == "DEAD": score -= 2
elif macd_signal == "BEAR": score -= 1
results.append({
"name": name, "sector": sector, "price": last_close,
"ret_5d": ret_5d, "ret_20d": ret_20d, "rsi": last_rsi,
"net_5d": net_5d, "net_ratio": net_ratio,
"macd": macd_signal, "score": score
})
print(f" {name:<10} {sector:<16} {last_close:>8.2f} {ret_5d:>+6.2f}% {ret_20d:>+6.2f}% {last_rsi:>6.1f} {net_5d:>+10.2f}亿 {macd_signal:>10} {score:>+3d}")
# Sort by score
print(f"\n {'='*80}")
print(f" RANKING BY SCORE (Edge-side AI Chips)")
print(f" {'='*80}")
results.sort(key=lambda x: x["score"], reverse=True)
for i, r in enumerate(results, 1):
if r["score"] >= 3:
tag = "STRONG BUY"
elif r["score"] >= 1:
tag = "BUY"
elif r["score"] >= -1:
tag = "HOLD"
else:
tag = "AVOID"
print(f" #{i:2d} {r['name']:<10} {r['sector']:<16} Score:{r['score']:>+3d} RSI:{r['rsi']:.0f} 5d:{r['ret_5d']:+.1f}% Flow:{r['net_ratio']:+.0f}% → {tag}")
bs.logout()