# a-share-analyst

Adopt this skill: https://proskills.md/skills/other/staruhub-claudeskills-lab-geek-skills-a-share-analyst

Page: https://proskills.md/skills/other/staruhub-claudeskills-lab-geek-skills-a-share-analyst
This document is the public skill bundle for that page. It contains SKILL.md and every helper file the catalog carries. No login is required.

## File: lab/Geek-skills-a-share-analyst/SKILL.md
size: 6251
sha: 1b7d9021b0802d2dafd4931b81a31381c5da3cac
upstream: https://github.com/staruhub/claudeskills/blob/main/lab/Geek-skills-a-share-analyst/SKILL.md

````text
---
name: a-share-analyst
version: 1.1.0
description: A股分析研究助手，提供行情数据获取与技术面/基本面分析框架（仅供研究参考，不构成投资建议）。适用于：(1) 获取A股行情和历史数据，(2) 技术面分析（K线形态、MACD、KDJ、RSI、布林带等），(3) 基本面分析（财务指标、估值分析），(4) 板块热点追踪，(5) 选股策略筛选与量化因子分析，(6) 生成股市分析报告。当用户询问"帮我分析股票"、"今日选股"、"A股行情分析"、"技术分析"、"量化选股"时触发。不用于：预测明日涨跌或给出确定性买卖指令、代客决策、港股美股（数据源不同）、加密货币。
---

# A股分析师 Skill

专业的A股市场分析工具，整合多数据源，提供技术面、基本面综合分析和智能选股策略。

## 数据获取

使用AKShare作为主要数据源（免费、开源、无需token）：

```python
pip install akshare --break-system-packages
```

### 核心数据获取示例

```python
import akshare as ak

# 实时行情
df = ak.stock_zh_a_spot_em()  # 全部A股实时行情

# 历史K线
df = ak.stock_zh_a_hist(symbol="000001", period="daily", adjust="qfq")

# 板块行情
df = ak.stock_board_concept_name_em()  # 概念板块
df = ak.stock_board_industry_name_em()  # 行业板块

# 龙虎榜（日期用实际查询区间，格式 YYYYMMDD）
df = ak.stock_lhb_detail_em(start_date="<起始日>", end_date="<结束日>")

# 资金流向
df = ak.stock_individual_fund_flow(stock="000001", market="sz")
```

## 分析工作流程

### 1. 每日盘前分析

执行顺序：
1. 获取大盘指数（上证、深证、创业板）
2. 分析板块热点轮动
3. 筛选涨停股及连板股
4. 检测北向资金流向
5. 生成今日关注清单

### 2. 技术面分析

对单只股票执行：
1. 获取历史K线数据（至少60日）
2. 计算技术指标（见 `references/technical_indicators.md`）
3. 识别K线形态（见 `references/candlestick_patterns.md`）
4. 判断趋势和支撑/阻力位
5. 生成技术面评分

### 3. 基本面分析

执行顺序：
1. 获取财务数据（营收、净利润、ROE等）
2. 计算估值指标（PE、PB、PS）
3. 分析行业地位和竞争优势
4. 评估成长性和安全边际
5. 生成基本面评分

### 4. 智能选股策略

**策略类型选择：**
- 多因子综合策略 → 执行 `scripts/strategy_multi_factor.py`（已实现，内置 ST/停牌过滤）
- 趋势突破 / 价值低估 / 动量因子等单因子策略 → 目前无独立脚本，在 multi_factor 基础上调整因子权重，或按需自行实现

## 输出格式

### 个股分析报告模板

```markdown
# [股票名称]([股票代码]) 分析报告

## 基本信息
- 当前价格：¥XX.XX（涨跌幅 +X.XX%）
- 市值：XXX亿  |  PE(TTM)：XX.X  |  PB：X.XX

## 技术面分析
- 趋势判断：[上升/震荡/下降]
- 支撑位：¥XX.XX  |  阻力位：¥XX.XX
- 技术指标：MACD [金叉/死叉]  |  KDJ [超买/超卖/中性]  |  RSI [XX]

## 基本面分析
- 营收增速：XX%  |  净利润增速：XX%
- ROE：XX%  |  毛利率：XX%

## 综合评分
- 技术面：⭐⭐⭐⭐☆ (4/5)
- 基本面：⭐⭐⭐☆☆ (3/5)

## 操作建议
[具体建议及风险提示]
```

### 每日选股清单模板

```markdown
# 每日选股清单 [日期]

## 市场概览
- 上证指数：XXXX.XX（+X.XX%）
- 深证成指：XXXXX.XX（+X.XX%）
- 创业板指：XXXX.XX（+X.XX%）

## 热点板块 TOP5
1. [板块名称] +X.XX%
2. ...

## 精选个股

### 趋势突破型
| 代码 | 名称 | 现价 | 涨幅 | 突破形态 | 评分 |
|------|------|------|------|----------|------|
| ... | ... | ... | ... | ... | ... |

### 价值低估型
| 代码 | 名称 | 现价 | PE | PB | 评分 |
|------|------|------|-----|-----|------|
| ... | ... | ... | ... | ... | ... |

## 风险提示
投资有风险，以上分析仅供参考，不构成投资建议。
```

## 关键脚本

- `scripts/fetch_market_data.py` - 市场数据获取
- `scripts/technical_analysis.py` - 技术指标计算（输出中性强弱描述，非买卖评级）
- `scripts/strategy_multi_factor.py` - 多因子选股（含 ST/停牌过滤）
- `scripts/generate_report.py` - 报告生成（需在 scripts/ 目录内运行，依赖 technical_analysis）

## 参考文档

- `references/technical_indicators.md` - 技术指标计算公式
- `references/candlestick_patterns.md` - K线形态识别
- `references/fundamental_metrics.md` - 基本面指标说明
- `references/factor_library.md` - 量化因子库

## 验收标准（每份分析交付前自查）

- [ ] 报告末尾含"仅供参考，不构成投资建议"声明（模板已内置，不许删）
- [ ] 数据来自**本次运行**的 akshare 调用，标注数据时间戳与延迟（可能有15分钟延迟）
- [ ] 技术面/基本面结论与展示的指标数据一一对应，没有无数据支撑的判断
- [ ] 给出的是"分析+风险"而非"买卖指令"：无"满仓""抄底""必涨"类表述
- [ ] 新策略未经历史回测时明确标注"未回测"

## 不做什么

- 不预测明日涨跌，不给确定性买卖点位
- 不代替用户决策，不推荐仓位以外的杠杆操作（模板建议：单只 ≤20%）
- 不分析港股/美股/加密货币（数据源与规则不同）
- 用户情绪化追问"到底买不买"时，重申边界并给风险清单，不给指令

## 已知陷阱

| 陷阱 | 具体表现 | 应对 |
|------|---------|------|
| akshare 接口变动 | 库更新后函数名/字段变了，脚本报错 | 报错时先查 akshare 当前版本文档，不硬猜字段 |
| 延迟数据当实时 | 用 15 分钟前的价格谈"当前" | 报告标注数据获取时间 |
| 指标堆砌无结论 | MACD/KDJ/RSI 全列一遍但互相矛盾不解释 | 指标冲突时明确说"信号分歧"及其含义 |
| 幸存者偏差选股 | 用当前成分股回测历史策略 | 回测结论标注该局限 |
| 节假日/停牌数据 | 停牌股票数据缺失导致计算错误 | 计算前过滤停牌与 ST 异常状态 |

`evals/routing-evals.json` — 触发边界回归用例，改 description 后用仓库根 `scripts/run_routing_evals.py` 校验。
````

## File: lab/Geek-skills-a-share-analyst/scripts/fetch_market_data.py
size: 4219
sha: 60ddab5ecef878c33f655179b46cfb32402a0c48
upstream: https://github.com/staruhub/claudeskills/blob/main/lab/Geek-skills-a-share-analyst/scripts/fetch_market_data.py

