分享

股票回测引擎

 老匹夫 2019-11-13

股票回测引擎


欢迎使用MindGo量化交易平台,本文档详细介绍了MindGo平台的股票回测引擎,内容较多,您可通过Ctrl+F进行关键字搜索。

如果您在使用过程中遇到帮助中无法解答的问题,您可以:

  • 给我们发送邮件: mindgo@myhexin.com;

编写股票交易策略

  • step 1.导航栏中,依次点击"我的策略"—"策略创作"—"策略研究"

  • step 2.新建"股票期货"策略,点击进入"策略编辑"页面,如下图

  • step 3.左侧编译环境内使用python 3.5 实现策略逻辑

    交易股票:贵州茅台
    买入:5日均线上穿20日均线
    卖出:5日均线下穿20日均线
  • step 4.右侧选择回测时间区间,并进行回测

  • 策略源码:

#初始化账户
def init(context):
    g.index='600519.SH'

def handle_bar(context,bar_dict):
    close = history(g.index, ['close'], 20, '1d', False, fq = 'pre', is_panel=0)
    MA5 = close['close'].values[-5:].mean()   
    #计算二十日均线价格   
    MA20 = close['close'].values.mean()   
    #如果五日均线大于二十日均线   
    if MA5 > MA20:            
        #使用所有现金买入证券            
        order_target_percent(g.index,1)  
        #记录本次买入
        log.info("全仓买入{0}".format(g.index))
    #如果五日均线小于二十日均线           
    if MA5 < MA20 :            
        #卖出所有证券            
        order_target_percent(g.index,0)
        #记录本次卖出
        log.info("全仓卖出{0}".format(g.index))

回测环境

  • 回测引擎运行在Python3.5之上, 请您使用Python3.5来实现策略逻辑

  • 我们支持所有的Python标准库和部分常用第三方库, 具体请看: Python库

  • 同时,我们也支持自定义Python库,只需将您的.py文件存放于“我的研究”根目录, 即可在回测中直接调用, 具体说明请参见常见问题-如何调用自定义Python库?

  • 支持代码调试功能,具体请看:代码调试

编译运行


1.您的策略必须在init()和handle_bar()函数框架下实现:

  • init为初始化函数,用于初始一些全局变量,在整个回测过程最开始执行一次。

  • handle_bar为时间驱动函数,用于设置买卖条件等,每个回测时间频率(每日/分钟)调用一次。

2.完成策略编写后,选定回测开始日期和结束日期,选择初始资金、运行频率(每日或每分钟)等参数,点击"编译运行";

3.回测引擎根据您选择的运行频率调用handle_bar函数,也就是执行该函数下的代码。回测引擎会实时显示策略当前时间的数据,如收益、风险指标、持仓等信息;

4.回测引擎会根据您所使用的下单方式进行下单,并根据后续实际成交情况进行订单处理;

5.您可以在任何时候调用log.info函数来打印需要输出的日志;通过record函数输出自定义图形。

  • 添加log.info函数与record函数后的代码如下:

#初始化账户
def init(context):
    g.index='600519.SH'

def handle_bar(context,bar_dict):
    close = history(g.index, ['close'], 20, '1d', False, fq = 'pre', is_panel=0)
    MA5 = close['close'].values[-5:].mean()   
    #计算二十日均线价格   
    MA20 = close['close'].values.mean()
    #设置交易信号
    trade_signal=0
    #如果五日均线大于二十日均线   
    if MA5 > MA20:            
        #使用所有现金买入证券            
        order_target_percent(g.index,1)  
        #记录本次买入
        log.info("全仓买入{0}".format(g.index))
        #记录买入信号
        trade_signal=1
    #如果五日均线小于二十日均线           
    if MA5 < MA20 :            
        #卖出所有证券            
        order_target_percent(g.index,0)
        #记录本次卖出
        log.info("全仓卖出{0}".format(g.index))
        #记录卖出信号
        trade_signal=-1

    log.info(trade_signal)
    record(trade_signal=trade_signal)

