download: https://www.itwangzi.cn/5177.html
量化交易策略是一系列量化规则的集合,包括量化进场和量化出场的条件,量化的资金管理和风险控制等。
本篇主要知识点
1、股票量化交易策略的基本组成
2、初始化函数
3、开盘前运行函数
4、开盘时运行函数
5、收盘后运行函数
6、设置函数、定时函数、下单函数
7、日志Log和常用对象
1.1 股票量化交易策略的组成
一个股票量化交易策略首先是导入聚宽函数库,具体代码如下: import jqdata
编写4个Python函数
初始化函数(initialize)、
开盘前运行函数(before_market_open)
开盘时运行函数(market_open)
收盘后运行函数(after_market_close)
1.1.1 初始化函数(initai)
def initialize(context):
# 设定沪深300作为基准
set_benchmark('000300.XSHG')
# 开启动态复权模式(真实价格)
set_option('use_real_price',True)
# 输出内容到日志 log.info()
log.info('初始函数开始运行且全局只运行一次')
股票相关设定
# 股票类每笔交易时的手续费是:买入时佣金万分之三,卖出时佣金万分之三加千分之一印花税,每笔交易佣金最低扣5块钱
set_order_cost(OrderCost(close_tax=0.001,open_commission=0.0003,close_commission=0.0003,min_commission=5),type='stock')
## 运行函数(reference_security为运行时间的参考标的;传入的标的只做种类区分,因此传入'000300.XSHG'或'510300.XSHG'是一样的)
# 开盘前运行
run_daily(before_market_open,time='before_open',reference_security='000300.XSHG')
# 开盘时运行
run_daily(market_open,time='open',reference_security='000300.XSHG')
# 收盘后运行
run_daily(after_market_close,time='after_close',reference_security='000300.XSHG')
initialize(context),即初始化函数,在整个回测模拟或实盘中最开始执行一次,用于初始一些全局变量。
参数context,是Context对象,用来存放有当前的账户或股票持仓信息。
set_benchmark('000300.XSHG'),是指设定沪深300作为基准。
set_option('use_real_price',True),是指开启动态复权模式(真实价格)。
复权就是对股价和成交量进行权息修复,股票的实际价值没有变,只是数量与价格变化了而已。
例如,原来20元的股票,十送十之后为10元,但实际还是相当于20元。从K线图上看这个价位看似很低,但很可能就是一个历史高位。
复权的作用是为了让股价连续,消除价格、指标的走势畸变。
log.info('初始函数开始运行且全局只运行一次'),是指输出内容到日志log.info(),这样便于事后分析、整理。
set_order_cost(OrderCost(close_tax=0.001,open_commission=0.0003,close_commission=0.0003,min_commission=5),type='stock')
是指每笔交易时的手续费是:买入时佣金万分之三,卖出时佣金万分之三加千分之一印花税,每笔交易佣金最低扣5块钱。
运行三个定时函数,即开盘前运行定时函数、开盘时运定时行函数、收盘后运行定时函数,其中reference_security为运行时间的参考标的。
1.1.2 开盘前运行函数
def before_market_open(context):
# 输出运行时间
log.info('函数运行时间(before_market_open):'+str(context.current_dt.time()))
# 给微信发送消息(添加模拟交易,并绑定微信生效)
send_message('美好的一天~')
# 要操作的股票:平安银行(g.为全局变量)
g.security = '000001.XSHE'
#首先输出运行时间到日志log.info(),然后给绑定手机的微信发送消息。在这里可以看到要操作的股票是平安银行,代码是000001。
1.1.3 开盘时运行函数
def market_open(context):
log.info('函数运行时间(market_open):'+str(context.current_dt.time()))
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
# 如果上一时间点价格高出五天平均价1%,则全仓买入
if current_price > 1.01*MA5:
# 记录这次买入
log.info("价格高于均价 1%%,买入 %s" % (security))
# 用所有 cash 买入股票
order_value(security,cash)
# 如果上一时间点价格低于五天平均价,则全部卖出
elif current_price < MA5 and context.portfolio.positions[security].closeable_amount > 0:
# 记录这次卖出
log.info("价格低于均价,卖出 %s" % (security))
# 卖出所有股票,使这只股票的最终持有量为0
order_target(security,0)
1.1.4 开盘时运行函数介绍
开盘时运行函数,即在股票交易的所有时间内一直在运行的函数,是实现买卖股票的函数。
首先输出运行时间到日志log.info(),然后利用security获取要操作的股票,即平安银行(000001)。
接着获取平安银行的收盘价、5日均线的价格、上一时间点的价格、当前账户的资金,如果上一时间点的价格高出5日均线的价格1%,,就会全仓买入,而上一时间点的价格低于5日均线的价格,就会卖出股票的所有持仓筹码
1.1.4 收盘后运行函数
收盘后运行函数的代码如下:
def after_market_close(context):
log.info(str('函数运行时间(after_market_close):'+str(context.current_dt.time())))
#得到当天所有成交记录
trades = get_trades()
for _trade in trades.values():
log.info('成交记录:'+str(_trade))
log.info('一天结束')
log.info('##############################################################')
#首先输出运行时间到日志log.info(),然后利用trades获得当天所有成交记录,再利用for循环语句把所有成交记录的值写入到日志log.info()中。
1.2 设置函数
在股票量化交易策略的初始化函数中,要进行一些初始化设置,如设置基准、设置佣金/印花税、设置成交量比例等,就会用到设置函数。
1.2.1 设置基准函数
设置基准函数的语法格式如下:
set_benchmark(security)
默认情况下,选定了沪深300指数的每日价格作为判断股票量化交易策略好坏和一系列风险值计算的基准。当然也可以使用set_benchmark指定其他股票、指数、ETF的价格作为基准。需要注意的是,这个函数只能在初始化函数(initialize)中调用。
参数security,是指股票、指数或ETF的代码。设置基准函数的返回值为None。
例如,设定50ETF基金指数(510050)为基准,其代码如下: set_benchmark(“510050.XSHG”)
再例如,设定深证成指(399001)为基准,其代码如下: set_benchmark(“399001.XSHG”)
还可以设置具体某一只股票,如设定招商银行(600036)为基准,其代码如下:set_benchmark(“600036.XSHG”)
1.2.2 设置佣金/印花税函数
设置佣金/印花税函数的语法格式如下: set_order_cost(cost,type,ref=None)
设置佣金/印花税函数,用来设定每笔交易要收取的手续费,系统会根据用户指定的费率计算每笔交易的手续费。该函数有三个参数,各个参数意义如下:
参数cost是OrderCost对象,各项子参数意义如下:
open_tax,买入时印花税 (只股票类标的收取,基金与期货不收)。
close_tax,卖出时印花税 (只股票类标的收取,基金与期货不收)。
open_commission,买入时佣金,申购场外基金的手续费。
close_commission,卖出时佣金,赎回场外基金的手续费。
close_today_commission,平今仓佣金。
min_commission,最低佣金,不包含印花税。
参数type,是指股票(stock)、基金(fund)、金融期货(index_futures)、期货(futures)、债券基金(bond_fund)、股票基金(stock_fund)、QDII 基金(QDII_fund)、货币基金(money_market_fund)、混合基金(mixture_fund)。
参数Ref,是参考代码,支持股票代码、基金代码、期货合约代码,以及期货的品种,如”000001.XSHE”、”510180.XSHG”、”IF1809”。
#股票类每笔交易时的手续费是:买入时佣金万分之三,卖出时佣金万分之三加千分之一印花税,每笔交易佣金最低扣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')
#单独设置黄金期货AU1809合约的费用
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')
1.2.3 设置滑点函数
设置滑点函数的语法格式如下:
set_slippage(object) 设定滑点,回测或模拟时有效。
当投资者下单后,真实的成交价格与下单时预期的价格总会有一定偏差,因此投资者加入了滑点模式可以更好的模拟真实市场的表现。需要注意的是,当前只支持固定滑点。
当投资者使用固定滑点时,投资者下单的多少并不会影响最后的成交价格,只需要指定一个价差。
当投资者下达一个买单指令时,成交的价格等于当时(执行order函数所在的单位时间)的平均价格加上价差的一半;
当投资者下达一个卖出指令时,卖出的价格等于当时的平均价格减去价差的一半。价差可以设定为一个固定值或者按照百分比设定。
固定值:是指这个价差可以是一个固定的值(比如0.02元,交易时加减0.01元),设定方式为:FixedSlippage(0.02)。
百分比:是指这个价差可以是是当时价格的一个百分比(比如0.2%,交易时加减当时价格的0.1%),设定方式为:PriceRelatedSlippage(0.002)。
设置滑点函数的实例代码如下:
#设定滑点为固定值
set_slippage(FixedSlippage(0.02))
#设定滑点为百分比
set_slippage(PriceRelatedSlippage(0.002))
提醒:如果没有调用 set_slippage 函数,系统默认的滑点是 PriceRelatedSlippage(0.00246)。
1.2.4 设置动态复权模式函数
设置动态复权(真实价格)模式函数的语法格式如下:
set_option('use_real_price',value) 注意,该函数只能在初始化函数(initialize)中调用。 参数value的值,是True或False。
设置动态复权(真实价格)模式函数的实例代码如下:
#开启动态复权模式
set_option('use_real_price',True)
#关闭动态复权模式
set_option('use_real_price',False)
提醒:为了更好的模拟,建议设置动态复权(真实价格)模式为True。在对接实盘交易时,此选项会强制设成True。
1.2.5 设置成交量比例函数
设置成交量比例函数的语法格式如下: set_option('order_volume_ratio',value)
参数value是一个float值,根据实际行情限制每个订单的成交量。对于每一笔订单,如果是市价单,成交量不超过:每日成交量×value;如果是限价单,限价单撮合时设定分价表中每一个价格的成交量的比率。
设置成交量比例函数的实例代码如下:
#设定成交量比例
set_option('order_volume_ratio',0.25)
#成交量不超过总成交量的四分之一
1.2.6 是否开启盘口撮合
设置是否开启盘口撮合模式函数的语法格式如下: set_option('match_with_order_book',value)
设置是否开启盘口撮合模式只对模拟盘生效,默认开启,即value的值为True。
如果value的值为False,关闭盘口撮合模式,使用Bar进行撮合。
设置是否开启盘口撮合模式函数代码如下:
#盘口撮合模式
set_option('match_with_order_book',True)
#盘口使用Bar进行撮合
set_option('match_with_order_book',False)
1.2.7 设置要操作的股票
设置要操作的股票池函数的语法格式如下: set_universe(security_list)
该函数只用于设定history函数的默认security_list,除此之外并无其他用处。参数security_list是指股票列表。
设置要操作的股票池函数代码如下: set_universe(['000001.XSHE','600000.XSHG'])
1.3 定时函数
1.3.1 定时函数的定义及分类
定时函数是指,在回测和模拟交易中指定每月、每周或者每天要运行的函数。
定时函数可以在具体每月或每周的第几个交易日(或者倒数第几天)的某一分钟执行。
定时函数可以分三种,分别是每日定时函数(run_daily)、每周定时函数(run_weekly)、每月定时函数(run_monthly)。
定时函数的语法格式如下:
#按月运行
run_monthly(func,monthday,time='open',reference_security)
# 按周运行
run_weekly(func,weekday,time='open',reference_security)
# 每天内何时运行
run_daily(func,time='open',reference_security)
需要注意的是,定时函数在日级模拟中使用时,如果设置 time=“open”或time=“9:30”,那么股票量化交易策略的实际运行时间是9:27~9:30之间。
股票量化交易策略类获取到的逻辑时间(context.current_dt)仍然是9:30。
1.3.2 定时函数各项参数的意义
参数func:是一个函数,并且该函数必须接受context参数。
参数monthday :用来指定每月的第几个交易日,可以是负数,表示倒数第几个交易日。
如果超出每月总交易日个数,则取临近的交易日执行。
参数weekday:用来指定每周的第几个交易日,可以是负数,表示倒数第几个交易日。
如果超出每周总交易日个数,则取临近的交易日执行。
参数time:一个字符串,可以是具体执行时间,支持time表达式。
比如 “10:00”,“01:00”或者“every_bar”,“open”,“before_open”,“after_close”,“ close”,“morning” 和 “night”。
(1)every_bar:只能在run_daily中调用;
按天会在每天的开盘时调用一次,按分钟会在每天的每分钟运行。
(2)open:开盘时运行(等同于”9:30”)。
(3)before_open:早上 9:00 运行。
(4)after_close:下午15:30运行。
(5)close:下午15:00运行。
(6)morning:早上 8:00 运行。
(7)night:晚上 20:00 运行。
参数reference_security:表示时间的参照标的。如果参照”000001.XSHG”,交易时间为 9:30-15:00;
如果参照”IF1812.CCFX”,2016-01-01之后的交易时间为 9:30-15:00,在此之前为 9:15-15:15;
如果参照”A99910.XDCE”,因为有夜盘,因此开始时间为21:00,结束时间为15:00。
1.3.3 定时函数的注意事项
定时函数的注意事项有5项,具体如下:
第一,参数 func 必须是一个全局的函数,不能是类的成员函数,实例代码如下:
def on_week_start(context):
#定义一个全局函数
pass
class MyObject(object):
#定义一个类
def on_week_start2(self,context): #在类中定义一个成员函数
pass
def initialize(context):
#量化交易策略的初始化函数
run_weekly(on_week_start,1) #正常运行
# 错误,下面的语句会报错
run_weekly(MyObject().on_week_start2,1)
第二,定时函数通过history或attribute_history获得每天数据时,是不包括当天的数据的。要获得当天数据,只能按分钟来获取。
第三,定时函数可以重复调用,即初始化函数中可以两个或多个同名定时函数,实例代码如下:
def on_week_start(context):
pass
def on_week_end(context):
pass
def initialize(context):
#初始化函数中有两个run_weekly定时函数
#在每周的第一个交易日和最后一个交易日分别调用两个函数
run_weekly(on_week_start,1)
run_weekly(on_week_end,-1)
第四,每次调用这些定时函数都会产生一个新的定时任务。如果想修改或者删除旧的定时任务,就要调用unschedule_all(取消所有定时运行)来删除所有定时任务,然后再添加新的。
提醒:取消所有定时运行的代码是:unschedule_all()
第五,如果定时函数在一月或一周交易日数不够,这样monthday或weekday就无法满足。
这时,我们可以找这周内最近的一个日期来执行。
1.3.4 定时函数的实例
首先定义三个全局函数,分别是weekly()、monthly()、daily(),接着定义初始化函数,实现一次调用monthly(),两次调用weekly(),四次调用daily(),具体代码如下:
def weekly(context):
print 'weekly %s %s' % (context.current_dt,context.current_dt.isoweekday())
def monthly(context):
print 'monthly %s %s' % (context.current_dt,context.current_dt.month)
def daily(context):
print 'daily %s' % context.current_dt
def initialize(context):
# 指定每月第一个交易日,在开盘后十分钟执行,即9:40
run_monthly(monthly,1,'open+10m')
# 指定每周倒数第一个交易日,在开盘前执行,即9:00
run_weekly(weekly,-1,'before_open')
# 指定每天收盘前10分钟运行,即14:50
run_weekly(daily,'close - 10m')
# 指定每天收盘后执行,即15:30
run_daily(daily,'after_close')
# 指定在每天的10:00运行
run_daily(daily,'10:00')
# 指定在每天的01:00运行
run_daily(daily,'01:00')
# 参照股指期货的时间每分钟运行一次,必须选择分钟回测,否则每天执行
run_daily(daily,'every_bar',reference_security='IF1512.CCFX')
1.4 下单函数
1.4.1 按股数下单函数
按股数下单函数的语法格式如下:
order(security,amount,style=None,side='long',pindex=0)
各项参数意义如下:
参数security:标的代码。
参数amount:交易数量,正数表示买入,负数表示卖出。
参数style:下单类型,有两种,分别是市价单(MarketOrder)和限价单(LimitOrder)。
市价单是指不论价格,接下单,直到交易全部完成。
限价单是指定一个价格,买入时不能高于它,卖出时不能低于它,如果不满足,则等待满足后再交易。
该参数的默认值为市价单(MarketOrder),即None代表MarketOrder。
参数side:用来指定开多单,还是空单。
其中long代表开多单,short代表开空单。默认为long,即开多单。需要注意的是,股票和基金暂不支持开空单。
参数pindex:在使用set_subportfolios创建了多个仓位时,指定subportfolio的序号,从 0 开始。
例如0指定第一个subportfolio,1指定第二个 subportfolio,默认为0。
按股数下单函数,如果创建订单成功,则返回Order对象,失败则返回None。按股数下单函数的实例代码如下:
#买入平安银行股票100股
order('000001.XSHE',100) # 下一个市价单
order('000001.XSHE',100,MarketOrderStyle()) #下一个市价单,功能同上
order('000001.XSHE',100,LimitOrderStyle(10.0)) # 以10块价格下一个限价单
1.4.2 按目标股数下单函数
目标股数下单函数的语法格式如下:
order_target(security,amount,style=None,side='long',pindex=0)
目标股数下单函数与按股数下单函数的参数几乎一样,只有第二个参数不一样。第二个参数amount表示期望的最终数量。
目标股数下单函数,如果创建订单成功,则返回Order对象,失败则返回None。目标股数下单函数的实例代码如下:
#卖出平安银行所有股票,即最终持有平安银行的股数为0
order_target('000001.XSHE',0)
#买入平安银行所有股票到100股,即最终持有平安银行的股数为100股
order_target('000001.XSHE',100)
1.4.3 按价值下单函数
按价值下单函数的语法格式如下:
order_value(security,value,style=None,side='long',pindex=0)
按价值下单函数与按股数下单函数的参数几乎一样,只有第二个参数不一样。
第二个参数value表示股票价值。
按价值下单函数,如果创建订单成功,则返回Order对象,若失败则返回None。按价值下单函数的实例代码如下:
#卖出价值为10000元的平安银行股票
order_value('000001.XSHE',-10000)
#买入价值为100000元的平安银行股票
order_value('000001.XSHE',10000)
1.4.4 目标价值下单函数
目标价值下单函数的语法格式如下:
order_target_value(security,value,style=None,side='long',pindex=0)
目标价值下单函数与按股数下单函数的参数几乎一样,只有第二个参数不一样。第二个参数value表示期望的股票最终价值。
目标价值下单函数,如果创建订单成功,则返回Order对象,失败则返回None。目标价值下单函数的实例代码如下:
#卖出平安银行所有股票
order_target_value('000001.XSHE',0)
#调整平安银行股票仓位到10000元价值
order_target_value('000001.XSHE',10000)
1.4.5 撤单函数
撤单函数的语法格式如下:
cancel_order(order)
参数orderj是指Order对象或者order_id。撤单函数,如果取消委托成功,则返回Order对象,委托不存在返回None。撤单函数的实例代码如下:
#自定义每个交易日结束运行函数
def after_trading_end(context):
# 得到当前未完成订单
orders = get_open_orders()
# 利用for循环撤销订单
for _order in orders.values():
cancel_order(_order)
1.4.6 获取未完成订单函数
获取未完成订单函数的语法格式如下:
get_open_orders()
该函数可以获得当天的所有未完成的订单。获取未完成订单函数的实例代码如下:
#自定义每个交易日结束运行函数
def after_trading_end(context):
#得到当前未完成订单
orders = get_open_orders()
for _order in orders.values():
log.info(_order.order_id)
1.4.7 获取订单信息函数
获取订单信息函数的语法格式如下:
get_orders(order_id=None,security=None,status=None)
该函数可以获取当天的所有订单。
各项参数意义如下:
参数order_id:订单id。
参数security:标的代码,可以用来查询指定标的的所有订单。
参数status:表示订单状态,可以查询特定订单状态的所有订单。
获取订单信息函数的实例代码如下:
#自定义每个交易日结束运行函数
def after_trading_end(context):
#得到当天所有订单
orders = get_orders()
for _order in orders.values():
log.info(_order.order_id)
# 根据订单id查询订单
get_orders(order_id='1517627499')
# 查询所有标的为 000002.XSHE 的订单
get_orders(security='000002.XSHE')
# 查询订单状态为 OrderStatus.held 的所有订单
get_orders(status=OrderStatus.held)
# 查询标的为 000002.XSHE 且状态为 OrderStatus.held 的所有订单
get_orders(security='000002.XSHE',status=OrderStatus.held)
1.4.8 获取成交信息函数
获取成交信息函数的语法格式如下:
get_trades()
该函数获取当天的所有成交记录。需要注意的是,一个订单可能分多次成交。
获取成交信息函数的实例代码如下:
#自定义每个交易日结束运行函数
def after_trading_end(context):
#得到当天所有成交记录
trades = get_trades()
for _trade in trades.values():
log.info(_trade.trade_id)
1.5 日志log
日志可以用来记录应用程序的状态、错误和信息消息,也经常作为调试程序的工具。下面来讲解一下设定log级别及最常用的log.info。
1.5.1 设定log级别
设定log级别语法格式如下:
log.set_level(name,level)
设置不同种类的log的级别,低于这个级别的log不会输出。
所有log的默认级别是debug。
各项参数意义如下:
参数name:字符串,但log种类只有三种,分别是”order”、”history”、”strategy”。
order表示调用order系列API产生的log;
history表示调用history系列API产生的log;
strategy表示程序员自己在策略代码中打的log。
参数level:字符串,必须是”debug”、”info”、”warning”、”error”中的一个。
级别是debug < info < warning < error。
各级别的语法格式如下: log.error(content) log.warn(content) log.info(content) log.debug(content)
设定log级别的实例代码如下:
#过滤掉order系列API产生的比error级别低的log log.set_level('order','error')
1.5.2 log.info
日志log最常用的方法是info,该方法的语法格式如下:
log.info(content)
log.info等同于print输出的结果。
参数content,可以是字符串、对象等。
log.info的实例代码如下:
#log.info(history(10))
#打印出 history(10)返回的结果
log.info("Selling %s,amount=%s",security,amount)
#打印出一个格式化后的字符串
print history(10),data,context.portfolio
1.6 常用对象
在股票量化交易策略中,还会用到一些常用的对象,如Order对象、全局对象g、Trade对象等。
下面详细讲解一下常用对象。
1.6.1 Order对象
Order对象其的常用属性如下:
Amount:下单数量,不管是买还是卖,都是正数。
filled:已经成交的股票数量,正数。
security:股票代码。
order_id:订单ID。
price:平均成交价格,已经成交的股票的平均成交价格(一个订单可能分多次成交)。
avg_cost:卖出时表示下卖单前的此股票的持仓成本,用来计算此次卖出的收益。
买入时表示此次买入的均价(等同于price)。
side:用来指定开多单,还是空单。如果其值是long代表开多单,如果其值是short代表开空单。
action:用来指定是开仓,还是平仓。
如果其值是open代表开仓,如果其值是close代表着平仓。
add_time:订单添加时间。
1.6.2 全局对象g
全局对象g,用来存储用户的各类可被pickle.dumps函数序列化的全局数据。
在模拟盘中,如果中途进程中断,我们会使用pickle.dumps序列化所有的g下面的变量内容,保存到磁盘中,再启动的时候模拟盘就不会有任何数据影响。
如果没有用g声明,会出现模拟盘重启后,变量数据丢失的问题。
如果不想g中的某个变量被序列化,可以让变量以”__”开头,这样,这个变量在序列化时就会被忽略。 全局对象g的实例代码如下:
def initialize(context):
g.security = "000001.XSHE"
g.count = 1
g.flag = 0
def process_initialize(context):
# 保存不能被序列化的对象,进程每次重启都初始化
g.__q = query(valuation)
def handle_data(context,data):
log.info(g.security)
log.info(g.count)
log.info(g.flag)
1.6.3 Trade对象
Trade对象用于记录订单的一次交易。但需要注意的是,一个订单可能分多次交易。
Trade对象的常用属性如下:
time:交易时间。
amount:交易数量。
price:交易价格。
trade_id:交易记录id。
order_id:对应的订单id。
1.6.4 tick对象
tick中的信息是在tick事件发生时,盘面的一个快照。tick对象的常用属性如下:
code:标的的代码。
datetime: tick 发生的时间。
current:最新价。
high:最高价。
low:最低价。
volume:截至到当前时刻的成交量。
amount:截至到当前时刻的成交额。
position:截至到当前时刻的持仓量,只适用于期货tick对象。
a1_v ~ a5_v:卖一量到卖五量,对于期货,只有卖一量。
a1_p ~ a5_p:卖一价到卖五价,对于期货,只有卖一量。
b1_v ~ b5_v:买一量到买五量,对于期货,只有买一量。
b1_p ~ b5_p:买一价到买五价,对于期货,只有买一价。
1.6.5 Context对象
Context对象,即量化交易策略回测对象,其常用属性如下:
subportfolios:当前单个操作仓位的资金和标的信息。
portfolio:账户信息,即subportfolios的汇总信息。
current_dt:当前单位时间的开始时间。
如果是按天回测,那么开始时间是hour = 9,minute = 30,second = microsecond = 0;
如果是按分钟回测,那么开始时间是second = microsecond = 0。
previous_date:前一个交易日。
universe:查询set_universe()设定的股票池,例如:[“000001.XSHE”、”600000.XSHG”]。
run_params:表示此次运行的参数,有如下属性:
start_date:回测/模拟开始日期。
end_date:回测/模拟结束日期。
type:运行方式
如果其值是“simple_backtest”, 表示回测是通过单击“编译运行”运行;
如果其值是“full_backtest”表示回测是通过单击“运行回测”运行;
如果其值是“sim_trade”,表示模拟交易。
frequency:运行频率,只能是“day”、“ minute”或“tick”。
为了让从其他平台迁移过来的程序员更顺手的使用系统,我们对此对象也做了和g一样的处理:
第一,可以添加自己的变量,每次进程关闭时持久保存,进程重启时恢复。
第二,以“__”开头的变量不会被持久保存。
第三,如果添加的变量与系统的冲突,将覆盖掉系统变量,如果想恢复系统变量,就要删除自己的变量,实例代码如下:
def handle_data(context,data):
# 执行下面的语句之后,context.portfolio 的整数1
context.portfolio = 1
log.info(context.portfolio)
# 要恢复系统的变量,只需要使用下面的语句即可
del context.portfolio
# 此时,context.portfolio 将变成账户信息.
log.info(context.portfolio.portfolio_value)
第四,以后可能会往context添加新的变量来支持更多功能,为了减少不必要的迷惑,还是建议大家使用g。
#Context对象的实例代码如下:
def handle_data(context,data):
#获得当前回测相关时间
year = context.current_dt.year
month = context.current_dt.month
day = context.current_dt.day
hour = context.current_dt.hour
minute = context.current_dt.minute
second = context.current_dt.second
#得到"年-月-日"格式
date = context.current_dt.strftime("%Y-%m-%d")
#得到周几
weekday = context.current_dt.isoweekday()
# 获取账户的持仓价值
positions_value = context.portfolio.positions_value
# 获取仓位subportfolios[0]的可用资金
available_cash = context.subportfolios[0].available_cash
# 获取subportfolios[0]中多头仓位的security的持仓成本
hold_cost = context.subportfolios[0].long_positions[security].hold_cost
1.6.6 Position对象
Position对象是持有的某个标的的信息,其常用属性如下:
security:标的代码。
price:最新行情价格。
avg_cost:开仓均价,买入标的的加权平均价。
hold_cost:持仓成本,针对期货有效。
init_time:建仓时间,格式为datetime.datetime。
transact_time:最后交易时间,格式为datetime.datetime。
total_amount::总仓位,但不包括挂单冻结仓位。
closeable_amount:可卖出的仓位。
today_amount:今天开的仓位。
locked_amount:挂单冻结仓位。
value:标的价值,计算方法是:price * total_amount * multiplier,,其中股票、基金的multiplier为1,期货为相应的合约乘数。
side:用来指定开多单,还是空单。
如果其值是long代表开多单,如果其值是short代表开空单。
pindex:仓位索引。
1.6.7 SubPortfolio对象
SubPortfolio对象是某个仓位的资金和标的信息,其常用属性如下:
inout_cash:累计出入金,比如初始资金1000元,后来转移出去100元,则这个值是1000 – 100=900元。
available_cash:可用资金,可用来购买证券的资金。
transferable_cash:可取资金,即可以提现的资金,不包括今日卖出证券所得资金。
locked_cash:挂单锁住资金。
type:账户所属类型。
long_positions:多单的仓位。
short_positions:空单的仓位。
positions_value:持仓价值,股票基金才有持仓价值,期货为0。
total_value:总资产,包括现金,保证金,仓位的总价值,可用来计算收益。
total_liability:总负债,等于融资负债、融券负债、利息总负债的总和。
net_value:净资产,等于总资产减去总负债。
cash_liability:融资负债。
sec_liability:融券负债。
interest:利息总负债。
maintenance_margin_rate:维持担保比例。
available_margin:融资融券可用保证金。
margin:保证金,股票、基金保证金都为100%;
融资融券保证金为0;
期货保证金会实时更新,总是等于当前期货价值×保证金比率,当保证金不足时,强制平仓。
平仓顺序是:亏损多的(相对于开仓均价)先平仓。
1.6.8 Portfolio对象
Portfolio对象是所有标的操作仓位的信息汇总,其常用属性如下:
inout_cash:累计出入金,比如初始资金1000元,后来转移出去100元,则这个值是1000 – 100=900元。
available_cash:可用资金,可用来购买证券的资金。
transferable_cash:可取资金,即可以提现的资金,不包括今日卖出证券所得资金。
locked_cash:挂单锁住资金。
margin:保证金,股票、基金保证金都为100%。
positions:等同于 long_positions。
long_positions:多单的仓位。
short_positions:空单的仓位。
total_value:总的权益,包括现金,保证金,仓位的总价值,可用来计算收益。
returns:总权益的累计收益。
starting_cash:初始资金。
positions_value:持仓价值,股票基金才有持仓价值,期货为0。
locked_cash_by_purchase:基金申购未完成所冻结的金额。
locked_cash_by_redeem:基金赎回未到账的金额。
locked_amount_by_redeem:基金赎回时,冻结的份额。
1.6.9 SecurityUnitData对象
SecurityUnitData对象是一个单位时间内的股票的数据,其常用属性如下:
security:股票代码。例如“000001.XSHE”。
returns:股票在这个单位时间的相对收益比例。
open:时间段开始时价格。
close:时间段结束时价格。
low:最低价。
high:最高价。
volume:成交的股票数量。
money:成交的金额。
factor:前复权因子。
利用前复权因子可以算出原始价格,方法是价格除以factor,即原始价格=close÷factor。
high_limit:涨停价。
low_limit:跌停价。
avg:这段时间的平均价。