周红伟:OpenClaw Skills 股票与加密货币分析(Stock Analysis)技能使用参考手册
·
概述
Stock Analysis是一个用于分析股票和加密货币的OpenClaw技能,支持8维度股票分析、加密货币分析、投资组合管理、观察列表、股息分析、热门扫描和谣言扫描功能。该技能整合了Yahoo Finance、CoinGecko、CNN Fear & Greed Index、SEC EDGAR等多个数据源,能够为用户提供清晰的BUY/HOLD/SELL投资建议,并附带详细的支持点和风险提示,帮助用户做出更明智的投资决策。
该技能特别适合两类场景:一类是你要做"快评内容",另一类是你要做"结构化研究笔记",把零散信息收敛成可复用的判断。
技能信息
- 名称:stock-analysis
- 描述:使用Yahoo Finance数据分析股票和加密货币,支持投资组合管理、带警报的观察列表、股息分析、8维度股票评分、热门趋势检测(Hot Scanner)和谣言/早期信号检测(Rumor Scanner)。可用于股票分析、投资组合跟踪、收益反应分析、加密货币监控、热门股票发现,或在主流新闻之前找到市场谣言。
- 版本:6.2.0
- 作者:udiedrichsen
- 主页:
https://finance.yahoo.com - 依赖:
- Python 3.10+
- yfinance>=0.2.40
- pandas>=2.0.0
- fear-and-greed>=0.4
- edgartools>=2.0.0
- feedparser>=6.0.0
- 安装命令:
npx clawhub@latest install stock-analysis - 支持的命令:
/stock- 分析股票或加密货币(例如:/stock AAPL)/stock_compare- 比较多个代码/stock_dividend- 分析股息指标/stock_watch- 添加/移除观察列表/stock_alerts- 检查触发的警报/stock_hot- 查找热门股票和加密货币(Hot Scanner)/stock_rumors- 查找早期信号、并购谣言、内幕交易活动(Rumor Scanner)/portfolio- 显示投资组合摘要/portfolio_add- 向投资组合添加资产
👤 作者:udiedrichsen
🦞 官方地址:https://clawhub.ai/udiedrichsen/stock-analysis
👉 Skills 下载地址:stock-analysis-6.2.0.zip
快速开始
股票分析
## 基本分析uv run scripts/analyze_stock.py AAPL## 快速模式(跳过内幕交易和突发新闻)uv run scripts/analyze_stock.py AAPL --fast## 比较多个股票uv run scripts/analyze_stock.py AAPL MSFT GOOGL## 加密货币分析uv run scripts/analyze_stock.py BTC-USD ETH-USD
股息分析
## 分析股息uv run scripts/dividends.py JNJ## 比较股息股票uv run scripts/dividends.py JNJ PG KO MCD --output json
观察列表与警报
## 添加到观察列表uv run scripts/watchlist.py add AAPL## 带价格目标警报uv run scripts/watchlist.py add AAPL --target 200## 带止损警报uv run scripts/watchlist.py add AAPL --stop 150## 信号变化警报uv run scripts/watchlist.py add AAPL --alert-on signal## 查看观察列表uv run scripts/watchlist.py list## 检查触发的警报uv run scripts/watchlist.py check## 移除观察列表uv run scripts/watchlist.py remove AAPL
投资组合管理
## 创建投资组合uv run scripts/portfolio.py create "Tech Portfolio"## 添加资产uv run scripts/portfolio.py add AAPL --quantity 100 --cost 150uv run scripts/portfolio.py add BTC-USD --quantity 0.5 --cost 40000## 查看投资组合uv run scripts/portfolio.py show## 分析投资组合uv run scripts/analyze_stock.py --portfolio "Tech Portfolio" --period weekly
热门扫描
## 完整扫描python3 scripts/hot_scanner.py## 快速扫描(跳过社交媒体)python3 scripts/hot_scanner.py --no-social## JSON输出python3 scripts/hot_scanner.py --json
谣言扫描
## 查找早期信号、并购谣言、内幕交易活动python3 scripts/rumor_scanner.py
功能详解
1. 股票分析
股票分析功能提供8维度的全面分析,包括:
- 收益惊喜(30%权重):EPS超出/低于预期的情况
- 基本面(20%权重):市盈率、利润率、增长率等
- 分析师情绪(20%权重):评级和目标价格
- 历史模式(10%权重):过去的收益反应
- 市场环境(10%权重):VIX指数、SPY/QQQ趋势
- 行业表现(15%权重):相对行业强度
- 动量(15%权重):RSI、52周区间
- 情绪(10%权重):恐惧/贪婪指数、空头头寸、内幕交易
分析结果会生成清晰的BUY/HOLD/SELL建议,并附带支持点和风险提示。
2. 加密货币分析
加密货币分析提供3维度的分析,包括:
- 市值与分类:加密货币的市值排名和分类
- BTC相关性:30天内与比特币的相关性
- 动量:RSI和价格区间
3. 股息分析
股息分析功能提供以下指标:
- 股息收益率:年度股息/价格
- 派息率:股息/EPS
- 5年增长率:股息的复合年增长率
- 连续增长年数:连续增加股息的年数
- 安全评分:0-100的综合评分
- 收入评级:优秀/良好/中等/较差
4. 投资组合管理
投资组合管理功能允许用户创建和管理多个投资组合,跟踪持仓、盈亏和集中度警告,支持股票和加密货币资产。
5. 观察列表与警报
观察列表功能允许用户添加股票和加密货币,并设置价格目标、止损和信号变化警报,当触发警报时会通知用户。
6. 热门扫描
热门扫描功能聚合多个数据源,实时查找热门股票和加密货币,数据源包括:
- CoinGecko(热门加密货币、最大涨跌幅)
- Google News(财经和加密货币头条)
- Yahoo Finance(涨幅榜、跌幅榜、最活跃股票)
- Twitter/X(社交情绪,可选)
- Reddit(r/wallstreetbets和r/cryptocurrency,可选)
7. 谣言扫描
谣言扫描功能查找早期信号、并购谣言和内幕交易活动,数据源包括:
- Twitter/X:"hearing that"、"sources say"等关键词
- Google News:并购、内幕交易、分析师升级/降级新闻
- 异常关键词检测
分析维度
股票(8维度)
| 维度 | 权重 | 描述 |
|---|---|---|
| 收益惊喜 | 30% | EPS超出/低于预期的情况 |
| 基本面 | 20% | 市盈率、利润率、增长率、债务等 |
| 分析师情绪 | 20% | 分析师评级和目标价格 |
| 历史模式 | 10% | 过去的收益反应模式 |
| 市场环境 | 10% | VIX指数、SPY/QQQ趋势 |
| 行业表现 | 15% | 相对行业强度 |
| 动量 | 15% | RSI、52周区间、成交量 |
| 情绪 | 10% | 恐惧/贪婪指数、空头头寸、内幕交易、看跌/看涨比率 |
加密货币(3维度)
- 市值与分类:加密货币的市值排名和分类(如智能合约L1、DeFi等)
- BTC相关性:30天内与比特币的相关性
- 动量:RSI和价格区间
风险检测
该技能会检测以下风险:
- 收益前风险:距离收益发布少于14天,预期高波动性
- 收益后飙升:5天内涨幅超过15%,收益可能已被定价
- 超买:RSI>70且接近52周高点,高风险入场
- 风险规避模式:GLD/TLT/UUP同时上涨,资金流向避险资产
- 地缘政治风险:检测台湾、中国、俄罗斯、中东等地缘政治关键词
- 突发新闻风险:过去24小时内的危机关键词
带中文注释的核心代码
1. analyze_stock.py(股票分析主脚本核心代码)
#!/usr/bin/env python3"""股票分析主脚本,使用Yahoo Finance数据进行8维度股票分析和加密货币分析"""import argparseimport asyncioimport jsonimport sysimport timefrom dataclasses import dataclass, asdictfrom datetime import datetime, timedeltafrom typing import Literal, Optional, Tuple, List, Dictimport yfinance as yfimport pandas as pdfrom fear_and_greed import FearAndGreed@dataclassclass StockData:"""股票数据类,存储从Yahoo Finance获取的所有数据"""ticker: strasset_type: Literal["stock", "crypto"]info: Dictearnings_history: Optional[pd.DataFrame]analyst_info: Optional[Dict]price_history: Optional[pd.DataFrame]@dataclassclass EarningsSurprise:"""收益惊喜分析结果"""score: floatexplanation: stractual_eps: Optional[float]expected_eps: Optional[float]surprise_pct: Optional[float]def fetch_stock_data(ticker: str, verbose: bool = False) -> Optional[StockData]:"""从Yahoo Finance获取股票数据,带重试逻辑Args:ticker: 股票代码verbose: 是否打印调试信息Returns:StockData对象或None"""max_retries = 3for attempt in range(max_retries):try:if verbose:print(f"正在获取 {ticker} 的数据...", file=sys.stderr)stock = yf.Ticker(ticker)info = stock.info# 检测资产类型asset_type = "crypto" if ticker.endswith("-USD") else "stock"# 获取收益历史earnings_history = stock.earnings if hasattr(stock, 'earnings') else None# 获取分析师信息analyst_info = stock.recommendations if hasattr(stock, 'recommendations') else None# 获取价格历史price_history = stock.history(period="1y")return StockData(ticker=ticker,asset_type=asset_type,info=info,earnings_history=earnings_history,analyst_info=analyst_info,price_history=price_history)except Exception as e:if verbose:print(f"获取 {ticker} 数据失败 (尝试 {attempt+1}/{max_retries}): {e}", file=sys.stderr)if attempt < max_retries - 1:wait_time = 2 ** attempt # 指数退避time.sleep(wait_time)return Nonedef analyze_earnings_surprise(data: StockData) -> Optional[EarningsSurprise]:"""分析收益惊喜情况Args:data: StockData对象Returns:EarningsSurprise对象或None"""if not data.earnings_history or data.earnings_history.empty:return None# 获取最近的收益数据latest_earnings = data.earnings_history.iloc[-1]actual_eps = latest_earnings.get("Reported EPS")expected_eps = latest_earnings.get("EPS Estimate")if actual_eps is None or expected_eps is None:return None# 计算惊喜百分比surprise_pct = ((actual_eps - expected_eps) / abs(expected_eps)) * 100# 计算分数score = surprise_pct / 100 # 标准化分数# 生成解释if surprise_pct > 0:explanation = f"超出预期 {surprise_pct:.1f}% - EPS ${actual_eps:.2f} 对比预期 ${expected_eps:.2f}"else:explanation = f"低于预期 {abs(surprise_pct):.1f}% - EPS ${actual_eps:.2f} 对比预期 ${expected_eps:.2f}"return EarningsSurprise(score=score,explanation=explanation,actual_eps=actual_eps,expected_eps=expected_eps,surprise_pct=surprise_pct)def main():"""主函数,处理命令行参数并执行分析"""parser = argparse.ArgumentParser(description="股票和加密货币分析工具")parser.add_argument("tickers", nargs="+", help="股票或加密货币代码")parser.add_argument("--output", choices=["text", "json"], default="text", help="输出格式")parser.add_argument("--verbose", "-v", action="store_true", help="显示详细信息")parser.add_argument("--fast", action="store_true", help="快速模式,跳过慢速分析")parser.add_argument("--no-insider", action="store_true", help="跳过内幕交易分析")parser.add_argument("--portfolio", help="分析投资组合")parser.add_argument("--period", choices=["daily", "weekly", "monthly"], default="daily", help="分析周期")args = parser.parse_args()# 处理投资组合模式if args.portfolio:# 加载投资组合try:from portfolio import PortfolioStorestore = PortfolioStore()portfolio = store.get_portfolio(args.portfolio)if not portfolio:print(f"错误:投资组合 '{args.portfolio}' 不存在", file=sys.stderr)sys.exit(1)if not portfolio.assets:print(f"投资组合 '{args.portfolio}' 没有资产", file=sys.stderr)sys.exit(1)args.tickers = [asset.ticker for asset in portfolio.assets]if args.verbose:print(f"正在分析投资组合: {args.portfolio} ({len(args.tickers)} 个资产)", file=sys.stderr)except ImportError:print("错误:无法导入portfolio模块", file=sys.stderr)sys.exit(1)# 分析每个代码results = []for ticker in args.tickers:data = fetch_stock_data(ticker.upper(), verbose=args.verbose)if not data:print(f"错误:无法获取 {ticker} 的数据", file=sys.stderr)continue# 分析各个维度earnings = analyze_earnings_surprise(data)# 其他分析函数...# 合成信号# signal = synthesize_signal(...)# results.append(signal)# 输出结果if args.output == "json":print(json.dumps([asdict(r) for r in results], indent=2, default=str))else:for signal in results:print(f"{'='*77}")print(f"股票分析: {signal.ticker} ({signal.company_name})")print(f"生成时间: {signal.timestamp}")print(f"{'='*77}")print(f"建议: {signal.recommendation} (置信度: {signal.confidence:.1%})")print("\n支持点:")for point in signal.supporting_points:print(f"• {point}")if signal.caveats:print("\n风险提示:")for caveat in signal.caveats:print(f"• {caveat}")print(f"\n{'='*77}")print("免责声明:不构成财务建议。")print(f"{'='*77}\n")if __name__ == "__main__":main()
2. portfolio.py(投资组合管理脚本核心代码)
#!/usr/bin/env python3"""投资组合管理脚本"""import argparseimport jsonimport sysfrom dataclasses import dataclass, asdictfrom datetime import datetimefrom pathlib import Pathimport yfinance as yf@dataclassclass Asset:"""资产类,存储投资组合中的资产信息"""ticker: strtype: str # "stock" or "crypto"quantity: floatcost_basis: floatadded_at: str@dataclassclass Portfolio:"""投资组合类,存储投资组合信息"""name: strcreated_at: strupdated_at: strassets: list[Asset]class PortfolioStore:"""投资组合存储管理类,处理投资组合的持久化"""def __init__(self, path: Optional[Path] = None):"""初始化存储路径"""self.path = path or Path.home() / ".clawdbot" / "skills" / "stock-analysis" / "portfolios.json"self._data: Optional[Dict] = Nonedef _load(self) -> Dict:"""从磁盘加载投资组合数据"""if self._data is not None:return self._datatry:if self.path.exists():with open(self.path, "r", encoding="utf-8") as f:self._data = json.load(f)return self._dataexcept (json.JSONDecodeError, IOError):pass# 如果加载失败,初始化空数据self._data = {"version": 1, "portfolios": {}}return self._datadef _save(self) -> None:"""将投资组合数据保存到磁盘(原子写入)"""if self._data is None:return# 确保目录存在self.path.parent.mkdir(parents=True, exist_ok=True)# 原子写入:先写入临时文件,然后重命名tmp_path = self.path.with_suffix(".tmp")try:with open(tmp_path, "w", encoding="utf-8") as f:json.dump(self._data, f, indent=2)tmp_path.replace(self.path)except Exception:if tmp_path.exists():tmp_path.unlink()raisedef create_portfolio(self, name: str) -> Portfolio:"""创建新投资组合"""data = self._load()key = name.lower().replace(" ", "-")if key in data["portfolios"]:raise ValueError(f"投资组合 '{name}' 已存在")now = datetime.now().isoformat()portfolio = {"name": name,"created_at": now,"updated_at": now,"assets": [],}data["portfolios"][key] = portfolioself._save()return Portfolio(name=name, created_at=now, updated_at=now, assets=[])def add_asset(self,portfolio_name: str,ticker: str,quantity: float,cost_basis: float,) -> Asset:"""向投资组合添加资产"""data = self._load()key = portfolio_name.lower().replace(" ", "-")# 查找投资组合if key not in data["portfolios"]:raise ValueError(f"投资组合 '{portfolio_name}' 不存在")portfolio = data["portfolios"][key]ticker = ticker.upper()# 检查资产是否已存在for asset in portfolio["assets"]:if asset["ticker"] == ticker:raise ValueError(f"资产 '{ticker}' 已在投资组合中。使用 'update' 来修改。")# 验证代码asset_type = "crypto" if ticker.endswith("-USD") else "stock"try:stock = yf.Ticker(ticker)info = stock.infoif "regularMarketPrice" not in info:raise ValueError(f"无效代码: {ticker}")except Exception as e:raise ValueError(f"无法验证代码 '{ticker}': {e}")now = datetime.now().isoformat()asset = {"ticker": ticker,"type": asset_type,"quantity": quantity,"cost_basis": cost_basis,"added_at": now,}portfolio["assets"].append(asset)portfolio["updated_at"] = nowself._save()return Asset(**asset)def main():"""主函数,处理命令行参数"""parser = argparse.ArgumentParser(description="投资组合管理工具")subparsers = parser.add_subparsers(dest="command", help="命令")# createcreate_parser = subparsers.add_parser("create", help="创建新投资组合")create_parser.add_argument("name", help="投资组合名称")# addadd_parser = subparsers.add_parser("add", help="向投资组合添加资产")add_parser.add_argument("ticker", help="股票/加密货币代码(例如:AAPL, BTC-USD)")add_parser.add_argument("--quantity", "-q", type=float, required=True, help="数量")add_parser.add_argument("--cost", "-c", type=float, required=True, help="单位成本")add_parser.add_argument("--portfolio", "-p", help="投资组合名称(默认:第一个投资组合)")# 其他命令...args = parser.parse_args()if not args.command:parser.print_help()sys.exit(1)store = PortfolioStore()try:if args.command == "create":portfolio = store.create_portfolio(args.name)print(f"创建投资组合: {portfolio.name}")elif args.command == "add":portfolio_name = args.portfolio or store.get_default_portfolio_name()if not portfolio_name:print("没有找到投资组合。先使用 'create' 命令创建一个。")sys.exit(1)asset = store.add_asset(portfolio_name, args.ticker, args.quantity, args.cost)print(f"已向 {portfolio_name} 添加 {asset.ticker} ({asset.type}): "f"{asset.quantity} 单位 @ ${asset.cost_basis:.2f}")# 其他命令处理...except ValueError as e:print(f"错误: {e}")sys.exit(1)except Exception as e:print(f"意外错误: {e}")sys.exit(1)if __name__ == "__main__":main()
元数据信息
该技能的元数据信息如下:
{"ownerId": "kn77fv9851hjcqe52zqx0bhhbx7z680h","slug": "stock-analysis","version": "6.2.0","publishedAt": 1770041353575}
更多推荐





所有评论(0)