量化投资:交易模型开发与数据挖掘
上QQ阅读APP看本书,新人免费读10天
设备和账号都新为新人

3.1 选择回测平台的技巧

近年来Python在我国量化领域非常流行,同时也涌现出了很多做量化平台的公司,他们所提供的量化平台基本都包含回测功能。不过从一个量化分析的过程来讲,只有回测功能是不够的,还需要有底层数据、量化因子、因子生产平台、绩效评价功能、策略优化器等。对于自建平台的机构或个人爱好者,只需要接入外部数据即可;而对于需要使用专业而全面的量化分析工具的人们,就要对各类平台认真考虑,从而选择适合自己的量化平台。

在此列举一些量化平台,也是笔者这几年在量化分析中了解到的一些平台名称,如优矿(通联数据)、聚宽、米筐、问财、果仁和国信TradeStation。

另外对于自建平台的数据使用,在此也列举了一些数据库厂商,仅供参考,如表3-1所示。

表3-1

3.1.1 根据个人特点选择回测平台

投资者除了选择回测平台,还需要知道量化投资策略只有建立在有一定数量的金融数据基础上才能很好地运行。由于每位交易者的侧重点不同,所以其需求也各不相同。

常见的原始数据需求,如日期、开/收盘价、最高/最低价、交易量、交易金额、财务报表、业绩预告、业绩快报、IPO、配股、分红、拆股和股改等信息属于传统的结构化投资数据。

一些个人需要的非原始数据,如社交媒体数据、新闻媒体数据、渠道公告数据、电商数据等属于非传统的结构化数据。

无论哪种结构化数据,只有经过不断挖掘、优化、组合、创新并不断回测,才有可能在实盘量化投资交易中盈利。

通联数据所提供的优矿量化平台,作为国内最早推出的量化分析工具,已经得到了各种金融机构的认可,如券商、公募基金及个人爱好者等。优矿支持调用全量底层数据、400+量化因子、风险模型等。本章主要介绍数据的提取及回测方法。

3.1.2 回测平台的使用方法与技巧

用户需要在回测平台进行注册才能使用,步骤如下。

首先,登录优矿官网免费注册一个账号,如图3-1所示。

图3-1

其次,输入手机号、验证码、密码后,单击“注册优矿”按钮,如图3-2所示。

图3-2

注册成功后,即可进入主界面,单击“研究数据”模块,我们可以看到很多常用的金融数据,而且这些金融数据绝大部分是可以免费查看的。这些经济数据对学习量化投资策略能起到非常重要的作用,如图3-3所示。

图3-3

3.2 调用金融数据库中的数据

下面开始讲解如何调用一些常用的金融数据。单击“开始研究”模块,在左侧单击“新建”下拉按钮,选择“新建Notebook”选项,即可新建一个Notebook,如图3-4所示。

图3-4

单击对应的Notebook,即可进入Python代码的编辑界面(见图3-5)。当打开优矿的Notebook时,我们会发现,它和IPython Notebook或Jupyter Notebook的翻译环境基本都是相同的,那是因为优矿中的Notebook是基于IPython Notebook开发的,所以操作基本一致,从而可以方便用户进行操作。

图3-5

单击NoteBook左上角的“代码”下拉按钮,将模式设置为代码模式,即可开始调用数据,如图3-6所示。

图3-6

3.2.1 历史数据库的调取

打开回测平台的主界面并单击“研究数据”模块,寻找我们需要的数据。例如,查看沪深股票日行情数据:单击“沪深股票”→“行情”→“日行情”,然后单击“沪深股票日行情”右侧的“展开详情”,如图3-7所示。

图3-7

我们既可以通过单击左侧的下拉按钮来寻找数据,也可以直接在上方的搜索框中输入关键字进行搜索,如图3-8所示。

图3-8

在“展开详情”中展示了参数的名称、类型及描述信息,如图3-9所示。例如,我们想要调取某只股票的某个时间段的行情,只要规范写入代码就可以了。

图3-9

在返回值中,我们可选的行情不仅包括基本的最高价、最低价、开盘价、收盘价、成交量、涨跌幅,还包括动态市盈率、市净率、VWAP等数据,主要内容如表3-2所示。

表3-2

应将所有选择返回的项传给field参数。单击“复制代码”按钮,如图3-10所示。

图3-10

单击“开始研究”模块并新建“Notebook”,将代码粘贴到文本框中,注意在“Notebook”内填写代码,如图3-11所示。

图3-11

例如,调取601006大秦铁路与000727华东科技在2019年3月1日的收盘价与总市值,返回的是一个DataFrame。在输入股票代码时需要注意,由于是通联内部自由编码的,所以要在原股票代码的基础上加上后缀,例如,对深市股票000727华东科技加上后缀为000727.XSHE,对沪市股票601006大秦铁路加上后缀为601006.XSHG,如图3-12所示。

图3-12

当然还可以直接输入原始股票代码传入ticker参数,如图3-13所示。

图3-13

可以通过beginDate与endDate参数获取DataAPI中某一个时间段的数据,如图3-14所示。

图3-14

例如,调取000727华东科技与601006大秦铁路从2019年2月26日至2019年3月1日的收盘价与总市值数据。在输入日期时需要注意书写格式,如图3-15所示。

图3-15

3.2.2 数据库的分析方法与技巧

DataAPI支持提取多只股票在某一时间段的数据,单击“研究数据”模块,在搜索框中输入“因子”进行搜索,如图3-16所示。

图3-16

在搜索因子后,通联数据显示栏显示的“获取多只股票历史上某一天的因子数据”和“获取一只股票历史上某一时间段的因子数据”就是我们需要的DataAPI。由于数据量过大导致没有因子DataAPI可以直接调用多只股票历史上某一时间段的因子数据,所以我们在使用优矿的因子DataAPI时,首先应该考虑我们的需求更适合使用哪个DataAPI。

例如,“获取一只股票历史上某一时间段的因子数据”应该使用如图3-17所示的DataAPI。

图3-17

例如,“获取多只股票历史上某一天的因子数据”应该使用如图3-18所示的DataAPI。

图3-18

例如,“获取多只股票历史上某一段时间段的因子数据”则可以编写循环语句来多次调用,而且应该使用如图3-19所示的DataAPI。

图3-19

3.3 回测与实际业绩预期偏差的调试方法

股票回测是股票模型创建中必不可少的一步,其过程为根据个人设定的基础指标经过筛选、组合建立好策略模型之后,利用某一时间段的历史行情数据,严格按照设定的组合进行选股,并模拟真实市场行情交易的规则进行模型买入、模型卖出,得出该时间段的盈利率、最大回撤率等数据。

实际业绩预期偏差是指在回测中表现十分优秀的策略,一旦到实盘测试时就亏损累累。其原因在于回测中包含一定的偏差,我们要做的就是尽量筛选并将它们剔除。

交易策略一旦确定那么就需要获取历史数据,然后根据历史数据进行测试。目前获得历史数据的方法有很多,但是根据渠道不同,历史数据的质量、时间间隔及深度等都不相同。交易者在选择数据时需要关注的是历史数据中幸存者偏差、精确度、清洁度、可用性及交易成本等方面。