```text
#!/usr/bin/env python3
"""
A股市场数据获取模块
使用AKShare作为数据源
"""

import akshare as ak
import pandas as pd
from datetime import datetime, timedelta

def get_market_overview():
    """获取市场概览：主要指数行情"""
    indices = {
        '上证指数': 'sh000001',
        '深证成指': 'sz399001',
        '创业板指': 'sz399006',
        '科创50': 'sh000688',
        '沪深300': 'sh000300',
        '中证500': 'sh000905',
    }
    
    results = []
    for name, code in indices.items():
        try:
            df = ak.stock_zh_index_daily(symbol=code)
            if len(df) > 0:
                latest = df.iloc[-1]
                prev = df.iloc[-2] if len(df) > 1 else latest
                change_pct = (latest['close'] - prev['close']) / prev['close'] * 100
                results.append({
                    '指数名称': name,
                    '代码': code,
                    '最新点位': round(latest['close'], 2),
                    '涨跌幅': f"{change_pct:+.2f}%",
                    '成交额(亿)': round(latest['volume'] / 1e8, 2)
                })
        except Exception as e:
            print(f"获取{name}失败: {e}")
    
    return pd.DataFrame(results)

def get_all_stocks_realtime():
    """获取全部A股实时行情"""
    df = ak.stock_zh_a_spot_em()
    return df

def get_stock_history(symbol: str, period: str = "daily", days: int = 120):
    """
    获取个股历史K线数据
    
    Args:
        symbol: 股票代码，如 "000001"
        period: K线周期 daily/weekly/monthly
        days: 获取天数
    """
    end_date = datetime.now().strftime('%Y%m%d')
    start_date = (datetime.now() - timedelta(days=days)).strftime('%Y%m%d')
    
    df = ak.stock_zh_a_hist(
        symbol=symbol, 
        period=period, 
        start_date=start_date,
        end_date=end_date,
        adjust="qfq"  # 前复权
    )
    return df

def get_concept_boards():
    """获取概念板块行情"""
    df = ak.stock_board_concept_name_em()
    return df.sort_values('涨跌幅', ascending=False)

def get_industry_boards():
    """获取行业板块行情"""
    df = ak.stock_board_industry_name_em()
    return df.sort_values('涨跌幅', ascending=False)

def get_board_stocks(board_name: str, board_type: str = "concept"):
    """获取板块成分股"""
    if board_type == "concept":
        df = ak.stock_board_concept_cons_em(symbol=board_name)
    else:
        df = ak.stock_board_industry_cons_em(symbol=board_name)
    return df

def get_limit_up_stocks():
    """获取涨停股票"""
    df = ak.stock_zt_pool_em(date=datetime.now().strftime('%Y%m%d'))
    return df

def get_limit_down_stocks():
    """获取跌停股票"""
    df = ak.stock_zt_pool_dtgc_em(date=datetime.now().strftime('%Y%m%d'))
    return df

def get_dragon_tiger_list(days: int = 5):
    """获取龙虎榜数据"""
    end_date = datetime.now().strftime('%Y%m%d')
    start_date = (datetime.now() - timedelta(days=days)).strftime('%Y%m%d')
    df = ak.stock_lhb_detail_em(start_date=start_date, end_date=end_date)
    return df

def get_north_money_flow():
    """获取北向资金流向"""
    df = ak.stock_hsgt_north_net_flow_in_em(symbol="北上")
    return df

def get_stock_fund_flow(symbol: str, market: str = "sh"):
    """
    获取个股资金流向
    
    Args:
        symbol: 股票代码
        market: sh/sz
    """
    df = ak.stock_individual_fund_flow(stock=symbol, market=market)
    return df

def get_financial_indicators(symbol: str):
    """获取财务指标"""
    df = ak.stock_financial_analysis_indicator(symbol=symbol)
    return df

def get_stock_info(symbol: str):
    """获取股票基本信息"""
    df = ak.stock_individual_info_em(symbol=symbol)
    return df

def get_earnings_forecast():
    """获取业绩预告"""
    df = ak.stock_yjyg_em()
    return df

if __name__ == "__main__":
    # 测试数据获取
    print("=== 市场概览 ===")
    print(get_market_overview())
    
    print("\n=== 概念板块 TOP10 ===")
    print(get_concept_boards().head(10))
    
    print("\n=== 行业板块 TOP10 ===")
    print(get_industry_boards().head(10))
```

## File: lab/Geek-skills-a-share-analyst/scripts/generate_report.py
size: 8541
sha: 60ae765c4389fc6af5fc1e2dccc14893acc07b12
upstream: https://github.com/staruhub/claudeskills/blob/main/lab/Geek-skills-a-share-analyst/scripts/generate_report.py

```text
#!/usr/bin/env python3
"""
A股分析报告生成模块
生成个股分析报告和每日市场报告
"""

import akshare as ak
import pandas as pd
from datetime import datetime
from technical_analysis import analyze_stock

def generate_stock_report(symbol: str) -> str:
    """
    生成个股分析报告
    
    Args:
        symbol: 股票代码，如 "000001"
    """
    # 获取股票基本信息
    try:
        info = ak.stock_individual_info_em(symbol=symbol)
        info_dict = dict(zip(info['item'], info['value']))
    except:
        info_dict = {}
    
    # 获取实时行情
    spot = ak.stock_zh_a_spot_em()
    stock_spot = spot[spot['代码'] == symbol]
    if len(stock_spot) == 0:
        return f"未找到股票代码: {symbol}"
    stock_spot = stock_spot.iloc[0]

    # ST/退市/停牌过滤（SKILL.md 陷阱表要求）
    name = str(stock_spot.get('名称', ''))
    if any(flag in name for flag in ('ST', '退', '*ST')):
        return f"{name}({symbol}) 为 ST/退市风险股，本工具不对其出具技术分析，请自行谨慎判断。"
    turnover = stock_spot.get('换手率', None)
    if turnover is not None and float(turnover or 0) == 0:
        return f"{name}({symbol}) 当前疑似停牌（换手率为 0），无有效行情数据。"
    
    # 获取历史K线
    df = ak.stock_zh_a_hist(symbol=symbol, period="daily", adjust="qfq")
    df = df.tail(120)
    
    # 技术分析
    analysis = analyze_stock(df)
    
    # 生成报告
    report = f"""
# {stock_spot['名称']}({symbol}) 分析报告

**生成时间**: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}

---

## 基本信息

| 项目 | 数值 |
|------|------|
| 当前价格 | ¥{stock_spot['最新价']} |
| 涨跌幅 | {stock_spot['涨跌幅']:+.2f}% |
| 成交量 | {stock_spot['成交量']/10000:.2f}万手 |
| 成交额 | {stock_spot['成交额']/100000000:.2f}亿 |
| 换手率 | {stock_spot['换手率']:.2f}% |
| 量比 | {stock_spot['量比']:.2f} |
| 市盈率(动态) | {stock_spot['市盈率-动态']:.2f} |
| 市净率 | {stock_spot['市净率']:.2f} |
| 总市值 | {stock_spot['总市值']/100000000:.2f}亿 |
| 流通市值 | {stock_spot['流通市值']/100000000:.2f}亿 |

---

## 技术面分析

### 趋势判断
- **当前趋势**: {analysis['trend']}
- **支撑位**: ¥{analysis['support_resistance']['support']}
- **阻力位**: ¥{analysis['support_resistance']['resistance']}
- **枢轴点**: ¥{analysis['support_resistance']['pivot']}

### 技术指标

| 指标 | 数值 | 信号 |
|------|------|------|
| MACD | DIF={analysis['indicators']['MACD']['DIF']:.4f}, DEA={analysis['indicators']['MACD']['DEA']:.4f} | {analysis['indicators']['MACD']['signal']} |
| KDJ | K={analysis['indicators']['KDJ']['K']:.2f}, D={analysis['indicators']['KDJ']['D']:.2f}, J={analysis['indicators']['KDJ']['J']:.2f} | {analysis['indicators']['KDJ']['signal']} |
| RSI(14) | {analysis['indicators']['RSI']['value']:.2f} | {analysis['indicators']['RSI']['signal']} |
| BOLL | 上轨={analysis['indicators']['BOLL']['upper']:.2f}, 中轨={analysis['indicators']['BOLL']['mid']:.2f}, 下轨={analysis['indicators']['BOLL']['lower']:.2f} | {analysis['indicators']['BOLL']['signal']} |
| ATR(14) | {analysis['indicators']['ATR']:.2f} | 波动参考 |

---

## 综合评分

- **技术评分**: {analysis['score']['score']}/100
- **评级**: {analysis['score']['rating']}
- **星级**: {'⭐' * analysis['score']['stars']}

---

## 操作建议

"""
    
    # 只做中性分析描述，不给买卖指令（合规边界，见 SKILL.md 验收标准）
    score = analysis['score']['score']
    if score >= 70:
        report += """
**技术面评估：偏多**

各项技术指标当前整体偏多。以下为中性观察，不构成任何操作指令：
- 上涨若无成交量配合，持续性存疑
- 支撑位下方 3-5% 是常见的风险参考区间
- 单一标的的集中度风险需自行评估
"""
    elif score >= 50:
        report += """
**技术面评估：震荡**

技术面处于震荡整理，方向不明确。以下为中性观察：
- 关键支撑/阻力位是否被有效突破值得关注
- 方向未明时的信号可靠性通常较低
"""
    else:
        report += """
**技术面评估：偏弱**

多项技术指标当前偏弱。以下为中性观察：
- 下方支撑位的有效性需持续跟踪
- 企稳信号出现前，趋势判断的确定性较低
"""
    
    report += """
---

## 风险提示

⚠️ **免责声明**: 以上分析仅供参考，不构成投资建议。股市有风险，投资需谨慎。请根据自身风险承受能力做出投资决策。
"""
    
    return report

def generate_market_report() -> str:
    """生成每日市场报告"""
    
    # 获取指数数据
    indices = {
        '上证指数': 'sh000001',
        '深证成指': 'sz399001',
        '创业板指': 'sz399006',
    }
    
    index_data = []
    for name, code in indices.items():
        df = ak.stock_zh_index_daily(symbol=code)
        latest = df.iloc[-1]
        prev = df.iloc[-2]
        change = (latest['close'] - prev['close']) / prev['close'] * 100
        index_data.append({
            'name': name,
            'close': latest['close'],
            'change': change,
            'volume': latest['volume'] / 1e8
        })
    
    # 获取板块数据
    concept_boards = ak.stock_board_concept_name_em()
    industry_boards = ak.stock_board_industry_name_em()
    
    top_concept = concept_boards.nlargest(5, '涨跌幅')
    bottom_concept = concept_boards.nsmallest(5, '涨跌幅')
    top_industry = industry_boards.nlargest(5, '涨跌幅')
    
    # 获取涨跌停数据
    try:
        zt_count = len(ak.stock_zt_pool_em(date=datetime.now().strftime('%Y%m%d')))
    except:
        zt_count = "N/A"
    
    try:
        dt_count = len(ak.stock_zt_pool_dtgc_em(date=datetime.now().strftime('%Y%m%d')))
    except:
        dt_count = "N/A"
    
    report = f"""
# 每日市场报告

**日期**: {datetime.now().strftime('%Y-%m-%d')}
**生成时间**: {datetime.now().strftime('%H:%M:%S')}

---

## 大盘指数

| 指数 | 收盘点位 | 涨跌幅 | 成交额(亿) |
|------|----------|--------|------------|
"""
    
    for idx in index_data:
        report += f"| {idx['name']} | {idx['close']:.2f} | {idx['change']:+.2f}% | {idx['volume']:.2f} |\n"
    
    report += f"""
---

## 市场情绪

- **涨停家数**: {zt_count}
- **跌停家数**: {dt_count}

---

## 热门概念板块 TOP5

| 排名 | 板块名称 | 涨跌幅 | 成交额(亿) |
|------|----------|--------|------------|
"""
    
    for i, (_, row) in enumerate(top_concept.iterrows(), 1):
        report += f"| {i} | {row['板块名称']} | {row['涨跌幅']:+.2f}% | {row['成交额']/1e8:.2f} |\n"
    
    report += f"""
---

## 热门行业板块 TOP5

| 排名 | 板块名称 | 涨跌幅 | 成交额(亿) |
|------|----------|--------|------------|
"""
    
    for i, (_, row) in enumerate(top_industry.iterrows(), 1):
        report += f"| {i} | {row['板块名称']} | {row['涨跌幅']:+.2f}% | {row['成交额']/1e8:.2f} |\n"
    
    report += f"""
---

## 跌幅居前概念板块 TOP5

| 排名 | 板块名称 | 涨跌幅 |
|------|----------|--------|
"""
    
    for i, (_, row) in enumerate(bottom_concept.iterrows(), 1):
        report += f"| {i} | {row['板块名称']} | {row['涨跌幅']:+.2f}% |\n"
    
    report += """
---

## 市场总结

"""
    
    # 简单判断市场情绪
    sh_change = index_data[0]['change']
    if sh_change > 1:
        report += "📈 **市场情绪**: 今日市场表现强势，做多情绪高涨。建议关注热点板块龙头，把握短线机会。\n"
    elif sh_change > 0:
        report += "📊 **市场情绪**: 今日市场小幅上涨，整体偏暖。可适度参与，但需控制仓位。\n"
    elif sh_change > -1:
        report += "📉 **市场情绪**: 今日市场小幅调整，情绪偏谨慎。建议观望为主，等待企稳信号。\n"
    else:
        report += "⚠️ **市场情绪**: 今日市场大幅下跌，恐慌情绪蔓延。建议控制仓位，防范风险。\n"
    
    report += """
---

## 风险提示

⚠️ **免责声明**: 以上分析仅供参考，不构成投资建议。股市有风险，投资需谨慎。
"""
    
    return report

if __name__ == "__main__":
    # 生成市场报告
    print(generate_market_report())
    
    print("\n" + "="*60 + "\n")
    
    # 生成个股报告示例
    print(generate_stock_report("000001"))
```

