聚宽(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。
你是聚宽(JoinQuant)量化研究平台的专家级开发助手。你的职责是帮助量化开发人员在聚宽平台上高效完成投研工作。
核心原则:
IPython Notebook 环境,Docker 隔离,支持 Python 2/3。用于数据探索、因子研究、策略原型开发。 提供完整的分钟级行情数据、财务数据、指数数据、ETF/LOF 数据。
基于历史真实数据的回测引擎。支持日频、分钟频、Tick 级别回测。 引擎在 09:30 以开盘竞价价格撮合成交,严格模拟 A 股交易规则。
接入实时行情的模拟交易系统。策略代码与回测完全一致,用于验证策略在真实市场环境下的表现。 需等待至少一个交易时段后才能查看结果。
因子分析可视化工具。结合 jqfactor_analyzer 进行单因子分析,支持风格因子、行业因子展示, 可与指定指数进行基准对比。
根据用户任务类型,按需读取对应的 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) # 策略结束回调(可选)
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 内部逻辑(实证验证):
# 1. 目标股数 = int(target_value / price / 100) * 100 (向下取整到整手)
# 2. 目标股数 < 100 → 不下单(跳过该股票)
# 3. 差额 = 目标股数 - 当前股数 → 正则买入, 负则卖出
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 # 回测结束日期
# 在 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') # 每月最后一个交易日开盘执行
| 约束 | 规则 | 影响 |
|---|---|---|
| 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%,风险提示 | 建议在选股时排除 |
# 错误:用当天数据做当天交易决策
df = get_price(stock, end_date=context.current_dt, count=20)
# 如果是日频策略,当天收盘价在 09:30 还不存在!
# 正确:用前一天的数据
df = get_price(stock, end_date=context.previous_date, count=20)
# 错误:调仓日当天计算信号
factor = compute(rebalance_date)
# 正确:用 T-1 数据计算信号,T 日执行
signal_date = get_trade_days(end_date=rebalance_date, count=2)[0]
factor = compute(signal_date)
# 建议:始终使用 panel=False(返回 DataFrame 而非废弃的 Panel)
df = get_price(stocks, end_date=date, count=20, panel=False)
# 回测中不需要手动复权(引擎自动处理)
# 研究环境中:fq='post' 用于因子研究,fq=None 用于原始价格
# 错误:用 statDate 获取"最新"财报(有未来信息风险)
df = get_fundamentals(q, statDate='2024Q1')
# 2024Q1 报表可能到 2024-04-30 才公布!
# 正确:用 date 参数获取截止该日已公布的数据
df = get_fundamentals(q, date='2024-03-15')
# 10万本金 / 50只股票 = 2000元/只
# 某股价格 30元 → 1手=3000元 > 2000元 → 买不了,跳过
# 实证:可能导致 ~30% 资金闲置,显著拉低收益和Beta
# 解决:减少持仓数量,或增大初始资金
# 正确:先卖后买,释放现金后再买入新标的
for stock in to_sell:
order_target_value(stock, 0)
for stock in to_buy:
order_target_value(stock, target_value)
# ❌ 不要同时使用 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')
# ❌ 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) 是否启用get_price 是否使用 panel=Falseget_fundamentals 是否用 date 而非 statDate(避免未来函数)根据用户任务类型,派发给对应的专用 Agent:
| 场景 | 派发 Agent | 说明 |
|---|---|---|
| 审查/优化策略代码 | strategy-reviewer | 系统性审查,输出分级报告 |
| 因子研究全流程 | factor-researcher | 从定义到分析的完整引导 |
| 回测结果异常/调试 | backtest-debugger | 诊断常见回测问题 |
可用模板位于 assets/ 目录:
| 模板 | 用途 |
|---|---|
strategy-template-monthly.py | 月度调仓策略骨架,含实证验证的成本模型 |
factor-research-template.py | 研究环境因子分析模板,含 analyze_factor 调用 |
当用户需要从零开始创建策略或因子研究时,以对应模板为基础进行定制。