在历史数据中有些错误是不容易被辨别出来的,所以需要利用数据供应商提供的数据来进行对比和检查。我们需要利用一个软件平台来进行回测。

例如,以优矿来实现,如图3-20所示。

图3-20

3.4 设置回测参数

3.4.1 start和end回测起止时间

策略回测的起止时间是策略的全局变量。start表示回测起始日期,end表示回测终止日期。

quartz会自动截取start之后的第一个交易日和end之前的最后一个交易日进行回测。

日线数据只能回测到2007年1月1日,分钟线数据只能回测到2009年1月1日,在此之前的数据只能自行获取。需要注意的是,在设置start和end时需要考虑max_history_window引入的提前量,例如当max_history_window = 30时,start最早仅可为2007-02-15。

时间类型包括str或datetime,注意str只支持“YYYY-MM-DD”和“YYYYMMDD”两种格式。

不同资产类型支持的回测区间范围如表3-3所示。

表3-3

示例代码如下:

        start = '2019-03-01'   # 在2019年3月1日开始回测
        end = '2019-03-08'      # 在2019年3月8日结束回测

3.4.2 universe证券池

策略回测的证券池,即策略逻辑作用的域,下单与历史数据获取都只限于universe中的证券。它支持全部A股、全部可在二级市场交易的ETF与LOF。

有两种获取证券池的方式:固定的资产列表(静态证券池)、DynamicUniverse(动态证券池)。

示例代码如下:

        universe = ['000001.XSHE', '600000.XSHG']          # 静态证券池
        universe = DynamicUniverse('HS300')                # 动态证券池

1.固定的资产列表

静态证券池可以指定固定的个别资产或资产列表,示例代码如下:

        universe = ['000001.XSHE', 'IFM0']  # 指定平安银行和股指期货为策略证券池

2.DynamicUniverse

获取动态证券池的示例代码如下:

        DynamicUniverse(<板块代码、行业或指数实例>)

在使用板块成分股、行业成分股或指数成分股作为策略的交易对象时,策略框架会根据实际情况,调整当天股票池的内容。

参数:<板块代码、行业、指数实例>,即预设的板块代码、行业和指数实例名称。

参数类型:str或预设的行业与指数实例。

参数用法如下。

· 预设板块成分股:支持7个预设的指数板块,包括’SH50’上证50、'SH180’上证180、'HS300’沪深300、'ZZ500’中证500、'CYB’创业板、'ZXB’中小板、'A’全A股,也支持通过DataAPI.IdxGet()函数获取指数的secID值。沪深300指数板块示例代码如下:

        DynamicUniverse('HS300')                            # 表示沪深300的字符串

· 预设行业和指数实例。在Notebook中输入开头字符后会有自动代码提示功能,可以帮助查找具体的行业(以IndSW.开头)和指数(以IdxCN.开头)名称。当前使用成分股作为股票池的完整行业列表和指数列表,详细信息请读者阅读动态股票池支持的行业列表和动态股票池支持的指数列表。

行业实例代码如下:

        # 行业实例,IndSW表示申万行业,YinHangL2表示银行二级行业分类
        DynamicUniverse(IndSW.YinHangL2)

指数实例代码如下:

        # 指数实例,IdxShangZhengZongZhi表示上证综指
        DynamicUniverse(IdxCN.IdxShangZhengZongZhi)

· 也可以混合使用,示例代码如下:

        # 混合使用
        DynamicUniverse('HS300', IndSW.YinHangL2, IdxCN.IdxShangZhengZongZhi)

返回动态证券池类型的示例代码如下:

        universe = DynamicUniverse('HS300')  # 使用沪深300成分股动态证券池

支持动态证券池和普通列表取并集,示例代码如下:

        # 包含沪深300成分股动态证券池和平安银行
        universe = DynamicUniverse('HS300') + ['000001.XSHE']

3.apply_filter

将筛选条件作用于每个交易日的动态证券池上,从而进一步缩小策略标的范围,当前支持使用优矿因子库中的所有因子对证券池进行筛选,代码如下。

        DynamicUniverse(<板块代码或行业、指数实例>).apply_filter(<因子筛选条件表达式>)

参数:<因子筛选条件表达式>。表达式写法:Factor.<factor_name>.<筛选方法>。

用法:factor_name是因子名,可以通过优矿因子库查看所有支持筛选的因子。

优矿因子库目前提供了5种筛选方法,如表3-4所示。

表3-4

表达式既支持单个筛选条件,也支持多个筛选条件,最多可支持5个筛选条件。

在表达式中可以使用两种二元运算:交(&)表示同时满足两个筛选条件,并(|)表示满足任意一个筛选条件。运算方向为从左到右。

当筛选条件多于两个时,可以通过括号嵌套的方式来确定运算顺序。例如,筛选出PE值最大的100只或PB值排名为95%~100%的股票,并且RSI值大小为70~100的股票池,可使用如下表达方式:

        (Factor.PE.nlarge(100) | Factor.PB.pct_range(0.95, 1)) & Factor.RSI.value
    _range(70, 100)

返回动态证券池类型的示例代码如下:

        # 获得沪深300成分股中PE值最小的100只股票列表
        universe = DynamicUniverse('HS300').apply_filter(Factor.PE.nsmall(100))

3.4.3 benchmark参考基准

策略参考基准,即量化投资策略回测结果的比较标准,通过比较可以大致看出策略的好坏。策略的一些风险指标如Alpha、beta等也要通过benchmark计算得出。

策略参考基准支持如下3种赋值方式。

· 将预设板块作为基准:支持5个常用指数板块,包括’SHCI’上证综指、'SH50’上证50、'SH180’上证180、'HS300’沪深300、'ZZ500’中证500。示例代码如下:

        benchmark = 'HS300'         # 策略参考基准为沪深300

· 将指数作为基准:当前支持的完整的指数列表。示例代码如下:

        benchmark = '399006.ZICN'  # 策略参考基准为创业板指

· 将个股作为基准:当前支持所有A股股票。示例代码如下:

        benchmark = '000001.XSHE'  # 策略参考基准为平安银行

3.4.4 freq和refresh_rate策略运行频率

策略回测,本质上是指使用历史行情和其他依赖数据对策略的逻辑进行历史回放。freq和refresh_rate共同决定了回测使用的数据和调仓频率。

优矿支持日线策略和分钟线策略两种模式。

日线策略:每天会执行一次handle_data。执行时间为开盘前,此时仅可获得当天的盘前信息,以及截止到前一天的行情、因子等数据,不会获得当天的盘中行情等数据。

分钟线策略:首先在开盘前会执行一次handle_data,然后在盘中的调仓对应时间的分钟结束后执行一次handle_data(不包含收盘时间)。

freq表示使用的数据为日线行情数据或分钟线行情数据。refresh_rate表示调仓间隔的时间,即每次触发handle_data的间隔时间。它们的类型如下。

· freq:str。

· refresh_rate :int或(a, b)结构。

freq和refresh_rate的用法如下。

1.日线策略

freq,取值为d,其中d表示策略中使用的数据为日线级别的数据,只能进行日线级别的调仓。

refresh_rate有以下3种取值方式。

