一、入门量化策略
JoinQuant聚宽API文档:https://www.joinquant.com/help/api/help?name=api
1、策略内容
设置股票池为沪深300的所有成分股
如果当前股价小于10元/股且当前不持仓,则买入;
如果当前股价比买入时上涨了25%,则清仓止盈;
如果当前股价比买入时下跌了10%,则清仓止损。
2、获取要操作的股票或指数成分股
# 导入函数库 import jqdata # 初始化函数,设定基准 def initialize(context): # 定义一个全局变量, 保存要操作的股票 # 方式一:操作一只股票 # g.security = '601318.XSHG' # 中国平安股票 # 方式二:操作多只股票 # g.security = ['601101.XSHG', '601106.XSHG'] # 方式三:操作指数成分股 g.security = get_index_stocks('000300.XSHG') # 沪深300 print(g.security)
执行显示沪深300指数成分股:
3、开启动态复权模式(真实价格)
开启真实价格回测功能很简单,只需一步即可搞定:在initialize中使用set_option。
(1)开启动态复权测试
# 导入函数库 import jqdata # 初始化函数,设定基准 def initialize(context): # 定义一个全局变量, 保存要操作的股票 # 方式一:操作一只股票 # g.security = '601318.XSHG' # 中国平安股票 # 方式二:操作多只股票 # g.security = ['601101.XSHG', '601106.XSHG'] # 方式三:操作指数成分股 g.security = get_index_stocks('000300.XSHG') # 沪深300 set_option('use_real_price', True)
由于沪深300不存在分红和股票拆合,显示效果和上图一致。
(2)开启动态复权(真实价格)模式对模拟交易的影响
在模拟交易中,在未开启动态复权(真实价格)模式时,我们是使用基于模拟交易创建日期的后复权价格。
后复权模式示意图如下图所示:
不开启真实价格模拟盘的运算结果是没有错误,只是会理解起来更费劲一些。
如果想知道今天的真实价格,还需知道模拟创建的日期,并进行复权计算。为了让用户使用更便于理解、更真实的模拟系统,强烈建议开启动态复权(真实价格)模式。开启方式:在代码中调用set_option('use_real_price', True)。
开启动态复权(真实价格)模式示意图如下图所示:
开启动态复权(真实)模式后,看到的价格都是最新的,每到新的一天, 如果持仓中有股票发生了拆合或者分红或者其他可能影响复权因子的情形, 会根据复权因子自动调整股票的数量.。但不要跨日期缓存这些 API 返回的结果。
4、设置佣金/印花税
交易税费包含券商手续费和印花税。可以通过 set_order_cost 来设置具体的交易税费的参数。
set_order_cost(cost, type, ref=None)
修改代码如下所示:
# 导入函数库 import jqdata # 初始化函数,设定基准 def initialize(context): # 定义一个全局变量, 保存要操作的股票 # 方式一:操作一只股票 # g.security = '601318.XSHG' # 中国平安股票 # 方式二:操作多只股票 # g.security = ['601101.XSHG', '601106.XSHG'] # 方式三:操作指数成分股 g.security = get_index_stocks('000300.XSHG') # 沪深300 set_option('use_real_price', True) # 股票类每笔交易时的手续费是:买入时佣金万分之三,卖出时佣金万分之三加千分之一印花税, 每笔交易佣金最低扣5块钱 set_order_cost( OrderCost( # OrderCost 对象 open_tax=0, # 买入时印花税 close_tax=0.001, # 卖出时印花税 open_commission=0.0003, # 买入时佣金 close_commission=0.0003, # 卖出时佣金 close_today_commission=0, # 平今日仓佣金 min_commission=5 # 最低佣金 ), type='stock' # 股票 )
(1)券商手续费
中国A股市场目前为双边收费,券商手续费系默认值为万分之三,即0.03%,最少5元。
(2)印花税
印花税对卖方单边征收,对买方不再征收,系统默认为千分之一,即0.1%。
(3)参数
-
cost: OrderCost 对象
-
open_tax,买入时印花税 (只股票类标的收取,基金与期货不收)
-
close_tax,卖出时印花税 (只股票类标的收取,基金与期货不收)
-
open_commission,买入时佣金,申购场外基金的手续费
-
close_commission, 卖出时佣金,赎回场外基金的手续费
-
close_today_commission, 平今仓佣金
-
min_commission, 最低佣金,不包含印花税
-
type: 股票、场内基金、场内交易的货币基金、分级A基金、分级B基金、分级母基金、金融期货、期货、债券基金、股票基金、QDII 基金、场外交易的货币基金、混合基金、场外基金,'stock'/ 'fund' / 'mmf' /'fja'/'fjb'/ 'fjm'/ 'index_futures' / 'futures' / 'bond_fund' / 'stock_fund' / 'QDII_fund' / 'money_market_fund' / ‘mixture_fund' / 'open_fund'
-
ref: 参考代码,支持股票代码/基金代码/期货合约代码,以及期货的品种,如 '000001.XSHE'/'510180.XSHG'/'IF1709'/'IF'/'000300.OF'
注意:针对特定的交易品种类别设置手续费时,必须将ref设为None;若针对特定的交易品种或者标的,需要将type设置为对应的交易品种类别,将ref设置为对应的交易品种或者标的。
(4)常用示例
# 股票类每笔交易时的手续费是:买入时佣金万分之三,卖出时佣金万分之三加千分之一印花税, 每笔交易佣金最低扣5块钱 set_order_cost(OrderCost(open_tax=0, close_tax=0.001, open_commission=0.0003, close_commission=0.0003, close_today_commission=0, min_commission=5), type='stock') # 期货类每笔交易时的手续费是:买入时万分之0.23,卖出时万分之0.23,平今仓为万分之23 set_order_cost(OrderCost(open_tax=0, close_tax=0, open_commission=0.000023, close_commission=0.000023, close_today_commission=0.0023, min_commission=0), type='index_futures') # 单独设置 000300.XSHG 的费用 set_order_cost(OrderCost(open_tax=0, close_tax=0.001, open_commission=0.0003, close_commission=0.0003, close_today_commission=0, min_commission=5), type='stock', ref='000300.XSHG') # 设置所有期货(包括金融指数期货)的费用 set_order_cost(OrderCost(open_tax=0, close_tax=0.001, open_commission=0.0003, close_commission=0.0003, close_today_commission=0, min_commission=5), type='futures') # 对 IF/IH/IC 三个品种有效 set_order_cost(OrderCost(open_tax=0, close_tax=0.001, open_commission=0.0003, close_commission=0.0003, close_today_commission=0, min_commission=5), type='index_futures') # 单独设置AU期货品种的费用 set_order_cost(OrderCost(open_tax=0, close_tax=0.001, open_commission=0.0003, close_commission=0.0003, close_today_commission=0, min_commission=5), type='futures', ref='AU') # 单独设置AU1709合约的费用 set_order_cost(OrderCost(open_tax=0, close_tax=0.001, open_commission=0.0003, close_commission=0.0003, close_today_commission=0, min_commission=5), type='futures', ref='AU1709')
二、单位时间运行策略函数
handle_data:该函数每个单位时间会调用一次, 如果按天回测,则每天调用一次,如果按分钟,则每分钟调用一次。
该函数依据的时间是股票的交易时间,即 9:30 - 15:00。 期货应使用定时函数。
该函数在回测中的非交易日是不会触发的(如回测结束日期为2016年1月5日,则程序在2016年1月1日-3日时,handle_data不会运行,4日继续运行)。
对于使用当日开盘价撮合的日级模拟盘,在9:25集合竞价完成时就可以获取到开盘价,出于减少并发运行模拟盘数量的目的,我们会提前到9:27~9:30之间运行, 策略内获取到逻辑时间(context.current_dt)仍然是 9:30。
# 导入函数库 import jqdata # 初始化函数,设定基准 def initialize(context): # 定义一个全局变量, 保存要操作的股票 # 方式一:操作一只股票 # g.security = '601318.XSHG' # 中国平安股票 # 方式二:操作多只股票 # g.security = ['601101.XSHG', '601106.XSHG'] # 方式三:操作指数成分股 g.security = get_index_stocks('000300.XSHG') # 沪深300 set_option('use_real_price', True) # 股票类每笔交易时的手续费是:买入时佣金万分之三,卖出时佣金万分之三加千分之一印花税, 每笔交易佣金最低扣5块钱 set_order_cost( OrderCost( # OrderCost 对象 open_tax=0, # 买入时印花税 close_tax=0.001, # 卖出时印花税 open_commission=0.0003, # 买入时佣金 close_commission=0.0003, # 卖出时佣金 close_today_commission=0, # 平今日仓佣金 min_commission=5 # 最低佣金 ), type='stock' # 股票 ) def handle_data(context, data): print('Hello')
执行效果如下所示:
1、获取当前时间数据
get_current_data():
获取当前单位时间(当天/当前分钟)的涨跌停价, 是否停牌,当天的开盘价等。
该方法返回值是一个dict, 其中 key 是股票代码, value 是拥有最新价、涨停价、跌停价等属性对象。
(1)返回字典key值对应value所拥有的属性对象
value值对应的属性对象:
- last_price : 最新价
- high_limit: 涨停价
- low_limit: 跌停价
- paused: 是否停止或者暂停了交易, 当停牌、未上市或者退市后返回 True
- is_st: 是否是 ST(包括ST, *ST),是则返回 True,否则返回 False
- day_open: 当天开盘价
- name: 股票现在的名称, 可以用这个来判断股票当天是否是 ST, *ST, 是否快要退市
- industry_code: 股票现在所属行业代码, 参见 行业概念数据
(2)示例
def handle_data(context, data): print( get_current_data()['601318.XSHG'].name, get_current_data()['601318.XSHG'].industry_code, get_current_data()['601318.XSHG'].day_open, get_current_data()['601318.XSHG'].high_limit, get_current_data()['601318.XSHG'].low_limit, )
输出结果如下所示:
2、获取历史数据
attribute_history:获取历史数据,可查询单个标的多个数据字段,返回数据格式为 DataFrame 或 Dict(字典)。
attribute_history(security, count, unit='1d', fields=['open', 'close', 'high', 'low', 'volume', 'money'], skip_paused=True, df=True, fq='pre')
查看某一支股票的历史数据, 可以选这只股票的多个属性, 默认跳过停牌日期。当取天数据时, 不包括当天的, 即使是在收盘后;分钟数据包括当前分钟的数据;