每日备份 2026-03-27

This commit is contained in:
OpenClaw Backup
2026-03-27 23:38:45 +08:00
parent 4f11cd7b03
commit d09281e48c
827 changed files with 6991 additions and 148648 deletions
@@ -0,0 +1,7 @@
{
"version": 1,
"registry": "https://clawhub.ai",
"slug": "a-stock-trading-assistant",
"installedVersion": "1.0.0",
"installedAt": 1774617361378
}
+105
View File
@@ -0,0 +1,105 @@
---
name: a-stock-trading-assistant
description: A股股票智能交易助手,专服务中国大陆股票市场。当用户询问A股股票行情、个股分析、大盘情绪、热点板块、交易策略、价格预警、涨跌幅、成交量、技术面或基本面分析时触发。只处理沪深A股(代码以6/00/30/68开头),自动忽略港股和美股。所有数据实时从东方财富、新浪财经、同花顺、雪球抓取。Use when: user asks about Chinese A-share stocks, 股票行情, 个股分析, 大盘分析, 板块热点, 买卖点, 止盈止损, 仓位建议, or any A-share trading-related query.
---
# A股股票智能交易助手
## 角色定位
你是专业A股交易助手,只服务中国大陆A股市场(沪深两市)。数据全部实时联网获取,数据源优先级:东方财富 → 新浪财经 → 同花顺 → 雪球。
## 股票代码识别规则
| 前缀 | 市场 | 示例 |
|------|------|------|
| 60xxxx | 上交所主板 | 600519 贵州茅台 |
| 00xxxx | 深交所主板 | 000001 平安银行 |
| 30xxxx | 创业板 | 300750 宁德时代 |
| 68xxxx | 科创板 | 688981 中芯国际 |
- 自动忽略港股(.HK)、美股(NASDAQ/NYSE)及其他境外市场
- 用户输入不带前缀时,根据数字范围自动判断市场
## 数据获取方式
优先用 `scripts/fetch_stock.py` 脚本获取实时数据。如脚本执行失败,改用 `web_fetch` 直接访问数据源。
详细 API 端点见 `references/data-sources.md`
### 快速调用脚本
```bash
# 查询单只股票实时行情
python3 /app/skills/a-stock-trading-assistant/scripts/fetch_stock.py --code 600519
# 查询大盘指数
python3 /app/skills/a-stock-trading-assistant/scripts/fetch_stock.py --index
# 查询热点板块
python3 /app/skills/a-stock-trading-assistant/scripts/fetch_stock.py --hot-sectors
```
## 六大核心能力工作流
### 1. 实时行情查询
1. 运行 `fetch_stock.py --code <代码>` 获取实时数据
2. 展示:当前价、涨跌幅、涨跌额、成交量、成交额、换手率、振幅、52周高/低
3. 附上分时走势摘要(涨跌节奏描述)
### 2. 个股综合分析
先获取实时行情,再分析:
- **技术面**:均线系统(MA5/10/20/60)、趋势判断、支撑位/压力位、量价结构、MACD/KDJ信号
- **基本面**:PE/PB估值、近期业绩、行业地位、主要风险点
- 技术面与基本面结合,给出综合判断(看多/看空/中性)
详细分析方法见 `references/analysis.md`
### 3. 大盘情绪与风险判断
获取上证指数、深证成指、创业板指实时数据,分析:
- 大盘强弱(趋势、量能、板块轮动)
- 市场情绪指数(赚钱效应、涨跌比)
- 风险等级(低/中/高)及应对建议
### 4. 热点板块与龙头股
1. 运行 `fetch_stock.py --hot-sectors` 获取涨幅榜板块
2. 识别:主线板块(连续性强)、情绪板块(短期热点)
3. 每个热点板块列出核心龙头股(涨停、强势领涨)
### 5. 交易策略与建议
基于用户的持仓/意向股,给出:
- **短线**(1-5天):催化剂、入场区间、止损位、止盈位
- **中线**(1-3月):趋势判断、分批建仓节奏、仓位比例
- 始终标注风险提示
格式模板:
```
【操作建议】XX股(XXXXXX
方向:做多/观望/回避
入场区间:XX.XX - XX.XX 元
止损位:XX.XX 元(跌破离场)
止盈位:XX.XX 元(分批减仓)
仓位:XX%(轻/中/重仓)
逻辑:[核心理由2-3条]
风险:[主要风险1-2条]
```
### 6. 价格预警监控
当用户设置预警时:
- 记录目标价、预警条件(突破/跌破/放量)到 `references/watchlist.md`
- 建议用户配合券商App实时推送,本工具做辅助分析
- 在后续对话中主动核对预警状态
## 输出规范
- 数据必须标注来源和获取时间(精确到分钟)
- 所有价格建议必须附风险提示
- 避免绝对化表述("必涨"/"稳赚"),用概率/可能性描述
- 数字精确到小数点后2位,成交额以亿元为单位
- 大盘/个股分析结构清晰,使用简洁表格或分项列出
@@ -0,0 +1,6 @@
{
"ownerId": "kn70hb4emf3csex5aeqt51arrx82d01z",
"slug": "a-stock-trading-assistant",
"version": "1.0.0",
"publishedAt": 1772789682966
}
@@ -0,0 +1,110 @@
# 个股分析方法参考
## 技术面分析框架
### 均线系统判断
| 形态 | 条件 | 含义 |
|------|------|------|
| 多头排列 | MA5>MA10>MA20>MA60 | 上升趋势强,可做多 |
| 空头排列 | MA5<MA10<MA20<MA60 | 下跌趋势中,回避 |
| 均线粘合 | 各均线收敛 | 方向待定,等待突破 |
| 金叉 | MA5上穿MA10/MA20 | 短期买入信号 |
| 死叉 | MA5下穿MA10/MA20 | 短期卖出信号 |
### 量价结构分析
- **放量上涨**:主力资金入场,趋势确认,可跟进
- **缩量上涨**:小心,动能不足,谨慎追高
- **放量下跌**:恐慌性出逃或主力砸盘,注意风险
- **缩量下跌**:调整中,无大资金出逃,可等底部
- **天量天价**:极端放量后往往是阶段顶部,注意减仓
- **地量地价**:成交极度萎缩后往往是底部信号
### 支撑位 / 压力位识别
1. **整数关口**100/200/300元等心理价位
2. **前期高点/低点**:突破前高=突破压力;跌破前低=下一支撑
3. **均线支撑**:MA20(月线)、MA60(季线)是重要支撑
4. **成交密集区**:历史上大量换手的价格区间,构成强支撑/压力
### MACD 信号
- **金叉+零轴上方**:强烈买入信号
- **死叉+零轴下方**:强烈卖出信号
- **顶/底背离**:价格创新高但MACD不创新高 = 顶背离(卖);价格创新低但MACD不创新低 = 底背离(买)
- **红柱/绿柱缩短**:动能减弱,可能转向
### KDJ 信号
- KDJ>80:超买区,注意回调
- KDJ<20:超卖区,反弹机会
- K线上穿D线(金叉):买入
- K线下穿D线(死叉):卖出
---
## 基本面分析框架
### 估值判断
| 指标 | 低估 | 合理 | 高估 |
|------|------|------|------|
| PE(市盈率) | <行业均值50% | 接近行业均值 | >行业均值2倍 |
| PB(市净率) | <1 | 1-3 | >5 |
- 消费/医药类:参考PE估值
- 银行/地产类:参考PB估值
- 成长类(科技/新能源):参考PEG(<1为合理)
### 业绩评估要点
- 近4个季度营收/净利增速趋势
- 毛利率变化(毛利率提升=竞争力增强)
- 净利率水平(与同行比较)
- 现金流情况(经营活动现金流>净利润=高质量利润)
### 行业地位
- 市占率排名(行业前3更优)
- 护城河类型:品牌/技术/成本/网络效应
- 政策支持方向(新能源/半导体/AI等优先)
---
## 大盘分析框架
### 市场情绪量化
| 指标 | 计算方式 | 情绪判断 |
|------|---------|---------|
| 赚钱效应 | 上涨股/总股数 | >60%强,<40%弱 |
| 涨停数量 | 当日涨停家数 | >100家热,<30家冷 |
| 量能比 | 今日量/5日均量 | >1.2放量,<0.8缩量 |
### 风险等级定义
| 级别 | 特征 | 建议仓位 |
|------|------|---------|
| 低风险 | 大盘趋势向上,量能充裕,涨多跌少 | 7-9成仓 |
| 中风险 | 方向不明,震荡整理 | 3-6成仓 |
| 高风险 | 趋势向下,缩量或恐慌放量 | 0-2成仓 |
---
## 热点板块判断标准
### 主线板块(可重点跟踪)
- 连续3天以上保持热度
- 有政策/事件催化
- 龙头股有持续涨停
### 情绪板块(短线机会)
- 单日暴热,次日需观察持续性
- 题材性质(概念股)
- 跟风盘多,需快进快出
### 龙头股识别
- 板块内首板/连板的核心票
- 换手率高但不崩盘
- 量价配合良好
@@ -0,0 +1,114 @@
# 数据源 API 参考
## 1. 新浪财经(最稳定,优先使用)
### 实时行情
```
# 单股(沪市加sh,深市加sz
GET http://hq.sinajs.cn/list=sh600519
GET http://hq.sinajs.cn/list=sz000001
# 多股同时查询
GET http://hq.sinajs.cn/list=sh600519,sz000001,sz300750
```
返回格式(逗号分隔的字符串):
```
var hq_str_sh600519="贵州茅台,1788.00,1785.00,1800.00,1810.00,1780.00,1799.00,1800.00,3456789,6234567890.00,100,1799.00,...,2024-01-15,15:00:00,00";
```
字段顺序:股票名,昨收,今开,当前价,最高,最低,买一价,卖一价,成交量(手),成交额,买一量,买一价,...,日期,时间
### 大盘指数
```
GET http://hq.sinajs.cn/list=s_sh000001,s_sz399001,s_sz399006
# 上证指数,深证成指,创业板指
```
---
## 2. 东方财富(数据全面,适合深度查询)
### 实时行情
```
GET http://push2.eastmoney.com/api/qt/stock/get?secid={market}.{code}&fields=f43,f44,f45,f46,f47,f48,f57,f58,f60,f107,f169,f170,f171,f530
```
market: 1=沪市, 0=深市
关键字段:
- f43: 最新价(×0.01
- f44: 最高价
- f45: 最低价
- f46: 今开
- f47: 成交量(手)
- f48: 成交额(元)
- f57: 股票代码
- f58: 股票名称
- f60: 昨收
- f170: 涨跌幅(%×100
- f169: 涨跌额
- f171: 换手率(%×100
### 涨幅榜/板块榜
```
# A股涨幅榜(前50
GET http://push2.eastmoney.com/api/qt/clist/get?pn=1&pz=50&po=1&np=1&ut=bd1d9ddb04089700cf9c27f6f7426281&fltt=2&invt=2&fid=f3&fs=m:0+t:6,m:0+t:13,m:0+t:80,m:1+t:2,m:1+t:23&fields=f1,f2,f3,f4,f5,f6,f7,f8,f9,f10,f12,f13,f14,f15,f16,f17,f18
# 板块涨跌榜(概念/行业)
GET http://push2.eastmoney.com/api/qt/clist/get?pn=1&pz=20&po=1&np=1&ut=bd1d9ddb04089700cf9c27f6f7426281&fltt=2&invt=2&fid=f3&fs=m:90+t:2+f:!50&fields=f1,f2,f3,f4,f5,f6,f7,f8,f12,f14,f20,f21
```
### 个股分时数据
```
GET http://push2.eastmoney.com/api/qt/stock/trends2/get?secid={market}.{code}&fields1=f1,f2,f3,f4,f5&fields2=f51,f52,f53,f54,f55,f56,f57,f58&iscr=0&iscca=0
```
---
## 3. 同花顺
### 实时行情
```
GET https://d.10jqka.com.cn/v4/time/hs_{code}/today.js
# code: 直接用6位数字,如 600519
```
注意:请求需要带 Referer: https://www.10jqka.com.cn
---
## 4. 雪球
### 实时行情
```
GET https://stock.xueqiu.com/v5/stock/quote.json?symbol={symbol}&extend=detail
# symbol: SH600519 / SZ000001 / SZ300750
```
注意:需要先访问 https://xueqiu.com 获取 cookiesession),再请求数据接口。脚本中已处理。
---
## 市场代码对照
| 代码前缀 | 新浪前缀 | 东财market | 雪球前缀 |
|---------|---------|-----------|---------|
| 600xxx / 601xxx / 603xxx / 605xxx / 688xxx | sh | 1 | SH |
| 000xxx / 001xxx / 002xxx / 003xxx / 300xxx / 301xxx | sz | 0 | SZ |
## 大盘指数代码
| 指数 | 新浪 | 东财secid |
|------|------|----------|
| 上证指数 | sh000001 | 1.000001 |
| 深证成指 | sz399001 | 0.399001 |
| 创业板指 | sz399006 | 0.399006 |
| 科创50 | sh000688 | 1.000688 |
| 北证50 | bj899050 | — |
@@ -0,0 +1,299 @@
#!/usr/bin/env python3
"""
A股实时行情抓取脚本
数据源:新浪财经(主)、东方财富(备)
用法:
python3 fetch_stock.py --code 600519
python3 fetch_stock.py --code 000001 sz000001 300750
python3 fetch_stock.py --index
python3 fetch_stock.py --hot-sectors
"""
import argparse
import json
import re
import sys
import urllib.request
import urllib.error
from datetime import datetime
HEADERS = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
"Referer": "https://finance.sina.com.cn",
"Accept-Language": "zh-CN,zh;q=0.9",
}
def get_market_prefix(code: str) -> str:
"""根据股票代码判断市场前缀"""
code = code.strip().upper()
if code.startswith("SH") or code.startswith("SZ"):
return code[:2].lower(), code[2:]
code = re.sub(r"[^0-9]", "", code)
if code.startswith(("60", "68", "51", "58", "11")):
return "sh", code
elif code.startswith(("00", "30", "15", "12", "16", "13")):
return "sz", code
return "sh", code # default
def fetch_url(url: str, extra_headers: dict = None) -> str:
req = urllib.request.Request(url, headers=HEADERS)
if extra_headers:
for k, v in extra_headers.items():
req.add_header(k, v)
try:
with urllib.request.urlopen(req, timeout=10) as resp:
charset = "gbk" if "sina" in url or "sinajs" in url else "utf-8"
return resp.read().decode(charset, errors="replace")
except Exception as e:
return ""
def parse_sina_stock(raw: str, symbol: str) -> dict:
"""解析新浪财经股票数据"""
match = re.search(r'"([^"]*)"', raw)
if not match:
return {}
parts = match.group(1).split(",")
if len(parts) < 32:
return {}
try:
name = parts[0]
prev_close = float(parts[2]) if parts[2] else 0
open_price = float(parts[1]) if parts[1] else 0
current = float(parts[3]) if parts[3] else 0
high = float(parts[4]) if parts[4] else 0
low = float(parts[5]) if parts[5] else 0
volume = int(parts[8]) if parts[8] else 0 # 手
amount = float(parts[9]) if parts[9] else 0 # 元
date_str = parts[30] if len(parts) > 30 else ""
time_str = parts[31] if len(parts) > 31 else ""
change = current - prev_close
change_pct = (change / prev_close * 100) if prev_close else 0
turnover_approx = volume / 1000 # 粗略换手(无流通股数据)
return {
"symbol": symbol,
"name": name,
"current": round(current, 2),
"change": round(change, 2),
"change_pct": round(change_pct, 2),
"open": round(open_price, 2),
"high": round(high, 2),
"low": round(low, 2),
"prev_close": round(prev_close, 2),
"volume_lot": volume, # 手
"amount_yuan": round(amount, 2),
"amount_yi": round(amount / 1e8, 2),
"date": date_str,
"time": time_str,
"source": "新浪财经",
"fetch_time": datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
}
except (ValueError, IndexError):
return {}
def fetch_single_stock(code: str) -> dict:
"""抓取单只股票行情"""
prefix, clean_code = get_market_prefix(code)
symbol = f"{prefix}{clean_code}"
url = f"http://hq.sinajs.cn/list={symbol}"
raw = fetch_url(url)
if raw:
data = parse_sina_stock(raw, symbol)
if data:
return data
# 备用:东方财富
market = 1 if prefix == "sh" else 0
url2 = (
f"http://push2.eastmoney.com/api/qt/stock/get"
f"?secid={market}.{clean_code}"
f"&fields=f43,f44,f45,f46,f47,f48,f57,f58,f60,f107,f169,f170,f171"
)
raw2 = fetch_url(url2, {"Referer": "https://www.eastmoney.com"})
if raw2:
try:
obj = json.loads(raw2)
d = obj.get("data", {}) or {}
if d.get("f43"):
prev = d["f60"] / 100
curr = d["f43"] / 100
chg = d["f169"] / 100
chg_pct = d["f170"] / 100
return {
"symbol": symbol,
"name": d.get("f58", ""),
"current": round(curr, 2),
"change": round(chg, 2),
"change_pct": round(chg_pct, 2),
"open": round(d["f46"] / 100, 2),
"high": round(d["f44"] / 100, 2),
"low": round(d["f45"] / 100, 2),
"prev_close": round(prev, 2),
"volume_lot": d.get("f47", 0),
"amount_yuan": d.get("f48", 0),
"amount_yi": round(d.get("f48", 0) / 1e8, 2),
"turnover_pct": round(d.get("f171", 0) / 100, 2),
"source": "东方财富",
"fetch_time": datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
}
except Exception:
pass
return {"error": f"无法获取 {code} 的行情数据", "symbol": symbol}
def fetch_index() -> list:
"""抓取主要大盘指数"""
symbols = "s_sh000001,s_sz399001,s_sz399006,s_sh000688"
names_map = {
"s_sh000001": "上证指数",
"s_sz399001": "深证成指",
"s_sz399006": "创业板指",
"s_sh000688": "科创50",
}
url = f"http://hq.sinajs.cn/list={symbols}"
raw = fetch_url(url)
results = []
if raw:
for sym, name in names_map.items():
pattern = rf'hq_str_{re.escape(sym)}="([^"]*)"'
m = re.search(pattern, raw)
if m:
parts = m.group(1).split(",")
if len(parts) >= 5:
try:
results.append({
"name": parts[0] or name,
"current": float(parts[1]),
"change": float(parts[2]),
"change_pct": float(parts[3]),
"volume_yi_lot": round(float(parts[4]) / 1e8, 2),
"amount_yi": round(float(parts[5]) / 1e8, 2) if len(parts) > 5 else 0,
"fetch_time": datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
"source": "新浪财经",
})
except (ValueError, IndexError):
pass
return results
def fetch_hot_sectors() -> list:
"""抓取热点板块(东方财富概念板块涨幅榜)"""
url = (
"http://push2.eastmoney.com/api/qt/clist/get"
"?pn=1&pz=20&po=1&np=1&ut=bd1d9ddb04089700cf9c27f6f7426281"
"&fltt=2&invt=2&fid=f3"
"&fs=m:90+t:2+f:!50"
"&fields=f2,f3,f4,f12,f14,f20,f128,f136,f207,f208,f209"
)
raw = fetch_url(url, {"Referer": "https://www.eastmoney.com"})
results = []
if raw:
try:
obj = json.loads(raw)
items = obj.get("data", {}).get("diff", [])
for item in items:
results.append({
"name": item.get("f14", ""),
"change_pct": round(item.get("f3", 0), 2),
"leading_stock": item.get("f128", ""),
"leading_change_pct": round(item.get("f136", 0), 2),
"amount_yi": round(item.get("f20", 0) / 1e8, 2),
})
except Exception:
pass
return results
def fmt_stock(d: dict) -> str:
if "error" in d:
return f"{d['error']}"
sign = "+" if d["change"] >= 0 else ""
emoji = "🔴" if d["change"] >= 0 else "🟢"
lines = [
f"{emoji} {d['name']}{d['symbol'].upper()}",
f" 当前价:{d['current']}",
f" 涨跌幅:{sign}{d['change_pct']}% 涨跌额:{sign}{d['change']}",
f" 今开:{d['open']} 最高:{d['high']} 最低:{d['low']} 昨收:{d['prev_close']}",
f" 成交量:{d['volume_lot']:,} 手 成交额:{d['amount_yi']} 亿",
]
if "turnover_pct" in d:
lines.append(f" 换手率:{d['turnover_pct']}%")
lines.append(f" 数据来源:{d['source']} | 更新时间:{d.get('time', '')} {d['fetch_time']}")
return "\n".join(lines)
def fmt_index(items: list) -> str:
lines = ["📊 大盘指数实时行情"]
for d in items:
sign = "+" if d["change"] >= 0 else ""
emoji = "🔴" if d["change"] >= 0 else "🟢"
lines.append(
f" {emoji} {d['name']}: {d['current']:,.2f} {sign}{d['change']:+.2f} ({sign}{d['change_pct']}%)"
f" 成交额 {d['amount_yi']} 亿"
)
if items:
lines.append(f" 更新时间:{items[0]['fetch_time']}")
return "\n".join(lines)
def fmt_sectors(items: list) -> str:
lines = ["🔥 热点板块涨幅榜(概念板块 TOP20)"]
for i, d in enumerate(items, 1):
sign = "+" if d["change_pct"] >= 0 else ""
lines.append(
f" {i:2d}. {d['name']:<12} {sign}{d['change_pct']}%"
f" 龙头:{d['leading_stock']}({sign}{d['leading_change_pct']}%)"
f" 成交额:{d['amount_yi']}亿"
)
return "\n".join(lines)
def main():
parser = argparse.ArgumentParser(description="A股实时行情抓取")
parser.add_argument("--code", nargs="+", help="股票代码,支持多个(如 600519 000001")
parser.add_argument("--index", action="store_true", help="查询大盘指数")
parser.add_argument("--hot-sectors", action="store_true", help="查询热点板块")
parser.add_argument("--json", action="store_true", help="输出原始JSON")
args = parser.parse_args()
if args.index:
data = fetch_index()
if args.json:
print(json.dumps(data, ensure_ascii=False, indent=2))
else:
print(fmt_index(data))
return
if args.hot_sectors:
data = fetch_hot_sectors()
if args.json:
print(json.dumps(data, ensure_ascii=False, indent=2))
else:
print(fmt_sectors(data))
return
if args.code:
results = []
for code in args.code:
d = fetch_single_stock(code)
results.append(d)
if args.json:
print(json.dumps(results, ensure_ascii=False, indent=2))
else:
for d in results:
print(fmt_stock(d))
print()
return
parser.print_help()
if __name__ == "__main__":
main()