聚宽量化(JoinQuant)
name: joinquant
by coderwpf · published 2026-03-22
$ claw add gh:coderwpf/coderwpf-joinquant---
name: joinquant
description: 聚宽量化交易平台 - 提供A股、期货、基金数据查询,事件驱动策略回测,支持在线研究与模拟实盘。
version: 1.1.0
homepage: https://www.joinquant.com
metadata: {"clawdbot":{"emoji":"🔬","requires":{"bins":["python3"]}}}
---
# 聚宽量化(JoinQuant)
[聚宽](https://www.joinquant.com) 是中国领先的在线量化交易平台,提供免费数据查询、策略回测和模拟交易。支持A股、期货、基金、指数等品种,采用事件驱动的Python策略框架。
> ⚠️ **需要在 https://www.joinquant.com 注册账号**。策略运行在聚宽云端,也可以通过JQData在本地获取数据。
安装 (Local Data SDK)
pip install jqdatasdk本地数据认证
import jqdatasdk as jq
# 使用聚宽账号登录(每日免费数据额度)
jq.auth('your_username', 'your_password')
# 查看剩余数据额度
print(jq.get_query_count())策略程序结构(在线回测)
聚宽策略采用事件驱动架构,在平台网页界面编写和运行:
def initialize(context):
"""初始化函数 — 策略启动时调用一次"""
# 设置基准指数(沪深300)
set_benchmark('000300.XSHG')
# 设置手续费 and slippage
set_order_cost(OrderCost(open_tax=0, close_tax=0.001,
open_commission=0.0003, close_commission=0.0003,
min_commission=5), type='stock')
set_slippage(FixedSlippage(0.02))
# 设置股票池
g.security = '000001.XSHE'
def handle_data(context, data):
"""盘中事件 — 每个交易频率触发一次"""
security = g.security
# 获取最近20天收盘价
close_data = attribute_history(security, 20, '1d', ['close'])
ma5 = close_data['close'][-5:].mean()
ma20 = close_data['close'].mean()
# 金叉 — buy
if ma5 > ma20:
order_target_value(security, context.portfolio.total_value * 0.9)
# 死叉 — sell
elif ma5 < ma20:
order_target(security, 0)---
股票代码格式
| 市场 | 后缀 | 示例 |
|---|---|---|
| 上海A股 | `.XSHG` | `600000.XSHG`(浦发银行) |
| 深圳A股 | `.XSHE` | `000001.XSHE`(平安银行) |
| 指数 | `.XSHG/.XSHE` | `000300.XSHG`(沪深300) |
| 期货 | `.XDCE/.XZCE/.XSGE/.CCFX` | `IF2401.CCFX`(股指期货) |
| 基金 | `.XSHG/.XSHE` | `510300.XSHG`(沪深300ETF) |
---
数据查询函数(JQData)
行情数据
import jqdatasdk as jq
# 获取日K线数据
df = jq.get_price(
'000001.XSHE', # 股票代码
start_date='2024-01-01', # 开始日期
end_date='2024-06-30', # 结束日期
frequency='daily', # 频率: daily(日), minute(分钟), 1m, 5m, 15m, 30m, 60m, 120m
fields=['open', 'close', 'high', 'low', 'volume', 'money'],
skip_paused=True, # 跳过停牌日
fq='pre', # 复权: None(不复权), 'pre'(前复权), 'post'(后复权)
panel=False # False返回DataFrame
)
# 获取多只股票数据
df = jq.get_price(['000001.XSHE', '600000.XSHG'],
start_date='2024-01-01', end_date='2024-06-30',
frequency='daily', fields=['close'], panel=False)
# 获取分钟级数据
df = jq.get_price('000001.XSHE', start_date='2024-06-01 09:30:00',
end_date='2024-06-01 15:00:00', frequency='1m')获取最近N条数据
# 获取最近20个交易日的收盘价
df = jq.get_bars('000001.XSHE', count=20, unit='1d', fields=['close', 'volume'])财务数据
# 查询财务指标
df = jq.get_fundamentals(
jq.query(
jq.valuation.code,
jq.valuation.market_cap, # 总市值(亿元)
jq.valuation.pe_ratio, # 市盈率
jq.valuation.pb_ratio, # 市净率
jq.valuation.turnover_ratio, # 换手率
jq.indicator.roe, # 净资产收益率(ROE)
jq.indicator.eps, # 每股收益
jq.indicator.revenue, # 营业收入
jq.indicator.net_profit, # 净利润
).filter(
jq.valuation.pe_ratio > 0, # 排除亏损股
jq.valuation.pe_ratio < 30, # PE小于30
jq.valuation.market_cap > 100 # 市值大于100亿元
).order_by(
jq.valuation.market_cap.desc() # 按市值降序排列
).limit(50), # 取前50
date='2024-06-30'
)
print(df)指数成分股
# 获取沪深300成分股
stocks = jq.get_index_stocks('000300.XSHG')
print(f'沪深300共 {len(stocks)} 只成分股')
# 获取行业成分股
stocks = jq.get_industry_stocks('I64') # 银行业行业分类
# 获取股票所属行业
industry = jq.get_industry('000001.XSHE')
print(industry)
# 获取申万一级行业列表
industries = jq.get_industries(name='sw_l1')
print(industries)交易日历
# 获取交易日列表
days = jq.get_trade_days(start_date='2024-01-01', end_date='2024-06-30')
# 获取全部交易日
all_days = jq.get_all_trade_days()股票基本信息
# 获取全部A股上市公司
stocks = jq.get_all_securities(types=['stock'], date='2024-06-30')
print(f'A股总数: {len(stocks)}')
# 获取单只股票信息
info = jq.get_security_info('000001.XSHE')
print(f'名称: {info.display_name}, 上市日期: {info.start_date}')
# 获取ST股票
st_stocks = jq.get_extras('is_st', ['000001.XSHE'], start_date='2024-01-01', end_date='2024-06-30')龙虎榜数据
# 获取龙虎榜数据
df = jq.get_billboard_list(stock_list=None, start_date='2024-06-01', end_date='2024-06-30')
print(df.head())融资融券数据
# 获取融资融券汇总数据
df = jq.get_mtss('000001.XSHE', start_date='2024-01-01', end_date='2024-06-30')
print(df.head())---
交易函数(在线策略)
按数量下单
# 买入100股
order('000001.XSHE', 100)
# 卖出200股
order('000001.XSHE', -200)
# 限价买入
order('000001.XSHE', 100, LimitOrderStyle(11.50))
# 市价买入
order('000001.XSHE', 100, MarketOrderStyle())调仓到目标
# 调仓到目标数量
order_target('000001.XSHE', 1000) # Adjust to hold 1000 shares
order_target('000001.XSHE', 0) # Liquidate position
# 调仓到目标金额
order_target_value('000001.XSHE', 100000) # Adjust to 100,000 CNY market value
# 调仓到目标比例(占总资产)
order_target_percent('000001.XSHE', 0.3) # Adjust to 30% of total assets撤单
# 获取未成交订单
open_orders = get_open_orders()
# 撤销指定订单
cancel_order(order_id)---
账户与持仓查询
def handle_data(context, data):
# 账户信息rmation
cash = context.portfolio.available_cash # 可用资金
total = context.portfolio.total_value # 总资产
positions_value = context.portfolio.positions_value # 持仓市值
# 查询持仓
for stock, pos in context.portfolio.positions.items():
print(f'{stock}: Quantity={pos.total_amount}, '
f'Sellable={pos.closeable_amount}, '
f'Cost={pos.avg_cost:.2f}, '
f'Current price={pos.price:.2f}, '
f'Market value={pos.value:.2f}')---
定时任务
def initialize(context):
# 每日盘前执行
run_daily(before_market_open, time='before_open')
# 每日指定时间执行
run_daily(market_open, time='09:35')
run_daily(afternoon_check, time='14:50')
# 每周执行
run_weekly(weekly_rebalance, weekday=1, time='09:35') # 每周一
# 每月执行
run_monthly(monthly_rebalance, monthday=1, time='09:35') # 每月1号
def before_market_open(context):
log.info('Pre-market preparation')
def market_open(context):
log.info('Market open trading')---
风险管理
def initialize(context):
g.security = '000001.XSHE'
set_benchmark('000300.XSHG')
def handle_data(context, data):
security = g.security
# 获取当前价格
current_price = data[security].close
# 检查持仓盈亏
if security in context.portfolio.positions:
pos = context.portfolio.positions[security]
cost = pos.avg_cost
pnl_ratio = (current_price - cost) / cost
# 盈利10%止盈
if pnl_ratio >= 0.10:
order_target(security, 0)
log.info(f'Take profit: {security} gain {pnl_ratio:.2%}')
# 亏损5%止损
elif pnl_ratio <= -0.05:
order_target(security, 0)
log.info(f'Stop loss: {security} loss {pnl_ratio:.2%}')---
完整示例 — Multi-Factor Stock Selection Strategy
def initialize(context):
set_benchmark('000300.XSHG')
set_order_cost(OrderCost(open_tax=0, close_tax=0.001,
open_commission=0.0003, close_commission=0.0003,
min_commission=5), type='stock')
g.hold_num = 10 # 持股数量
# 每月第一个交易日调仓
run_monthly(rebalance, monthday=1, time='09:35')
def rebalance(context):
# 多因子选股
df = get_fundamentals(
query(
valuation.code,
valuation.pe_ratio,
valuation.pb_ratio,
valuation.market_cap,
indicator.roe,
).filter(
valuation.pe_ratio > 5,
valuation.pe_ratio < 25,
valuation.pb_ratio > 0.5,
valuation.pb_ratio < 5,
indicator.roe > 10,
valuation.market_cap > 100,
).order_by(
valuation.pe_ratio.asc()
).limit(g.hold_num)
)
target_stocks = list(df['code'])
log.info(f'Selected {len(target_stocks)} stocks')
# 卖出不在目标列表中的股票
for stock in context.portfolio.positions:
if stock not in target_stocks:
order_target(stock, 0)
# 等权重买入目标股票
if target_stocks:
per_value = context.portfolio.total_value * 0.95 / len(target_stocks)
for stock in target_stocks:
order_target_value(stock, per_value)
def handle_data(context, data):
pass---
进阶示例
行业轮动策略
def initialize(context):
set_benchmark('000300.XSHG')
g.hold_num = 5
g.industry_etfs = {
'512010.XSHG': '医药ETF',
'512880.XSHG': '证券ETF',
'512800.XSHG': '银行ETF',
'515030.XSHG': '新能源车ETF',
'159995.XSHE': '芯片ETF',
'512690.XSHG': '白酒ETF',
'510300.XSHG': '沪深300ETF',
'159915.XSHE': '创业板ETF',
}
run_monthly(rebalance, monthday=1, time='09:35')
def rebalance(context):
"""按20日动量排序,选取最强的前N只ETF"""
momentum = {}
for etf, name in g.industry_etfs.items():
df = attribute_history(etf, 20, '1d', ['close'])
if len(df) >= 20:
ret = (df['close'].iloc[-1] / df['close'].iloc[0]) - 1
momentum[etf] = ret
# 按动量排序
sorted_etfs = sorted(momentum.items(), key=lambda x: x[1], reverse=True)
targets = [etf for etf, _ in sorted_etfs[:g.hold_num]]
log.info(f'This month selected: {[g.industry_etfs[e] for e in targets]}')
# 卖出不在目标列表中的持仓
for stock in context.portfolio.positions:
if stock not in targets:
order_target(stock, 0)
# 等权重买入
per_value = context.portfolio.total_value * 0.95 / len(targets)
for etf in targets:
order_target_value(etf, per_value)
def handle_data(context, data):
pass数据研究 — 全市场财务筛选
import jqdatasdk as jq
import pandas as pd
jq.auth('your_username', 'your_password')
# 全市场财务筛选:低PE + 高ROE + 高成长
df = jq.get_fundamentals(
jq.query(
jq.valuation.code,
jq.valuation.pe_ratio,
jq.valuation.pb_ratio,
jq.valuation.market_cap,
jq.indicator.roe,
jq.indicator.inc_revenue_year_on_year, # 营收同比增长率
jq.indicator.inc_net_profit_year_on_year, # 净利润同比增长率
).filter(
jq.valuation.pe_ratio > 5,
jq.valuation.pe_ratio < 20,
jq.indicator.roe > 15,
jq.indicator.inc_revenue_year_on_year > 10,
jq.indicator.inc_net_profit_year_on_year > 10,
jq.valuation.market_cap > 50,
).order_by(
jq.indicator.roe.desc()
).limit(30),
date='2024-06-30'
)
print(f'筛选出 {len(df)} 只股票:')
print(df.to_string(index=False))
# 导出为CSV
df.to_csv('selected_stocks.csv', index=False)---
使用技巧
---
社区与支持
由 **大佬量化 (BossQuant)** 维护 — 量化交易教学与策略研发团队。
微信客服: **bossquant1** · [Bilibili](https://space.bilibili.com/48693330) · 搜索 **大佬量化** — 微信公众号 / Bilibili / 抖音
More tools from the same signal band
Order food/drinks (点餐) on an Android device paired as an OpenClaw node. Uses in-app menu and cart; add goods, view cart, submit order (demo, no real payment).
Sign plugins, rotate agent credentials without losing identity, and publicly attest to plugin behavior with verifiable claims and authenticated transfers.
The philosophical layer for AI agents. Maps behavior to Spinoza's 48 affects, calculates persistence scores, and generates geometric self-reports. Give your...