从零搭建 A 股量化分析助手:OpenCLAW + DeepSeek-V4-Pro 实战指南
关于如何使用这篇指南?(本文仅做技术探究,股市有风险,入市须谨慎)下载Trae,在solo模式下通过对话框将此文链接给他,告诉它按此文进行搭建即可
web端效果

飞书端效果

为什么选择 OpenCLAW
OpenCLAW 是开源 AI Agent 框架,内置 exec(执行本地脚本)、web_search(搜索实时资讯)、memorySearch(RAG 检索)等工具。通过 Gateway 本地运行,支持计划任务后台部署。
为什么选择 DeepSeek-V4-Pro
DeepSeek-V4-Pro 在国产大模型中能力与 GLM-5.1 同档,但 API 调用成本远低于后者,原生支持 tool calls,适合 Agent 工作流。
实现功能
-
个股实时行情:输入股票代码,返回现价、涨跌幅、最高最低、PE、成交额 -
个股买卖建议:结合实时数据 + 投资策略库,输出参考买入区间、止损位、目标位 -
多股估值对比:同时拉取多只股票数据,横向对比 PE/涨跌幅,给出优选结论 -
量化选股:五大因子评分(技术面/基本面/筹码峰/集中度/成交量震荡),TOP 推荐 -
盘中消息分析:搜索实时资讯,判断消息面对股价的影响 -
策略合规检查:检索用户自定的仓位/止损规则,检查持仓是否超标 -
盘前晨报/收盘复盘:自动生成外围市场、板块、自选股的结构化报告
技术栈
|
|
|
|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
| 东方财富 push2 API |
|
| 同花顺 time API |
|
|
|
|
| mootdx(通达信) |
|
| 腾讯财经 HTTP API |
|
| 同花顺财报 API |
|
|
|
|
|
|
|
|
|
memorySearch
|
一、环境准备
|
|
|
|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
安装 openclaw:
npm install -g openclaw@2026.5.20
安装 Python 依赖:
pip install requests beautifulsoup4 akshare pandas numpy mootdx
项目目录结构(后续章节会逐步创建)。
二、投资策略知识库
在 d:\workspace\openclaw\rag-docs\ 下创建以下三个文件。memorySearch 启动时会将它们向量化,之后每次股票分析都会自动检索这些策略。
选股标准
文件:rag-docs/投资策略-选股标准.md
# A股选股标准## 核心选股条件### 基本面筛选1. 市盈率(PE)< 30倍(金融股可放宽至15倍以内)2.ROE(净资产收益率)> 15%3. 流通市值 50亿 - 500亿4. 近三年营收复合增长 > 10%5. 资产负债率 < 60%(金融股除外)6. 经营现金流为正### 技术面筛选1. 股价位于20日均线之上2. 近20日处于上升趋势3. 成交量温和放大(非暴涨暴跌)4.MACD 处于金叉状态或即将金叉### 排除条件1.ST 股票、*ST 股票2. 上市不满 60 天的新股3. 近一月有重大负面新闻4. 股东近期有大额减持公告5. 地产、教培行业(政策风险高)## 评分体系(满分10分)| 维度 | 权重 | 标准 ||------|------|------|| 基本面 | 4分 | PE<20得4分, PE20-30得2分 || 技术面 | 3分 | 上升趋势+放量得3分 || 行业前景 | 2分 | 政策支持+景气周期得2分 || 资金面 | 1分 | 北向资金增持+融资余额增加得1分 |## 推荐等级-8-10分:强烈推荐-6-7分:推荐关注-4-5分:观望-1-3分:不推荐
风险控制
文件:rag-docs/投资策略-风险控制.md
# 风险控制规则## 仓位管理1. 单只股票仓位不超过总资金的 20%2. 同一行业持仓不超过总资金的 30%3. 总持仓不超过账户资金的 80%(保留20%现金)4. 单日新开仓不超过总资金的 10%## 止损规则1. 买入后亏损超过 -8%,无条件止损2. 从最高点回落超过 -10%,止盈离场3. 连续3天跑输大盘,减仓一半4. 单月亏损超过 -15%,当月停止交易## 交易纪律1. 不在开盘前30分钟和收盘前30分钟下单2. 不追涨停板(封板前已启动除外)3. 不在下跌趋势中加仓4. 不因利好消息冲动买入(等市场反应后再判断)5. 不持有一只股票超过3个月(除非明确长期投资逻辑)## 风控检查清单每次交易前确认:- [ ] 是否在止损线以内?- [ ] 单只股票仓位是否超标?- [ ] 该行业仓位是否集中?- [ ] 是否有明确的买入/卖出逻辑?- [ ] 是否情绪化操作?## 推荐风格- 偏好:稳健价值投资,追求年化 15-20% 收益- 持股周期:中线为主(2周-3个月)- 换手率:每月不超过5次交易- 止损纪律:严格执行,不存侥幸心理
行业偏好
文件:rag-docs/投资策略-行业偏好.md
# 行业偏好与关注方向## 重点关注行业### 1. 消费(白酒、食品饮料、家电)- 代表标的:贵州茅台、五粮液、美的集团### 2. 医药(创新药、医疗器械、中药)- 代表标的:恒瑞医药、迈瑞医疗、片仔癀### 3. 新能源(光伏、储能、电动车)- 代表标的:宁德时代、比亚迪、阳光电源### 4. 半导体(芯片设计、设备、材料)- 代表标的:中芯国际、北方华创### 5. 金融(银行、保险)- 代表标的:招商银行、中国平安## 不关注/排除行业1. 房地产及其产业链2. 教育培训(K12相关)3. 高污染/高能耗行业4. 商业模式不清晰的公司5. 过度依赖政府补贴的公司
三、配置 openclaw.json
编辑 C:\Users\admin\.openclaw\openclaw.json。以下为完整配置文件,关键位置已添加注释。复制后替换 apiKey 和 token 即可使用。
{"models": {"providers": {// ========== DeepSeek API (主力模型 + 备用模型) =========="deepseek-api": {"baseUrl": "https://api.deepseek.com/v1","apiKey": "sk-你的DeepSeek_API密钥","api": "openai-completions","models": [ { "id": "deepseek-v4-pro", "name": "DeepSeek-V4-Pro" }, { "id": "deepseek-v4-flash", "name": "DeepSeek-V4-Flash" } ] },// ========== 阿里百炼 (embedding 模型,用于 RAG 检索) =========="dashscope": {"baseUrl": "https://dashscope.aliyuncs.com/compatible-mode/v1","apiKey": "sk-你的百炼API密钥","api": "openai-completions","models": [ { "id": "text-embedding-v3", "name": "text-embedding-v3" } ] } } },"agents": {"defaults": {// ========== 默认模型 =========="model": { "primary": "deepseek-api/deepseek-v4-pro" },// ========== Agent 工作目录 =========="workspace": "C:\\Users\\admin\\.openclaw\\workspace",// ========== RAG 知识库 (检索投资策略文档) =========="memorySearch": {"enabled": true,"sources": ["memory", "sessions"],"extraPaths": ["d:\\workspace\\openclaw\\rag-docs"],"provider": "dashscope","model": "text-embedding-v3","query": {"hybrid": {"enabled": true,"vectorWeight": 0.7,"textWeight": 0.3 } } } },"list": [{"id": "ollama-local","model": {"primary": "deepseek-api/deepseek-v4-pro","fallbacks": ["deepseek-api/deepseek-v4-flash"] },// ========== 工具权限(exec 为必开项) =========="tools": {"alsoAllow": ["memory_search","memory_get","browser","canvas","agents_list","exec","web_search","web_fetch" ],"deny": [] } }] },// ========== Gateway 服务 =========="gateway": {"port": 18789,"mode": "local","auth": {"mode": "token","token": "你的网关令牌(自定义字符串)" } }}
配置要点:
|
|
|
|---|---|
| deepseek-api |
|
| dashscope |
|
| memorySearch.enabled |
true,否则不检索策略库 |
| memorySearch.extraPaths |
|
| tools.alsoAllow
|
|
| tools.alsoAllow
|
|
| gateway.port |
|
| gateway.auth.token |
|
四、部署量化脚本
4.1 安装基础技能
量化选股脚本依赖 clawhub 上的两个基础技能:
-
stock-watcher:自选股管理技能,提供自选股的增删查改脚本(add/remove/list),以及自选股文件初始化。安装后 skills/stock-watcher/scripts/下的四个 Python 脚本可直接使用。 -
quant-stock-selector:量化选股技能,提供六大因子计算引擎(factor_calculator.py)、筹码分布计算(chip_distribution.py)和成交量震荡检测(volume_spike_oscillation.py)。这三个模块是后续 stock_scanner.py批量选股的底层依赖,安装后自动就位。
在终端执行安装:
openclaw skill install stock-watcheropenclaw skill install quant-stock-selector
4.2 部署 SearXNG 搜索引擎(web_search 后端)
web_search 工具需要一个搜索引擎后端来执行实际的搜索请求。推荐自部署 SearXNG——隐私安全、无配额限制、聚合 Google/Bing/DuckDuckGo 等多引擎结果。
在远程服务器上用 Docker 部署:
# 1. 拉取镜像并启动(单 worker,适合个人使用)docker run -d --name searxng \ -p 18080:8080 \ -e SEARXNG_WORKERS=1 \ searxng/searxng:latest# 2. 查看日志,确认启动成功docker logs searxng --tail 20# 看到 "running at http://0.0.0.0:8080" 即成功# 3. 开放防火墙端口(如使用云服务器)# 阿里云/腾讯云安全组 → 入方向 → 允许 TCP 18080
如果看到
RuntimeError: can't start new thread,说明线程数超限。删掉容器重新启动,加上-e SEARXNG_WORKERS=1并--ulimit nproc=65535:65535即可。
获取 SearXNG 地址:http://你的服务器IP:18080/
配置 openclaw.json:
"plugins": {"entries": {"searxng": {"enabled": true,"config": {"webSearch": {"baseUrl": "http://你的服务器IP:18080" } } } }}
重启 Gateway 后,web_search 工具即可正常使用。所有搜索请求链路:模型 → Gateway → 远程 SearXNG → 聚合搜索 → 返回结果。
安装后 skills/ 目录下自动生成以下文件结构:
skills/├── stock-watcher/│ └── scripts/│ ├── add_stock.py ← 添加自选股│ ├── remove_stock.py ← 删除自选股│ ├── list_stocks.py ← 列出自选股列表│ └── config.py ← 自选股路径配置└── quant-stock-selector/ └── factors/ ├── factor_calculator.py ← 六大因子计算引擎 ├── chip_distribution.py ← 筹码分布计算 └── volume_spike_oscillation.py ← 成交量震荡检测
以上文件来自 clawhub 安装,无需手动创建。原版技能的功能不足以支撑实际的股票分析需求,以下列出新增或重写的脚本,按顺序创建到对应目录即可。
4.3 实时行情(新增)
创建文件:skills/stock-watcher/scripts/get_stock_quote.py
数据源:东方财富 push2 API(主)+ 同花顺 time API(备)。东方财富 API 返回 PE 数据,不可用时自动回退至同花顺。
用法:python get_stock_quote.py 600519 或 python get_stock_quote.py 600519 600036 000858
输出格式:600519 贵州茅台 price=1290.2 -1.59%(down) high=1310.95 low=1290.2 pre=1311.0 PE14.83 vol=63.72yi [EM]
[EM] 表示东方财富数据源,[THS] 表示同花顺回退。
import sys, requests, re, jsonEM_H = {'User-Agent': 'Mozilla/5.0', 'Referer': 'https://quote.eastmoney.com/'}THS_H = {'User-Agent': 'Mozilla/5.0', 'Referer': 'https://stockpage.10jqka.com.cn/'}def_em(code):try: mkt = '1'if code.startswith('6') else'0' url = 'https://push2.eastmoney.com/api/qt/stock/get?secid=%s.%s&fields=f43,f44,f45,f46,f47,f48,f57,f58,f60,f162,f170,f171' % (mkt, code) r = requests.get(url, headers=EM_H, timeout=10) d = r.json().get('data')ifnot d:returnNonereturn {'price': d['f43'] / 100,'high': d['f44'] / 100,'low': d['f45'] / 100,'pre': d.get('f60', 0) / 100,'pct': d['f170'] / 100,'pe': round(d['f162'] / 100, 2) if d.get('f162') and d['f162'] > 0else'N/A','name': d.get('f58', code),'amount': round(d['f48'] / 1e8, 2), }except Exception:returnNonedef_ths(code):try: url = 'https://d.10jqka.com.cn/v6/time/hs_%s/last.js' % code r = requests.get(url, headers=THS_H, timeout=10) m = re.search(r'quotebridge[^(]+\((.+)\)', r.text, re.DOTALL)ifnot m:returnNone stock = json.loads(m.group(1)).get('hs_%s' % code)ifnot stock:returnNone pre = float(stock['pre']) ticks = [t.split(',') for t in stock.get('data', '').split(';') if t.strip()] prices = [float(t[1]) for t in ticks if len(t) >= 2and t[1]]ifnot prices:returnNone cur = prices[-1]return {'price': cur,'high': max(prices),'low': min(prices),'pre': pre,'pct': round((cur - pre) / pre * 100, 2),'pe': 'N/A','name': stock['name'],'amount': 0, }except Exception:returnNonecodes = [a for a in sys.argv[1:] if a.isdigit() and len(a) == 6]ifnot codes: codes = ['600519']for c in codes: d = _em(c) src = 'EM'ifnot d: d = _ths(c) src = 'THS'ifnot d: print(c + ' data unavailable')continue arrow = '+'if d['pct'] > 0else'' fx = 'up'if d['pct'] > 0else'down'if d['pct'] < 0else'flat' yd = ' !!ALERT!!'if abs(d['pct']) >= 5else'' peer = (' PE' + str(d['pe'])) if d['pe'] != 'N/A'else'' amt = (' vol=' + str(d['amount']) + 'yi') if d['amount'] > 0else'' print(c + ' ' + d['name'] +' price=' + str(d['price']) +' ' + arrow + str(d['pct']) + '%(' + fx + ')' + yd +' high=' + str(d['high']) +' low=' + str(d['low']) +' pre=' + str(d['pre']) + peer + amt +' [' + src + ']')
4.4 多源数据层(新增)
K 线数据双源回退:东方财富 → mootdx 通达信 TCP。基本面数据三源:腾讯财经(PE/PB)+ 同花顺财报(ROE 自动年化/营收增速/利润增速)+ 东方财富(兜底)。
创建文件:skills/quant-stock-selector/data/__init__.py(空文件)
创建文件:skills/quant-stock-selector/data/akshare_data.py
ROE 年化规则:Q1(03-31) 数据自动 ×4,Q2(06-30) ×2,Q3(09-30) ×4/3,Q4(12-31) 不需调整。确保跨季度比较公平。
import pandas as pdimport akshare as akimport requestsfrom datetime import datetime, timedeltaclassAKShareData:# K线双源回退:东方财富(HTTP) → mootdx 通达信(TCP)# PE/PB:腾讯财经(HTTP) → 东方财富(兜底)# ROE/营收增速/利润增速:同花顺财报(THS)defget_history_kline(self, stock_code): end = datetime.now().strftime('%Y%m%d') start = (datetime.now() - timedelta(days=365)).strftime('%Y%m%d') df = self._kline_em(stock_code, start, end)if df isnotNone:return df df = self._kline_mootdx(stock_code)if df isnotNone:return dfreturn pd.DataFrame()def_kline_em(self, code, start, end):# 东方财富 K 线(主数据源),列名中文需重命名try: df = ak.stock_zh_a_hist(symbol=code, period='daily', start_date=start, end_date=end, adjust='qfq')if df isnotNoneandnot df.empty: df = df.rename(columns={'开盘': 'open', '最高': 'high', '最低': 'low','收盘': 'close', '成交量': 'volume'}) df['date'] = pd.to_datetime(df['日期']) df = df.set_index('date').sort_index()return df[['open', 'high', 'low', 'close', 'volume']]except Exception:passreturnNonedef_kline_mootdx(self, code):# mootdx 通达信 TCP 直连(备数据源),零鉴权不封 IP# 注意:datetime 列与 index 重复,需先删除try:from mootdx.quotes import Quotes mkt = 1if code.startswith('6') else0 symbol = mkt * 1000000 + int(code) client = Quotes.factory(market='std', timeout=15) df = client.bars(symbol=symbol, frequency=9, start=0, offset=800)if df isnotNoneandnot df.empty:if'datetime'in df.columns: df = df.drop(columns=['datetime'], errors='ignore') df['date'] = pd.to_datetime(df.index) df = df.set_index('date').sort_index() cols = [c for c in ['open', 'high', 'low', 'close', 'volume'] if c in df.columns]if len(cols) >= 4:return df[cols]except Exception:passreturnNonedefget_financial_indicators(self, stock_code):# PE/PB 优先腾讯财经(零鉴权 HTTP),失败回退东方财富 result = self._fundamentals_tencent(stock_code)if result isNone: result = self._fundamentals_em(stock_code)# ROE/营收增速/利润增速 从同花顺财报获取真实数据# 返回 (年化ROE, 营收增速%, 利润增速%, 报告期) annual_roe, rev_growth, profit_growth, period = self._fundamentals_ths(stock_code) result['roe'] = annual_roe result['revenue_growth'] = rev_growth result['profit_growth'] = profit_growth result['report_period'] = periodreturn resultdef_fundamentals_tencent(self, code):# 腾讯财经实时行情接口,~ 分隔 GBK 编码# 索引 39=PE(TTM),索引 46=PB(不是 43!全网教程都写错了)try: prefix = 'sh'if code.startswith('6') else'sz' r = requests.get('http://qt.gtimg.cn/q=%s%s' % (prefix, code), headers={'User-Agent': 'Mozilla/5.0'}, timeout=8) r.encoding = 'gbk' parts = r.text.split('~') pe = float(parts[39]) if len(parts) > 39and parts[39] else15 pb = float(parts[46]) if len(parts) > 46and parts[46] else2return {'pe': max(0.1, pe), 'pb': max(0.1, pb),'roe': 10, 'gross_margin': 30,'revenue_growth': 5, 'profit_growth': 5,'report_period': 'default'}except Exception:returnNonedef_fundamentals_em(self, code):return {'pe': 15, 'pb': 2, 'roe': 10, 'gross_margin': 30,'revenue_growth': 5, 'profit_growth': 5,'report_period': 'default'}def_fundamentals_ths(self, code):# 同花顺财报摘要接口,返回最新季度的 ROE/营收增速/利润增速# ROE 是单季度值,需要根据报告期月份年化try: df = ak.stock_financial_abstract_ths(symbol=code, indicator='按报告期')if df isnotNoneandnot df.empty: latest = df.tail(1).iloc[0] roe_raw = latest.get('净资产收益率', 0) roe_val = float(str(roe_raw).replace('%', '')) if roe_raw else10 period = str(latest.get('报告期', ''))# 根据报告期月份确定 ROE 年化倍率# Q1(03-31): ×4 | Q2(06-30): ×2 | Q3(09-30): ×4/3 | Q4(12-31): ×1 multiplier = 1.0if'-03-31'in period: multiplier = 4.0elif'-06-30'in period: multiplier = 2.0elif'-09-30'in period: multiplier = 4.0 / 3.0 annual_roe = max(0.1, roe_val * multiplier) rev_growth = self._parse_pct(latest.get('营业总收入同比增长率', 0)) profit_growth = self._parse_pct(latest.get('净利润同比增长率', 0))return (annual_roe, max(-100, min(100, rev_growth)), max(-100, min(100, profit_growth)), period)except Exception:passreturn (10, 5, 5, 'default') @staticmethoddef_parse_pct(val):# 处理同花顺字段的特殊值:None/空/False 都视为中性值 5%if val isNoneor val == ''or str(val).lower() == 'false':return5try:return float(str(val).replace('%', ''))except (ValueError, AttributeError):return5
创建文件:skills/quant-stock-selector/factors/__init__.py(空文件)
__init__.py为空文件,作用是让 Python 将目录识别为包,stock_scanner.py中的from data.akshare_data import ...才能正常执行。
4.5 批量选股扫描器(新增)
创建文件:skills/quant-stock-selector/stock_scanner.py
五大因子评分体系(优化版公式):
|
|
|
|
|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
评分 0-100。60 以上关注,80 以上推荐。
基本面评分公式(PE 按行业区分):
-
PE 得分 = 行业基准 / PE(银行基准=6,科技基准=25,新能源基准=20,默认=12) -
PB 得分 = 2 / PB(PB<2 → 满分,PB=7 → 0.28) -
ROE 得分 = 年化 ROE / 20%(ROE≥20% → 满分) -
增长率得分 = (营收增速 + 利润增速) / 60%
用法:python stock_scanner.py(扫描自选股)或 python stock_scanner.py 600519 000858 300750(指定代码)
import sys, json, pandas as pdfrom data.akshare_data import AKShareDatafrom factors.factor_calculator import FactorCalculatorfrom factors.chip_distribution import ChipDistributionCalculatorfrom factors.volume_spike_oscillation import VolumeSpikeOscillationCalculatordefscan_stock(code, calc):# 单只股票全因子扫描:K线获取 → 技术面 → 基本面 → 筹码峰 → 成交量震荡 → 综合评分 data = AKShareData() df = data.get_history_kline(code)if df.empty:returnNone tech = calc.calculate_technical_factors(df) fund = calc.calculate_fundamental_factors(code)# 筹码峰因子(含上方压力/获利盘/近期涨幅/90%集中度) chip_score = 0 pressure_ratio = 100try: chip_calc = ChipDistributionCalculator() chip_result = chip_calc.calculate_chip_score(df) chip_score = chip_result.get('score', 0) pressure_ratio = chip_result['details']['pressure_ratio']except: pass# 成交量震荡因子(放量检测 + 缩量洗盘判断) vol_score = 0try: vol_calc = VolumeSpikeOscillationCalculator() vol_result = vol_calc.calculate_volume_oscillation_score(df) vol_score = vol_result.get('score', 0)except: pass chip_factors = {'chip_score': chip_score, 'details': {'pressure_ratio': pressure_ratio}} vol_factors = {'volume_score': vol_score} score = calc.calculate_combined_score(tech, fund, chip_factors, vol_factors)# 直接取原始 PE 值(不再反推) pe = fund.get('raw_pe', 99)ifnot isinstance(pe, (int, float)) or pe > 1000or pe <= 0: pe = 99return {'code': code,'score': round(score, 2),'pe': round(pe, 1),'kline_days': len(df), }defload_watchlist():# 从 watchlist.txt 加载自选股代码# 格式:每行 "股票代码|股票名称" path = r'C:\Users\admin\.clawdbot\stock_watcher\watchlist.txt' codes = []try:with open(path, encoding='utf-8') as f:for line in f: line = line.strip()if line and'|'in line: codes.append(line.split('|')[0].strip())except FileNotFoundError: passreturn codesdefmain(): codes = [a for a in sys.argv[1:] if a.isdigit() and len(a) == 6]ifnot codes: codes = load_watchlist()ifnot codes: print('无候选股票。示例: python stock_scanner.py 600519 000858 300750')return calc = FactorCalculator() results = []for code in codes:try: r = scan_stock(code, calc)if r: results.append(r) print(" %s 综合得分: %.1f PE: %.1f K线: %d天" % (code, r['score'], r['pe'], r['kline_days']))else: print(" %s 数据获取失败" % code)except Exception as e: print(" %s 错误: %s" % (code, e))ifnot results: print('所有股票数据获取失败')return# 按综合得分降序排列,取 TOP5 results.sort(key=lambda x: x['score'], reverse=True) print('\n' + '=' * 40) print('TOP 推荐') print('=' * 40)for i, r in enumerate(results[:5], 1): badge = '***'if r['score'] >= 80else'**'if r['score'] >= 60else'*' print("#%d %s 得分: %.1f PE: %.1f %s" % (i, r['code'], r['score'], r['pe'], badge)) print('\n评分标准: 60+关注 80+强烈推荐 满分100')if __name__ == '__main__': main()
4.6 自选股管理(来自 clawhub,无需手动创建)
以下脚本由
openclaw skill install stock-watcher自动安装,列出仅供了解,无需手动创建。
list_stocks.py — 列出自选股列表
自选股文件路径:C:\Users\admin\.clawdbot\stock_watcher\watchlist.txt,格式每行 股票代码|股票名称。
初始化示例(创建文件并写入8只基础股票:4只银行 + 4只科技):
600036|招商银行601398|工商银行601166|兴业银行000001|平安银行688981|中芯国际002415|海康威视002371|北方华创688111|金山办公
4.7 数据源健康检查(新增)
创建文件:skills/stock-watcher/scripts/health_check.py
用法:python health_check.py
import requests, re, jsondefcheck_em():try: r = requests.get('https://push2.eastmoney.com/api/qt/stock/get?secid=1.600036&fields=f43,f58', headers={'User-Agent': 'Mozilla/5.0'}, timeout=8) d = r.json().get('data')if d and d.get('f58'):returnTrue, str(d['f43'] / 100)except: passreturnFalse, 'FAIL'defcheck_ths():try: r = requests.get('https://d.10jqka.com.cn/v6/time/hs_600036/last.js', headers={'User-Agent': 'Mozilla/5.0', 'Referer': 'https://stockpage.10jqka.com.cn/'}, timeout=8) m = re.search(r'quotebridge[^(]+\((.+)\)', r.text, re.DOTALL) d = json.loads(m.group(1))['hs_600036']returnTrue, d['name'] + ' ' + d['pre']except: passreturnFalse, 'FAIL'defcheck_tencent():try: r = requests.get('http://qt.gtimg.cn/q=sh600036', headers={'User-Agent': 'Mozilla/5.0'}, timeout=8) r.encoding = 'gbk' parts = r.text.split('~')returnTrue, 'PE=' + parts[39] + ' PB=' + parts[46]except: passreturnFalse, 'FAIL'defcheck_mootdx():try:from mootdx.quotes import Quotes client = Quotes.factory(market='std', timeout=10) df = client.bars(symbol=600036, frequency=9, start=0, offset=1)returnTrue, str(len(df)) + ' bars'except: passreturnFalse, 'FAIL'em_ok, em_info = check_em()ths_ok, ths_info = check_ths()tx_ok, tx_info = check_tencent()mdx_ok, mdx_info = check_mootdx()print('Data Source Health Check')print('-' * 45)print('EastMoney ', 'OK ' + em_info if em_ok else'FAIL')print('TongHuaShun ', 'OK ' + ths_info if ths_ok else'FAIL')print('Tencent ', 'OK ' + tx_info if tx_ok else'FAIL')print('Mootdx(TDX)', 'OK ' + mdx_info if mdx_ok else'FAIL')print('-' * 45)print('K-line sources:', sum([em_ok, ths_ok, mdx_ok]), 'available')print('PE sources:', 'EM+TX'if em_ok and tx_ok else ('TX only'if tx_ok else'NONE'))
五、配置助手身份
5.1 SOUL.md
文件:C:\Users\admin\.openclaw\workspace\SOUL.md
# SOUL.md - 专业A股量化分析助手## 身份A股量化分析助手。精通技术面、基本面、资金面分析。数据源:东方财富+同花顺双活。## 核心铁律:禁止凭空编造数据分析任何涉及股价/PE/涨跌的问题时,必须先用 exec 拉实时数据:cd C:/Users/admin/.openclaw/workspace/skills/stock-watcher/scripts && python get_stock_quote.py <代码>输出末尾 [EM] 表示东方财富源(含PE),[THS] 表示同花顺回退(无PE)。## 财务分析铁律给出买卖建议前,必须用 web_search 搜索该公司最近一季度或最近年度的营收、净利润、经营现金流数据。PE 可能因利润波动而产生误导,不结合财务数据做判断属于高风险分析。搜索模板:- "XX 2026年一季度 营收 净利润"- "XX 2025年报 营收 净利润 现金流"## 分析时必须调用的工具| 场景 | 必须先执行 ||------|-----------|| 个股分析 | 1. python get_stock_quote.py <代码> 2. web_search 搜索该公司最新季度营收、净利润、现金流 || 选股推荐 | python stock_scanner.py || 批量行情 | python get_stock_quote.py <代码1><代码2> ... || 组合分析 | memory_search 查投资策略 || 行业/板块 | web_search 搜实时消息 || 数据源诊断 | python health_check.py |## 分析模板【结论】买/卖/观望(一句话)【实时数据】价格/涨跌/PE/成交 - 标注 exec 获取+数据源【财务数据】最近季度 营收/净利润/现金流 - 标注 web_search 来源,判断增收还是降收【理由】核心逻辑(结合财务 + 技术面 + 策略)【价位】建议买入区间 XX-XX | 止损 XX | 目标 XX【风险】关注点(财务风险如果有需特别标注)## 禁止输出- 免责声明套话- 无数据来源的价格/PE- 堆砌无关知识
5.2 TOOLS.md
文件:C:\Users\admin\.openclaw\workspace\TOOLS.md
# 股票工具命令速查## 单股实时行情(分析任何股票前必须调用)cd C:/Users/admin/.openclaw/workspace/skills/stock-watcher/scripts && python get_stock_quote.py <代码>## 量化选股cd C:/Users/admin/.openclaw/workspace/skills/quant-stock-selector && python stock_scanner.py## 批量行情cd C:/Users/admin/.openclaw/workspace/skills/stock-watcher/scripts && python get_stock_quote.py <代码1><代码2> ...## 自选股列表cd C:/Users/admin/.openclaw/workspace/skills/stock-watcher/scripts && python list_stocks.py## 添加自选股 / 删除自选股cd C:/Users/admin/.openclaw/workspace/skills/stock-watcher/scripts && python add_stock.py <代码>cd C:/Users/admin/.openclaw/workspace/skills/stock-watcher/scripts && python remove_stock.py <代码>## 盘前晨报 / 收盘复盘## 使用铁律分析任何股票 → 立刻 exec get_stock_quote.py 拉实时数据禁止凭训练数据回答价格/PE/涨跌幅问题
六、启动 Gateway
打开 cmd,执行:
openclaw gateway --port 18789
浏览器访问 http://127.0.0.1:18789/,输入 openclaw.json 中设置的 gateway.auth.token 完成配对。
七、应用场景
7.1 个股实时行情
用户:招商银行现在什么价位 PE 多少
模型执行:**exec** python get_stock_quote.py 600036
输出:
【实时数据】600036 招商银行 price=37.02 -0.35%(down) high=37.33 low=36.99 pre=37.15 PE10.9 vol=21.96yi [EM]【结论】PE 10.9 处于银行股合理区间。价格 37.02,距昨收 37.15 跌 0.35%。
7.2 个股买卖建议
用户:茅台现在值得买入吗 给个参考价位
模型执行:
-
**exec** python get_stock_quote.py 600519 -
web_search 搜索”贵州茅台 2026年一季度 营收 净利润” -
**memory_search**检索选股标准
输出:
【结论】观望,等回调至建仓区间【实时数据】600519 贵州茅台 price=1290.2 -1.59%(down) high=1310.95 low=1290.2 pre=1311.0 PE14.83【财务数据】2026Q1 营收 456 亿(+12%)| 净利润 241 亿(+14%)| 经营现金流 198 亿(+11%)营收利润双增,基本面健康【理由】PE 14.83,对应 14% 利润增速 PEG 约 1.06,估值合理但非低估。今日跌 1.59%,成交 63.72 亿放量下跌。20 日均线 1325,当前价格已跌破。【价位】买入区间 1200-1250(PE 14 以下对应价格)止损位 1150(-8%)目标位 1400【风险】白酒消费税改革预期、北向资金持续流出
7.3 多股估值对比
用户:茅台和五粮液哪个更值得买
模型执行:
-
**exec** python get_stock_quote.py 600519 000858 -
**memory_search**检索行业偏好
输出:
【结论】五粮液性价比高于茅台【对比】 茅台 五粮液price 1290.2 84.03pct -1.59% -1.55%PE 14.83 10.11【理由】五粮液 PE 10.11 低于茅台 14.83,估值折价明显。两者均跌约 1.5%。五粮液分红率更高,年内涨幅落后大盘有补涨空间。【价位】五粮液买入区间 78-82 | 止损 74茅台等回调至 1200-1250 再考虑
7.4 盘中消息分析
用户:宁德时代跌了 2% 新能源有什么消息
模型执行:
-
**exec** python get_stock_quote.py 300750 -
web_search 搜索”新能源 板块 消息”
输出:
【结论】短期消息面偏空,技术面未破位【实时数据】300750 宁德时代 price=411.16 -0.11%(down) high=416.37 low=410.44 pre=411.63【消息】特斯拉 Q2 交付不及预期,拖累新能源板块工信部发布动力电池回收新规,利好长期【技术面】20 日均线 418 | 已跌破MACD 死叉 | RSI 42 偏弱支撑位 400 | 压力位 420【建议】持仓可继续持有,止损放 400。未建仓等回到 418 之上再考虑。
7.5 策略合规检查
用户:宁德时代占我 25% 仓位 合规吗
模型执行:**memory_search** 检索投资策略-风险控制
输出:
【结论】超标 5%,建议减仓【策略规定】单只股票不超过总仓位 20%同行业(新能源)不超过 30%【当前情况】宁德时代占 25%(超标 5%)【建议】减仓至 20% 以下,或等反弹减仓
7.6 量化选股推荐
用户:用量化模型推荐 3 只
模型执行:**exec** python stock_scanner.py
输出:
扫描 8 只股票...#1 600036 招商银行 得分: 78.5 PE: 10.9 ***#2 002594 比亚迪 得分: 72.3 PE: 28.1 **#3 600519 贵州茅台 得分: 68.7 PE: 14.8 **评分标准: 60+关注 80+强烈推荐 满分100
7.7 每日使用节奏
|
|
|
|
|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
八、架构总览
浏览器 UI │ WebSocketGateway (exec / web_search / memorySearch) │ ├── exec → Python 脚本 │ ├── 东方财富 API(主,含 PE) │ └── 同花顺 API(备,不含 PE) │ ├── web_search → 实时资讯 │ └── memorySearch → RAG 投资策略库
九、相关文件索引
|
|
|
|
|---|---|---|
|
|
C:\Users\admin\.openclaw\**openclaw.json** |
|
|
|
C:\Users\admin\.openclaw\workspace\SOUL.md |
|
|
|
C:\Users\admin\.openclaw\workspace\TOOLS.md |
|
|
|
skills/stock-watcher/scripts/get_stock_quote.py |
|
|
|
skills/quant-stock-selector/stock_scanner.py |
|
|
|
skills/stock-watcher/scripts/health_check.py |
|
|
|
skills/stock-watcher/scripts/ |
|
|
|
d:\workspace\openclaw\rag-docs\ |
|
十、相关概念速查
估值指标
|
|
|
|
|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
技术面指标
|
|
|
|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
筹码指标
|
|
|
|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
交易术语
|
|
|
|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
财务指标
|
|
|
|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
附录:飞书接入
将助手接入飞书后,可在飞书群聊中 @机器人 查询行情或获取分析建议,无需打开浏览器。
一、飞书开放平台创建应用
-
访问 飞书开放平台,登录后进入「开发者后台」 -
创建企业自建应用,填写应用名称(如「股票助手」) -
在「安全设置」中,添加机器人能力 -
在「权限管理」中,搜索并开启以下权限: -
获取用户在群组中 @ 机器人消息 -
获取群组信息 -
获取与发送单聊、群组消息 -
发布版本,等待管理员审批上线 -
审批通过后,在应用首页复制 App ID和App Secret
二、配置飞书通道
拿到 App ID 和 App Secret 后,执行以下命令,按向导填写即可:
openclaw channels add feishu
命令会交互式引导您输入 App ID、App Secret 等参数,自动写入 openclaw.json 并验证连接。无需手动编辑配置文件。
如需手动配置,在 openclaw.json 中追加以下内容:
{"plugins": {"entries": {"feishu": {"enabled": true } } },"channels": {"feishu": {"enabled": true,"groupPolicy": "open","appId": "cli_xxxxxxxxxxxx","appSecret": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx","requireMention": true } }}
配置项说明:
|
|
|
|---|---|
plugins.entries.feishu.enabled |
true 启用飞书插件 |
channels.feishu.enabled |
true 启用飞书通道 |
channels.feishu.groupPolicy |
open
|
channels.feishu.appId |
|
channels.feishu.appSecret |
|
channels.feishu.requireMention |
true
|
安全隔离:创建飞书专用 Agent
考虑到飞书群中可能有多个用户,为防止通过飞书对话误改代码或配置,建议为飞书创建独立的 Agent,与网页 UI 使用的 Agent 分离:
# 1. 创建飞书专用 Agent 目录mkdir %USERPROFILE%\.openclaw\agents\feishu-agent\agent# 2. 将飞书通道绑定到新 Agentopenclaw agents add feishu-agent --workspace C:\Users\<用户名>\.openclaw\workspaceopenclaw agents bind --agent feishu-agent --bind feishu
然后在 openclaw.json 中确认飞书 Agent 的工具权限只包含查询类工具:
"feishu-agent": {"tools": {"alsoAllow": ["memory_search", "memory_get", "exec", "web_search", "web_fetch"],"deny": [] }}
在 C:\Users\<用户名>\.openclaw\agents\feishu-agent\agent\SOUL.md 中加入只读约束:
你绝对不能修改、删除、创建、覆盖任何文件。如果用户要求修改文件或执行非查询命令,直接回复”飞书频道仅支持股票查询,不支持文件操作”。
这样飞书用户只能查行情、搜索资讯、检索策略,无法通过对话修改脚本或配置。
三、使用方式
在飞书群中添加机器人后,@机器人 并发送消息:
@股票助手 招商银行 PE 多少@股票助手 茅台现在值得买入吗@股票助手 用量化模型跑一下自选股
助手的行为与网页版一致:自动调用 exec 拉行情、web_search 搜财务数据、memorySearch 检索策略库,然后返回分析建议。
夜雨聆风