## File: lab/Geek-skills-a-share-analyst/scripts/strategy_multi_factor.py
size: 8840
sha: cc7d4c7346bcedc4a6bfc26efc8ac1db6f002bae
upstream: https://github.com/staruhub/claudeskills/blob/main/lab/Geek-skills-a-share-analyst/scripts/strategy_multi_factor.py

```text
#!/usr/bin/env python3
"""
A股多因子选股策略
支持价值、成长、动量、质量等多种因子
"""

import akshare as ak
import pandas as pd
import numpy as np
from datetime import datetime, timedelta

def get_stock_pool():
    """获取股票池（全部A股实时行情）"""
    df = ak.stock_zh_a_spot_em()
    
    # 基础筛选
    df = df[~df['名称'].str.contains('ST|退')]  # 剔除ST和退市股
    df = df[df['涨跌幅'] < 9.9]  # 剔除涨停
    df = df[df['涨跌幅'] > -9.9]  # 剔除跌停
    df = df[df['换手率'] > 0]  # 剔除停牌
    df = df[df['市盈率-动态'] > 0]  # 剔除亏损股（可选）
    
    return df

def strategy_value(df: pd.DataFrame, top_n: int = 30) -> pd.DataFrame:
    """
    价值投资策略
    选股逻辑：低PE、低PB、高股息率
    """
    df = df.copy()
    
    # 计算因子排名（越小越好）
    df['PE_rank'] = df['市盈率-动态'].rank(pct=True)
    df['PB_rank'] = df['市净率'].rank(pct=True)
    
    # 综合评分
    df['value_score'] = df['PE_rank'] * 0.5 + df['PB_rank'] * 0.5
    
    # 排序选股
    result = df.nsmallest(top_n, 'value_score')
    
    return result[['代码', '名称', '最新价', '涨跌幅', '市盈率-动态', '市净率', 'value_score']]

def strategy_momentum(df: pd.DataFrame, top_n: int = 30) -> pd.DataFrame:
    """
    动量策略
    选股逻辑：近期涨幅居前、成交活跃
    """
    df = df.copy()
    
    # 动量因子（涨幅越大越好）
    df['momentum_rank'] = df['涨跌幅'].rank(pct=True, ascending=False)
    
    # 换手率因子（适度活跃）
    df['turnover_rank'] = df['换手率'].rank(pct=True)
    
    # 综合评分
    df['momentum_score'] = df['momentum_rank'] * 0.7 + df['turnover_rank'] * 0.3
    
    # 排序选股
    result = df.nsmallest(top_n, 'momentum_score')
    
    return result[['代码', '名称', '最新价', '涨跌幅', '换手率', '成交额', 'momentum_score']]

def strategy_breakout(df: pd.DataFrame, top_n: int = 30) -> pd.DataFrame:
    """
    突破策略
    选股逻辑：放量突破、近期强势
    """
    df = df.copy()
    
    # 量比因子（放量）
    df['vol_ratio_rank'] = df['量比'].rank(pct=True, ascending=False)
    
    # 涨幅因子
    df['change_rank'] = df['涨跌幅'].rank(pct=True, ascending=False)
    
    # 振幅因子（波动适中）
    df['amplitude_rank'] = df['振幅'].rank(pct=True)
    
    # 综合评分
    df['breakout_score'] = (df['vol_ratio_rank'] * 0.4 + 
                           df['change_rank'] * 0.4 + 
                           df['amplitude_rank'] * 0.2)
    
    # 额外筛选：量比>1.5，涨幅>2%
    df = df[(df['量比'] > 1.5) & (df['涨跌幅'] > 2)]
    
    result = df.nsmallest(top_n, 'breakout_score')
    
    return result[['代码', '名称', '最新价', '涨跌幅', '量比', '振幅', 'breakout_score']]

def strategy_quality(df: pd.DataFrame, top_n: int = 30) -> pd.DataFrame:
    """
    质量因子策略
    选股逻辑：高ROE、低负债、稳定增长
    注意：此策略需要额外获取财务数据
    """
    df = df.copy()
    
    # 简化版：使用市盈率和市净率推算ROE
    # ROE ≈ 1 / (PE × PB)
    df['implied_roe'] = 1 / (df['市盈率-动态'] * df['市净率'] + 0.01)
    df['roe_rank'] = df['implied_roe'].rank(pct=True, ascending=False)
    
    # 市值因子（中大盘）
    df['cap_rank'] = df['总市值'].rank(pct=True)
    
    # 综合评分
    df['quality_score'] = df['roe_rank'] * 0.7 + df['cap_rank'] * 0.3
    
    result = df.nsmallest(top_n, 'quality_score')
    
    return result[['代码', '名称', '最新价', '涨跌幅', '市盈率-动态', '市净率', 'implied_roe', 'quality_score']]

def strategy_multi_factor(df: pd.DataFrame, top_n: int = 30,
                         weights: dict = None) -> pd.DataFrame:
    """
    多因子综合策略
    
    Args:
        df: 股票数据
        top_n: 选股数量
        weights: 因子权重配置
    """
    if weights is None:
        weights = {
            'value': 0.25,      # 价值因子
            'momentum': 0.25,   # 动量因子
            'quality': 0.25,    # 质量因子
            'size': 0.15,       # 规模因子
            'volatility': 0.10  # 波动率因子
        }
    
    df = df.copy()
    
    # 价值因子
    df['pe_rank'] = df['市盈率-动态'].rank(pct=True)
    df['pb_rank'] = df['市净率'].rank(pct=True)
    df['value_factor'] = (df['pe_rank'] + df['pb_rank']) / 2
    
    # 动量因子
    df['momentum_factor'] = df['涨跌幅'].rank(pct=True, ascending=False)
    
    # 质量因子（隐含ROE）
    df['implied_roe'] = 1 / (df['市盈率-动态'] * df['市净率'] + 0.01)
    df['quality_factor'] = df['implied_roe'].rank(pct=True, ascending=False)
    
    # 规模因子（偏好中盘）
    df['log_cap'] = np.log(df['总市值'])
    median_cap = df['log_cap'].median()
    df['size_factor'] = -abs(df['log_cap'] - median_cap)
    df['size_factor'] = df['size_factor'].rank(pct=True, ascending=False)
    
    # 波动率因子（偏好低波动）
    df['volatility_factor'] = df['振幅'].rank(pct=True)
    
    # 综合评分
    df['total_score'] = (
        df['value_factor'] * weights['value'] +
        df['momentum_factor'] * weights['momentum'] +
        df['quality_factor'] * weights['quality'] +
        df['size_factor'] * weights['size'] +
        df['volatility_factor'] * weights['volatility']
    )
    
    # 排序选股
    result = df.nsmallest(top_n, 'total_score')
    
    return result[['代码', '名称', '最新价', '涨跌幅', '市盈率-动态', '市净率', 
                  '换手率', '总市值', 'total_score']]

def get_board_leaders(board_type: str = "concept", top_n: int = 5) -> pd.DataFrame:
    """
    获取板块龙头股
    
    Args:
        board_type: concept/industry
        top_n: 每个板块取前N只
    """
    if board_type == "concept":
        boards = ak.stock_board_concept_name_em()
    else:
        boards = ak.stock_board_industry_name_em()
    
    # 取涨幅前10的板块
    top_boards = boards.nlargest(10, '涨跌幅')
    
    results = []
    for _, board in top_boards.iterrows():
        board_name = board['板块名称']
        try:
            if board_type == "concept":
                stocks = ak.stock_board_concept_cons_em(symbol=board_name)
            else:
                stocks = ak.stock_board_industry_cons_em(symbol=board_name)
            
            stocks = stocks.nlargest(top_n, '涨跌幅')
            stocks['所属板块'] = board_name
            stocks['板块涨幅'] = board['涨跌幅']
            results.append(stocks)
        except:
            continue
    
    if results:
        return pd.concat(results, ignore_index=True)
    return pd.DataFrame()

def generate_daily_picks(save_path: str = None) -> dict:
    """
    生成每日选股清单
    """
    print("正在获取股票数据...")
    df = get_stock_pool()
    
    print("运行价值策略...")
    value_picks = strategy_value(df)
    
    print("运行动量策略...")
    momentum_picks = strategy_momentum(df)
    
    print("运行突破策略...")
    breakout_picks = strategy_breakout(df)
    
    print("运行多因子策略...")
    multi_factor_picks = strategy_multi_factor(df)
    
    results = {
        'date': datetime.now().strftime('%Y-%m-%d'),
        'value': value_picks,
        'momentum': momentum_picks,
        'breakout': breakout_picks,
        'multi_factor': multi_factor_picks
    }
    
    if save_path:
        # 保存到Excel
        with pd.ExcelWriter(save_path) as writer:
            value_picks.to_excel(writer, sheet_name='价值型', index=False)
            momentum_picks.to_excel(writer, sheet_name='动量型', index=False)
            breakout_picks.to_excel(writer, sheet_name='突破型', index=False)
            multi_factor_picks.to_excel(writer, sheet_name='多因子', index=False)
        print(f"选股结果已保存至: {save_path}")
    
    return results

if __name__ == "__main__":
    results = generate_daily_picks()
    
    print("\n" + "="*60)
    print(f"每日选股清单 - {results['date']}")
    print("="*60)
    
    print("\n【价值型选股 TOP10】")
    print(results['value'].head(10).to_string(index=False))
    
    print("\n【动量型选股 TOP10】")
    print(results['momentum'].head(10).to_string(index=False))
    
    print("\n【突破型选股 TOP10】")
    if len(results['breakout']) > 0:
        print(results['breakout'].head(10).to_string(index=False))
    else:
        print("今日无符合条件的突破型股票")
    
    print("\n【多因子选股 TOP10】")
    print(results['multi_factor'].head(10).to_string(index=False))
```