策略回测

  • 如果策略能成功完成编译运行,则说明策略代码在指定历史区间是可运行的。

  • 一般而言,策略回测是将可运行的策略代码进行历史区间回测,并获取策略回测详情报告:交易明细、历史持仓、收益&风险指标分析、组合归因等。

  • 步骤1.将可运行的策略代码,点击"开始回测"

  • 步骤2.在策略详情页面,查看收益概况、交易明细、历史持仓及相关分析结果,如下图:

模拟交易

  • 顺利完成回测的策略,在回测详情页面,点击"开启仿真交易",即绑定模拟交易~ 

数据

MindGo提供海量优质的金融数据,以便您能实现策略逻辑

  • 股票数据、指数数据、基金数据、行情数据、财务数据、因子数据、行业数据、概念数据、商品期货数据、股指期货数据、外汇数据等等

  • 数据提取——详见股票API文档

  • 数据详情查看——详见数据文档

运行频率

  • 在"开始回测"左侧选择运行频率参数,参数分"每日"和"分钟"两种。

  • 选择"每日",则系统按"日回测"进行回测,即每个交易日09:30运行一次

  • 选择"分钟",则系统按"分钟回测"进行回测,即每个交易日内每分钟都会运行一次

运行时间


1.开盘前(9:00)运行:
  before_trading函数
2.盘中运行:
  handle_bar函数
   >日回测(9:31:00)运行一次 
   >分钟回测(9:31:00-11:30,13:01:00-15:00:00),每分钟运行一次 
   >tick回测(9:30:03-11:30,13:00:03-15:00:00),每3秒钟运行一次 
3.收盘后(15:30)运行:
  after_trading函数

佣金与印花税


  • 券商佣金默认值为万分之二点五,即0.025%,最少5元,双边收费;

  • 印花税默认值为千分之一,即0.1%,卖出时收费;

  • 您还可以通过set_commission来设置具体的手续费参数。

滑点


在实战交易中,往往最终成交价和预期价格有一定偏差,因此我们提供两种滑点模式来帮助您更好地模拟真实市场的表现:

  • 设置固定滑点,即最终成交价和委托价之差为固定值。

  • 设置可变滑点,即最终成交价和预期价格之比为固定百分比。默认为可变滑点0.2%,即买入成交价为委托价上浮0.1%,卖出成交价为委托价下调0.1%。

  • 默认无滑点,不过您可通过set_slippage函数来设置回测具体的滑点参数。

拆分合并与分红


当股票发生拆分,合并或者分红时,股价会出现跳空缺口,为了消除这种价格变化对回测结果的影响,我们会根据个股除权除息信息对账户中的现金或持股数量进行相应的调整修正,并自动更新到您的context信息中。
为了使回测结果更加准确,更加贴近实盘场景,我们做了如下处理:

  • 回测所用价格数据与下单所用价格数据是独立的。即在回测过程中,您可采用前复权/不复权或后复权价格来计算交易下单信号,回测引擎均采用真实价格(即不复权价格)下单;

  • 回测引擎会在除权除息当日,调用before_trading_start函数之前,自动处理并更新您的账户信息。

  • 前复权数据采用动态复权模式,即在回测过程中,轮循至某个股除权除息日,则按除权后价格对之前的价格数据进行调整。

订单处理


对于您在某个单位时间下的单,我们会做如下处理:

1.按天回测

 A.交易价格:
 >市价单:开盘价+滑点。
 >限价单:委托价。
 B.最大成交量:
 >默认为下单当日总成交量的25%,该比例可通过市场参与度函数set_volume_limit进行调整。
 >若下单量低于最大成交量,则按下单量成交;若下单量大于最大成交量,则按最大成交量成交。
 C.撮合方式:
 >市价单:开盘下单,一次性撮合,不成交或未成交部分不再撮合。
 >限价单:开盘下单,一次性撮合,不成交或未成交部分不再撮合。

2.分钟回测

 A.交易价格:
 >市价单:当前分钟起始价+滑点
 >限价单:委托价
 B.最大成交量:
 >默认为下单当前分钟总成交量的25%,该比例可通过市场参与度函数set_volume_limit进行调整。
 >若下单量低于最大成交量,则按下单量成交;若下单量大于最大成交量,则按最大成交量成交。
 C.撮合方式:
 >市价单:分钟起始点下单,一次性撮合,不成交或未成交部分即刻取消委托。
 >限价单:分钟起始点下单,之后每分钟均按分钟价量撮合一次,未成交部分顺延至下一分钟进行撮合,直到完全成交或者当天收盘为止。

