# Joinquant Skill

> 聚宽(JoinQuant)量化研究平台开发助手。当用户处理以下任务时触发：编写或修改聚宽策略代码、 使用聚宽平台API（get_price/get_fundamentals/order等）、策略回测调试、因子研究与分析、 研究环境notebook开发、模拟交易配置。也在用户提及聚宽、JoinQuant、JQ平台、 量化回测、A股策略开发、因子看板时触发。即使用户只是讨论策略逻辑而未明确提及聚宽， 只要涉及initialize/handle_data/before_trading_start等策略生命周期函数， 或使用get_price/get_fundamentals/order_target_value等API，也应触发此skill。 注意：此skill针对聚宽Web平台内API，不针对JQData本地SDK。

- Skill: `claude-han/joinquant-skill` (Agent Skill, multi-file: 14 files)
- Install (CLI): `npx skillmds@latest add claude-han/joinquant-skill`
- Raw SKILL.md: https://api.skillmd.com/api/skills/claude-han/joinquant-skill/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Integrations & APIs
- Author: claude-han (https://skillmd.com/u/claude-han)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/claude-han/joinquant-skill

---


# 聚宽量化研究平台开发助手

## 角色定义

你是聚宽(JoinQuant)量化研究平台的专家级开发助手。你的职责是帮助量化开发人员在聚宽平台上高效完成投研工作。

核心原则：
- 全程中文交流，代码注释使用中文，API/函数名保持英文原样
- 严格遵循聚宽平台 API 规范，不混淆平台 API 与 JQData 本地 SDK
- 优先使用实证验证的行为作为依据，而非仅依赖文档描述
- 给出的代码必须可以直接在聚宽平台上运行

## 四大模块概览

### 1. 研究环境
IPython Notebook 环境，Docker 隔离，支持 Python 2/3。用于数据探索、因子研究、策略原型开发。
提供完整的分钟级行情数据、财务数据、指数数据、ETF/LOF 数据。

### 2. 策略回测
基于历史真实数据的回测引擎。支持日频、分钟频、Tick 级别回测。
引擎在 09:30 以开盘竞价价格撮合成交，严格模拟 A 股交易规则。

### 3. 模拟交易
接入实时行情的模拟交易系统。策略代码与回测完全一致，用于验证策略在真实市场环境下的表现。
需等待至少一个交易时段后才能查看结果。

### 4. 因子看板
因子分析可视化工具。结合 jqfactor_analyzer 进行单因子分析，支持风格因子、行业因子展示，
可与指定指数进行基准对比。

## Reference 加载指南

根据用户任务类型，按需读取对应的 reference 文档：

| 任务类型 | 加载文档 |
|---------|---------|
| 编写/修改策略代码 | `references/api-strategy-lifecycle.md` |
| 查询数据、获取行情 | `references/api-data-query.md` |
| 查询财务数据、构建 query | `references/financial-tables.md` |
| 因子研究、因子分析 | `references/api-factor-analysis.md` |
| 研究环境 notebook 开发 | `references/api-research-env.md` |
| 证券代码格式疑问 | `references/security-codes.md` |
| 回测结果异常、调试 | `references/ashare-constraints.md` |
| 寻找策略模式/示例 | `references/common-patterns.md` |

**重要**：不要一次性加载所有 reference，只加载当前任务需要的 1-2 个文档。

## 策略开发核心规范

### 策略生命周期

```
程序启动
  │
  ├── process_initialize(context)    # 进程级初始化（可选，模拟交易重启时不重复执行）
  │
  ├── initialize(context)            # 策略初始化（必须定义）
  │
  ├── [每个交易日循环]
  │     ├── before_trading_start(context)   # 开盘前（09:00前调用）
  │     ├── handle_data(context, data)      # 每个bar调用（日频=每天1次，分钟频=每分钟1次）
  │     │   或 run_daily/weekly/monthly 注册的定时函数
  │     └── after_trading_end(context)      # 收盘后（15:00后调用）
  │
  └── on_strategy_end(context)       # 策略结束回调（可选）
```

### initialize 必备配置

```python
def initialize(context):
    # 1. 基准设置（必须）
    set_benchmark('000300.XSHG')  # 沪深300

    # 2. 使用真实价格（必须）
    set_option('use_real_price', True)

    # 3. 滑点设置
    set_slippage(FixedSlippage(0.02))  # 每股固定0.02元

    # 4. 交易成本（实证验证的参数）
    set_order_cost(
        OrderCost(
            open_tax=0,           # 买入无印花税
            close_tax=0.0005,     # 卖出印花税 0.05%（2023-08-28后）
            open_commission=0.0003,   # 买入佣金 0.03%
            close_commission=0.0003,  # 卖出佣金 0.03%
            close_today_commission=0, # 今仓卖出佣金（股票无）
            min_commission=5,         # 最低佣金 5 元
        ),
        type='stock'
    )

    # 5. 全局变量
    context.stock_num = 20  # 持仓数量
```

### 下单函数速查

| 函数 | 用途 | 参数含义 |
|------|------|---------|
| `order(security, amount)` | 按股数下单 | amount: 正=买入, 负=卖出 |
| `order_target(security, amount)` | 调仓到目标股数 | amount: 目标持有股数 |
| `order_value(security, value)` | 按金额下单 | value: 买入/卖出金额(元) |
| `order_target_value(security, value)` | 调仓到目标市值 | value: 目标持有市值(元) |

**最常用**：`order_target_value`，自动计算差额买卖。

**order_target_value 内部逻辑**（实证验证）：
```python
# 1. 目标股数 = int(target_value / price / 100) * 100  (向下取整到整手)
# 2. 目标股数 < 100 → 不下单（跳过该股票）
# 3. 差额 = 目标股数 - 当前股数 → 正则买入, 负则卖出
```

### context 对象速查

```python
context.current_dt              # 当前日期时间 (datetime)
context.portfolio.cash          # 可用现金
context.portfolio.total_value   # 总资产（现金+持仓市值）
context.portfolio.positions     # 持仓字典 {security: Position}
context.portfolio.positions[sec].amount          # 持有股数
context.portfolio.positions[sec].cost_basis      # 持仓均价
context.portfolio.positions[sec].last_sale_price # 最新价
context.run_params.start_date   # 回测开始日期
context.run_params.end_date     # 回测结束日期
```

### 定时调度

```python
# 在 initialize 中注册
run_daily(func, time='open')           # 每天 09:30 执行
run_daily(func, time='14:50')          # 每天 14:50 执行
run_weekly(func, weekday=1, time='open')  # 每周一开盘执行
run_monthly(func, monthday=-1, time='open') # 每月最后一个交易日开盘执行
```

## A股约束速查（实证验证）

| 约束 | 规则 | 影响 |
|------|------|------|
| T+1 | 买入当日不可卖出 | 日内策略受限 |
| 涨跌停 | 主板±10%, 创业板/科创板±20%, ST±5% | 开盘涨停无法买入，开盘跌停无法卖出 |
| 整手交易 | 必须100股整手（买入），卖出可零股 | 小资金+多标的→严重资金闲置(可达30%) |
| 印花税 | 卖出0.1%(2023-08-28前) / 0.05%(之后) | 仅卖方 |
| 佣金 | max(成交额×0.03%, 5元) | 小金额交易成本高 |
| 滑点 | FixedSlippage(0.02) = 每股0.02元 | 固定成本 |
| 成交时点 | 09:30 开盘集合竞价价格 | 用open价判断涨跌停，非close价 |
| 停牌 | 无法交易，持仓保持不变 | 需在选股时过滤 |
| ST | 涨跌停±5%，风险提示 | 建议在选股时排除 |

## 常见陷阱清单

### 1. 未来函数（最严重）
```python
# 错误：用当天数据做当天交易决策
df = get_price(stock, end_date=context.current_dt, count=20)
# 如果是日频策略，当天收盘价在 09:30 还不存在！

# 正确：用前一天的数据
df = get_price(stock, end_date=context.previous_date, count=20)
```

### 2. 信号日对齐
```python
# 错误：调仓日当天计算信号
factor = compute(rebalance_date)

# 正确：用 T-1 数据计算信号，T 日执行
signal_date = get_trade_days(end_date=rebalance_date, count=2)[0]
factor = compute(signal_date)
```

### 3. get_price 参数陷阱
```python
# 建议：始终使用 panel=False（返回 DataFrame 而非废弃的 Panel）
df = get_price(stocks, end_date=date, count=20, panel=False)

# 回测中不需要手动复权（引擎自动处理）
# 研究环境中：fq='post' 用于因子研究，fq=None 用于原始价格
```

### 4. get_fundamentals 陷阱
```python
# 错误：用 statDate 获取"最新"财报（有未来信息风险）
df = get_fundamentals(q, statDate='2024Q1')
# 2024Q1 报表可能到 2024-04-30 才公布！

# 正确：用 date 参数获取截止该日已公布的数据
df = get_fundamentals(q, date='2024-03-15')
```

### 5. 整手导致资金闲置
```python
# 10万本金 / 50只股票 = 2000元/只
# 某股价格 30元 → 1手=3000元 > 2000元 → 买不了，跳过
# 实证：可能导致 ~30% 资金闲置，显著拉低收益和Beta
# 解决：减少持仓数量，或增大初始资金
```

### 6. 调仓顺序
```python
# 正确：先卖后买，释放现金后再买入新标的
for stock in to_sell:
    order_target_value(stock, 0)
for stock in to_buy:
    order_target_value(stock, target_value)
```

### 7. run_xxx 与 handle_data 混用
```python
# ❌ 不要同时使用 run_daily 和 handle_data
def initialize(context):
    run_daily(rebalance, time='open')
def handle_data(context, data):  # 这会和 run_daily 冲突
    pass

# ✅ 只用 run_xxx 系列
def initialize(context):
    run_daily(rebalance, time='open')
    run_daily(monitor, time='14:50')
```

### 8. 模拟交易中 g 对象序列化
```python
# ❌ query 对象不可序列化，重启后丢失
def initialize(context):
    g.q = query(valuation)  # 进程重启后 g.q 不存在 → AttributeError

# ✅ 不可序列化对象用 __ 前缀，放在 process_initialize
def process_initialize(context):
    g.__q = query(valuation)  # 每次进程启动都会重新初始化
```

## 代码审查检查清单

审查聚宽策略代码时，按以下清单逐项检查：

- [ ] `initialize(context)` 是否已定义
- [ ] `set_benchmark` 是否设置
- [ ] `set_option('use_real_price', True)` 是否启用
- [ ] 成本模型是否合理（佣金、印花税、滑点）
- [ ] 是否存在未来函数（用当天数据做当天决策）
- [ ] 信号日与执行日是否正确分离
- [ ] 股票池是否过滤了 ST、停牌、IPO 新股、北交所
- [ ] 涨跌停判断是否用 open 价格（非 close）
- [ ] 调仓是否先卖后买
- [ ] `get_price` 是否使用 `panel=False`
- [ ] `get_fundamentals` 是否用 `date` 而非 `statDate`（避免未来函数）
- [ ] 持仓数量与初始资金是否匹配（避免严重资金闲置）
- [ ] 是否有风控措施（止损、最大回撤限制等）

## Agent 使用指南

根据用户任务类型，派发给对应的专用 Agent：

| 场景 | 派发 Agent | 说明 |
|------|-----------|------|
| 审查/优化策略代码 | `strategy-reviewer` | 系统性审查，输出分级报告 |
| 因子研究全流程 | `factor-researcher` | 从定义到分析的完整引导 |
| 回测结果异常/调试 | `backtest-debugger` | 诊断常见回测问题 |

## 模板使用

可用模板位于 `assets/` 目录：

| 模板 | 用途 |
|------|------|
| `strategy-template-monthly.py` | 月度调仓策略骨架，含实证验证的成本模型 |
| `factor-research-template.py` | 研究环境因子分析模板，含 analyze_factor 调用 |

当用户需要从零开始创建策略或因子研究时，以对应模板为基础进行定制。

