# Stock Analysis

> 分析任意股票的技术指标和趋势，或修改 TradingAgentsV2 中的分析师节点。当用户需要分析某只股票、查看技术指标、获取市场趋势判断时，使用独立分析脚本；当需要新增/修改分析师节点时，参考架构模板。

- Skill: `modbender/stock-analysis-3` (Agent Skill, multi-file: 3 files)
- Install (CLI): `npx skillmds@latest add modbender/stock-analysis-3`
- Raw SKILL.md: https://api.skillmd.com/api/skills/modbender/stock-analysis-3/raw
- Safety review: pending (external: skill-scanner PASS, skillspector PASS)
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: modbender (https://skillmd.com/u/modbender)
- Updated: 2026-09-21
- Page: https://skillmd.com/skills/modbender/stock-analysis-3

---


# 股票分析 Skill

## 快速分析（独立脚本）

脚本位置：`.cursor/skills/stock-analysis/analyze_stock.py`（项目根目录也有一份副本 `analyze_stock.py`）

当用户要求分析某只股票时，直接执行此脚本：

```bash
python .cursor/skills/stock-analysis/analyze_stock.py <股票代码> [选项]
```

### 参数

| 参数 | 说明 | 默认值 |
|------|------|--------|
| `symbol` (必填) | 股票代码，如 META, AAPL, 0700.HK, TSLA | - |
| `--date`, `-d` | 分析日期，格式 YYYY-MM-DD | 今天 |
| `--days`, `-n` | 回看天数 | 90 |
| `--indicators`, `-i` | 逗号分隔的指标列表，或 `all` | 8个核心指标 |

### 示例

```bash
python .cursor/skills/stock-analysis/analyze_stock.py META
python .cursor/skills/stock-analysis/analyze_stock.py AAPL --date 2025-02-20
python .cursor/skills/stock-analysis/analyze_stock.py 0700.HK --days 60
python .cursor/skills/stock-analysis/analyze_stock.py TSLA -i rsi,macd,atr,close_50_sma
python .cursor/skills/stock-analysis/analyze_stock.py NVDA -i all
```

### 数据源（多源容灾）

脚本按以下优先级获取数据，自动容灾切换：

1. **Stooq**（免费、无需API key、不限速）
2. **Yahoo Chart API**（直接 HTTP 请求）
3. **yfinance**（Ticker.history）
4. **本地缓存**（`tradingagents/dataflows/data_cache/` 中已有的 CSV）

成功获取的数据会自动缓存到 `data_cache/` 目录。

### 报告输出内容

1. **近期行情** - 最近 15 个交易日 OHLCV + 涨跌统计
2. **技术指标** - 每个指标的时间序列趋势
3. **综合分析** - 趋势判断、动量分析、波动率分析、短期信号
4. **指标汇总表** - 所有指标的当前值和信号判断

### 分析逻辑

脚本内置的分析逻辑对应 `market_analyst.py` 的 prompt：

- **趋势判断**: 基于价格与 50SMA/200SMA 的位置关系（多头/空头排列 + 金叉/死叉）
- **动量分析**: RSI 超买超卖（70/30 阈值）+ MACD 与信号线交叉 + 柱状图方向
- **波动率**: ATR 占股价比例 + 布林带位置
- **短期信号**: 价格与 10EMA 的关系

### 支持的全部指标

```
close_50_sma, close_200_sma, close_10_ema,
macd, macds, macdh,
rsi,
boll, boll_ub, boll_lb,
atr,
vwma
```

### 依赖

```
yfinance, stockstats, pandas, requests
```

---

## 项目架构（LangGraph 分析师节点）

```
tradingagents/
├── agents/analysts/           # 分析师节点
│   ├── market_analyst.py      # 市场/技术分析
│   ├── fundamentals_analyst.py # 基本面分析
│   ├── news_analyst.py        # 新闻分析
│   └── social_media_analyst.py # 社交媒体情绪分析
├── dataflows/
│   └── interface.py           # 数据接口（工具函数定义）
└── graph/
    └── trading_graph.py       # LangGraph 交易图
```

## 分析师节点结构

每个分析师遵循统一模式：`create_xxx_analyst(llm, toolkit) -> node_function`

### 核心模板

```python
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
from langchain_core.messages import HumanMessage
from ...dataflows.interface import get_market_type

def create_xxx_analyst(llm, toolkit):
    def xxx_analyst_node(state):
        current_date = state["trade_date"]
        ticker = state["company_of_interest"]
        market_type = get_market_type()  # "CN" 或 "US"

        # 1. 根据 market_type 设置 system_message 和 tools
        if market_type == "CN":
            system_message = "..."
            tools = [toolkit.cn_tool_1, toolkit.cn_tool_2]
        else:
            system_message = "..."
            if toolkit.config["online_tools"]:
                tools = [toolkit.online_tool]
            else:
                tools = [toolkit.offline_tool_1, toolkit.offline_tool_2]

        # 2. 构建 prompt（CN/US 可分别定义或共用）
        prompt = ChatPromptTemplate.from_messages([
            ("system",
             "你是一个有帮助的AI助手，与其他助手协作完成任务。"
             "使用提供的工具来推进回答问题。如果你无法完全回答，没关系；"
             "其他拥有不同工具的助手会在你停下的地方继续帮忙。"
             "你可以使用以下工具：{tool_names}\n{system_message}"
             "供参考，当前日期是 {current_date}。我们正在分析的公司是 {ticker}"),
            MessagesPlaceholder(variable_name="messages"),
        ])
        prompt = prompt.partial(
            system_message=system_message,
            tool_names=", ".join([t.name for t in tools]),
            current_date=current_date,
            ticker=ticker,
        )

        # 3. 调用 LLM
        chain = prompt | llm.bind_tools(tools)
        messages = state["messages"].copy()

        # 工具调用次数限制（防止无限循环）
        tool_call_count = sum(
            1 for msg in messages
            if hasattr(msg, 'tool_calls') and msg.tool_calls
        )
        if tool_call_count >= 3:
            final_prompt = ChatPromptTemplate.from_messages([
                ("system", system_message + "\n\n重要提醒：请基于已获取的信息生成最终报告，不要再调用任何工具。"),
                MessagesPlaceholder(variable_name="messages"),
            ])
            result = (final_prompt | llm).invoke(messages)
        else:
            if not (messages and getattr(messages[-1], "role", None) == "user"):
                messages.append(HumanMessage(content=f"请分析{ticker}的相关信息，并调用相关工具获取数据。"))
            result = chain.invoke(messages)

        # 4. 返回结果（key 与 state schema 对应）
        return {
            "messages": [result],
            "xxx_report": result.content,
        }

    return xxx_analyst_node
```

### State 返回字段映射

| 分析师 | 返回 key | 说明 |
|--------|----------|------|
| market_analyst | `market_report` | 技术指标与趋势分析 |
| fundamentals_analyst | `fundamentals_report` | 财务与基本面分析 |
| news_analyst | `news_report` | 新闻与公告分析 |
| social_media_analyst | `sentiment_report` | 社交媒体情绪分析 |

## 可用技术指标（市场分析师）

指标名称必须与以下精确匹配，否则工具调用会失败：

| 类别 | 指标 | 说明 |
|------|------|------|
| 移动平均线 | `close_50_sma` | 50日简单移动平均线 |
| | `close_200_sma` | 200日简单移动平均线 |
| | `close_10_ema` | 10日指数移动平均线 |
| MACD | `macd` | MACD 值 |
| | `macds` | MACD 信号线 |
| | `macdh` | MACD 柱状图 |
| 动量 | `rsi` | 相对强弱指数 |
| 波动率 | `boll` / `boll_ub` / `boll_lb` | 布林带（中/上/下轨） |
| | `atr` | 平均真实波幅 |
| 成交量 | `vwma` | 成交量加权移动平均线 |

选择指标时最多 8 个，避免冗余（如不要同时选 rsi 和 stochrsi）。

## 数据工具对照表

| 分析师 | A股(CN)工具 | 美股(US)在线工具 | 美股离线工具 |
|--------|------------|-----------------|-------------|
| 市场分析 | `get_akshare_data` / `get_akshare_data_online` | `get_YFin_data_online` | `get_YFin_data` |
| | `get_stockstats_indicators_report` / `_online` | `get_stockstats_indicators_report_online` | `get_stockstats_indicators_report` |
| 基本面 | `get_akshare_balance_sheet` | `get_fundamentals_openai` | `get_simfin_*` / `get_finnhub_*` |
| | `get_akshare_cashflow` / `income_stmt` / `finance_analysis` | | |
| | `get_akshare_special_data` | | |
| 新闻 | `get_company_news` / `get_market_news` | `get_global_news_openai` / `get_google_news` | `get_finnhub_news` / `get_reddit_news` / `get_google_news` |
| 社交媒体 | `get_xueqiu_stock_info` | `get_stock_news_openai` | `get_reddit_stock_info` / `get_finnhub_news` |

工具函数定义在 `tradingagents/dataflows/interface.py`。

## 市场类型配置

通过 `get_market_type()` 获取，返回 `"CN"` 或 `"US"`。配置来源于 `tradingagents/dataflows/config.py`。

## 修改指南

### 新增技术指标

1. 在 `interface.py` 的 stockstats 工具中添加指标定义
2. 在 `market_analyst.py` 的 `system_message` 中添加指标描述
3. 指标名需与 stockstats 库一致

### 新增分析师类型

1. 在 `tradingagents/agents/analysts/` 创建新文件
2. 遵循上方核心模板
3. 在 `trading_graph.py` 中注册新节点
4. 返回值 key 需在 state schema 中定义

### 修改报告格式

所有分析师 `system_message` 末尾已要求附加 Markdown 表格总结。如需修改格式，调整 `system_message` 的指令即可。

## 注意事项

- 工具调用上限默认 3 次，超出后强制生成报告（防死循环）
- `online_tools` 配置决定使用在线/离线数据源
- 所有分析师输出中文，`system_message` 统一用中文编写
- 报告末尾需附 Markdown 表格，方便前端展示

