Based on the offline documentation in this directory, write Python strategies for the JoinQuant official website (backtesting / simulation / research). When answering API questionsyou must first consult the local documentation, and must not fabricate function signatures or parameters from memory.
Differences from jqdatasdk:
jqdataUsed in the official website strategy environment;jqdatasdkis a local Python library, with slightly different APIs, and cannot be used in official website backtesting/simulation/research.
Documentation consultation process
- Determine the question type, and locate files according to reference.md locate files
- Use Grep/Read to search forthe target function name or Chinese keyword (e.g.,
get_price、order_target、市盈率) - cross-validation: for API behavior consult
api.md, for fields/table structures consultdata/*.md, for pitfalls consultfaq.md - When giving an answercite the calling methods, parameters, return values, and example code from the documentation
需要写策略框架? → api.md「开始写策略」「策略程序架构」
需要查数据 API? → api.md「数据获取函数」+ data/ 对应品种文档
需要下单/持仓? → api.md「交易函数」「对象」
需要财务/估值数据? → data/Stock.md(run_query + valuation/fundamentals 表)
需要行业/概念选股? → data/plateData.md + api.md get_industry_stocks 等
需要技术指标? → data/technicalanalysis.md(from jqlib.technical_analysis import *)
需要 Alpha 因子? → data/Alpha101.md、data/Alpha191.md
需要自定义因子? → fator.md(jqfactor.Factor、calc_factors)
需要因子看板数据? → data/factor_values.md
Strategy skeleton
Minimal runnable structure:
# 导入聚宽函数库
import jqdata
def initialize(context):
g.security = '000001.XSHE'
set_benchmark('000300.XSHG')
set_option('use_real_price', True) # 开启动态复权(真实价格),建议开启
run_daily(trade, time='open') # 或 time='every_bar' / '9:30'
def trade(context):
security = g.security
close_data = attribute_history(security, 5, '1d', ['close'])
MA5 = close_data['close'].mean()
current_price = close_data['close'][-1]
cash = context.portfolio.available_cash
if current_price > 1.01 * MA5:
order_value(security, cash)
elif current_price < MA5 and context.portfolio.positions[security].closeable_amount > 0:
order_target(security, 0)
Lifecycle functions
| Function | Description |
|---|---|
initialize(context) |
Global initialization, runs only once; use g to store global variables |
run_daily/weekly/monthly(func, ...) |
Scheduled tasks;func func must bea global function, and cannot be a class method |
handle_data(context, data) |
Driven by the backtest frequency;not recommended to be mixed with run_daily |
before_trading_start |
Before market open (9:00) |
after_trading_end |
After market close (15:30) |
APIs marked with ♠ are supported only inbacktest/simulation, and cannot be called in the research module.jqdata The module can be used in both the research and backtest environments.
Security code specifications
| Market | Suffix | Example |
|---|---|---|
| Shanghai Stock Exchange | .XSHG |
600519.XSHG |
| Shenzhen Stock Exchange | .XSHE |
000001.XSHE |
| China Financial Futures Exchange | .CCFX |
IC9999.CCFX |
| Dalian Commodity Exchange | .XDCE |
A9999.XDCE |
| Shanghai Futures Exchange | .XSGE |
AU9999.XSGE |
| Zhengzhou Commodity Exchange | .XZCE |
CY8888.XZCE |
| OTC funds | .OF |
519671.OF |
For futures strategies, set run_daily 's reference_security to the corresponding main contract (e.g., IF9999.CCFX), to match the night session opening time.
Common API quick reference
Market quotes and history
get_price(security, start_date, end_date, frequency='daily', fields=None, fq='pre')
attribute_history(security, count, unit, fields) # 回测环境,不含当天
history(count, unit, field, security_list, df=True)
get_bars(security, count, unit, fields, include_now=True)
Universe and sectors
get_all_securities(types=['stock'], date=None) # date 防未来函数
get_index_stocks('000300.XSHG', date=None)
get_industry_stocks('C15', date=None)
get_concept_stocks('GN036', date=None)
set_universe([...]) # 设置后 history 可不传 security_list
Financial data (SQL query)
from jqdata import *
q = query(valuation).filter(valuation.code == '000001.XSHE')
df = get_fundamentals(q, date='2015-10-15')
# 或 run_query(单次最多 4000 行,不可连表)
df = finance.run_query(query(finance.STK_XXX).filter(...).limit(4000))
Trading
order(security, amount) # 按股数,正买负卖
order_value(security, value) # 按金额
order_target(security, amount) # 调到目标股数
order_target_value(security, value) # 调到目标市值
order_target_percent(security, percent) # 调到目标仓位比例
The buy quantity for A-shares must be an integer multiple of 100 (200 minimum for STAR Market); when selling all positions there is no limit. A maximum of 10,000 orders per day.
Technical indicators
from jqlib.technical_analysis import *
# check_date 策略中建议用 context.current_dt,避免盘中取当日收盘指标产生未来数据
result = MACD(security_list, check_date=context.current_dt, SHORT=12, LONG=26, MID=9)
Custom factors
from jqfactor import Factor, calc_factors
class MyFactor(Factor):
name = 'my_factor'
max_window = 5
dependencies = ['close']
def calc(self, data):
return data['close'].mean()
factors = calc_factors(securities, [MyFactor()], start_date, end_date)
See fator.md and data/Alpha101.md、data/Alpha191.md。
Key precautions
Prevent look-ahead bias
get_all_securities(date=...)、get_index_stocks(..., date=...)etc. must be passedthe historical point-in-time'sdate, and future dates cannot be usedhistory/attribute_historyWhen fetching daily data withdoes not include the current day; to get the current day's data you need to fetch minute-level data- Technical indicator
check_dateReturns the closing value only when precise to the date; calling intraday on the current day will produce future data - Financial data is processed by announcement date by default; note
get_fundamentalsofdateparameter meaning
Run frequency
- Prefer to use
run_daily, avoid mixing withhandle_datamixed use run_daily(func, time='every_bar')frequency is consistent with the backtest settingsrun_weekly/monthlyofforce=Falsecan avoid nearest execution when registered late
Data query limits
run_query/get_fundamentalsreturns at most 4000 rowsrun_queryJoin queries are not supported- Default market data isforward-adjusted;
fq=Noneis unadjusted
Environment and product distinction
| Product | Use case |
|---|---|
jqdata(official website) |
Backtest, simulation, research |
jqdatasdk(local) |
Local quantitative research,cannotbe imported in official website strategies |
Choose documentation by scenario
| Scenario | Read first | Further reference |
|---|---|---|
| Beginners writing their first strategy | api.md"Start Writing Strategies" |
api.md"Strategy Program Architecture" |
| Stock selection + financials | data/Stock.md |
api.md get_fundamentals |
| Index constituent stock strategies | data/index.md |
api.md get_index_stocks |
| Industry/concept rotation | data/plateData.md |
api.md get_industry_stocks |
| Futures strategies | data/Future.md |
api.md"Futures Strategy Dedicated Functions" |
| Options strategies | data/Option.md |
api.md options-related |
| Funds/ETFs | data/fund.md |
data/OTCfund.md |
| Convertible bonds | data/bond.md |
— |
| Macro data | data/macroData.md |
— |
| Technical analysis indicators | data/technicalanalysis.md |
— |
| Factor stock selection | fator.md + data/factor_values.md |
data/Alpha101.md |
| Margin trading and securities lending | data/Stock.md margin trading and securities lending chapter |
api.md margin trading and securities lending dedicated functions |
| Errors/data questions | faq.md |
api.md"Notes" |
Strategy examples
For complete examples, see api.md "Strategy Examples" at the end: moving average strategy, multi-stock positions, chasing rallies strategy, Halloween effect, etc.
Documentation updates
The local data dictionary is synchronized from the official website by script:
bun scripts/get-joinquant-docs.ts
# 强制覆盖已有 md:FORCE_UPDATE=1 bun scripts/get-joinquant-docs.ts
Additional resources
- Complete documentation index:reference.md
- Platform API full text:api.md
- FAQ:faq.md
- Factor analysis:fator.md