3.注意:

  1.一天结束后, 所有未完成的订单会被取消。
  2.每次订单完成(完全成交)或者取消后,我们会根据成交量计算交易费(参见set_commission), 减少您的现金。

股票期货混合策略

  • 如果您的策略不仅有股票交易,而且还有商品期货和股指期货的交易,有关期货部分的回测引擎介绍,请查看期货回测引擎~

风险模型

  • 风险模型主要提供证券的风险预测与业绩归因的作用。在此过程中,风险模型需要对股票收益建立因子模型,对组合过去历史的收益来源进行归因,依据统计方法和经验对股票未来风险形成推断与预测。对风险的度量要满足灵活性,准确性等要求。风险模型使用标准差来度量风险,且统计特征清晰,随时间变化稳定。对风险的预测有很多种方式,MindGo风险模型建立在多因子模型的基础上,认为股票收益率与多个因子之间存在线性的关系,即:

r=α+βf+μ
其中:r为股票收益率向量,β为因子暴露,μ为特质收益,f为因子收益率
当股票特质收益率与公共因子不相关时,组合预期风险可以分解为公共因子解释的风险及特质风险:
wΣw′=wβΩβ′w′+wΔw′
其中:w为组合成份股权重,Ω为因子收益率的协方差矩阵,Δ为股票的特质风险矩阵,我们假设股票的特质风险之间也互不相关,所以Δ是一个对角矩阵
  • 风险模型当中的因子主要包括两个部分,风格因子与行业因子:

    行业因子:中信一级行业分类
    风格因子:市值,Beta,动量,估值,盈利,成长,杠杆,波动,非线性市值,流动性

  • 风险模型数据提取函数详见:get_stylefactor

组合优化器

组合优化器函数查询:OptimizePort,opt.add_constraint

优化方式
组合优化器优化方式暂定为三种:最大化夏普比(MVO)、最大化信息比率、效用最大化(剔除成本影响)优化方式后期持续增加,例如L-B模型、风险平价模型等常用的资产配置模型。

  • MVO算法
    公式: 

    使用最优化算法求解,使target最大。R为一系列个股预期收益值[r1,r2,...rn],n为股票数量,为函数输入参数项,可以选择使用历史平均收益作为预期收益,需输入股票代码。W为各个股票的权重,为优化器所要计算的未知量[w1,w2,...wn],n为股票数量。∑为个股协方差矩阵(nXn),使用个股历史涨跌幅计算,取数范围为前120个周期,例如日频数据,则选取前120个交易日的涨跌幅,如为周频,则使用日频数据进行转换。

  • 最大化信息比率
    公式:

    使用最优化算法求解,使target最大。R,W,∑定义同1.1.1中描述。Wb为个股在所选基准中所占的权重,为[wb1,wb2,...wbn],n为股票数量,当个股没有在基准中时,wb为0。基准可自由选择,作为函数输入项,默认为中证500。

  • 效用最大化
    公式:

    使用最优化算法求解,使target最大。R,W,∑定义同1.1中描述。γ 为风险厌恶系数,函数输入参数项,默认为0.5。λ为交易成本,函数输入参数项,默认为0。Wi,t-1 为股票初始权重,可自定义输入,也可选择初始权重都为0。

