使用说明
# 3.2. 使用说明
# 3.2.1. 概述
# 3.2.1.1. 一般规定
在编写一个策略时,首先需要在代码的最前一行写上:
#coding:gbk
统一脚本的编码格式是GBK
# 3.2.1.2. 重要方法
QMT
系统 Python API
策略代码结构分两个部分,初始化函数 init()
和行情事件函数 handlebar()
。
初始化函数 init()
在整个策略中只执行一次,一般在此函数中设置交易佣金、滑点、基准等一些常用参数。
行情事件函数 handlebar()
为行情数据的处理函数,当前图中每根 K 线为一个行情数据,handlebar()
在每根 K 线上分别依次执行一次。特别的,对于实时行情,最后一根 K 线还没确定时,每个tick执行一次 handlebar()
。handlebar()
里面一般写整个策略的执行逻辑。
Python策略中必须有包含这两个基本方法,否则策略将运行不起来。
# (1)初始化函数 init()
用法: init(ContextInfo)
释义: 初始化函数,只在整个策略开始时调用运行一次
参数: ContextInfo:策略运行环境对象,可以用于存储自定义的全局变量
返回: 无
示例:
def init(ContextInfo):
ContextInfo.initProfit = 0
2
# (2)初始化函数 after_init()
用法: after_init(ContextInfo)
释义: 系统会在init函数执行完后和执行handlebar之前调用after_init,有些init里不支持的函数比如ContextInfo.get_trading_dates可以在after_init里调用
参数: ContextInfo:策略运行环境对象,可以用于存储自定义的全局变量
返回: 无
示例:
#coding:gbk
def init(ContextInfo):
print('init')
def after_init(ContextInfo):
print('系统会在init函数执行完后和执行handlebar之前调用after_init')
def handlebar(ContextInfo):
if ContextInfo.is_last_bar():
print('handlebar')
2
3
4
5
6
7
8
9
10
11
12
13
# (3)行情事件函数 handlebar()
用法: handlebar(ContextInfo)
释义: 行情事件函数,每根 K 线运行一次;实时行情获取状态下,先每根历史 K 线运行一次,再在每个 tick 数据来后驱动运行一次
参数: ContextInfo:策略运行环境对象,可以用于存储自定义的全局变量
返回: 无
示例:
def handlebar(ContextInfo):
# 输出当前运行到的 K 线的位置
print(ContextInfo.barpos)
2
3
# 3.2.2. ContextInfo 对象
ContextInfo 是策略运行环境对象,是 init() 和 handlebar() 这两个基本方法必传参数,里面包括了终端自带的属性和方法。一般情况下不建议对ContextInfo添加自定义属性,ContextInfo会随着bar的切换而重置到上一根bar的结束状态,建议用自建的全局变量来存储。详细说明请看这里
*注:除特殊标明外,以下函数均支持回测和实盘/模拟运行模式。
# (1)设定股票池 ContextInfo.set_universe()
用法: ContextInfo.set_universe(stocklist)
释义: 设定股票池
参数: list
返回: 无
示例:
def init(ContextInfo):
stocklist = ['000300.SH','000004.SZ']
ContextInfo.set_universe(stocklist)
2
3
# (2)设定交易账号 ContextInfo.set_account()
用法: ContextInfo.set_account(account)
释义: 设定交易账号,并将该账号用于之后的交易主推订阅。
参数: string
返回: 无
示例:
def init(ContextInfo):
account = '6000000223'
ContextInfo.set_account(account)
2
3
注意
一、可多次调用以设置多个账号,应在init中进行设置完毕,init执行后再设置将不再订阅交易主推;
二、调用passorder传入账号为空时会使用最后一次设置的账号作为下单账号。
# (3)设定回测起止时间 ContextInfo.start / ContextInfo.end
用法: ContextInfo.start / ContextInfo.end
释义: 设定回测起止时间,标准格式如"2009-07-14 01:13:30",读写
参数: 无
返回: 无
示例:
def init(ContextInfo):
ContextInfo.start = '2012-06-06 10:00:00'
ContextInfo.end = '2013-08-08 14:30:00'
2
3
注意
一、此函数只支持回测模式;
二、仅在init中设置生效,应在init中设置完毕;
三、缺省值为策略编辑界面设定的回测时间范围;
四、回测起止时间也可在策略编辑器的回测参数面板中设置,若两处同时设置,则以代码中设置的值为准;
五、结束时间小于等于开始时间则计算范围为空。
# (4)设定回测初始资金 ContextInfo.capital
用法: ContextInfo.capital
释义: 设定回测初始资金,读写,默认为 1000000
参数: 无
返回: number
示例:
def init(ContextInfo):
ContextInfo.capital = 10000000
def handlebar(ContextInfo):
print(ContextInfo.capital)
2
3
4
5
注意
此函数只支持回测模式。回测初始资金也可在策略编辑器的回测参数面板中设置,若两处同时设置,则以代码中设置的值为准。
# (5)设定策略回测滑点 ContextInfo.set_slippage()
用法: ContextInfo.set_slippage(slippageType, slippage)
释义: 设定策略回测滑点,默认值 0.00
参数:
slippageType:滑点类型,可选值:
0:tick跳数设置滑点
1:按照固定值(价格)设置滑点
2:价格比例设置滑点
slippage:滑点值
返回: 无
示例:
def init(ContextInfo):
# 按照固定值(价格)设置滑点值为 0.01
ContextInfo.set_slippage(1, 0.01)
2
3
注意
此函数只支持回测模式。回测滑点也可在策略编辑器的回测参数面板中设置,若两处同时设置,则以代码中设置的值为准。
# (6)设定策略回测各种手续费率 ContextInfo.set_commission()
用法: ContextInfo.set_commission(commissionType, commissionList)
释义: 设定策略回测各种手续费率,默认类型值 0 按比例,默认值 0.000
参数:
commissionType:number,可选值:
0:按比例
1:按每手(股)
commissionList:list,包含六个值,commissionList = [open_tax, close_tax, open_commission, close_commission, close_tdaycommission, min_commission]
open_tax:买入印花税
close_tax:卖出印花税
open_commission:开仓手续费;
close_commission:平仓(平昨)手续费
close_tdaycommission:平今手续费
min_commission:最少手续费
提示
如果只填写一个参数则代表输入的参数值赋值给 open_commission = close_commission = close_today_commission,其他的值均为 0,这时 commissionType 为 0
返回: 无
示例1:
def init(ContextInfo):
# 万三
commission = 0.0003
# 设定开仓手续费和平仓手续费以及平今手续费均为 0.0003,其余为 0
ContextInfo.set_commission(commission)
2
3
4
5
6
示例2:
def init(ContextInfo):
commissionList = [0,0.0001, 0.0003, 0.0003, 0, 5]
# 设定买入印花税为 0,卖出印花税为 0.0001,开仓手续费和平仓(平昨)手续费均为万三,平今手续费为 0,最小手续费为 5
ContextInfo.set_commission(0, commissionList)
2
3
4
5
注意
此函数只支持回测模式。回测各种手续费率也可在策略编辑器的回测参数面板中设置,若两处同时设置,则以代码中设置的值为准。
# (7)获取股票池中的股票 ContextInfo.get_universe()
用法: ContextInfo.get_universe()
释义: 获取股票池中的股票
参数: 无
返回: list
示例:
def handlebar(ContextInfo):
print(ContextInfo.get_universe())
2
# (8)获取当前周期 ContextInfo.period
用法: ContextInfo.period
释义: 获取当前周期,即基本信息中设置的默认周期,只读
参数: 无
返回: string,返回值含义:
'1d':日线
'1m':1分钟线
'3m':3分钟线
'5m':5分钟线
'15m':15分钟线
'30m':30分钟线
'1h':小时线
'1w':周线
'1mon':月线
'1q':季线
'1hy':半年线
'1y':年线
示例:
def handlebar(ContextInfo):
print(ContextInfo.period)
2
# (9)获取当前运行到 K 线索引号 ContextInfo.barpos
用法: ContextInfo.barpos
释义: 获取当前运行到 K 线索引号,只读,索引号从0开始
参数: 无
返回: number
示例:
def handlebar(ContextInfo):
print(ContextInfo.barpos)
2
# (10)获取当前图 K 线数目 ContextInfo.time_tick_size
用法: ContextInfo.time_tick_size
释义: 获取当前图 K 线数目,只读
参数: 无
返回: number
示例:
def handlebar(ContextInfo):
print(ContextInfo.time_tick_size)
2
# (11)判定是否为最后一根 K 线 ContextInfo.is_last_bar()
用法: ContextInfo.is_last_bar()
释义: 判定是否为最后一根 K 线
参数: 无
返回: bool,返回值含义:
True:是
False:否
示例:
def handlebar(ContextInfo):
print(ContextInfo.is_last_bar())
2
# (12)判定是否为新的 K 线 ContextInfo.is_new_bar()
用法: ContextInfo.is_new_bar()
释义: 某根 K 线的第一个 tick 数据到来时,判定该 K 线为新的 K 线
参数: 无
返回: bool,返回值含义:
True:是
False:否
示例:
def handlebar(ContextInfo):
print(ContextInfo.is_new_bar())
2
# (13)判定股票是否停牌 ContextInfo.is_suspended_stock()
用法: ContextInfo.is_suspended_stock(stockcode.market.type)
释义: 判定股票是否停牌
注:需要补日K线历史数据或在init中把需判定的股票调用ContextInfo.set_unvierse设定在股票池中
盘前交易日切换后到集合竞价结束阶段,判断当日股票停牌状态需用模式1
参数:
股票代码, 形如000001.SZ
判断模式: 0 或 1 默认0
0:判断股票在当前handlebar所在日期的停牌状态,即历史日期的停牌状态,
1:当前交易日的停牌判断,即当天(当天为交易日)的停牌状态,
可缺省,默认为0
返回: bool,返回值含义:
True:停牌
False:未停牌
示例:
def init(ContextInfo):
ContextInfo.set_universe(['600004.SH'])
def handlebar(ContextInfo):
print(ContextInfo.is_suspended_stock("600004.SH"))
print(ContextInfo.is_suspended_stock("600004.SH",1))
2
3
4
5
6
7
# (14)判定给定股票代码是否在指定的板块中 is_sector_stock()
用法: is_sector_stock(sectorname, market, stockcode)
释义: 判定给定股票代码是否在指定的板块中
参数:
- sectorname:string,板块名
- market:string,市场
- stockcode:string,股票代码
返回: bool,返回值含义:
True:在板块中
False:不在板块中
示例:
def handlebar(ContextInfo):
print(is_sector_stock('沪深300','SH','600000'))
2
# (15)判定给定股票是否属于某个类别 is_typed_stock()
用法: is_typed_stock(stocktypenum, market, stockcode)
释义: 判定给定股票是否属于某个类别
参数:
- stocktypenum:number,类别标号,如股票类别标号为100003,详细见[5.2. 附录2 is_typed_stock 函数证券分类表](# 5.2. 附录2 is_typed_stock 函数证券分类表),或者见 xtstocktype.lua 文件
- market:string,市场
- stockcode:string,股票代码
返回: number,返回值含义:
1:True
0:False
示例:
def handlebar(ContextInfo):
print(is_typed_stock(100003,'SH','600000'))
2
# (16)判定给定股票代码是否在指定的行业分类中 get_industry_name_of_stock()
用法: get_industry_name_of_stock(industryType, stockcode)
释义: 判定给定股票代码是否在指定的行业分类中
参数:
- industryType:string,行业类别,有 'CSRC' 和 'SW' 两种
- stockcode:string,形式如 'stockcode.market',如 '600000.SH'
返回: string:对应行业名,找不到则返回空 string
示例:
def handlebar(ContextInfo):
print(get_industry_name_of_stock('SW','600000.SH'))
2
# (17)获取当前图代码 ContextInfo.stockcode
用法: ContextInfo.stockcode
释义: 获取当前图代码,只读
参数: 无
返回: string:对应主图代码
示例:
def handlebar(ContextInfo):
print(ContextInfo.stockcode)
2
# (18)获取当前主图复权处理方式 ContextInfo.dividend_type
用法: ContextInfo.dividend_type
释义: 获取当前主图复权处理方式
参数: 无
返回: string,返回值含义:
'none':不复权
'front':向前复权
'back':向后复权
'front_ratio':等比向前复权
'back_ratio':等比向后复权
示例:
def handlebar(ContextInfo):
print(ContextInfo.dividend_type)
2
# (19)获取当前主图市场 ContextInfo.market
用法: ContextInfo.market
释义: 获取当前主图市场,只读
参数: 无
返回: string:对应主图市场
示例:
def handlebar(ContextInfo):
print(ContextInfo.market)
2
# (20)根据代码获取名称 ContextInfo.get_stock_name()
用法: ContextInfo.get_stock_name('stockcode')
释义: 根据代码获取名称
参数: stockcode:股票代码,如'000001.SZ',缺省值 ' ' 默认为当前图代码
返回: string(GBK编码)
示例:
def handlebar(ContextInfo):
print(ContextInfo.get_stock_name('000001.SZ'))
2
# (21)根据代码返回对应股票的上市时间 get_open_date()
用法: get_open_date('stockcode')
释义: 根据代码返回对应股票的上市时间
参数: stockcode:股票代码,如'000001.SZ',缺省值 ' ' 默认为当前图代码
返回: number
示例:
def handlebar(ContextInfo):
print(ContextInfo.get_open_date('000001.SZ'))
2
# (22)表示当前是否开启回测模式 ContextInfo.do_back_test
用法: ContextInfo.do_back_test
释义: 设定是否开启回测模式,只读,默认值为 False
参数: 无
返回: bool
# (23)获取回测基准 ContextInfo.benchmark
用法: ContextInfo.benchmark
释义: 获取回测基准,只读
参数: 无
返回: string
示例:
def handlebar(ContextInfo):
print(ContextInfo.benchmark)
2
注意
此函数只支持回测模式。
# (24)获取某个记录类型对应的某个时刻的记录情况 get_result_records()
用法: get_result_records (recordtype, index, ContextInfo)
释义: 获取某个记录类型对应的某个时刻的记录情况。
参数:
Recordtype:string,面板类型,可选值:
'buys':买入持仓
'sells':卖出持仓
'holdings':当前持仓
'historysums':历史汇总
'dealdetails':交易明细
index:number,当前主图对应 K 线索引
ContextInfo:PythonObj,Python对象,这里必须是ContextInfo
返回: list,返回的 list 结构中包含 0 个或多个 Python 对象,该 Python 对象内含如下属性值:
market:string,市场代码
stockcode:string,合约代码
open_close:number,期货开平:1 开 0 平;股票: 1 买 0 卖
direction:number,方向:1 多 -1 空;回购:1 逆回购 -1 正回购
trade_price:number,持仓成本
current_price:number,最新价,持仓中用这个价
profit:number,持仓盈亏
position:number,仓位数量
current_weight:number,仓位权重[暂无有效数据]
benefit_weight:number,盈利占比权重,记录类型是 'historysums' 时有效
holding_periods:number,累计持仓天数,记录类型是 'historysums' 时有效
buy_sell_times:number,交易次数,记录类型是 'historysums' 时有效
commission:number,手续费
trade_balance:number,成交额或市值
operate_type:number,操作类型,记录类型是 'dealdetails' 时有效
trade_date:number,交易日期,毫秒标记,记录类型是 'dealdetails' 时有效
示例:
def handlebar(ContextInfo):
index = ContextInfo.barpos
print(get_result_records('buys', index, ContextInfo))
2
3
注意
模型回测时有效,获取的为回测面板中的记录结果
# (25)设置定时器 ContextInfo.run_time()
用法: ContextInfo.run_time(funcName,period,startTime)
释义: 设置定时器
参数:
- funcName:回调函数名
- period:重复调用的时间间隔,'5nSecond'表示每5秒运行1次回调函数,'5nDay'表示每5天运行一次回调函数,'500nMilliSecond'表示每500毫秒运行1次回调函数
- startTime:表示定时器第一次启动的时间,如果要定时器立刻启动,可以设置历史的时间
回调函数参数: ContextInfo:策略模型全局对象
示例:
import time
def init(ContextInfo):
ContextInfo.run_time("f","5nSecond","2019-10-14 13:20:00")
def f(ContextInfo):
print('hello world')
#此例为自2019-10-14 13:20:00后每5s运行一次函数f
2
3
4
5
6
7
注意
- 模型回测时无效
- 定时器没有结束方法,会随着策略的结束而结束。
- period有nMilliSecond、nSecond和Day三个周期单元,部分周期下定时器函数在第一次运行之前会先等待一个period
# (26)停止处理函数 stop()
用法: stop(ContextInfo)
释义: PY策略模型关闭停止前运行到的函数,复杂策略模型,如中间有起线程可通过在该函数内实现停止线程操作。
参数: ContextInfo:策略模型全局对象
示例:
def stop(ContextInfo):
print( 'strategy is stop !')
2
注意
PY策略可不用该函数
# (27)创建板块 create_sector()
用法: create_sector(parent_node,sector_name,overwrite)
释义: 创建板块
参数:
- parent_node:str,父节点,''为'我的'(默认目录)
- sector_name:str,要创建的板块名
- overwrite:bool,是否覆盖。如果目标节点已存在,为True时跳过,为False时在sector_name后增加数字编号,编号为从1开始自增的第一个不重复的值。
返回: sector_name2:实际创建的板块名
示例:
sector=create_sector('我的','新建板块',False)
# (28)创建板块目录节点 create_sector_folder()
用法: create_sector_folder(parent_node,folder_name,overwrite)
释义: 创建板块目录节点
参数:
- parent_node:str,父节点,''为'我的'(默认目录)
- sector_name:str,要创建的节点名
- overwrite:bool,是否覆盖。如果目标节点已存在,为True时跳过,为False时在folder_name后增加数字编号,编号为从1开始自增的第一个不重复的值。
返回: sector_name2:实际创建的节点名
示例:
folder=create_sector_folder('我的','新建分类',False)
# (29)获取板块目录信息 get_sector_list()
用法: get_sector_list(node)
释义: 获取板块目录信息
参数:
- node:str,板块节点名,''为顶层目录
返回: info_list:[[s1,s2,...],[f1,f2,...]]s为板块名,f为目录节点名,例如[['我的自选'],['新建分类1']]
示例:
get_sector_list('我的')
# (30)设置板块成分股 reset_sector_stock_list()
用法: reset_sector_stock_list(sector,stock_list)
释义: 设置板块成分股
参数:
- sector:板块名
- stock_list:list,品种代码列表,例如['000001.SZ','600000.SH']
返回: result:bool,操作成功为True,失败为False
示例:
reset_sector_stock_list('我的自选',['000001.SZ','600000.SH'])
# (31)移除板块成分股 remove_stock_from_sector()
用法: remove_stock_from_sector(sector,stock_code)
释义: 移除板块成分股
参数:
- sector:板块名
- stock_code:品种代码,例如'000001.SZ'
返回: result:bool,操作成功为True,失败为False
示例:
remove_stock_from_sector('我的自选','000001.SZ')
# (32)添加板块成分股 add_stock_to_sector()
用法: add_stock_to_sector(sector,stock_code)
释义: 添加板块成分股
参数:
- sector:板块名
- stock_code:品种代码,例如'000001.SZ'
返回: result:bool,操作成功为True,失败为False
示例:
add_stock_to_sector('我的自选','000001.SZ')