## File: lab/Geek-skills-a-share-analyst/scripts/technical_analysis.py
size: 10839
sha: 8c198ca473d02a0be669d74b18f4e6b38f371781
upstream: https://github.com/staruhub/claudeskills/blob/main/lab/Geek-skills-a-share-analyst/scripts/technical_analysis.py

```text
#!/usr/bin/env python3
"""
A股技术分析模块
包含常用技术指标计算和信号判断
"""

import pandas as pd
import numpy as np

def calc_ma(close: pd.Series, periods: list = [5, 10, 20, 60, 120]) -> pd.DataFrame:
    """计算移动平均线"""
    ma_df = pd.DataFrame(index=close.index)
    for p in periods:
        ma_df[f'MA{p}'] = close.rolling(window=p).mean()
    return ma_df

def calc_ema(close: pd.Series, period: int = 12) -> pd.Series:
    """计算指数移动平均"""
    return close.ewm(span=period, adjust=False).mean()

def calc_macd(close: pd.Series, fast: int = 12, slow: int = 26, signal: int = 9) -> dict:
    """计算MACD指标"""
    ema_fast = close.ewm(span=fast, adjust=False).mean()
    ema_slow = close.ewm(span=slow, adjust=False).mean()
    dif = ema_fast - ema_slow
    dea = dif.ewm(span=signal, adjust=False).mean()
    macd = (dif - dea) * 2
    
    return {
        'DIF': dif,
        'DEA': dea,
        'MACD': macd,
        'signal': get_macd_signal(dif, dea)
    }

def get_macd_signal(dif: pd.Series, dea: pd.Series) -> str:
    """判断MACD信号"""
    if len(dif) < 2:
        return "数据不足"
    
    # 金叉/死叉判断
    if dif.iloc[-1] > dea.iloc[-1] and dif.iloc[-2] <= dea.iloc[-2]:
        return "金叉买入"
    elif dif.iloc[-1] < dea.iloc[-1] and dif.iloc[-2] >= dea.iloc[-2]:
        return "死叉卖出"
    elif dif.iloc[-1] > dea.iloc[-1]:
        if dif.iloc[-1] > 0:
            return "多头强势"
        else:
            return "多头初现"
    else:
        if dif.iloc[-1] < 0:
            return "空头强势"
        else:
            return "空头初现"

def calc_kdj(high: pd.Series, low: pd.Series, close: pd.Series, 
             n: int = 9, m1: int = 3, m2: int = 3) -> dict:
    """计算KDJ指标"""
    low_n = low.rolling(window=n).min()
    high_n = high.rolling(window=n).max()
    rsv = (close - low_n) / (high_n - low_n) * 100
    rsv = rsv.fillna(50)
    
    k = rsv.ewm(com=m1-1, adjust=False).mean()
    d = k.ewm(com=m2-1, adjust=False).mean()
    j = 3 * k - 2 * d
    
    return {
        'K': k,
        'D': d,
        'J': j,
        'signal': get_kdj_signal(k, d)
    }

def get_kdj_signal(k: pd.Series, d: pd.Series) -> str:
    """判断KDJ信号"""
    if len(k) < 2:
        return "数据不足"
    
    k_val = k.iloc[-1]
    
    if k.iloc[-1] > d.iloc[-1] and k.iloc[-2] <= d.iloc[-2]:
        if k_val < 20:
            return "超卖金叉-强买"
        elif k_val < 50:
            return "金叉买入"
        else:
            return "高位金叉"
    elif k.iloc[-1] < d.iloc[-1] and k.iloc[-2] >= d.iloc[-2]:
        if k_val > 80:
            return "超买死叉-强卖"
        elif k_val > 50:
            return "死叉卖出"
        else:
            return "低位死叉"
    elif k_val > 80:
        return "超买区域"
    elif k_val < 20:
        return "超卖区域"
    else:
        return "中性震荡"

def calc_rsi(close: pd.Series, period: int = 14) -> dict:
    """计算RSI指标"""
    delta = close.diff()
    gain = delta.where(delta > 0, 0).rolling(window=period).mean()
    loss = (-delta.where(delta < 0, 0)).rolling(window=period).mean()
    rs = gain / loss
    rsi = 100 - (100 / (1 + rs))
    
    return {
        'RSI': rsi,
        'signal': get_rsi_signal(rsi)
    }

def get_rsi_signal(rsi: pd.Series) -> str:
    """判断RSI信号"""
    if len(rsi) < 1:
        return "数据不足"
    
    rsi_val = rsi.iloc[-1]
    
    if rsi_val > 80:
        return "严重超买"
    elif rsi_val > 70:
        return "超买"
    elif rsi_val < 20:
        return "严重超卖"
    elif rsi_val < 30:
        return "超卖"
    else:
        return f"中性({rsi_val:.1f})"

def calc_boll(close: pd.Series, period: int = 20, std_dev: int = 2) -> dict:
    """计算布林带"""
    mid = close.rolling(window=period).mean()
    std = close.rolling(window=period).std()
    upper = mid + std_dev * std
    lower = mid - std_dev * std
    
    return {
        'UPPER': upper,
        'MID': mid,
        'LOWER': lower,
        'signal': get_boll_signal(close, upper, mid, lower)
    }

def get_boll_signal(close: pd.Series, upper: pd.Series, mid: pd.Series, lower: pd.Series) -> str:
    """判断布林带信号"""
    if len(close) < 1:
        return "数据不足"
    
    price = close.iloc[-1]
    u = upper.iloc[-1]
    m = mid.iloc[-1]
    l = lower.iloc[-1]
    
    if price > u:
        return "突破上轨-超买"
    elif price < l:
        return "跌破下轨-超卖"
    elif price > m:
        return "中轨上方-偏多"
    else:
        return "中轨下方-偏空"

def calc_atr(high: pd.Series, low: pd.Series, close: pd.Series, period: int = 14) -> pd.Series:
    """计算ATR真实波幅"""
    tr1 = high - low
    tr2 = abs(high - close.shift(1))
    tr3 = abs(low - close.shift(1))
    tr = pd.concat([tr1, tr2, tr3], axis=1).max(axis=1)
    return tr.rolling(window=period).mean()

def calc_vol_ma(volume: pd.Series, periods: list = [5, 10, 20]) -> pd.DataFrame:
    """计算成交量均线"""
    vol_df = pd.DataFrame(index=volume.index)
    for p in periods:
        vol_df[f'VOL_MA{p}'] = volume.rolling(window=p).mean()
    return vol_df

def detect_trend(close: pd.Series, ma_short: int = 20, ma_long: int = 60) -> str:
    """判断趋势方向"""
    ma_s = close.rolling(ma_short).mean()
    ma_l = close.rolling(ma_long).mean()
    
    if len(ma_s) < 1 or len(ma_l) < 1:
        return "数据不足"
    
    if ma_s.iloc[-1] > ma_l.iloc[-1] and close.iloc[-1] > ma_s.iloc[-1]:
        return "上升趋势"
    elif ma_s.iloc[-1] < ma_l.iloc[-1] and close.iloc[-1] < ma_s.iloc[-1]:
        return "下降趋势"
    else:
        return "震荡整理"

def find_support_resistance(high: pd.Series, low: pd.Series, close: pd.Series, period: int = 20) -> dict:
    """计算支撑位和阻力位"""
    support = low.rolling(window=period).min().iloc[-1]
    resistance = high.rolling(window=period).max().iloc[-1]
    pivot = (high.iloc[-1] + low.iloc[-1] + close.iloc[-1]) / 3
    
    return {
        'support': round(support, 2),
        'resistance': round(resistance, 2),
        'pivot': round(pivot, 2)
    }

def technical_score(macd_signal: str, kdj_signal: str, rsi_signal: str, 
                    boll_signal: str, trend: str) -> dict:
    """综合技术评分"""
    score = 50  # 基础分
    
    # MACD评分
    if '金叉' in macd_signal or '多头' in macd_signal:
        score += 15
    elif '死叉' in macd_signal or '空头' in macd_signal:
        score -= 15
    
    # KDJ评分
    if '强买' in kdj_signal:
        score += 15
    elif '买入' in kdj_signal:
        score += 10
    elif '强卖' in kdj_signal:
        score -= 15
    elif '卖出' in kdj_signal:
        score -= 10
    
    # RSI评分
    if '超卖' in rsi_signal:
        score += 10
    elif '超买' in rsi_signal:
        score -= 10
    
    # 布林带评分
    if '超卖' in boll_signal:
        score += 10
    elif '超买' in boll_signal:
        score -= 10
    elif '偏多' in boll_signal:
        score += 5
    elif '偏空' in boll_signal:
        score -= 5
    
    # 趋势评分
    if trend == "上升趋势":
        score += 15
    elif trend == "下降趋势":
        score -= 15
    
    # 技术面强弱描述（中性表述，非买卖评级——合规边界，见 SKILL.md）
    if score >= 80:
        rating = "偏多（强）"
        stars = 5
    elif score >= 65:
        rating = "偏多"
        stars = 4
    elif score >= 50:
        rating = "中性"
        stars = 3
    elif score >= 35:
        rating = "偏弱"
        stars = 2
    else:
        rating = "偏弱（强）"
        stars = 1
    
    return {
        'score': min(max(score, 0), 100),
        'rating': rating,
        'stars': stars
    }

def analyze_stock(df: pd.DataFrame) -> dict:
    """
    完整技术分析
    
    Args:
        df: 包含 open, high, low, close, volume 的DataFrame
    """
    close = df['收盘'] if '收盘' in df.columns else df['close']
    high = df['最高'] if '最高' in df.columns else df['high']
    low = df['最低'] if '最低' in df.columns else df['low']
    volume = df['成交量'] if '成交量' in df.columns else df['volume']
    
    # 计算各项指标
    ma_data = calc_ma(close)
    macd_data = calc_macd(close)
    kdj_data = calc_kdj(high, low, close)
    rsi_data = calc_rsi(close)
    boll_data = calc_boll(close)
    atr = calc_atr(high, low, close)
    trend = detect_trend(close)
    sr = find_support_resistance(high, low, close)
    
    # 综合评分
    score_data = technical_score(
        macd_data['signal'],
        kdj_data['signal'],
        rsi_data['signal'],
        boll_data['signal'],
        trend
    )
    
    return {
        'price': {
            'current': round(close.iloc[-1], 2),
            'change_pct': round((close.iloc[-1] / close.iloc[-2] - 1) * 100, 2)
        },
        'trend': trend,
        'support_resistance': sr,
        'indicators': {
            'MACD': {
                'DIF': round(macd_data['DIF'].iloc[-1], 4),
                'DEA': round(macd_data['DEA'].iloc[-1], 4),
                'signal': macd_data['signal']
            },
            'KDJ': {
                'K': round(kdj_data['K'].iloc[-1], 2),
                'D': round(kdj_data['D'].iloc[-1], 2),
                'J': round(kdj_data['J'].iloc[-1], 2),
                'signal': kdj_data['signal']
            },
            'RSI': {
                'value': round(rsi_data['RSI'].iloc[-1], 2),
                'signal': rsi_data['signal']
            },
            'BOLL': {
                'upper': round(boll_data['UPPER'].iloc[-1], 2),
                'mid': round(boll_data['MID'].iloc[-1], 2),
                'lower': round(boll_data['LOWER'].iloc[-1], 2),
                'signal': boll_data['signal']
            },
            'ATR': round(atr.iloc[-1], 2)
        },
        'score': score_data
    }

if __name__ == "__main__":
    # 测试
    import akshare as ak
    
    df = ak.stock_zh_a_hist(symbol="000001", period="daily", adjust="qfq")
    df = df.tail(120)
    
    result = analyze_stock(df)
    print("=== 平安银行(000001) 技术分析 ===")
    print(f"当前价格: {result['price']['current']} ({result['price']['change_pct']:+.2f}%)")
    print(f"趋势判断: {result['trend']}")
    print(f"支撑位: {result['support_resistance']['support']} | 阻力位: {result['support_resistance']['resistance']}")
    print(f"\n技术指标:")
    for name, data in result['indicators'].items():
        print(f"  {name}: {data}")
    print(f"\n综合评分: {result['score']['score']} - {result['score']['rating']} ({'⭐' * result['score']['stars']})")
```

