Loading...
Loading...
JoinQuant Official Strategy Development Guide, covering backtesting, paper trading, data APIs, trading functions, factors and technical indicators. Use this when users write JoinQuant strategies, perform backtesting, use paper trading, query JoinQuant APIs, work with get_price/order/run_daily, Alpha factors, technical indicators, or mention joinquant, JoinQuant, jqdata strategies. For local data retrieval, use the jqdatasdk skill.
npx skill4agent add lzwme/finance-quant-skills joinquant-docsDifference from jqdatasdk:is used in the official website strategy environment;jqdatais a local Python library with slightly different APIs, and cannot be used in the official website's backtesting/paper trading/research modules.jqdatasdk
get_priceorder_targetapi.mddata/*.mdfaq.mdNeed to write a strategy framework? → api.md "Start Writing Strategies" "Strategy Program Architecture"
Need to check data APIs? → api.md "Data Retrieval Functions" + corresponding product documents in data/
Need to place orders/check positions? → api.md "Trading Functions" "Objects"
Need financial/valuation data? → data/Stock.md (run_query + valuation/fundamentals tables)
Need industry/concept stock selection? → data/plateData.md + api.md get_industry_stocks etc.
Need technical indicators? → data/technicalanalysis.md (from jqlib.technical_analysis import *)
Need Alpha factors? → data/Alpha101.md, data/Alpha191.md
Need custom factors? → fator.md (jqfactor.Factor, calc_factors)
Need factor dashboard data? → data/factor_values.md# Import JoinQuant function library
import jqdata
def initialize(context):
g.security = '000001.XSHE'
set_benchmark('000300.XSHG')
set_option('use_real_price', True) # Enable dynamic forward adjustment (real price), recommended to enable
run_daily(trade, time='open') # Or 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)| Function | Description |
|---|---|
| Global initialization, runs only once; use |
| Scheduled tasks; |
| Driven by backtesting frequency; not recommended to use with run_daily |
| Before market opens (9:00) |
| After market closes (15:30) |
jqdata| Market | Suffix | Example |
|---|---|---|
| Shanghai Stock Exchange | | |
| Shenzhen Stock Exchange | | |
| CFFEX | | |
| DCE | | |
| SHFE | | |
| CZCE | | |
| OTC Fund | | |
reference_securityrun_dailyIF9999.CCFXget_price(security, start_date, end_date, frequency='daily', fields=None, fq='pre')
attribute_history(security, count, unit, fields) # Backtesting environment, does not include the current day
history(count, unit, field, security_list, df=True)
get_bars(security, count, unit, fields, include_now=True)get_all_securities(types=['stock'], date=None) # date prevents look-ahead bias
get_index_stocks('000300.XSHG', date=None)
get_industry_stocks('C15', date=None)
get_concept_stocks('GN036', date=None)
set_universe([...]) # After setting, security_list does not need to be passed to historyfrom jqdata import *
q = query(valuation).filter(valuation.code == '000001.XSHE')
df = get_fundamentals(q, date='2015-10-15')
# Or run_query (maximum 4000 rows per query, join tables not allowed)
df = finance.run_query(query(finance.STK_XXX).filter(...).limit(4000))order(security, amount) # By share count, positive for buy, negative for sell
order_value(security, value) # By amount
order_target(security, amount) # Adjust to target share count
order_target_value(security, value) # Adjust to target market value
order_target_percent(security, percent) # Adjust to target position ratiofrom jqlib.technical_analysis import *
# In strategies, it is recommended to use context.current_dt for check_date to avoid look-ahead bias caused by retrieving the day's closing indicator during trading hours
result = MACD(security_list, check_date=context.current_dt, SHORT=12, LONG=26, MID=9)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)fator.mddata/Alpha101.mddata/Alpha191.mdget_all_securities(date=...)get_index_stocks(..., date=...)datehistoryattribute_historycheck_datedateget_fundamentalsrun_dailyhandle_datarun_daily(func, time='every_bar')force=Falserun_weekly/monthlyrun_queryget_fundamentalsrun_queryfq=None| Product | Usage Scenario |
|---|---|
| Backtesting, paper trading, research |
| Local quantitative research, cannot be imported in official website strategies |
| Scenario | First Read | Further Consultation |
|---|---|---|
| Newcomer writing first strategy | | |
| Stock selection + financial data | | |
| Index component strategy | | |
| Industry/concept rotation | | |
| Futures strategy | | |
| Options strategy | | |
| Fund/ETF | | |
| Convertible bonds | | — |
| Macro data | | — |
| Technical analysis indicators | | — |
| Factor-based stock selection | | |
| Margin trading | Margin trading section in | Margin trading-specific functions in |
| Errors/data questions | | "Notes" in |
api.mdbun scripts/get-joinquant-docs.ts
# Force overwrite existing md files: FORCE_UPDATE=1 bun scripts/get-joinquant-docs.ts