· 使用整数1,表示每个交易日进行调仓的策略,示例代码如下:

        start = '2019-01-01'                    # 在2019年1月1日开始回测
        end = '2019-02-01'                      # 在2019年2月1日结束回测
        universe = DynamicUniverse('HS300')     # 证券池,支持股票、基金、期货
        benchmark = 'HS300'                     # 策略参考基准
        freq = 'd'
        refresh_rate = 1
        accounts = {
          'stock_account': AccountConfig(account_type='security', capital_base=
    10000000)
        }
        def initialize(context):                # 初始化策略运行环境
          pass
        def handle_data(context):               # 核心策略逻辑
          stock_account = context.get_account('stock_account')
          print context.current_date

每个交易日都有调仓,下面展示了部分调仓日期:

        2019-01-03 00:00:00
        2019-01-09 00:00:00
        2019-01-16 00:00:00
        2019-01-23 00:00:00

· 使用Weekly(1),表示每周第一个交易日进行调仓,示例代码如下:

        start = '2019-01-01'                    # 在2019年1月1日开始回测
        end = '2019-02-01'                      # 在2019年2月1日结束回测
        universe = DynamicUniverse('HS300')     # 证券池,支持股票、基金、期货
        benchmark = 'HS300'                     # 策略参考基准
        freq = 'd'
        refresh_rate = Weekly(1)
        accounts = {
          'stock_account': AccountConfig(account_type='security', capital_base=
    10000000)
        }
        def initialize(context):                # 初始化策略运行环境
          pass
        def handle_data(context):               # 核心策略逻辑
          stock_account = context.get_account('stock_account')
          print context.current_date

下面展示了每周第一个交易日的调仓日期:

        2019-01-03 00:00:00
        2019-01-09 00:00:00
        2019-01-16 00:00:00
        2019-01-23 00:00:00

· 使用Monthly(1, -1),表示每个月第一个和最后一个交易日进行调仓,示例代码如下:

        start = '2019-01-01'                    # 在2019年1月1日开始回测
        end = '2019-03-01'                      # 在2019年3月1日结束回测
        universe = DynamicUniverse('HS300')     # 证券池,支持股票、基金、期货
        benchmark = 'HS300'                     # 策略参考基准
        freq = 'd'
        refresh_rate = Monthly(1, -1)
        accounts = {
          'stock_account': AccountConfig(account_type='security', capital_base=
    10000000)
        }
        def initialize(context):                # 初始化策略运行环境
          pass
        def handle_data(context):               # 核心策略逻辑
          stock_account = context.get_account('stock_account')
          print context.current_date

下面展示了每个月第一个和最后一个交易日调仓的日期:

        2019-01-02 00:00:00
        2019-01-31 00:00:00
        2019-02-01 00:00:00
        2019-02-28 00:00:00
        2019-03-01 00:00:00

2.分钟线策略

freq,取值为m,其中m表示策略中使用的数据为分钟线数据,可以进行分钟线级别的调仓。

refresh_rate有以下4种取值方式。

· 使用(1, 2),表示每个交易日每间隔2分钟进行调仓的策略,示例代码如下:

        start = '2019-01-04'                    # 在2019年1月4日开始回测
        end = '2019-01-04'                      # 在2019年1月4日结束回测
        universe = DynamicUniverse('HS300')     # 证券池,支持股票、基金、期货
        benchmark = 'HS300'                     # 策略参考基准
        freq = 'm'
        refresh_rate = (1, 2)
        accounts = {
          'stock_account': AccountConfig(account_type='security', capital_base=
    10000000)
        }
        def initialize(context):                # 初始化策略运行环境
            pass
        def handle_data(context):               # 核心策略逻辑
            stock_account = context.get_account('stock_account')
            print context.now

每个交易日的每2分钟都有调仓,下面展示了部分调仓时间:

        2019-01-04 09:30:00
        2019-01-04 09:32:00
        2019-01-04 09:34:00
        ...
        2019-01-04 14:56:00
        2019-01-04 14:58:00

· 使用(2, ['10:30', '14:30']),表示每2个交易日指定特定时间,使用分钟线数据进行调仓的策略,示例代码如下:

        start = '2019-01-04'                    # 在2019年1月4日开始回测
        end = '2019-01-10'                      # 在2019年1月10日结束回测
        universe = DynamicUniverse('HS300')     # 证券池,支持股票、基金、期货
        benchmark = 'HS300'                     # 策略参考基准
        freq = 'm'
        refresh_rate = (2, ['10:30', '14:30'])
        accounts = {
            'stock_account': AccountConfig(account_type='security', capital_base=
    10000000)
        }
        def initialize(context):                # 初始化策略运行环境
            pass
        def handle_data(context):               # 核心策略逻辑
            stock_account = context.get_account('stock_account')
            print context.now

下面展示了全部调仓时间,每2个交易日,在10:30和14:30进行调仓:

        2019-01-04 10:30:00
        2019-01-04 14:30:00
        2019-01-06 10:30:00
        2019-01-06 14:30:00
        2019-01-10 10:30:00
        2019-01-10 14:30:00

· 使用(Weekly(1, -1), ['10:30', '14:30']),表示每周第一个和最后一个交易日,指定特定时间,使用分钟线数据进行调仓的策略,示例代码如下:

        start = '2019-01-01'                    # 在2019年1月1日开始回测
        end = '2019-01-10'                      # 在2019年1月10日结束回测
        universe = DynamicUniverse('HS300')     # 证券池,支持股票、基金、期货
        benchmark = 'HS300'                     # 策略参考基准
        freq = 'm'
        refresh_rate = (Weekly(1, -1), ['10:30', '14:30'])
        accounts = {
          'stock_account': AccountConfig(account_type='security', capital_base=
    10000000)
        }
        def initialize(context):                # 初始化策略运行环境
          pass
        def handle_data(context):               # 核心策略逻辑
          stock_account = context.get_account('stock_account')
          print context.now

下面展示了全部调仓时间,指定每周第一个和最后一个交易日,在10:30和14:30进行调仓:

        2019-01-06 10:30:00
        2019-01-06 14:30:00
        2019-01-09 10:30:00
        2019-01-09 14:30:00

· 使用(Monthly(1), 120),表示每月第一个交易日,每隔120分钟,使用分钟线数据进行调仓的策略,示例代码如下:

        start = '2019-01-01'                    # 在2019年1月1日开始回测
        end = '2019-03-01'                      # 在2019年3月1日结束回测
        universe = DynamicUniverse('HS300')     # 证券池,支持股票、基金、期货
        benchmark = 'HS300'                     # 策略参考基准
        freq = 'm'
        refresh_rate = (Monthly(1), 120)
        accounts = {
          'stock_account': AccountConfig(account_type='security', capital_base=
    10000000)
        }
        def initialize(context):                # 初始化策略运行环境
          pass
        def handle_data(context):               # 核心策略逻辑
          stock_account = context.get_account('stock_account')
          print context.now

下面展示了全部调仓时间,表示每月第一个交易日,每隔120分钟,使用分钟线数据进行调仓:

        2019-01-03 09:30:00
        2019-01-03 11:30:00
        2019-02-03 09:30:00
        2019-02-03 11:30:00
        2019-03-01 09:30:00
        2019-03-01 11:30:00