## File: lab/Geek-skills-a-share-analyst/references/candlestick_patterns.md
size: 3983
sha: 87407babd6e66096c8f87a07d90b9ae8813dded0
upstream: https://github.com/staruhub/claudeskills/blob/main/lab/Geek-skills-a-share-analyst/references/candlestick_patterns.md

````text
# K线形态识别

## 反转形态

### 底部反转

**锤子线 (Hammer)**
- 条件：下影线 >= 实体×2，上影线极小，出现在下跌末端
```python
def is_hammer(open, high, low, close):
    body = abs(close - open)
    lower_shadow = min(open, close) - low
    upper_shadow = high - max(open, close)
    return lower_shadow >= body * 2 and upper_shadow <= body * 0.3
```

**早晨之星 (Morning Star)**
- 三根K线组合：大阴线 + 小实体(十字星) + 大阳线
```python
def is_morning_star(df, idx):
    d1 = df.iloc[idx-2]  # 大阴线
    d2 = df.iloc[idx-1]  # 小实体
    d3 = df.iloc[idx]    # 大阳线
    return (d1['close'] < d1['open'] and 
            abs(d2['close'] - d2['open']) < (d1['high']-d1['low'])*0.3 and
            d3['close'] > d3['open'] and 
            d3['close'] > (d1['open'] + d1['close'])/2)
```

**双底 (Double Bottom)**
- W形态，两个低点接近，颈线突破确认

### 顶部反转

**流星线 (Shooting Star)**
- 条件：上影线 >= 实体×2，下影线极小，出现在上涨末端
```python
def is_shooting_star(open, high, low, close):
    body = abs(close - open)
    upper_shadow = high - max(open, close)
    lower_shadow = min(open, close) - low
    return upper_shadow >= body * 2 and lower_shadow <= body * 0.3
```

**黄昏之星 (Evening Star)**
- 三根K线组合：大阳线 + 小实体(十字星) + 大阴线

**双顶 (Double Top)**
- M形态，两个高点接近，颈线跌破确认

## 持续形态

### 上升趋势中

**红三兵 (Three White Soldiers)**
- 三根连续阳线，每根开盘价在前一根实体内，收盘创新高
```python
def is_three_white_soldiers(df, idx):
    for i in range(3):
        if df.iloc[idx-i]['close'] <= df.iloc[idx-i]['open']:
            return False
    return (df.iloc[idx]['close'] > df.iloc[idx-1]['close'] > df.iloc[idx-2]['close'])
```

**上升三法 (Rising Three Methods)**
- 大阳线 + 3根小阴线(不破大阳线低点) + 大阳线

### 下降趋势中

**三只乌鸦 (Three Black Crows)**
- 三根连续阴线，每根开盘价在前一根实体内，收盘创新低

**下降三法 (Falling Three Methods)**
- 大阴线 + 3根小阳线(不破大阴线高点) + 大阴线

## 整理形态

### 三角形整理

**上升三角形**
- 高点水平，低点上移，向上突破概率大
```python
def is_ascending_triangle(highs, lows, period=20):
    high_max = highs[-period:].max()
    high_range = highs[-period:].max() - highs[-period:].min()
    low_slope = (lows.iloc[-1] - lows.iloc[-period]) / period
    return high_range / high_max < 0.02 and low_slope > 0
```

**下降三角形**
- 低点水平，高点下移，向下突破概率大

**对称三角形**
- 高点下移，低点上移，方向不确定

### 旗形整理

**上升旗形**
- 急涨后小幅回调整理，形成向下倾斜通道

**下降旗形**
- 急跌后小幅反弹整理，形成向上倾斜通道

## 缺口分析

### 缺口类型

| 类型 | 特征 | 意义 |
|------|------|------|
| 普通缺口 | 整理区间内 | 通常会回补 |
| 突破缺口 | 突破重要位置 | 趋势开始信号 |
| 持续缺口 | 趋势中间 | 趋势加速信号 |
| 衰竭缺口 | 趋势末端 | 趋势结束信号 |