约束条件
目前暂定七个约束条件:换手率、跟踪误差、组合风险、个股权重、风格因子主动暴露、行业因子主动暴露、行业中性。

  • 换手率约束
    约束条件:
    Wi,t 为函数求解值,个股优化后的权重;Wi,t-1 为股票初始权重,可自定义输入,也可选择初始权重都为0。Uplimit为输入的换手率限制值,不可小于0,最大值为100(默认单位%)。

  • 跟踪误差
    约束条件:
    W和Wb为组合中的股票和基准中的股票做并集后的权重向量。例如组合中有股票A,B,C,基准包含的股票为A,B,D,则W和Wb两个向量都有四个元素[WA,WB,WC,WD]和[WbA,WbB,WbC,WbD],且WD和WbC 为0。[WA,WB,WC]为组合中股票的权重,为优化器所要求解的未知量[w1,w2,...wn],n为股票数量。∑为个股协方差矩阵(nXn),n为组合和基准股票的并集,算法同1.1.1中描述。基准可自由选择,作为函数输入项,默认为中证500。Downlimt和uplimit作为输入的跟踪误差上下限,downlimt不可小于0。

  • 组合风险
    约束条件:
    W为各个股票的权重,为优化器所要求解的未知量[w1,w2,...wn],n为股票数量。∑为个股协方差矩阵(nXn),计算同1.1中描述。Downlimt和uplimit作为输入的组合风险上下限,downlimt不可小于0。

  • 个股权重
    约束条件:
    可针对每个股票做单独的权重约束,downlimt和uplimt为所对应股票的权重上下限,可自由输入。函数输入项包含个股代码及所要约束的上下限值,输入的股票数量0<=w<=n(优化目标中所输入的股票总数)。每个股票需在优化目标中输入的股票列表中,否则报错。为内置权重约束,所有股票的权重值加起来等于1。

  • 风格因子主动暴露度
    约束条件:
    Downlimt和uplimit为自定义输入的某个因子的暴露度约束上下限,输入方式为因子名称、下限值、上限值。当前共有十个风格因子,如需针对全部因子做限制,则需要输入十个相对应的风格因子暴露度上下限值。Xstyle 为个股对该风格因子的暴露度,为[x1 style1,x2style1,...xnstyle1]该数据由风险模型模块计算得出(目前易源博每日会更新该数据)。W为各个股票的权重,为优化器所要求解的未知量[w1,w2,...wn]。

  • 行业因子主动暴露度
    约束条件:
    Downlimt和uplimit为自定义输入的某个行业因子的暴露度约束上下限,输入方式为行业因子名称、下限值、上限值。当前共有29个行业因子(中信一级),如需针对全部因子做限制,则需要输入29个相对应的行业因子暴露度上下限值。Xindustry 为个股对该行业的暴露度(即该个股是否属于该行业,属于为1,不属于为0)。W为各个股票的权重,为优化器所要求解的未知量[w1,w2,...wn]。 Windustry为该行业在基准中所占的权重,不是矩阵,为数值。

  • 行业中性
    约束条件:
    Xindustry 为个股对该行业的暴露度(即该个股是否属于该行业,属于为1,不属于为0)。W为各个股票的权重,为优化器所要求解的未知量[w1,w2,...wn]。
    Windustry为该行业在基准中所占的权重,不是矩阵,为数值。

组合归因

  • 什么是组合归因?

组合归因是对资产组合进行分析,将其回报和风险归到提前设定的可能的原因上。目前该功能可实现对股票型策略进行收益及风险拆分,主要分为Brinson分析和风格分析。
我们首先会对每一期的持仓表进行单期归因,然后将多期的结果使用进行累计。下面我们会介绍单期归因的算法和累计归因所得到的结果。

  • 如何使用组合归因

策略成功回测后,在回测详情页面点击组合归因功能,如下图:

组合归因详解

一、Brinson组合归因

Brinson 是目前最为人知的归因方案。除了需要组合持仓内容之外,还设定一个基准。最初的brinson模型是把收益拆解为行业选择收益、个股选择收益和交叉收益,我们在传统模型基础上做了进一步的扩展,拆分出配置收益和交易收益。

  • 1.1多期brinson收益分解

对于各个拆分收益的计算如下:


上述指标的计算只针对单期的brinson拆解,为了分析策略在一个周期里的收益归类,我们使用Carino简化因子调整。

Carino简化因子的计算方式如下:


Rt,bt为t期策略和基准的收益率;r,b为区间内策略和基准收益率。

使用简化因子对多期收益分解进行加和:


At,St,It为t期收益的分解项。

  • 1.2 行业绩效归因拆解

把收益按行业拆分,查看每个策略在每个行业是否带来了主动收益。图中主动收益展示的也是多期的收益率,通过Carino因子进行调整。主动风险计算的是多期主动风险的方差,衡量多期主动收益的稳定性。主动权重是统计整个回测区间内各行业主动权重的均值。