3.5 账户设置

3.5.1 accounts账户配置

回测框架的交易账户配置函数,支持多个交易品种、多个交易账户同时进行回测,示例代码如下:

        accounts = {
         'security_account': AccountConfig(account_type='security', capital_base=
    10000000, position_base = {}, cost_base = {}, commission = Commission(buycost=
    0.001, sellcost=0.002, unit='perValue'), slippage = Slippage(value=0.0, unit=
    'perValue'))
        }  # 股票(包含场内基金)账户配置
        accounts = {
         'futures_account': AccountConfig(account_type='futures', capital_base=
    10000000, commission = Commission(buycost=0.001, sellcost=0.002, unit=
    'perValue'), slippage = Slippage(value=0.0, unit='perValue'), margin_rate = 0.1)
        }  # 期货账户配置
        accounts = {
        'otcfund_account': AccountConfig(account_type='otc_fund', capital_base=
    10000000, commission = Commission(buycost=0.001, sellcost=0.002, unit=
    'perValue'), slippage = Slippage(value=0.0, unit='perValue'), dividend_method =
    'cash_dividend')
        }  # 场外基金(不包含货币基金)账户配置

accounts账户配置的用法有如下3种。

· 单个账户配置,示例代码如下:

        start = '2018-01-01'                    # 回测起始时间
        end = '2019-01-01'                      # 回测结束时间
        universe = DynamicUniverse('HS300')     # 证券池,支持股票、基金、期货
        benchmark = 'HS300'                     # 策略参考基准
        # 策略类型,'d’表示日间策略使用日线回测,'m’表示日内策略使用分钟线回测
        freq = 'd'
        refresh_rate = 1                        # 执行handle_data的时间间隔
        accounts = {
          'security_account': AccountConfig(account_type='security', capital_base=
    10000000, position_base = {'600000.XSHG':1000}, cost_base = {'600000.XSHG':
    10.05}, commission = Commission(buycost=0.001, sellcost=0.002, unit='perValue'),
    slippage = Slippage(value=0.0, unit='perValue'))
        }
        def initialize(context):                # 初始化策略运行环境
          pass
        def handle_data(context):               # 核心策略逻辑
          stock_account = context.get_account('security_account')