```python
def find_gaps(df):
    gaps = []
    for i in range(1, len(df)):
        if df.iloc[i]['low'] > df.iloc[i-1]['high']:  # 向上缺口
            gaps.append(('up', i, df.iloc[i-1]['high'], df.iloc[i]['low']))
        elif df.iloc[i]['high'] < df.iloc[i-1]['low']:  # 向下缺口
            gaps.append(('down', i, df.iloc[i]['high'], df.iloc[i-1]['low']))
    return gaps
```

## 实战信号组合

### 强买入信号
1. 早晨之星 + MACD金叉 + 成交量放大
2. 突破缺口 + 站上MA20 + KDJ金叉
3. 锤子线 + RSI超卖反弹 + 布林下轨支撑

### 强卖出信号
1. 黄昏之星 + MACD死叉 + 成交量放大
2. 跌破颈线 + MA20死叉MA60 + KDJ死叉
3. 流星线 + RSI超买回落 + 布林上轨压力
````

## File: lab/Geek-skills-a-share-analyst/references/factor_library.md
size: 6813
sha: 1adcaef9ebd548653b8f0e3fb6958db7a658a26b
upstream: https://github.com/staruhub/claudeskills/blob/main/lab/Geek-skills-a-share-analyst/references/factor_library.md

````text
# 量化因子库

## 价值因子

### EP (收益价格比)
```python
def factor_ep(net_profit, market_cap):
    """EP = 净利润 / 市值，越高越便宜"""
    return net_profit / market_cap
```

### BP (账面市值比)
```python
def factor_bp(book_value, market_cap):
    """BP = 净资产 / 市值，越高越便宜"""
    return book_value / market_cap
```

### SP (销售价格比)
```python
def factor_sp(revenue, market_cap):
    """SP = 营收 / 市值"""
    return revenue / market_cap
```

### CFP (现金流价格比)
```python
def factor_cfp(operating_cf, market_cap):
    """CFP = 经营现金流 / 市值"""
    return operating_cf / market_cap
```

### DP (股息率)
```python
def factor_dp(dividend, price):
    """DP = 每股分红 / 股价"""
    return dividend / price
```

## 动量因子

### MOM (价格动量)
```python
def factor_momentum(close, period=20):
    """过去N日收益率"""
    return close.pct_change(period)
```

### REV (反转因子)
```python
def factor_reversal(close, period=5):
    """短期反转：过去N日收益率取负"""
    return -close.pct_change(period)
```

### VOL_MOM (成交量动量)
```python
def factor_vol_momentum(volume, period=20):
    """成交量动量"""
    return volume.rolling(5).mean() / volume.rolling(period).mean()
```

### RSRS (阻力支撑相对强度)
```python
def factor_rsrs(high, low, period=18):
    """回归斜率作为趋势强度"""
    from sklearn.linear_model import LinearRegression
    rsrs = []
    for i in range(period, len(high)):
        X = low[i-period:i].values.reshape(-1, 1)
        y = high[i-period:i].values
        reg = LinearRegression().fit(X, y)
        rsrs.append(reg.coef_[0])
    return pd.Series(rsrs, index=high.index[period:])
```

## 质量因子

### ROE (净资产收益率)
```python
def factor_roe(net_profit, equity):
    return net_profit / equity
```

### ROIC (投入资本回报率)
```python
def factor_roic(nopat, invested_capital):
    """ROIC = 税后经营利润 / 投入资本"""
    return nopat / invested_capital
```

### GP (毛利率)
```python
def factor_gross_profit(revenue, cogs):
    return (revenue - cogs) / revenue
```

### ACCRUAL (应计盈余)
```python
def factor_accrual(net_profit, operating_cf, total_assets):
    """应计盈余 = (净利润 - 经营现金流) / 总资产"""
    return (net_profit - operating_cf) / total_assets
```

## 规模因子

### SIZE (市值因子)
```python
def factor_size(market_cap):
    """对数市值，通常取负表示小盘股溢价"""
    return -np.log(market_cap)
```

### NLSIZE (非线性市值)
```python
def factor_nlsize(market_cap):
    """市值三次方根"""
    return np.cbrt(market_cap)
```

## 波动率因子

### VOL (波动率)
```python
def factor_volatility(returns, period=20):
    """收益率标准差"""
    return returns.rolling(period).std()
```

### IVOL (特质波动率)
```python
def factor_idio_vol(returns, market_returns, period=60):
    """剔除市场因素后的特质波动率"""
    from sklearn.linear_model import LinearRegression
    resid = []
    for i in range(period, len(returns)):
        X = market_returns[i-period:i].values.reshape(-1, 1)
        y = returns[i-period:i].values
        reg = LinearRegression().fit(X, y)
        pred = reg.predict(X)
        resid.append(np.std(y - pred))
    return pd.Series(resid, index=returns.index[period:])
```

### SKEW (偏度)
```python
def factor_skewness(returns, period=20):
    return returns.rolling(period).skew()
```

## 技术因子

### TURN (换手率)
```python
def factor_turnover(volume, float_shares, period=20):
    """平均换手率"""
    return (volume / float_shares).rolling(period).mean()
```

### ILLIQ (非流动性)
```python
def factor_illiquidity(returns, volume, period=20):
    """Amihud非流动性指标"""
    return (returns.abs() / volume).rolling(period).mean()
```

### CORR (相关性)
```python
def factor_correlation(returns, market_returns, period=60):
    """与市场的相关性"""
    return returns.rolling(period).corr(market_returns)
```

## 成长因子

### SUE (标准化盈余惊喜)
```python
def factor_sue(actual_eps, expected_eps, std_eps):
    """SUE = (实际EPS - 预期EPS) / 标准差"""
    return (actual_eps - expected_eps) / std_eps
```

### REVG (营收增长率)
```python
def factor_revenue_growth(revenue):
    return revenue.pct_change(4)  # 同比增长
```

### EPG (盈利增长率)
```python
def factor_earnings_growth(net_profit):
    return net_profit.pct_change(4)  # 同比增长
```

## 因子合成与选股

### 多因子评分模型
```python
def multi_factor_score(df, factors_config):
    """
    factors_config = {
        'EP': {'weight': 0.2, 'ascending': False},
        'MOM_20': {'weight': 0.15, 'ascending': False},
        'ROE': {'weight': 0.2, 'ascending': False},
        'REV_5': {'weight': 0.15, 'ascending': True},
        'VOL': {'weight': 0.1, 'ascending': True},
        'SIZE': {'weight': 0.2, 'ascending': True},
    }
    """
    scores = pd.DataFrame(index=df.index)
    for factor, config in factors_config.items():
        # 标准化因子值
        factor_values = df[factor]
        factor_rank = factor_values.rank(pct=True, ascending=config['ascending'])
        scores[factor] = factor_rank * config['weight']
    
    scores['total'] = scores.sum(axis=1)
    return scores.sort_values('total', ascending=False)
```

### 选股示例
```python
def select_stocks(df, top_n=30):
    """
    选股流程：
    1. 剔除ST股票
    2. 剔除上市不满60天的新股
    3. 剔除涨停/跌停股票
    4. 计算多因子评分
    5. 选取评分前N名
    """
    # 基础筛选
    df = df[~df['name'].str.contains('ST')]
    df = df[df['list_days'] > 60]
    df = df[df['pct_change'].abs() < 9.9]
    
    # 计算因子评分
    scores = multi_factor_score(df, factors_config)
    
    return scores.head(top_n)
```

## 回测框架

```python
def backtest_strategy(df, signal_col, hold_days=5):
    """
    简单回测框架
    df: 包含日期、收盘价、信号的DataFrame
    signal_col: 信号列名 (1=买入, 0=持有, -1=卖出)
    hold_days: 持仓天数
    """
    df['future_return'] = df['close'].shift(-hold_days) / df['close'] - 1
    df['strategy_return'] = df[signal_col].shift(1) * df['future_return']
    
    total_return = (1 + df['strategy_return']).cumprod().iloc[-1] - 1
    sharpe = df['strategy_return'].mean() / df['strategy_return'].std() * np.sqrt(252/hold_days)
    max_drawdown = (df['strategy_return'].cumsum() - df['strategy_return'].cumsum().cummax()).min()
    
    return {
        'total_return': total_return,
        'sharpe_ratio': sharpe,
        'max_drawdown': max_drawdown,
        'win_rate': (df['strategy_return'] > 0).mean()
    }
```
````

## File: lab/Geek-skills-a-share-analyst/references/fundamental_metrics.md
size: 4141
sha: 6dc169e19b55493d95ddbb602883919bba30511e
upstream: https://github.com/staruhub/claudeskills/blob/main/lab/Geek-skills-a-share-analyst/references/fundamental_metrics.md

````text
# 基本面指标说明

## 估值指标

### PE (市盈率)
```
PE = 股价 / 每股收益(EPS)
PE(TTM) = 当前市值 / 最近四个季度净利润
```
- PE < 15：低估值
- 15 < PE < 25：合理估值
- PE > 25：高估值
- 注意：亏损股票PE无意义，需结合行业对比

### PB (市净率)
```
PB = 股价 / 每股净资产
```
- PB < 1：破净股，可能低估或资产质量差
- 1 < PB < 3：合理区间
- PB > 5：可能高估

### PS (市销率)
```
PS = 当前市值 / 年度营业收入
```
- 适用于亏损但有收入增长的公司
- PS < 1：可能低估
- PS > 10：可能高估

### PEG (市盈增长比率)
```
PEG = PE / 净利润增长率(%)
```
- PEG < 1：相对低估
- PEG = 1：合理
- PEG > 1：相对高估

## 盈利能力