二、风格分析

  • 基于风格因子的归因是一种更为精细的归因方式。我们使用同花顺内部准备好的一系列风格因子及因子收益率,将组合的回报和风险分别划分到这些因子上,从而得到组合的投资风格。当前包含的风格因子有:

风格因子代码因子名称含义备注
betabeta上市公司与指数之间的协同性个股的Beta值,指数收益使用HS300
bp估值记账价值和市值的比值市净率=总市值/归属于母公司所有者权益合计
earnings_yield盈利分析师预测与过去财年收益统计
growth成长由销售额及盈利统计。
leverage杠杆上市公司的使用杠杆的情况。
liquidity流动性由交易量和频率不同而带来的收益
momentum动量能量性指标,表示相对强度从过去某一天开始,向过去再推504天,计算其每天的超额收益对数值,再针对这504天进行加权平均
non_linear_size非线性市值上市公司的规模处于中等的程度
size市值上市公司的规模,即该公司是大盘股的程度对数市值
volatility波动率对大盘偏离的不确定性
  • 风格归因效果图:

    其中主动收益是多期的收益率,通过Carino因子进行调整。主动风险计算的是多期主动风险的方差,衡量多期主动收益的稳定性。

  • 策略和基准风格对比图:

  • 衡量回测期内策略整体风格和基准的差异,点击特定的风格因子柱状图可查看策略及基准的历史风格变化,如下图:

  • 组合风格稳定性:

选取策略组合在回测期间的四个界面查看其当期的主动收益、主动风险及主动暴露度。相关的计算公式如下:



收益&风险指标—评定策略的优劣

策略收益率—Returns

策略年化收益率—Annualized Returns

基准收益率—Benchmark Returns

基准年化收益率—Annualized Benchmark Returns

超额收益率—Excess Return

非系统性风险—Alpha

系统风险—Beta

夏普比率—Sharpe

收益波动率—Volatility

信息比率—Information Ratio

最大回撤—Max Drawdown

索提诺比率—Sortino

跟踪误差—Tracking error

下行波动率—Downside Risk

调试功能

  • 程序能一次写完并正常运行的概率很小,基本不超过1%。总会有各种各样的bug需要修正。有的bug很简单,看看错误信息就知道,有的bug很复杂,我们需要知道出错时,哪些变量的值是正确的,哪些变量的值是错误的,因此,需要一整套调试程序的手段来修复bug。

    1.简单直接粗暴有效的方式是用print把可能有问题的变量打印出来看看,逐个检查,用print最大的坏处是将来还得删掉它,想想程序里到处都是print,运行结果也会包含很多垃圾信息。

    2.在策略编辑页面,MindGo提供代码调试功能,你可以采用这套完整的调试程序来修复程序bug

  • 如何启动调试程序?

  在策略编辑器左侧,点击"行号",设置断点后,点击"编译运行"启动调试程序。

  • 调试程序简介

    1.启动调试程序后,代码会自动运行到第一个断点处,如上图,第一个断点是行7,代码当前已运行完行7(行8还未运行)
    2.调试程序右上角显示的时间是回测系统的运行时间
    3.调试程序上方菜单栏,从左到右共6个按钮,分别为:恢复执行代码(跳至下一个断点),执行下一步(不运行函数),执行下一步(运行函数),跳出此函数,清空console,结束调试继续编译
    4.调试程序左侧即为console面板,右侧为监控属性面板
    5.1分钟内不使用调试程序,则自动关闭调试程序
    6.调试时,程序无视注释内容

  • 菜单栏按钮介绍

    1.恢复执行代码(跳至下一个断点):直接运行至下一个断点处
    2.执行下一步(不运行函数):运行下一行代码,如果下一行代码调用函数,则直接运行完该函数,接着准备下一行代码
    3.执行下一步(运行函数):运行下一行代码,如果下一行代码调用函数,则会进入函数内,执行函数内第一行代码
    4.跳出此函数:如果当前行处于函数中,则直接运行完该函数
    5.清空console:清空左侧console面板的所有内容
    6.结束调试继续编译:关闭调试程序,策略继续编译

  • 如何使用console面板?

    输入变量,“Enter”输出变量值(无法修改参数)
    变量之间运算,“Enter”输出结果
    判断变量是否满足条件,“Enter”输出结果 

  • 如何监控变量?

    调试程序右侧监控属性,点击"+添加",输入变量名,点击“完成”,即可进行监控 
    监控面板显示当前监控的变量及变量值,继续运行代码 
    运行代码的过程中,监控面板实时显示监控变量及变量值,便于您进行观察,不需要print打印函数来逐一输出。 