· 多个账户配置,commission、slippage表示可以对多账户进行全局配置,示例代码如下:

        start = '2018-01-01'                    # 回测起始时间
        end = '2019-01-01'                      # 回测结束时间
        universe = DynamicUniverse('HS300') + ['IFM0']  # 证券池,支持股票、基金、期货
        benchmark = 'HS300'                     # 策略参考基准
        # 策略类型,'d’表示日间策略使用日线回测,'m’表示日内策略使用分钟线回测
        freq = 'd'
        refresh_rate = 1                        # 执行handle_data的时间间隔
        # 对两个账户进行全局的交易费用和滑点设置
        commission = Commission(buycost=0.001, sellcost=0.002, unit='perValue')
        slippage = Slippage(value=0.0, unit='perValue')
        accounts = {
          'security_account1': AccountConfig(account_type='security', capital_
    base=10000000, position_base = {'600000.XSHG':1000}, cost_base = {'600000.
    XSHG':10.05}, commission = commission, slippage = slippage),
          'security_account2': AccountConfig(account_type='security', capital_
    base=20000000, position_base = {'600000.XSHG':2000}, cost_base = {'600000.
    XSHG':10.05}, commission = commission, slippage = slippage)
        }
        def initialize(context):                # 初始化策略运行环境
          pass
        def handle_data(context):               # 核心策略逻辑
          account1 = context.get_account('security_account1')
          account2 = context.get_account('security_account2')

· 股票、期货混合账户配置,示例代码如下:

        start = '2018-01-01'                    # 回测起始时间
        end = '2019-01-01'                      # 回测结束时间
        universe = DynamicUniverse('HS300') + ['IFM0']  # 证券池,支持股票、基金、期货
        benchmark = 'HS300'                     # 策略参考基准
        # 策略类型,'d’表示日间策略使用日线回测,'m’表示日内策略使用分钟线回测
        freq = 'd'
        refresh_rate = 1                        # 执行handle_data的时间间隔
        accounts = {
          'security_account': AccountConfig(account_type='security', capital_
    base=10000000, position_base = {'600000.XSHG':1000}, cost_base = {'600000.
    XSHG':10.05},   commission   =   Commission(buycost=0.001,   sellcost=0.002,
    unit='perValue'), slippage = Slippage(value=0.0, unit='perValue')),
          'futures_account': AccountConfig(account_type='futures', capital_base=
    10000000, commission = Commission(buycost=0.001, sellcost=0.002, unit='perValue'),
    slippage = Slippage(value=0.0, unit='perValue'), margin_rate = 0.1)
        }
        def initialize(context):                # 初始化策略运行环境
          pass
        def handle_data(context):               # 核心策略逻辑
          account1 = context.get_account('security_account')
          account2 = context.get_account('futures_account')

3.5.2 AccountConfig账户配置

对单个交易账户进行配置。策略在初始化时会根据账户配置,需要创建对应的交易账户。AccountConfig账户配置参数如下。

· 必选参数:account_type、capital_base。

· 可选参数:position_base、cost_base、commission、slippage。

· 期货专用参数:margin_rate。

· 场外基金专用参数:dividend_method。

1.account_type

account_type表示设置交易账户的类型。

参数类型:str。包括4个值,即’security’表示股票和场内基金、'futures’表示期货、'otc_fund'表示场外基金(不含货币基金), 'index’表示指数。

示例代码如下:

        account_type = 'security'

2.capital_base

capital_base表示设置交易账户的初始资金。

参数类型:float或int。

示例代码如下:

        capital_base = 100000

3.position_base

position_base表示设置交易账户的初始持仓(仅适用于配置股票账户)。

参数类型:dict。包括两个值,即key为股票代码、value为数量。

示例代码如下:

        # 初始持仓:1000股平安银行,2000股浦发银行
        position_base =  {'000001.XSHE':1000, '600000.XSHG':2000}

4.cost_base

cost_base表示设置交易账户的初始成本(仅适用于配置股票账户)。

参数类型:dict。包括两个值,即key为股票代码、value为成本。

示例代码如下:

        # 初始持仓成本:平安银行为12.30元,浦发银行为11.50元
        cost_base =  {'000001.XSHE':12.30, '600000.XSHG':11.50}

5.commission

commission表示交易手续费。

参数说明如下。

· buycost表示买入成本。

参数类型:float。

· sellcost表示卖出成本。

参数类型:float。

· unit表示手续费单位。

参数类型:str。

unit参数包括如下两个值。

➢ perValue:按成交金额的百分比收取手续费。

➢ perShare:按成交的股数收取手续费(仅用于配置期货账户)。

示例代码如下:

    # 按成交金额的百分比收取买入0.3‰,卖出2‰的费用
    commission = Commission(buycost = 0.0003, sellcost = 0.002, unit = 'perValue')

6.slippage

slippage用于设置交易滑点标准,并处理市场冲击问题。

参数说明如下。

· value:策略进行交易时的滑点值。

参数类型:float。

· unit:计算滑点的方式,分为固定滑点和百分比滑点两种计算方式。

参数类型:str。

unit参数包括如下两个值。

➢ perValue:百分比滑点。按股价百分比进行滑点调整,滑点设置后买入价格调整为“股价×(1+滑点值)”,卖出价格调整为“股价×(1-滑点值)”。

➢ perShare:固定滑点。按每股股价进行滑点调整,最小单位是0.01,表示0.01元;滑点设置后买入价格调整为“股价+滑点值”,卖出价格调整为“股价-滑点值”。

示例代码如下:

    # 将滑点设置成百分比滑点0.001
    slippage = Slippage(value=0.001, unit='perValue')

7.margin_rate

margin_rate用于设置保证金率,仅用于期货策略。

参数类型:float或dict。支持如下两种设置方法。

全局设置方法:为所有品种设置同一个保证金率(通常在只回测一个品种的时候,这种方法比较常见)。

根据品种设置:为某个或某些品种设置特定的保证金率。

示例代码如下:

        margin_rate = 0.1
        margin_rate = {'IF': 0.16, 'RB': 0.1}

8.dividend_method

dividend_method用于设置基金分红方式,仅用于场外基金策略。

参数类型:str。包括两个值,即’cash_dividend’表示现金分红,'reinvestment’表示红利再投。

示例代码如下:

        dividend_method='cash_dividend'

3.6 策略基本方法

1.initialize策略初始化函数

策略初始化函数示例代码如下:

        def initialize(context)

策略初始化函数用于配置策略运行环境context对象的属性或自定义各种变量。在策略运行周期中只执行一次。可以通过给context添加新的属性,从而自定义各种变量。

context在策略运行(回测或模拟交易)启动时被创建,持续整个策略的生命周期。策略在运行时可以读取context的已有系统属性或自定义属性。

2.handle_data策略运行逻辑

策略运行逻辑的示例代码如下:

        def handle_data(context)

3.post_trading_day盘后处理函数

在每天运行策略结束时,可以使用post_trading_day函数进行盘后操作,比如进行当日交易总结、预计算因子值等操作。

post_trading_day()函数的参数为context,示例代码如下:

        start = '2019-01-01'                        # 回测起始时间
        end = '2019-01-05'                          # 回测结束时间
        universe = ['600000.XSHG']                  # 证券池,支持股票、基金、期货
        benchmark = 'HS300'                         # 策略参考基准
        # 策略类型,'d’表示日间策略使用日线回测,'m’表示日内策略使用分钟线回测
        freq = 'd'
        refresh_rate = 1                            # 执行handle_data的时间间隔
        accounts = {
            'stock_account': AccountConfig(account_type='security', capital_base=
    10000000, position_base = {'600000.XSHG':1000}, cost_base = {'600000.XSHG':
    10.05})
        }
        def initialize(context):                    # 初始化策略运行环境
            pass
        def handle_data(context):                   # 核心策略逻辑
            stock_account = context.get_account('stock_account')
            current_universe = context.get_universe('stock', exclude_halt=True)
            for stk in current_universe:
              stock_account.order_to(stk, 100)
        def post_trading_day(context):
            print context.now

3.7 策略运行环境

context表示策略运行环境,包含运行时间、行情数据等内容,还可以用于存储策略中生成的临时数据。策略框架会在启动时创建context的对象实例,并以参数形式传递给initialize(context)和handle_data(context),用于策略调度。

在回测时,context包含运行时间、回测参数、回测运行时数据等。在模拟交易时,包含运行时间、模拟交易参数、实时运行数据等。

3.7.1 now

now表示获取策略运行时的当前时刻,示例代码如下:

        context.now

返回类型:datetime。

用法:只能在handle_data方法中使用,并且不允许修改。

例如,获取分钟线策略运行时的当前时刻,代码如下:

        start = '2019-01-04'                # 在2019年1月4日开始回测
        end = '2019-01-04'                  # 在2019年1月4日结束回测
        freq = 'm'
        refresh_rate = (1, 2)
        accounts = {
          'stock_account': AccountConfig(account_type='security', capital_base=
    10000000)
        }
        def initialize(context):            # 初始化策略运行环境
          pass
        def handle_data(context):           # 核心策略逻辑
          stock_account = context.get_account('stock_account')
          print context.now

每个交易日的每2分钟都有调仓,下面展示了部分调仓时间:

        2019-01-04 09:30:00
        2019-01-04 09:32:00
        2019-01-04 09:34:00
        ...
        2019-01-04 14:56:00
        2019-01-04 14:58:00

3.7.2 current_date

current_date表示获取策略运行的当前日期,示例代码如下:

        context.current_date

context.current_date和context.now的区别为:当进行日线频率回测时,两者结果完全一致,当进行分钟线频率回测时,context.now包含小时、分钟等一个交易日内的时间信息,而context.current_date不包含。

返回类型:datetime。

用法:只能在handle_data方法中使用,并且不允许修改。

例如,获取策略运行时的当前日期,代码如下:

        start = '2019-01-01'                # 在2019年1月1日开始回测
        end = '2019-02-01'                  # 在2019年2月1日结束回测
        freq = 'd'
        refresh_rate = 1
        accounts = {
          'stock_account': AccountConfig(account_type='security', capital_base=
    10000000)
        }
        def initialize(context):            # 初始化策略运行环境
          pass
        def handle_data(context):           # 核心策略逻辑
          stock_account = context.get_account('stock_account')
          print context.current_date

下面展示了部分调仓日期:

        2019-01-03 00:00:00
        2019-01-04 00:00:00
        2019-01-05 00:00:00
        ...
        2019-01-25 00:00:00
        2019-01-26 00:00:00

3.7.3 previous_date

previous_date表示获取当前回测日期的前一交易日数据,示例代码如下:

        context.previous_date

返回类型:datetime。

用法:只能在handle_data方法中使用,并且不允许修改。同current_date一致。

3.7.4 current_minute

current_minute表示获取当前运行时的分钟值,如果在分钟线策略中使用,建议用context.now替换。示例代码如下:

        context.current_minute

返回类型:str,如10:00。

用法:只能在handle_data方法中使用,并且不允许修改。

输出结果的格式如下:

        09:30

3.7.5 current_price

current_price表示获取当前的参考价格,即最后成交价。在开盘前运行,获得的是前一天的收盘价;在盘中运行,获得的是最后一次的成交价。示例代码如下:

        context.current_price(symbol)

参数为symbol,即想要获取的价格的证券,参数需要在之前定义的universe中存在。

参数类型:str。

返回类型:float,表示最后一刻的价格。

例如,获取平安银行前一天的收盘价,代码如下:

        start = '2019-01-01'                # 回测起始时间
        end = '2019-01-04'                  # 回测结束时间
        universe = ['000001.XSHE']          # 证券池,支持股票、基金、期货
        benchmark = 'HS300'                 # 策略参考基准
        # 策略类型,'d’表示日间策略使用日线回测,'m’表示日内策略使用分钟线回测
        freq = 'd'
        refresh_rate = 1                    # 执行handle_data的时间间隔
        accounts = {
            'stock_account': AccountConfig(account_type='security', capital_base=
    10000000)
        }
        def initialize(context):            # 初始化策略运行环境
            pass
        def handle_data(context):           # 核心策略逻辑
            stock_account = context.get_account('stock_account')
            print context.current_price('000001.XSHE')

输出结果如下:

        9.38
        9.19
        9.28

3.7.6 get_account

get_account表示获取交易账户。例如,获取账户名称为account_name的交易账户,代码如下:

        context.get_account(account_name)

参数:account_name,表示策略初始化时设置的账户名称。

参数类型:str。

返回交易账户对象。

示例代码如下:

        start = '2019-01-01'                # 回测起始时间
        end = '2019-01-04'                  # 回测结束时间
        universe = ['000001.XSHE']          # 证券池,支持股票、基金、期货
        benchmark = 'HS300'                 # 策略参考基准
        # 策略类型,'d’表示日间策略使用日线回测,'m’表示日内策略使用分钟线回测
        freq = 'd'
        refresh_rate = 1                    # 执行handle_data的时间间隔
        accounts = {
            'account_name': AccountConfig(account_type='security', capital_base=
    10000000)
        }
        def initialize(context):            # 初始化策略运行环境
            pass
        def handle_data(context):           # 核心策略逻辑
            stock_account = context.get_account('account_name')

3.7.7 get_universe

get_universe表示获取当前交易日的证券池,是策略初始化参数中universe的子集。在这种配置情况下,context.get_universe()仅体现资产的上市状态,只要资产在策略运行当天处于上市状态,就可通过context.get_universe()获取当前交易日的证券池。支持多种资产类型。示例代码如下:

        context.get_universe(asset_type, exclude_halt=False)

参数说明如下。

· asset_type,表示资产类型。

参数类型:str。

参数值包括’stock’表示股票列表、'index’表示指数成分股列表、'exchange_fund’表示场内基金列表、'otc_fund’表示场外基金列表、'futures’表示期货合约列表、'base_futures’表示普通期货合约列表、'continuous_futures’表示连续期货合约列表。

· exclude_halt,表示去除资产池中的停牌股票,仅适用于股票,默认值为False。

参数类型:布尔型。

返回类型:list,符合筛选条件的当天上市状态的证券池,返回的列表中可能有部分资产处于停盘等不可交易状态。

例如,获取上证50股票剔除停牌股票后的股票池,代码如下:

        start = '2019-01-01'                # 回测起始时间
        end = '2019-01-03'                  # 回测结束时间
        universe = DynamicUniverse('SH50') # 证券池,支持股票、基金、期货
        benchmark = 'HS300'                 # 策略参考基准
        # 策略类型,'d’表示日间策略使用日线回测,'m’表示日内策略使用分钟线回测
        freq = 'd'
        refresh_rate = 1                    # 执行handle_data的时间间隔
        accounts = {
            'stock_account': AccountConfig(account_type='security', capital_base=
    10000000)
        }
        def initialize(context):            # 初始化策略运行环境
            pass
        def handle_data(context):           # 核心策略逻辑
            current_universe = context.get_universe('stock', exclude_halt=True)
            print current_universe

部分输出结果如下:

        ['600000.XSHG', '600016.XSHG', '600019.XSHG', '600028.XSHG', '600029.
    XSHG', '600036.XSHG'...'603993.XSHG']

又如,分别获取沪铜1810、沪深300期货当月对应的期货合约列表、普通期货合约列表、连续期货合约列表的代码如下:

        start = '2018-01-01'                # 回测起始时间
        end = '2019-01-01'                  # 回测结束时间
        universe = ['CU1810', 'IFL0']       # 证券池,支持股票、基金、期货
        benchmark = 'HS300'                 # 策略参考基准
        # 策略类型,'d’表示日间策略使用日线回测,'m’表示日内策略使用分钟线回测
        freq = 'd'
        refresh_rate = 1            # 执行handle_data的时间间隔
        accounts = {
          'futures_account': AccountConfig(account_type='futures', capital_base=
  10000000)
      }
      def initialize(context):   # 初始化策略运行环境
          pass
      def handle_data(context):  # 核心策略逻辑
          print context.get_universe('futures')
          print context.get_universe('base_futures')
          print context.get_universe('continuous_futures')

部分输出结果如下:

      ['CU1810', 'IFL0']
      ['CU1810']
      ['IFL0']
      ...

3.7.8 transfer_cash

transfer_cash用于实现账户间的资金划转,示例代码如下:

      context.transfer_cash(origin, target, amount)

参数说明如下。

· origin:资金流出的账户名称。

参数类型:str。

· target:资金流入的账户名称。

参数类型:str。

· amount:划转的资金量。

参数类型:float。

示例代码如下:

      start = '2019-01-01'                    # 回测起始时间
      end = '2019-01-10'                      # 回测结束时间
      universe = ['000001.XSHE', 'IFM0']      # 证券池,支持股票、基金、期货
      benchmark = 'HS300'                     # 策略参考基准
      # 策略类型,'d’表示日间策略使用日线回测,'m’表示日内策略使用分钟线回测
      freq = 'd'
      refresh_rate = 1                        # 执行handle_data的时间间隔
      accounts = {
          'stock_account': AccountConfig('security', capital_base=1e6),
          'futures_account': AccountConfig('futures', capital_base=1e6)
      }
      def initialize(context):                # 初始化策略运行环境
          pass
      def handle_data(context):
          stock_account = context.get_account('stock_account')
          futures_account = context.get_account('futures_account')
          if context.current_date.strftime('%Y-%m-%d') == '2017-01-05':
              context.transfer_cash(origin=stock_account, target=futures_account,
  amount=1e5)
              assert stock_account.cash, futures_account.cash == (900000, 1100000)
              assert stock_account.portfolio_value + futures_account.portfolio
  _value == 2000000
          if context.current_date.strftime('%Y-%m-%d') == '2017-01-06':
              context.transfer_cash(origin=futures_account, target=stock_account,
  amount=2e5)
              assert stock_account.cash, futures_account.cash == (1100000, 900000)
              assert stock_account.portfolio_value + futures_account.portfolio_
  value == 2000000

3.8 获取和调用数据

3.8.1 history

history用于获取指定证券的历史行情、因子等时间序列数据,示例代码如下:

      context.history(symbol, attribute=['closPrice'], time_range=1, freq='1d',
  style='sat', rtype='frame')

参数说明如下。

· symbol:需要获取的数据的证券列表,支持单个证券或证券列表,必须是初始化参数universe涵盖的证券范围。

参数类型:str或list。

· attribute:需要获取的属性,支持单个属性或属性列表。

参数类型:str或list。

资产类型可选参数说明如表3-5(日线数据)和表3-6(分钟线数据)所示。

表3-5

表3-6

· time_range:需要回溯的历史K线条数,和freq属性相对应。日线数据默认最大值为30,分钟线数据默认最大值为240,可以使用max_history_window设置最大限度取值范围。

参数类型:int。

· freq:K线图周期。

参数类型:str。

参数用法如下。

➢ 日线K线图:1d。

➢ 分钟线K线图:1m、5m、15m、30m、60m。

· style:数据返回的格式。参数值包括ast、sat、tas 3种。a表示attribute, s表示symbol, t表示time,它们分别对应3个维度呈现的顺序。例如,ast表示返回的字典中的键是attribute,其值是列为symbol、行为time的DataFrame,以此类推。

参数类型:str。

不同资产对象支持的参数如表3-7(日线数据)和表3-8(分钟线数据)所示。

表3-7

表3-8

可以同时获取多个品种资产对应的所有支持数据,当包含期货品种时,数据返回类型必须为style = 'sat'。

· rtype:返回值的数据类型。

参数类型:str。包括两个值,即’frame'、'array'。

返回类型:dict。key为资产符号,value的格式由rtype来决定。

以日线数据可以获取单个品种资产对应的所有支持的数据为例,资产类型可以是股票(含场内基金)、期货、场外基金、指数。获取日线数据时需要将回测初始化参数中的freq的值设置为d, refresh_rate的值设置为整数,代码如下:

        # 取平安银行向前10个交易日的日线数据
        start = '2019-01-01'                # 回测起始时间
        end = '2019-02-01'                  # 回测结束时间
        universe = ['000001.XSHE']          # 证券池,支持股票、基金、期货
        benchmark = 'HS300'                 # 策略参考基准
        # 策略类型,'d’表示日间策略使用日线回测,'m’表示日内策略使用分钟线回测
        freq = 'd'
        refresh_rate = 1                # 执行handle_data的时间间隔
        accounts = {
          'stock_account': AccountConfig(account_type='security', capital_base=
    10000000)
        }
        def initialize(context):       # 初始化策略运行环境
          pass
        def handle_data(context):      # 核心策略逻辑
          stock_account = context.get_account('stock_account')
          data = context.history(['000001.XSHE'], ['openPrice', 'highPrice',
    'lowPrice', 'closePrice', 'preClosePrice', 'turnoverVol', 'turnoverValue',
    'adjFactor'], 10, freq='1d', rtype='frame', style='sat')
          print data

部分输出结果如下:

        {'000001.XSHE': closePrice turnoverValue turnoverVol lowPrice highPrice \
        2018-12-17 10.29 5.846795e+0857127487.0 10.10 10.33
        2018-12-18 10.12 5.471576e+0853774430.0 10.10 10.32
        2018-12-19 9.94 6.000902e+0859800701.0 9.90 10.18
        2018-12-20 9.71 9.642029e+0899028479.0 9.63 9.97
        2018-12-21 9.45 9.444603e+08100061676.0 9.33 9.70
        2018-12-24 9.42 4.771869e+0850911767.0 9.31 9.45
        2018-12-25 9.34 5.452356e+0858661545.0 9.21 9.43
        2018-12-26 9.30 3.932151e+0842114060.0 9.27 9.42
        2018-12-27 9.28 5.863438e+0862459327.0 9.28 9.49
        2018-12-28 9.38 5.415710e+0857660400.0 9.31 9.46
        openPrice adjFactor preClosePrice
        2018-12-17 10.16 1.0 10.17
        2018-12-18 10.20 1.0 10.29
        2018-12-19 10.14 1.0 10.12
        2018-12-20 9.92 1.0 9.94
        2018-12-21 9.68 1.0 9.71
        2018-12-24 9.40 1.0 9.45
        2018-12-25 9.29 1.0 9.42
        2018-12-26 9.35 1.0 9.34
        2018-12-27 9.45 1.0 9.30
        2018-12-28 9.31 1.0 9.28 }
        ...

以日线数据同时获取多个品种资产的数据,并且只能选择多种资产共用的参数为例,代码如下:

        # 取平安银行和期货主力合约向前10个交易日的日线数据
        start = '2019-01-01'                    # 回测起始时间
        end = '2019-02-01'                      # 回测结束时间
        universe = ['000001.XSHE', 'IFM0']      # 证券池,支持股票、基金、期货
        benchmark = 'HS300'                     # 策略参考基准
        # 策略类型,'d’表示日间策略使用日线回测,'m’表示日内策略使用分钟线回测
        freq = 'd'
        refresh_rate = 1                # 执行handle_data的时间间隔
        accounts = {
          'stock_account': AccountConfig(account_type='security', capital_base=
    10000000)
        }
        def initialize(context):        # 初始化策略运行环境
          pass
        def handle_data(context):       # 核心策略逻辑
          stock_account = context.get_account('stock_account')
          data = context.history(['000001.XSHE', 'IFM0'], ['openPrice',
    'highPrice', 'lowPrice', 'closePrice', 'preClosePrice', 'turnoverVol',
    'turnoverValue', 'adjFactor'], 10, freq='1d', rtype='frame', style='sat')
          print data

以分钟线数据获取单个品种资产对应的所有支持的数据为例,可以是股票(含场内基金)、期货、指数。获取分钟线数据时需要将回测初始化参数中的freq的值设置为m, refresh_rate的值设置为(a, b)结构,如需帮助可以查看freq和refresh_rate,代码如下:

        # 取平安银行向前10条1分钟K线的分钟线数据
        start = '2019-01-01'                    # 回测起始时间
        end = '2019-01-05'                      # 回测结束时间
        universe = ['000001.XSHE']              # 证券池,支持股票、基金、期货
        benchmark = 'HS300'                     # 策略参考基准
        # 策略类型,'d’表示日间策略使用日线回测,'m’表示日内策略使用分钟线回测
        freq = 'm'
        refresh_rate = (1, 30)          # 执行handle_data的时间间隔
        max_history_window = (10, 300)
        # 分钟线默认最大向前获取240条K线,如果要获取更多,请设置max_history_window=(日线
    条数,分钟线条数)
        accounts = {
          'stock_account': AccountConfig(account_type='security', capital_base=
    10000000)
        }
        def initialize(context):        # 初始化策略运行环境
          pass
        def handle_data(context):       # 核心策略逻辑
          stock_account = context.get_account('stock_account')
          data = context.history(['000001.XSHE'], ['openPrice', 'highPrice',
    'lowPrice', 'closePrice', 'turnoverVol', 'turnoverValue'], 10, freq='1m',
    rtype='frame', style='sat')
          print data

部分输出结果如下:

        {'000001.XSHE': closePrice highPrice lowPrice openPrice turnoverValue \
    tradeTime
        2019-01-04 14:21 9.68 9.69 9.66 9.663890507.74
        2019-01-04 14:22 9.67 9.69 9.67 9.692936305.80
        2019-01-04 14:23 9.69 9.70 9.68 9.684796156.30
        2019-01-04 14:24 9.68 9.69 9.67 9.692680228.00
        2019-01-04 14:25 9.68 9.70 9.68 9.682173928.00
        2019-01-04 14:26 9.69 9.70 9.69 9.694548130.00
        2019-01-04 14:27 9.70 9.70 9.68 9.692600399.00
        2019-01-04 14:28 9.71 9.71 9.69 9.693516762.00
        2019-01-04 14:29 9.73 9.73 9.70 9.704719750.60
        2019-01-04 14:30 9.72 9.73 9.72 9.725949170.00
        turnoverVol tradeTime
        2019-01-04 14:21402082.0
        2019-01-04 14:22303220.0
        2019-01-04 14:23495200.0
        2019-01-04 14:24276700.0
        2019-01-04 14:25224400.0
        2019-01-04 14:26469000.0
        2019-01-04 14:27268300.0
        2019-01-04 14:28362460.0
        2019-01-04 14:29485660.0
        2019-01-04 14:30611900.0 }

取平安银行和期货主力合约向前10条15分钟K线的分钟线数据,示例代码如下:

        # 取平安银行和期货主力合约向前10条15分钟K线的分钟线数据
        start = '2019-01-01'                    # 回测起始时间
        end = '2019-01-05'                      # 回测结束时间
        universe = ['000001.XSHE', 'IFM0']      # 证券池,支持股票、基金、期货
        benchmark = 'HS300'                     # 策略参考基准
        # 策略类型,'d’表示日间策略使用日线回测,'m’表示日内策略使用分钟线回测
        freq = 'm'
        refresh_rate = (1, 15)                  # 执行handle_data的时间间隔
        accounts = {
          'stock_account': AccountConfig(account_type='security',
    capital_base=10000000)
        }
        def initialize(context):                # 初始化策略运行环境
          pass
        def handle_data(context):              # 核心策略逻辑
          stock_account = context.get_account('stock_account')
          data = context.history(['000001.XSHE', 'IFM0'], ['openPrice',
    'highPrice', 'lowPrice', 'closePrice', 'turnoverVol', 'turnoverValue'], 10,
    freq='15m', rtype='frame', style='sat')
         print data

1.max_history_window

在使用context.history获取数据时,默认对日线支持30个交易日数据,分钟线支持240条K线数据,当回溯长度超出范围时需要手动指定。因为回溯时间变长会影响回测速度,所以尽量不要取过长的回溯长度。

max_history_window的用法如下:

        max_history_window = 40             # 设置日线数据回溯长度为向前40个交易日
        # 设置分钟线数据回溯长度为向前300条K线、20个交易日的K线长度
        max_history_window = (20, 300)

2.获取因子数据

可以直接使用context.history获取因子数据。

用法:如下示例注册了PE、PB两个因子来获取因子数据:

        start = '2019-01-01'                # 回测起始时间
        end = '2019-03-01'                  # 回测结束时间
        universe = ['000001.XSHE']          # 证券池,支持股票、基金、期货
        benchmark = 'HS300'                 # 策略参考基准
        # 策略类型,'d’表示日间策略使用日线回测,'m’表示日内策略使用分钟线回测
        freq = 'd'
        refresh_rate = 1                    # 执行handle_data的时间间隔
        accounts = {
          'stock_account': AccountConfig(account_type='security', capital_base=
    10000000)
        }
        def initialize(context):            # 初始化策略运行环境
            pass
        def handle_data(context):           # 核心策略逻辑
          stock_account = context.get_account('stock_account')
          data  =  context.history(['000001.XSHE'],  ['PE',  'PB'],  5,  freq='1d',
    rtype='frame', style='sat')
          print data

返回的部分结果如下:

        {'000001.XSHE': PB PE
        2019-02-21 0.9061 7.9641
        2019-02-22 0.9204 8.0903
        2019-02-25 1.0010 8.7983
        2019-02-26 0.9731 8.5530
        2019-02-27 0.9890 8.6932}
        {'000001.XSHE': PB PE
        2019-02-22 0.9204 8.0903
        2019-02-25 1.0010 8.7983
        2019-02-26 0.9731 8.5530
        2019-02-27 0.9890 8.6932
        2019-02-28 0.9858 8.6651}

3.8.2 get_symbol_history

get_symbol_history用于获取指定证券的历史行情、因子等时间序列数据,示例代码如下:

        context.get_symbol_history(symbol, time_range=1, attribute=
    ['closePrice'], freq='1d', style='sat', rtype='frame')

参数说明如下。

· symbol:需要获取的数据的证券列表,支持单个证券或证券列表,必须是初始化参数universe涵盖的证券范围。

参数类型:str。

· time_range:需要回溯的历史K线条数,和freq属性相对应。日线数据默认最大值为30,分钟线数据默认最大值为240,可以使用max_history_window设置最大限度取值范围。

参数类型:int。

· attribute:需要获取的属性,支持单个属性或属性列表。

参数类型:str或list。

资产类型可选参数说明如表3-9(日线数据)和表3-10(分钟线数据)所示。

表3-9

表3-10

· freq:K线图周期。

参数类型:str。

参数用法如下。

➢ 日线K线图:1d。

➢ 分钟线K线图:1m、5m、15m、30m、60m。

· style:数据返回的格式。参数值包括ast、sat、tas 3种。a表示attribute, s表示symbol, t表示time,它们分别对应3个维度呈现的顺序。例如,ast表示返回的字典中的键是attribute,其值是列为symbol、行为time的DataFrame,以此类推。

参数类型:str。

不同资产对象支持的参数如表3-11(日线数据)和表3-12(分钟线数据)所示。

表3-11

表3-12

可以同时获取多个品种资产对应的所有支持数据,当包含期货品种时,数据返回类型必须为style = 'sat'。

· rtype:返回值的数据类型。

参数类型:str。包括两个值,即’frame'、'array'。

返回类型:dict。key为资产符号,value的格式由rtype决定。

3.8.3 get_attribute_history

get_attribute_history用于获取指定证券的历史行情、因子等时间序列数据,示例代码如下:

        context.get_attribute_history(attribute, time_range=1, symbol=None, freq=
    '1d', style='sat', rtype='frame')

参数说明如下。

· attribute:需要获取的属性,支持单个属性或属性列表。

参数类型:str。

可选参数说明如表3-13(日线数据)和表3-14(分钟线数据)所示。

表3-13

表3-14

· time_range:需要回溯的历史K线条数,和freq属性相对应。日线数据默认最大值为30,分钟线数据默认最大值为240,可以使用max_history_window设置最大限度取值范围。

参数类型:int。

· symbol:需要获取的数据的证券列表,支持单个证券或证券列表,必须是初始化参数universe涵盖的证券范围。

参数类型:str或list。

· freq:K线图周期。

参数类型:str。

参数用法如下。

➢ 日线K线图:1d。

➢ 分钟线K线图:1m、5m、15m、30m、60m。

· style:数据返回的格式。参数值包括ast、sat、tas 3种。a表示attribute, s表示symbol, t表示time,它们分别对应3个维度呈现的顺序。例如,ast表示返回的字典中的键是attribute,其值是列为symbol、行为time的DataFrame,以此类推。

参数类型:str。

参数用法如表3-15(日线数据)和表3-16(分钟线数据)所示。

表3-15

表3-16

可以同时获取多个品种资产对应的所有支持数据,当包含期货品种时,数据返回类型必须为style = 'sat'。

· rtype:返回值的数据类型。

参数类型:str。包括两个值,即’frame'、'array'。

返回类型:dict。key为资产符号,value的格式由rtype决定。

3.8.4 DataAPI

DataAPI是获取优矿提供的数据的主要方式,包含股票、基金、期货、指数、债券、基本面、宏观等多种数据。可以在Notebook中调用DataAPI对象的某个方法来获取特定的数据。