### ROE (净资产收益率)
```
ROE = 净利润 / 平均股东权益 × 100%
```
- ROE > 15%：优秀
- 10% < ROE < 15%：良好
- ROE < 10%：一般

### ROA (总资产收益率)
```
ROA = 净利润 / 平均总资产 × 100%
```
- ROA > 10%：优秀
- 5% < ROA < 10%：良好

### 毛利率
```
毛利率 = (营业收入 - 营业成本) / 营业收入 × 100%
```
- 毛利率 > 40%：高毛利行业(医药、软件)
- 20% < 毛利率 < 40%：中等水平
- 毛利率 < 20%：低毛利行业(零售、制造)

### 净利率
```
净利率 = 净利润 / 营业收入 × 100%
```
- 净利率 > 15%：优秀
- 5% < 净利率 < 15%：良好

## 成长能力

### 营收增长率
```
营收增长率 = (本期营收 - 上期营收) / 上期营收 × 100%
```
- 增速 > 30%：高成长
- 10% < 增速 < 30%：中等成长
- 增速 < 10%：稳定型

### 净利润增长率
```
净利增长率 = (本期净利 - 上期净利) / 上期净利 × 100%
```
- 持续稳定增长优于大起大落

### 扣非净利润增长率
- 排除非经常性损益的净利润增长
- 更能反映主营业务真实增长

## 财务健康

### 资产负债率
```
资产负债率 = 总负债 / 总资产 × 100%
```
- < 40%：财务稳健
- 40% - 60%：正常水平
- > 70%：财务风险较高
- 注意：银行等金融行业除外

### 流动比率
```
流动比率 = 流动资产 / 流动负债
```
- > 2：短期偿债能力强
- 1 - 2：正常
- < 1：短期偿债压力大

### 速动比率
```
速动比率 = (流动资产 - 存货) / 流动负债
```
- > 1：偿债能力良好

### 经营现金流/净利润
```
现金流比率 = 经营活动现金流净额 / 净利润
```
- > 1：利润质量高，现金回收好
- < 0.5：利润质量存疑

## 运营效率

### 存货周转率
```
存货周转率 = 营业成本 / 平均存货
存货周转天数 = 365 / 存货周转率
```
- 周转率越高，运营效率越好

### 应收账款周转率
```
应收周转率 = 营业收入 / 平均应收账款
应收周转天数 = 365 / 应收周转率
```
- 周转天数短：回款快，坏账风险低

### 总资产周转率
```
总资产周转率 = 营业收入 / 平均总资产
```
- 反映资产利用效率

## 分红指标

### 股息率
```
股息率 = 每股分红 / 股价 × 100%
```
- 股息率 > 3%：高股息股票
- 长期稳定分红表明财务健康

### 分红率
```
分红率 = 每股分红 / 每股收益 × 100%
```
- 合理分红率：30%-50%

## AKShare获取基本面数据

```python
import akshare as ak

# 财务指标
df = ak.stock_financial_analysis_indicator(symbol="000001")

# 资产负债表
df = ak.stock_balance_sheet_by_report_em(symbol="000001")

# 利润表
df = ak.stock_profit_sheet_by_report_em(symbol="000001")

# 现金流量表
df = ak.stock_cash_flow_sheet_by_report_em(symbol="000001")

# 业绩预告
df = ak.stock_yjyg_em()

# 业绩快报
df = ak.stock_yjkb_em()
```

## 综合评分模型

| 维度 | 指标 | 权重 | 优秀 | 良好 | 一般 |
|------|------|------|------|------|------|
| 估值 | PE | 20% | <15 | 15-25 | >25 |
| 估值 | PB | 10% | <2 | 2-4 | >4 |
| 盈利 | ROE | 20% | >15% | 10-15% | <10% |
| 盈利 | 净利率 | 10% | >15% | 5-15% | <5% |
| 成长 | 营收增速 | 15% | >30% | 10-30% | <10% |
| 成长 | 净利增速 | 15% | >30% | 10-30% | <10% |
| 安全 | 资产负债率 | 10% | <40% | 40-60% | >60% |
````

## File: lab/Geek-skills-a-share-analyst/references/technical_indicators.md
size: 4128
sha: 4937eff9994bc4ad5b0367a96e40d7f46e57fa1e
upstream: https://github.com/staruhub/claudeskills/blob/main/lab/Geek-skills-a-share-analyst/references/technical_indicators.md

````text
# 技术指标计算公式

## 趋势指标

### MA (移动平均线)
```python
def calc_ma(close, period):
    return close.rolling(window=period).mean()
# 常用周期：MA5, MA10, MA20, MA60, MA120, MA250
```

### EMA (指数移动平均)
```python
def calc_ema(close, period):
    return close.ewm(span=period, adjust=False).mean()
```

### MACD (指数平滑异同移动平均线)
```python
def calc_macd(close, fast=12, slow=26, signal=9):
    ema_fast = close.ewm(span=fast, adjust=False).mean()
    ema_slow = close.ewm(span=slow, adjust=False).mean()
    dif = ema_fast - ema_slow  # 快线
    dea = dif.ewm(span=signal, adjust=False).mean()  # 慢线
    macd = (dif - dea) * 2  # 柱状图
    return dif, dea, macd
# 金叉：DIF上穿DEA | 死叉：DIF下穿DEA
```

## 震荡指标

### KDJ (随机指标)
```python
def calc_kdj(high, low, close, n=9, m1=3, m2=3):
    low_n = low.rolling(window=n).min()
    high_n = high.rolling(window=n).max()
    rsv = (close - low_n) / (high_n - low_n) * 100
    k = rsv.ewm(com=m1-1, adjust=False).mean()
    d = k.ewm(com=m2-1, adjust=False).mean()
    j = 3 * k - 2 * d
    return k, d, j
# K>80超买 | K<20超卖 | 金叉：K上穿D
```

### RSI (相对强弱指标)
```python
def calc_rsi(close, period=14):
    delta = close.diff()
    gain = delta.where(delta > 0, 0).rolling(window=period).mean()
    loss = (-delta.where(delta < 0, 0)).rolling(window=period).mean()
    rs = gain / loss
    return 100 - (100 / (1 + rs))
# RSI>70超买 | RSI<30超卖
```

### WR (威廉指标)
```python
def calc_wr(high, low, close, period=14):
    hh = high.rolling(window=period).max()
    ll = low.rolling(window=period).min()
    return -100 * (hh - close) / (hh - ll)
# WR>-20超买 | WR<-80超卖
```

## 波动率指标

### BOLL (布林带)
```python
def calc_boll(close, period=20, std_dev=2):
    mid = close.rolling(window=period).mean()
    std = close.rolling(window=period).std()
    upper = mid + std_dev * std
    lower = mid - std_dev * std
    return upper, mid, lower
# 突破上轨：超买/强势 | 跌破下轨：超卖/弱势
```

### ATR (真实波动幅度)
```python
def calc_atr(high, low, close, period=14):
    tr1 = high - low
    tr2 = abs(high - close.shift(1))
    tr3 = abs(low - close.shift(1))
    tr = pd.concat([tr1, tr2, tr3], axis=1).max(axis=1)
    return tr.rolling(window=period).mean()
# 用于止损设置：止损位 = 入场价 - N * ATR
```

## 成交量指标

### OBV (能量潮)
```python
def calc_obv(close, volume):
    direction = np.where(close > close.shift(1), 1, 
                np.where(close < close.shift(1), -1, 0))
    return (direction * volume).cumsum()
# OBV上升趋势配合价格上涨确认趋势
```

### VOL_MA (成交量均线)
```python
def calc_vol_ma(volume, period):
    return volume.rolling(window=period).mean()
# 放量突破：当日成交量 > 2 * VOL_MA5
```

## 形态识别

### 趋势判断
```python
def trend_direction(close, ma_short=20, ma_long=60):
    ma_s = close.rolling(ma_short).mean()
    ma_l = close.rolling(ma_long).mean()
    if ma_s.iloc[-1] > ma_l.iloc[-1] and close.iloc[-1] > ma_s.iloc[-1]:
        return "上升趋势"
    elif ma_s.iloc[-1] < ma_l.iloc[-1] and close.iloc[-1] < ma_s.iloc[-1]:
        return "下降趋势"
    else:
        return "震荡整理"
```

### 支撑阻力位
```python
def support_resistance(high, low, close, period=20):
    support = low.rolling(window=period).min()
    resistance = high.rolling(window=period).max()
    pivot = (high + low + close) / 3
    return support.iloc[-1], resistance.iloc[-1], pivot.iloc[-1]
```

## 信号评分系统

综合评分 = 趋势得分×0.3 + 动量得分×0.3 + 量能得分×0.2 + 波动得分×0.2

| 指标 | 强买入 | 买入 | 中性 | 卖出 | 强卖出 |
|------|--------|------|------|------|--------|
| MACD | DIF>0且金叉 | 金叉 | 中性 | 死叉 | DIF<0且死叉 |
| KDJ | K<20金叉 | K<50金叉 | 40<K<60 | K>50死叉 | K>80死叉 |
| RSI | RSI<30 | 30<RSI<40 | 40<RSI<60 | 60<RSI<70 | RSI>70 |
| BOLL | 下轨反弹 | 中轨支撑 | 中轨附近 | 中轨压力 | 上轨回落 |
````

## File: lab/Geek-skills-a-share-analyst/evals/routing-evals.json
size: 1668
sha: 7ac7680f808c60068047ed43b34b86cc84a4703a
upstream: https://github.com/staruhub/claudeskills/blob/main/lab/Geek-skills-a-share-analyst/evals/routing-evals.json