对比功能

一般而言,量化策略会存在一个或多个参数,在验证策略逻辑的过程中,宽客们往往会尝试用不同的参数进行回测,比如在2018年,对平安银行采用双均线策略,采用不同周期的两条均线会使策略收益截然不同哦~

如何启动回测对比?

策略回测列表中,选取相应的回测,点击左上角的对比按钮,即可启动~

如何使用回测对比?
  • 对比功能,包括:概况、累积收益、回撤、源码。

  • 其中概况页面,详细展示了所选回测的回测指标,我们以平安银行双均线策略为例,创建3组参数,分别为(5,20),(10,55),(20,60)。

  • 累积收益页面,详细展示了所选回测的收益走势,可以发现(20,60)参数组的累积收益较高,参数周期越短,交易次数越多,收益反而越差,可能与18年的暴跌行情相关。

  • 回撤页面,详细展示了所选回测的回撤情况,可以发现(20,60)参数组的回撤较低,参数周期越短,交易次数越多,回撤反而越大,可能与18年的暴跌行情相关。

  • 源码页面,详细展示了所选回测的源码,同时只能选取两个回测进行对比

python库

MindGo平台支持所有Python的基础库(https://docs./3.5/library/index.html),并支持目前流行的第三方库,例如NumPy,pandas,Ta-Lib,scikit-learn,TuShare等。主要模块介绍如下表所示。

库名版本简介网址
arch4.1提供了Univariate volatility模型,Bootstrapping和Multiple comparison procedureshttps://pypi./pypi/arch
beautifulsoup44.5.3Python的爬虫包https://pypi./pypi/beautifulsoup4/
cvxopt1.1.8提供了凸优化的解的Python库https://pypi./pypi/cvxopt/1.1.8
gensim0.13.4.1用于计算文本相似度http:///gensim/tutorial.html
hmmlearn0.2.0Python的隐马尔可夫模型模块,类似scikit-learn的APIhttps://github.com/hmmlearn/hmmlearn
jieba0.38Python的中文分词组件https://pypi./pypi/jieba
lasagne0.1Python深度学习库http://lasagne./en/latest/
matplotlib2.0.1Python 2D绘图函数库http:///contents.html
mpl_toolkits2.0.1Python 3D绘图函数库http:///mpl_toolkits/index.html
numpy1.12.1Python的数值计算扩展http://www./
pandas0.20.1Python的数据分析包http://pandas./pandas-docs/version/0.16.2/
pymc2.3.6机器学习中一个图模型库https://pypi./pypi/pymc/
pywt0.5.2Python的小波变换库https://pypi./pypi/PyWavelets
scipy0.19.0为科学和工程设计的Python工具包https://www./
seaborn0.7.1Python的统计数据可视化库http://seaborn./
sklearn0.18Python的机器学习模块http:///stable/
statsmodels0.8.0可以研究数据,构架统计模型和进行统计测试http://statsmodels./
talib0.4.10用来对金融市场的数据进行技术分析http://mrjbq7./ta-lib/funcs.html
theano0.8.2Python深度学习库http:///software/theano/
tensorflow1.1.0谷歌第二代人工智能学习系统http://www./
tushare0.7.5国内的开源数据库https://pypi./pypi/tushare/
xlrd1.0.0Python读取Excel的扩展工具https://pypi./pypi/xlrd/
xlwt1.1.2Python写入Excel文件的扩展工具https://pypi./pypi/xlwt/

为了保障MindGo平台的安全,以下的python包和功能已被禁用,如有不便敬请见谅:

属性和方法
os__builtins__
sys__import__
sixget_ipython
subprocessexec
pickleeval
socket
ast
IPython
ipykernel

【案例】MACD交易策略

#导入talib库
import talib
#初始化函数
def init(context):
    #输入股票代码
    g.security = '600519.SH' 
    #设置MACD模型参数
    #短周期平滑均线参数
    g.Short = 12
    #长周期平滑均线参数
    g.Long = 26 
    #DIFF的平滑均线参数
    g.M = 9 
#每日运行函数
def handle_bar(context, bar_dict):
    #调用MACD计算函数,获取MACD值
    macd = get_macd(g.security)
    #判断金叉,且无持仓
    if macd[-1]>0 and macd[-2]<0 and context.portfolio.market_value == 0:
        #执行全仓买入
        order_value(g.security,context.portfolio.available_cash)    
        #打印日志
        log.info("买入 %s" % (g.security))  
    #判断死叉,且有持仓
    if macd[-2]>0 and macd[-1]<0 and context.portfolio.market_value > 0:  
        #执行清仓
        order_target(g.security,0)    
        #打印日志
        log.info("卖出 %s" % (g.security))
#MACD计算函数
def get_macd(stock):
    #获取数据
    price = history(stock, ['close'], 500, '1d', True, 'pre', is_panel=1)['close']
    #talib库调用MACD计算方法
    DIFF, DEA, MACD = talib.MACD(price.values,
            fastperiod = g.Short, slowperiod = g.Long, signalperiod = g.M)
    #输出MACD值
    return MACD

【案例】三因子选股模型

import pandas as pd
import numpy as np
import datetime

def init(context):
    # 设置最大持股数
    context.max_stocks = 10 
    #记录天数,隔20个交易日调仓
    g.day = 0
def handle_bar(context, bar_dict):
    if g.day%20 !=0:
        return None
    g.day =  g.day +1
    # 每个调仓日先清仓持有的股票
    for security in list(context.portfolio.positions.keys()):
        order_target(security, 0)
    # 首先获得当前日期
    time = get_datetime()
    date = time.strftime('%Y%m%d')
    # 获得股票池列表
    sample = get_index_stocks('000300.SH',date)
    # 创建字典用于存储因子值
    df = {'security':[], 1:[], 2:[], 3:[], 'score':[]}
    # 因子选择
    for security in sample:
        q=query(
            profit.roic,# 投资回报率
            valuation.pb,# 市净率
            valuation.ps_ttm,# 市销率
        ).filter(
            profit.symbol==security
        )

        # 缺失值填充为0
        fdmt = get_fundamentals(q, date=date).fillna(0)

        # 判断是否有数据
        if (not (fdmt['profit_roic'].empty or
                fdmt['valuation_pb'].empty or
                fdmt['valuation_ps_ttm'].empty)):
            # 计算并填充因子值
            df['security'].append(security)
            df[1].append(fdmt['profit_roic'][0])# 因子1:投资回报率
            df[2].append(fdmt['valuation_pb'][0])# 因子2:市净率
            df[3].append(fdmt['valuation_ps_ttm'][0])#因子3:市销率

    for i in range(1, 4):
        # 因子极值处理,中位数去极值法
        m = np.mean(df[i])
        s = np.std(df[i])
        for j in range(len(df[i])):
            if df[i][j] <= m-3*s:
                df[i][j] = m-3*s
            if df[i][j] >= m+3*s:
                df[i][j] = m+3*s
        m = np.mean(df[i])
        s = np.std(df[i])

        # 因子无量纲处理,标准化法
        for j in range(len(df[i])):
            df[i][j] = (df[i][j]-m)/s

    # 计算综合因子得分
    for i in range(len(df['security'])):
        # 等权重计算(注意因子方向)
        s = (df[1][i]-df[2][i]-df[3][i])
        df['score'].append(s)

    # 按综合因子得分由大到小排序
    df = pd.DataFrame(df).sort_values(by ='score', ascending=False)

    # 等权重分配资金
    cash = context.portfolio.available_cash/context.max_stocks

    # 买入新调仓股票
    for security in df[:context.max_stocks]['security']:
        order_target_value(security, cash)

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多