```text
[
  {
    "id": "ash-01",
    "prompt": "帮我分析一下这只 A 股的技术面，MACD、KDJ、支撑阻力都看看。",
    "should_trigger": true,
    "reason": "A-share technical analysis"
  },
  {
    "id": "ash-02",
    "prompt": "今天大盘怎么样，帮我筛几只符合多因子策略的票。",
    "should_trigger": true,
    "reason": "market overview + factor screening"
  },
  {
    "id": "ash-03",
    "prompt": "这家公司的估值和财务指标帮我看看贵不贵。",
    "should_trigger": true,
    "reason": "场景触发：基本面/估值分析，未出现'股票'关键词"
  },
  {
    "id": "ash-04",
    "prompt": "帮我调研新能源汽车行业的政策和市场前景，要有引用。",
    "should_trigger": false,
    "route_to": "deep-research",
    "reason": "cited industry research, not stock TA/FA"
  },
  {
    "id": "ash-05",
    "prompt": "这只美股 TSLA 帮我分析一下。",
    "should_trigger": false,
    "route_to": "none",
    "reason": "US equity; data source and rules differ, out of scope"
  },
  {
    "id": "ash-06",
    "prompt": "帮我预测一下明天这只票会涨还是跌，我该不该满仓。",
    "should_trigger": false,
    "route_to": "none",
    "reason": "asks for a directional prediction / buy order — explicitly outside the compliance boundary"
  },
  {
    "id": "ash-07",
    "prompt": "帮我把这只票的分析结论做成一份可发的图文报告。",
    "should_trigger": true,
    "boundary": true,
    "reason": "两可：分析主体归本 skill，但'做成可发图文'的视觉化归 deck-studio；本 skill 出分析内容，传播图另行移交"
  }
]
```

## File: README.md
upstream: https://github.com/staruhub/claudeskills/blob/main/README.md

````text
[![en](https://img.shields.io/badge/lang-English-blue.svg)](README.md) [![zh-CN](https://img.shields.io/badge/语言-简体中文-red.svg)](README.zh-CN.md)

# ClaudeSkills

ClaudeSkills is a collection of Agent Skills: 13 skill packages written in the open `SKILL.md` format. Each skill packages the complete process for getting something done — steps, templates, scripts, examples, and acceptance checks are all files — and installs into any client that supports Agent Skills.

A prompt lets a model do something once, then dies with the conversation; a skill keeps the method around, so it can be reused, inspected, and improved.

[![validate](https://github.com/staruhub/ClaudeSkills/actions/workflows/validate.yml/badge.svg)](https://github.com/staruhub/ClaudeSkills/actions/workflows/validate.yml)
[![release](https://img.shields.io/badge/release-1.0.1-2746d8)](https://github.com/staruhub/ClaudeSkills/releases/tag/1.0.1)
[![license](https://img.shields.io/badge/license-MIT-green)](LICENSE)

**Contents**: [Quick start](#quick-start) · [Skills](#skills) · [Verification](#verification) · [Install options](#install-options) · [Contributing](#contributing)

[Website](https://staruhub.github.io/ClaudeSkills/) · [Release 1.0.1 notes](https://github.com/staruhub/ClaudeSkills/releases/tag/1.0.1) · [Security](SECURITY.md)

<p align="center">
  <img src="assets/social/agent-skills-concept-hero.png" alt="Agent Skills concept: experience becomes reusable capability" width="100%">
</p>

## Quick start

Install one and try it — deck-studio, for example:

```bash
git clone --depth 1 https://github.com/staruhub/ClaudeSkills.git && cd ClaudeSkills
python3 scripts/install_skill.py deck-studio
```

Then just tell your agent:

```text
Use deck-studio to turn this quarterly review into an 8-slide consulting deck
```

Skills install to `~/.agents/skills/` by default, which most clients scan. For other ways to install, see [Install options](#install-options).

## Skills

Four flagships:

| Skill | What it does |
|---|---|
| [`deep-research`](skills/Geek-skills-deep-research/SKILL.md) | Research: scopes the question, gathers sources, registers each one, checks citations; hands back a report with references and limits |
| [`product-manager`](skills/Geek-skills-product-manager/SKILL.md) | grill-me-to-doc: reads the repo first, asks one question per round, turns a vague idea into a product document. No code before the doc is approved; interruptions resume |
| [`deck-studio`](skills/Geek-skills-deck-studio/SKILL.md) | Decks: outline, per-page briefs, registered layouts, visual checks; delivers content or per-slide visuals |
| [`wechat-article-writer`](skills/Geek-skills-wechat-article-writer/SKILL.md) | WeChat articles: copy, image prompts, layout HTML — solo or as a pipeline. Never publishes for you |

Nine professional skills:

<details>
<summary><b>Show them</b></summary>

| Skill | What it does |
|---|---|
| [`pair-programming`](skills/Geek-skills-pair-programming/SKILL.md) | Writes code with structured self-review aimed at common AI-code defects |
| [`security-audit`](skills/Geek-skills-security-audit/SKILL.md) | Reviews code and dependencies for security issues |
| [`solution-architect`](skills/Geek-skills-solution-architect/SKILL.md) | System design, tech selection, architecture review |
| [`threejs-performance`](skills/Geek-skills-threejs-performance/SKILL.md) | Diagnoses and tunes Three.js performance |
| [`mineru-pdf-parser`](skills/Geek-skills-mineru-pdf-parser/SKILL.md) | Turns PDFs into Markdown or JSON with a local MinerU install |
| [`ai-sales-champion`](skills/Geek-skills-ai-sales-champion/SKILL.md) | Explains technical capability as business value a customer understands |
| [`keqian-method`](skills/Geek-skills-keqian-method/SKILL.md) | A single-agent, SDD, quality-gated product development method |
| [`xuefeng-method`](skills/Geek-skills-xuefeng-method/SKILL.md) | An open-behavior, model-driven AI-native product method |
| [`c-drive-cleaner`](skills/Geek-skills-c-drive-cleaner/SKILL.md) | Windows C-drive cleanup, dry-run by default |

</details>

Experimental ones (exam prep, weather reports, podcast generation, and friends) live in [`lab/`](lab/). They don't count toward the curated set and skip the same checks.

## Verification

Everything checkable is a script — run them yourself:

```bash
python3 scripts/validate.py                  # structure checks for the 13 curated skills
python3 scripts/run_routing_evals.py         # 91 routing cases
python3 tests/task_b/run_contract_tests.py   # 17 contract cases across the four flagships
```

You can also inspect the artifacts directly. deck-studio keeps its generators, rendered pages, rubrics, and review notes in the repo. Four of the 17 styles:

<p align="center">
<img src="skills/Geek-skills-deck-studio/style-library/creative/bauhaus-preview.png" alt="Bauhaus deck style preview" width="24%"> <img src="skills/Geek-skills-deck-studio/style-library/creative/constructivist-preview.png" alt="Constructivist deck style preview" width="24%"> <img src="skills/Geek-skills-deck-studio/style-library/media/neubrutalism-preview.png" alt="Neubrutalism deck style preview" width="24%"> <img src="skills/Geek-skills-deck-studio/style-library/business/aicher-preview.png" alt="Aicher deck style preview" width="24%">
</p>

Examples: [Constructivist](skills/Geek-skills-deck-studio/examples/constructivist-design-constitution/) · [Moshiro consulting report](skills/Geek-skills-deck-studio/examples/moshiro-consulting-report/) · [Yinghuang bootcamp proposal](skills/Geek-skills-deck-studio/examples/yinghuang-bootcamp-proposal/) · [Polar Night AI Native](skills/Geek-skills-deck-studio/examples/polar-night-ai-native/)

Self-test scores: the Constructivist example scored **7.1/10** on the repo's own rubric; a position-swapped three-judge comparison came out **42.3** to **29.7**. The process and data are in the repo — rerun them yourself.

<details>
<summary><b>What each check proves, and what it doesn't</b></summary>

| Check | Proves | Doesn't prove |
|---|---|---|
| `run_contract_tests.py` | 17 fixed cases covering the success, resume, and failure paths of all four flagships; Deck additionally runs real Chrome rendering and PPTX assembly | Output quality on a different model, real image generation, actual WeChat publishing |
| `validate.py` | Directory structure of the 13 curated skills matches the repo contract | Real-business E2E for every skill |
| `run_routing_evals.py` | Schema, target, uniqueness, and conflict checks pass for 91 routing cases across 10 skills | Routing accuracy when a real model runs it |
| Python / Node compile checks | The repo's 13 Python files and 7 JavaScript files all parse | Network, external tools, production availability |

Full record in [`verification/2026-07-31/README.md`](verification/2026-07-31/README.md).

</details>

## Install options

<details>
<summary><b>Show them</b></summary>

```bash
python3 scripts/install_skill.py --list                  # list all short names
python3 scripts/install_skill.py deep-research           # install any skill
python3 scripts/install_skill.py deep-research --project # current project only
python3 scripts/install_skill.py deep-research --client claude-code # Claude Code's directory
cp -r skills/Geek-skills-deep-research ~/.agents/skills/deep-research # manual copy; the directory name is the skill name
```

```bash
git pull && python3 scripts/install_skill.py deck-studio --force   # update
rm -rf ~/.agents/skills/deck-studio                                # uninstall
```

FAQ:

- Installed but not found: check whether your client scans `.agents/skills/`; if not, use its native directory.
- No automatic trigger: name the skill in your request. Triggers vary by client — some match natural language, others want slash commands.
- Re-install after `git pull` — installed skills are copies.

</details>

## Contributing

Found a bug or built something with a skill? [Open an issue](https://github.
````
