精华内容
下载资源
问答
  • 机器学习量化多因子选股策略

    千次阅读 多人点赞 2019-07-25 14:25:23
    一、前言 多因子选股策略是一种应用十分广泛的选股策略,其基本思构想就是找到某些和收益率最相关的指标,找出股票收益率与各种指标之间的“关系”,借此“关系”建立股票组合,并期望该...机器学习和多因子选股...

    一、前言

    多因子选股策略是一种应用十分广泛的选股策略,其基本思构想就是找到某些和收益率最相关的指标,找出股票收益率与各种指标之间的“关系”,借此“关系”建立股票组合,并期望该组合可以跑赢指数。

    多因子回归是多因子选股策略最常用的方法,它用过去的股票的收益率对多因子进行回归,得到一个回归方程,然后把当下的因子数值代入回归方程得到未来股票的预期收益,最后以此为依据进行选股。

    机器学习和多因子选股策略的结合,从实践的角度来看,机器学习所做的工作是在现有因子的数据集上建立模型,对股票收益率进行拟合,然后对模型进行评估和优化。

    用机器学习做模型预测有一套基本流程:数据获取、数据预处理、模型训练、模型评估和模型预测。接下来本文沿着这套流程用python中的机器学习库sklearn完成一个简单的多因子回归的选股模型。

     

    二、获取数据

    机器学习所需数据主要有两个来源:网络爬虫和专业数据库,这里我们使用的数据为A股股票的历史数据,因此数据来源取自wind数据库。

    原始数据包含了所有A股股票——以2018/06/30当日的股票为准,时间段选取1998/04/30至2018/06/30,每个月度每只股票取数十个不同的指标,以月末最后一日的数据作为截面数据保存。

    由于数据过于冗杂,我们先对数据进行结构化降维,使用csv格式进行存储,每个月度的截面数据保存在一个csv文件中,文件名有序排列。每个csv文件中包含了该月份最后一日所有股票的部分基本信息、下一个月的收益率、和数十个指标因子的值。

     

    三、数据预处理

    首先是特征提取,特征提取这一步主要基于人的经验,对于指导股票投资的模型,则选取作出投资决策中经常考虑的一些数据指标。这里,我们选取以下几类指标进行考量:

    估值指标:营业收入、净利润、净资产等

    成长指标:营收同比增速、净利润同比增速等

    财务指标:毛利率、资产周转率、经营性现金流等

    杠杆指标:流动比率、现金比率等

    流动性指标:N日日均换手率等

    其他绝对指标:市值、股价、股东数、beta 等

    情绪指标:wind评级、wind一直目标价等

    技术指标:MACD、RSI、动量反转……

    特征因子的选取对于模型的拟合结果和预测准确度有很大影响,因此特征因子要精挑细选。以上指标都是市场中各类投资者经常考虑的指标的总结,有效性有待商议,现在先从wind中提取出这些指标。

    接下来是数据清洗,数据清洗需要做的是缺失值填充、数据标准化、数据降维等等。

    由于从wind中所取得的指标有限,而且原始数据因为未上市、停牌、涨跌停等多种原因产生了很多空值、不可使用的数据,这部分因子的数值需要进行缺失值填充;部分指标属于绝对值类指标,不同公司间差异性较大,类似营业收入、净利润、现金流等因子,换做与其市值的比值后横向可比性更强;其他有些数据也因为各种原因存在着去极值、标准化和降维等需要。

    下表为自1998年4月起的第244个月的csv文件部分截图,文件的列结构如下:

    第1列:当前文件所属月份

    第2列:wind股票代码

    第3列:交易状态,1为正常交易,0为ST/停牌/次新股

    第4列:下一个月超额收益率(相对于沪深300)

    5列后已完成数据预处理的特征因子70个

     

    四、模型训练

     1 、模块导入

    该模型依赖的模块主要有:numpy,pandas和sklearn。

    其中numpy是Python做数据处理常用的扩充程序库,主要用于支持高维数组与矩阵运算,同时针对数组运算提供大量的数学函数库;而pandas是基于numpy的高效数据模型库,由于为面板数据分析和时间序列分析提供了很好的支持,因此常备用作金融数据分析的基础工具包。

    sklearn全称是scikit-learn,是谷歌开发的一个机器学习框架,是python重要的机器学习库。sklearn支持包括分类、回归、降维和聚类四大机器学习算法,还包含了特征提取、数据处理和模型评估三大模块。sklearn建立在NumPy和matplotlib库的基础上,利用这几大模块的优势,大大提高机器学习的效率,是机器学习领域最知名的python模块之一。

    sklearn支持的机器学习方式:

    1.Classification 监督学习-分类(预测未来变化方向)

    2.Regression 监督学习-回归(预测未来变化幅度)

    3.Clustering 非监督学习-聚类(选取相近的样本)

    4.Dimensionality reduction 非监督学习-降维(选取有代表性的因子)

    5.Model Selection 模型选择(选择更好的模型)

    6.Preprocessing 数据预处理(如何选择特征,做预处理)

     2 、参数设置

    模型中所有参数都在这一部分进行定义,其中包含样本内数据集、样本外数据集、正反数据比例、验证集比例、随机数种子点、置信度、特征因子序列等等。具体参数如下:

    1.month_in_sample = range(1,141+1)    # 样本内数据月份范围

    2.month_test = range(142,243+1)        # 样本外数据月份范围

    3.percent_select = [0.2,0.2]            # 正例和反例数据的比例

    4.percent_cv = 0.1                       # 验证集比例

    5.seed = 45                             # 随机数种子点

    6.logi_C = 0.0005                        # 置信度

    7.n_stock = 3625                         # 现今股票数

    8.n_stock_select = 10                   # 选出股票数

    9.parameters = ('EP':'bias')   # 模型所使用的特征因子

    这里的参数后期都可以根据不同需要进行调整,以获得更有效的模型。

     3 、数据处理

    对于数据,使用经典的内外划分方式,将整体数据集244个月的A股月数据分为两部分:

    样本内数据,通过设定month_in_sample参数的值,选取1998年4月~2009年12月的数据,用于模型训练

    样本外数据,通过设定month_test参数的值,选取2010年1月~2018年6月的数据,用于模型预测

    对于样本内的数据,先进行数据的进一步清洗和整理,循环读取每一期的csv表:

    1.根据parameters参数,从csv文件中读取相关因子数据,并保存在临时表

    2.删除单元格有空值的股票

    3.加入标签项,根据次月超额收益对个股打标签

    4.根据percent_select的参数留下收益最高和最低的部分股票

    5.将收益最好的股票打标签1,收益最差的股票打标签0

    最终,得到的数据集data_in_sample为处理好的样本内数据集,可以用来进行模型训练,该数据集的部分截图展示如下。

    4 、模型训练

    模型训练前,先将样本内数据集再一次进行拆分,拆分为训练集和验证集,验证集的比例根据percent_cv参数确定,集合的拆分由train_test_split完成,因此具有随机性。

    根据拆分出的训练集,对模型进行训练,模型训练使用sklearn中的函数model.fit。这里可用的模型很多,包括线性回归模型、支持向量机模型、SGD模型等等。这里以线性回归模型为例,在置信度为logi_C的水平下进行线性回归,经过机器学习得到拟合后的model

    五、模型评估

    用此model对样本内数据集的训练集和验证集进行预测,sklearn中有专门的函数predict和decision_function对模型进行预测。

    这样可以得到预测的涨跌标签值以及涨跌的概率,通过将预测数据和真实数据进行比较,metrics中有专门的函数accuracy_score可以进行矩阵直接的比较,最终得到两矩阵的相似性,可以理解为模型预测的准确率。

    因此,若参数按上文中进行设置,可以得到的模型训练集的预测准确率为59%,验证集的预测准确度为58%,系统输出结果如下:

    training set: accuracy = 0.59

    cv set: accuracy = 0.58

    六、策略构建

    使用该model构建多因子选股策略:对于所有A股股票,以月度为频率,取parameters中定义的特征因子进行拟合,给出预测涨跌的概率,对预测涨跌概率进行排序,选取前n_stock_select个股票构建等权组合,进行买入。

    七、策略预测

    有了通过对训练集机器学习后确定的model,就可以对样本外的数据进行回测。在回测之前同样需要对样本外数据进行清洗和整理,然后按月循环带入model,给出每个月每只个股的涨跌预测以及涨跌概率的预测,并根据策略构建投资组合进行轮动。

    回测部分需要有以下输出内容:

    1.将预测涨跌概率的矩阵输出到PredResult.csv,

    2.将股票组合的月收益率序列记录到return_test表,该表的部分展示如下图,

    3.计算出投资组合在样本外预测月份的净值序列,输出到Value.csv。

    八、策略评价

    根据回测中得到的组合月度超额收益率return_test表,以及组合净值Value.csv,可以计算出该策略的超额年化收益波动率信息比率。本策略中,按上文设定的参数给出的投资组合各项指标,输出如下:

    annualized excess return = 0.28

    annualized excess volatility = 0.19

    information ratio = 1.44

    该策略组合的平均超额年化收益率为28%,平均年化收益波动率为0.19,信息比率IR为1.44,每承担1单位波动风险获得1.44的超额收益。

    最后,绘制出回测时间段内,2010年1月~2018年6月,该选股策略下的投资组合净值曲线,输出如:

    九、其他改进

     1 、因子原因

    特征因子的选择对于限行回归模型的有效性有着较大影响,本文的实例中将70个不同层面的特征因子一起放入了sklearn的线性模型中进行拟合,后续可以考虑有选择性的对模型进行带入,或许会有更好的拟合效果。

    例如,在原模型的基础上,去掉技术指标类的特征因子,只保留基本面的特征因子,模型的预测能力和回测评价输出如下:

    training set: accuracy = 0.57

    cv set: accuracy = 0.57

    annualized excess return = 0.25

    annualized excess volatility = 0.17

    information ratio = 1.46

    反之,若只使用技术指标类的特征因子,完全不考虑基本面的指标,模型的预测能力和回测评价输出如下:

    training set: accuracy = 0.58

    cv set: accuracy = 0.57

    annualized excess return = 0.10

    annualized excess volatility = 0.29

    information ratio = 0.33

     2 、变量调参

    可以根据model拟合后的预测准确率指标进行适当的参数调整,将下述输出指标进行优化。

    trainingset: accuracy = 0.59

    cv set: accuracy = 0.58

    例如,将percent_select参数调整为[0.3,0.3],即选择前30%的股票作为正例,后30%的股票作为反例,对模型进行训练,模型的预测能力和回测评价输出如下:

    training set: accuracy = 0.57

    cv set: accuracy = 0.57

    annualized excess return = 0.27

    annualized excess volatility = 0.20

    information ratio = 1.33

    或者,将n_stock_select参数调整为50,即每一期使用model进行预测时选取前50只股票买入,模型的预测能力不会改变,但是回测评价输出如下:

    annualized excess return = 0.24

    annualized excess volatility = 0.18

    information ratio = 1.34

    再或者,将logi_C参数调整为0.005,即对拟合的置信度进行放宽,对模型进行训练,模型的预测能力和回测评价输出如下:

    training set: accuracy = 0.59

    cv set: accuracy = 0.57

    annualized excess return = 0.29

    annualized excess volatility = 0.21

    information ratio = 1.41

     3 、模型改进

    线性回归模型虽然简单、对特征因子选取的依赖性较强,但也是可解释性、可控性较强的模型。除此之外,我们也可以引入其他模型,sklearn中包含了很多机器学习模块可供使用:

    1.逻辑回归(可解释性更强,训练速度更快):

    fromsklearn.linear_model import LogisticRegression

    2.随机森林模型:from sklearn import tree

    3.支持向量机模型(高维非线性拟合,训练速度慢):

    fromsklearn.svm import SVC

    4.K近邻算法:from sklearn import neighbors

    5.多层神经网络(高频海量数据的机器学习,小题大做):

    fromsklearn.neural_network import MLPClassifier

    另一方面,模型的训练和检验方式,也有多种选择,除了交叉验证外,还有滚动训练回测、检验曲线等等。都可以作为后期模型改进可以尝试的方向。

    来源:西藏信托

    拓展阅读:

    1.一个量化策略师的自白(好文强烈推荐)

    2.学习Python量化有哪些书籍?这里有一份书单送给你

    3.学了那么多技术指标为什么还不赚钱?从量化角度告诉你

    4.最科学的仓位管理利器-凯利公式,从方法上胜过99%散户

    5.网格交易法,一个不容易亏钱的投资策略(附源码)

    展开全文
  • 垒土投资 机器学习量化价值挖掘初探 2 0 1 8 - 5 - 6 学习投资 2017年自下而上的价值 投资得到较大发挥但价 值投资并非简单的买白马 戒者大盘蓝筹通过量化 宏观 行业 斱法可以做价值投资吗 信息 信息 宏观数据 传统...
  • 使用拓扑数据分析和机器学习量化斑点和条纹的代码 作者:梅利莎·R·麦奎尔(Melissa R. McGuirl),亚历山大·沃尔肯(Alexandria Volkening),比约恩·桑德斯特(Bjorn Sandstede) 如有疑问/意见,请联系梅利莎...
  • Python机器学习量化交易

    千次阅读 2019-12-30 17:33:15
    量化交易简介1.1 量化交易的历史1.2 什么是量化交易1.3 量化交易分类1.4 金融产品及衍生品的投资策略1.5 量化交易的优势1.6 如何做量化交易项目2. 量化回测框架介绍2.1 回测框架介绍2.2 策略创建运行的流程2.3 数据...

    1. 量化交易简介
    1.1 量化交易的历史

    ➢ 全球量化交易的发展历史:

    • 量化投资的产生(60年代):1969年,爱德华·索普利用他发明的“科学股票市场系统”(实际上是一种股票权证定价模型),成立了第一个量化投资基金。索普也被称之为量化投资的鼻祖。
    • 量化投资的兴起(70~80年代):1988年,詹姆斯·西蒙斯成立了大奖章基金,从事高频交易和多策略交易。基金成立20多年来收益率达到了年化70%左右,除去报酬后达到40%以上。西蒙斯也因此被称为"量化对冲之王"。[计算机、金融专业和数学等专业]
    • 量化交易的繁荣(90年代):991年,彼得·穆勒发明了alpha系统策略等,开始用计算机+金融数据来设计模型,构建组合。

    ➢ 国内量化交易的发展历史:

    • 量化投资元年:2010年,沪深300股指期货上市,此时的量化基金终于具备了可行的对冲工具,各种量化投资策略如alpha策略、股指期货套利策略才真正有了大展拳脚的空间,可以说2010年是中国量化投资元年。
    • 量化投资高速发展、多元化发展:2013-2015年股指新政之前可以说是国内量化基金有史以来最风光的一段时期。国内量化投资机构成批涌现,国内量化投资高速发展。

    2012年到2016年量化对冲策略管理的资金规模增长了20倍,管理期货策略更是增长了30倍,增长的速度是所有策略中最快的。相比美国量化基金发展历程,中国现在基本处于美国90年代至21世纪之间的阶段。

    1.2 什么是量化交易

    量化交易(量化投资)是借助现代统计学和数学(机器学习)的方法,利用计算机技术来进行交易的证券投资方式。学习量化交易,我们需要掌握:金融策略、挖掘技术和计算机技术。

    量化交易从庞大的历史数据中海选能够带来超额收益的多种“大概率”事件以指定策略,用数量模型验证及固化这些规律和策略,然后严格执行已固化的策略来指导,以求获得可持续的、稳定且高于平均收益的超额回报。

    1.3 量化交易分类

    在这里插入图片描述

    • 趋势性交易:适合一些主观交易的高手,用技术指标作为辅助工具在市场中如鱼得水的,但如果只用各种技术指标或指标组合作为核心算法构建模型,从未见过能长期盈利的。一般也会做一些量化分析操作,使用编程如 Python/matlab 。适合金融专业出生的,对财务、金融市场非常了解,如交易员、基金经理等。
    • 市场中性: 在任何市场环境下风险更低,收益稳定性更高,资金容量更大。适合一些量化交易者,发现市场中的alpha因子赚取额外收益,例如股票与股指期货的对冲策略等。会做一些量化分析操作,使用编程如 Python/matlab。适合计算机出生,擅长编程、机器学习、数据挖掘技术(量化分析),真正的量化交易人员
    • 高频交易:在极短的时间内频繁买进卖出,完成多次大量的交易,此类交易方式对硬件系统以及市场环境的要求极高,所以只有在成熟市场中的专业机构才会得到应用。适合一些算法高手,使用C/C++ 编程语言去进行算法交易,对软硬件条件要求比较高
    1.4 金融产品及衍生品的投资策略
    • 股票:市场中性投资占大多数、涉及少量的趋势性交易
    • 期货:趋势性策略占大多数(期货不属于金融产品)
    1.5 量化交易的优势
    • 严格的纪律性
    • 完备的系统性:首先表现在多层次,包括在大类资产配置、行业选择、精选个股三个层次上我们都有模型;其次是多角度,量化交易的核心投资思想包括宏观周期、市场结构、估值、成长、盈利质量、分析师盈利预测、市场情绪等多个角度;再者就是多数据,就是海量数据的处理。人脑处理信息的能力是有限的,当一个资本市场只有100只股票,这对定性投资基金经理是有优势的,他可以深刻分析这100家公司。但在一个很大的资本市场,比如有成千上万只股票的时候,强大的定量化交易的信息处理能力能反映它的优势,能捕捉更多的投资机会,拓展更大的投资机会。
    • 数学模型取胜:股票实际操作过程中,运用概率分析,提高买卖成功的概率
    • 股票的量化投资可以说是一种价值投资(价值投资是很多量化公司、基金公司所推崇的),我们所做的也是去挖掘市场中的价值股票,而并非去预测股票涨跌来进行投资等等(至少目前机构不会采取这种方式指导投资),这需要大家明确的一个问题。其实,由于中国散户太多,有些公司本身公司不怎么样,但股票也涨得很厉害。美国的量化投资稳定一些,主要是因为美国几乎没有什么个人投资者,他们都是找一些基金公司代理去做投资。
    • 最终量化分析是众多投资机构的工具、分析手段而已。
    1.6 如何做量化交易项目

    量化投资涵盖整个交易流程,需要一个完整的作为研究的量化回测框架和实盘交易系统作为支撑。

    ➢ 量化交易研究流程

    量化回测框架提供完整的数据,以及回测机制进行策略评估研究,并能够实时进行模拟交易,为实盘交易提供选择,我们的研究一般在回测平台中做。

    • 获取数据:行情数据、基本面数据
    • 数据挖掘:这部分很重要,大多数在公司会做这个部分。需要用到机器学习算法、特征工程等来分析结果,指导我们的策略。
    • 构建策略
    • 策略回测
    • 策略分析:策略不是一直有效的,基金公司频繁去分析数据、挖掘数据,更新策略。
    • 模拟交易
    • 实盘交易

    ➢ 什么是量化策略

    量化策略是指使用计算机作为工具,通过一套固定的逻辑来分析、判断和决策。 量化策略既可以自动执行,也可以人工执行。其实策略也可以理解为,分析数据之后,决策买什么以及交易时间。

    ➢ 流程包含的内容

    • 获取数据:公司财务、新闻数据;基本行情数据。
    • 数据分析与挖掘:传统分析方法、机器学习,数据挖掘方法;数据处理,标准化,去极值,中性化分组回测,行业分布。
    • 构建策略:获取历史行情,历史持仓信息,调仓记录等;止盈止损单,限价单,市价单。
    • 回测:股票涨跌停、停复牌处理;市场冲击,交易滑点,手续费。
    • 策略分析:订单分析,成交分析,持仓分析。
    • 模拟交易:接入实时行情,实时获取成交回报;实时监控,实时归因分析。
    • 实盘交易:接入真实券商账户。

    ➢ 量化开发和研究岗位要求

    • 基于交易市场数据,研究、开发交易策略,进行基础建模
    • 负责对交易策略进行回测、跟踪、分析、优化
    • 定期对交易策略的运行结果进行总结,给出分析报告,评估市场适用度
    • 负责数据挖掘、处理,数据统计分析,从数据中发现规律,为量化分析提供支持,开发量化模型策略
    • 与基金经理合作跟踪优化股票市场量化策略在实盘的表现
    2. 量化回测框架介绍
    2.1 回测框架介绍

    ➢ 基础回测框架

    Zipline是一个Pythonic算法交易库,这是一个支持回测和现场交易的事件驱动系统。目前,Zipline被用于生产后测和实时交易引擎,为Quantopian提供动力。是一个免费的,以社区为中性的托管平台。Zipline本身只支持美国的证券,如果我们用需要改很多东西。

    ➢ 云端的框架

    • 提供部分满足需求的数据(但是平台数据质量不行,指标不完整)
    • 策略运行在远端服务器

    ➢ 不去实现一个回测框架的原因

    • 没有完整的股票行情和基本面数据
    • 回测平台是载体,重点在于快速验证策略
    • 证券投资机构各自使用回测框架不同,没有通用的框架

    ➢ RiceQuant回测平台介绍
    在这里插入图片描述

    2.2 策略创建运行的流程

    ➢ 一个完整的策略需要做的事情

    • 选择策略的运行信息:选择运行区间和初始资金,选择回测频率,选择股票池
    • 编写策略的逻辑:获取股票行情、基本面数据
    • 分析结果:策略指标分析

    ➢ 策略初始设置

    • 基础设置:指定回测的起止日期、初始资金和回测频率。起止日期是策略运行的时间区间;初始资金是用于投资的总资金;回测的频率有两种选择,日回测和分钟回测(对于市场中性,判断周期可能更长,一个月等)。做股票量化选择日回测即可
    • 高级设置:略

    ➢ 策略主体运行流程分析

    • init函数中实现策略初始化逻辑,策略的股票池:在哪些股票中进行交易判断(例如:HS300)
    • 可以选择在before_trading函数进行一些每日开盘之前的操作,比如获取历史行情做一些数据预处理,获取当前账户资金等。
    • handle_bar函数中实现策略具体逻辑,包括交易信号的产生、订单的创建。handle_bar内的逻辑会在每次bar数据更新的时候被触发。

    运行顺序:在运行策略时首先运行init函数,但只运行一次。before_trading和handle_bar函数每日都会被调用,每日交易之前首先运行before_trading,然后再运行handle_bar函数进行每日的交易的判断。

    2.3 数据获取接口

    ➢ 数据接口的种类

    • 指定行业、板块股票列表
    • 指定股票合约历史数据 [ history_bars ]
    • 查询财务数据[ get_fundamentals ]

    ➢ 获取行业股票列表

    以获取餐饮业的股票列表为例:

    def init(context):
        # 获取餐饮业股票列表
        context.catering_stock_list = industry('H62')
    
    def before_trading(context):
        # 打印股票列表
        print(context.catering_stock_list)
    
    def handle_bar(context, bar_dict):
    	# 主要的算法逻辑
        pass
    

    打印出餐饮业股票列表:

    2019-12-02 INFO ['000721.XSHE', '002306.XSHE', '002186.XSHE']
    2019-12-03 INFO ['000721.XSHE', '002306.XSHE', '002186.XSHE']
    2019-12-04 INFO ['000721.XSHE', '002306.XSHE', '002186.XSHE']
    2019-12-05 INFO ['000721.XSHE', '002306.XSHE', '002186.XSHE']
    2019-12-06 INFO ['000721.XSHE', '002306.XSHE', '002186.XSHE']
    2019-12-09 INFO ['000721.XSHE', '002306.XSHE', '002186.XSHE']
    2019-12-10 INFO ['000721.XSHE', '002306.XSHE', '002186.XSHE']
    

    ➢ 获取板块股票列表

    以获取能源板块列表为例:

    def init(context):
        # 获取能源板块列表
        context.energy_sector_list = sector("Energy")
    
    def before_trading(context):
        # 打印能源板块列表
        print(context.energy_sector_list)
    
    def handle_bar(context, bar_dict):
        # 主要的算法逻辑
        pass
    

    打印能源板块列表:

    2019-12-02 INFO ['600688.XSHG', '600397.XSHG', '600777.XSHG', '002353.XSHE', '000059.XSHE', '300309.XSHE', 
    '000937.XSHE', '600028.XSHG', '000159.XSHE', '600583.XSHG', '000968.XSHE', '600871.XSHG', '000552.XSHE', 
    '600792.XSHG', '603727.XSHG', '002554.XSHE', '601666.XSHG', '603113.XSHG', '002207.XSHE', '601101.XSHG', 
    '600508.XSHG', '600989.XSHG', '300164.XSHE', '002278.XSHE', '000780.XSHE', '600123.XSHG', '600725.XSHG', 
    '600759.XSHG', '300191.XSHE', '000406.XSHE', '600997.XSHG', '603800.XSHG', '600403.XSHG', '002018.XSHE', 
    '600971.XSHG', '600065.XSHG', '000763.XSHE', '600387.XSHG', '002629.XSHE', '300157.XSHE', '300471.XSHE', 
    '601898.XSHG', '601798.XSHG', '603036.XSHG', '000956.XSHE', '600740.XSHG', '600758.XSHG', '600188.XSHG', 
    '600968.XSHG', '603798.XSHG', '603619.XSHG', '002128.XSHE', '601808.XSHG', '000698.XSHE', '600002.XSHG', 
    '002828.XSHE', '300084.XSHE', '600395.XSHG', '000852.XSHE', '000983.XSHE', '000096.XSHE', '600772.XSHG', 
    '601015.XSHG', '600256.XSHG', '601857.XSHG', '601699.XSHG', '000817.XSHE', '000723.XSHE', '002259.XSHE', 
    '002221.XSHE', '002490.XSHE', '000866.XSHE', '000571.XSHE', '600348.XSHG', '601088.XSHG', '600121.XSHG', 
    '601918.XSHG', '000554.XSHE', '601001.XSHG', '300540.XSHE', '601011.XSHG', '000637.XSHE', '601225.XSHG']
    

    ➢ 获取指数成分股

    一般很少选择使用某个行业或某个板块的股票,这些板块的股票很可能不是很好。我们要投的是一些前景比较好的公司,所以我们选择指数成份股票。股票成份股是实时更新的,

    常见的指数成分股有:

    "000001.XSHG" # 上证A股
    "000300.XSHG" # HS300,沪深300
    "000905.XSHG" # ZZ500,中正500
    "000016.XSHG" # SZ50,深圳50
    

    以中正500为例获取中正500的股票列表:

    def init(context):
        # 获取中正500股票列表
        context.zz500_index_components_list = index_components("000905.XSHG")
    
    def before_trading(context):
        # 打印中正500股票列表
        print(context.zz500_index_components_list)
    
    def handle_bar(context, bar_dict):
        # 主要的算法逻辑
        pass
    

    打印中正500的股票列表:

    2019-12-03 INFO ['000587.XSHE', '600008.XSHG', '002157.XSHE', '601958.XSHG', '002589.XSHE', '600307.XSHG', 
    '601127.XSHG', '600416.XSHG', '600169.XSHG', '002500.XSHE', '600750.XSHG', '000488.XSHE', '603877.XSHG', 
    '002390.XSHE', '603556.XSHG', '600939.XSHG', '600642.XSHG', '002503.XSHE', '600037.XSHG', '601005.XSHG', 
    '601699.XSHG', '000552.XSHE', '600183.XSHG', '600694.XSHG', '002670.XSHE', '000559.XSHE', '600820.XSHG', 
    '601777.XSHG', '600280.XSHG', '002583.XSHE', '000686.XSHE', '002635.XSHE', '601866.XSHG', '000600.XSHE', 
    '300316.XSHE', '603868.XSHG', '600874.XSHG', '603501.XSHG', '000869.XSHE', '601615.XSHG', '600598.XSHG', 
    '002131.XSHE', '000727.XSHE', '600884.XSHG', '000513.XSHE', '000541.XSHE', '601168.XSHG', '600393.XSHG', 
    '000690.XSHE', '002414.XSHE', '300199.XSHE', '600141.XSHG', '600848.XSHG', '002002.XSHE', '600486.XSHG', 
    ……
    

    ➢ 获取股票合约数据

    使用到的方法(相关参数的解释直接看API文档):history_bars(order_book_id, bar_count, frequency, fields=None, skip_suspended=True, include_now=False),获取指定合约的历史行情,同时支持日以及分钟历史数据,该模块不可以在init方法中调用!!!

    股票合约数据API文档链接:https://www.ricequant.com/doc/api/python/chn#data-methods-history_bars

    获取股票合约数据:

    def init(context):
        # 在context中保存全局变量
        context.s1 = "000001.XSHE"
    
    # before_trading函数会在每天策略交易开始前被调用,当天只会被调用一次
    def before_trading(context):
        pass
    
    def handle_bar(context, bar_dict):
        # 主要的算法逻辑,必填项
        # order_book_id:获取的历史数据数量,必填项
        # bar_count:获取的历史数据数量,必填项
        # frequency:获取数据什么样的频率进行。'1d'或'1m'分别表示每日和每分钟,必填项。您可以指定不同的分钟频率,例如'5m'代表5分钟线
        # fields:返回数据字段。必填项。
        # skip_suspended:是否跳过停牌,默认True,跳过停牌
        # include_now:是否包括不完整的bar数据。默认为False,不包括。
        # 获取开盘价格
        open_price = history_bars(context.s1,5,'1d','open')
        # 获取其它类型的价格
        history_data = history_bars(context.s1,5,'1d',['open','high','low','close','volume','total_turnover','datetime'])
        logger.info(open_price)
        logger.info(history_data)
        # 如果把频率改成1m,则回测频率必须为分钟回测
        history_data02 = history_bars(context.s1,5,'1m',['open','high','low','close','volume','total_turnover','datetime'])
        print(history_data02)
    

    打印股票合约数据:

    2019-12-02 INFO [15.89 15.64 15.47 15.54 15.35]
    2019-12-02 INFO [(15.89, 15.89, 15.49, 15.62, 81529753., 1271594662, 20191126000000)
     (15.64, 15.64, 15.39, 15.47, 47616998.,  736584294, 20191127000000)
     (15.47, 15.54, 15.44, 15.49, 37801651.,  585252046, 20191128000000)
     (15.54, 15.55, 15.18, 15.29, 65386691., 1001451096, 20191129000000)
     (15.35, 15.43, 15.23, 15.36, 55387738.,  849784129, 20191202000000)]
    2019-12-03 INFO [15.64 15.47 15.54 15.35 15.3 ]
    2019-12-03 INFO [(15.64, 15.64, 15.39, 15.47, 47616998.,  736584294, 20191127000000)
     (15.47, 15.54, 15.44, 15.49, 37801651.,  585252046, 20191128000000)
     (15.54, 15.55, 15.18, 15.29, 65386691., 1001451096, 20191129000000)
     (15.35, 15.43, 15.23, 15.36, 55387738.,  849784129, 20191202000000)
     (15.3 , 15.46, 15.21, 15.45, 45541805.,  700293548, 20191203000000)]
     ……
    

    bar_dict是Bar对象,Bar对象与history_bars的区别是:Bar只能获取当天的交易数据,不能获取历史交易数据logger.info(bar_dict[context.s1].close):只能获取当前日期的交易信息

    ➢ 获取财务数据

    使用get_fundamentals(query, entry_date=None, interval='1d', report_quarter=False)方法来查询财务数据。

    注意:这里的数据指标类别虽然有400多种,但是RQ平台的这些指标数据质量不高,很多指标没有经过运算处理成需要的指标,跟我们在讲金融数据处理的时候列出来的那些财务指标差别比较大。

    使用query查询的方式来获取指标q = query(fundamentals.eod_derivative_indicator.pe_ratio)

    def init(context):
        # 在context中保存全局变量
        # context.s1 = "000001.XSHE"
        pass
    
    # before_trading函数会在每天策略交易开始前被调用,当天只会被调用一次
    def before_trading(context):
        pass
    
    def handle_bar(context, bar_dict):
        # 获取财务数据,默认是获取所有A股的股票财务数据
        # 创建一个查询语句
        q = query(fundamentals.eod_derivative_indicator.pe_ratio)
        fund = get_fundamentals(q) # 回测不需要传入日期,默认是当天的数据
        logger.info(fund.T)
    
    # after_trading函数会在每天策略交易结束后被调用,当天只会被调用一次
    def after_trading(content):
        pass
    

    此外还可以设置一些过滤条件来帮助我们选股:

    • query().filter():过滤大小
    • query().order_by():排序
    • query().limit():限制数量
    • fundamentals.stockcode.in_():在指定的股票池当中过滤

    测试使用过滤条件filter过滤股票:

    def init(context):
        # 在context中保存全局变量
        # context.s1 = "000001.XSHE"
        pass
    
    # before_trading函数会在每天策略交易开始前被调用,当天只会被调用一次
    def before_trading(context):
        pass
    
    def handle_bar(context, bar_dict):
        # 获取财务数据,默认是获取所有A股的股票财务数据
        # 创建一个查询语句
        q = query(
            fundamentals.eod_derivative_indicator.pe_ratio,
            fundamentals.eod_derivative_indicator.pcf_ratio
        ).filter(
            fundamentals.eod_derivative_indicator.pe_ratio > 20,
            fundamentals.eod_derivative_indicator.pcf_ratio < 50
        )
        fund = get_fundamentals(q) # 回测不需要传入日期,默认是当天的数据
        logger.info(fund.T)
    
    # after_trading函数会在每天策略交易结束后被调用,当天只会被调用一次
    def after_trading(content):
        pass
    

    测试结果:

    2019-12-02 09:31:00  INFO              pe_ratio pcf_ratio
    000020.XSHE  469.167  -132.305
    000023.XSHE  24.2256    14.034
    000025.XSHE   74.511  -1304.65
    000009.XSHE  36.5007    4.2342
    000008.XSHE  27.8938  -16.5274
    000021.XSHE  38.9316   33.4623
    ……
    

    测试使用过滤条件order_by过滤股票:

    def init(context):
        # 在context中保存全局变量
        # context.s1 = "000001.XSHE"
        pass
    
    # before_trading函数会在每天策略交易开始前被调用,当天只会被调用一次
    def before_trading(context):
        pass
    
    def handle_bar(context, bar_dict):
        # 获取财务数据,默认是获取所有A股的股票财务数据
        # 创建一个查询语句
        q = query(
            fundamentals.eod_derivative_indicator.pe_ratio,
            fundamentals.eod_derivative_indicator.pcf_ratio
        ).filter(
            fundamentals.eod_derivative_indicator.pe_ratio > 20,
            fundamentals.eod_derivative_indicator.pcf_ratio < 50
        ).order_by(
            fundamentals.eod_derivative_indicator.pe_ratio # 默认按照升序排序,降序使用 fundamentals.eod_derivative_indicator.pe_ratio.asc
        )
        fund = get_fundamentals(q) # 回测不需要传入日期,默认是当天的数据
        logger.info(fund.T)
    
    # after_trading函数会在每天策略交易结束后被调用,当天只会被调用一次
    def after_trading(content):
        pass
    

    测试结果:

    2019-12-02 09:31:00  INFO              pe_ratio pcf_ratio
    600113.XSHG  20.0129   21.9759
    600676.XSHG  20.0165   10.1316
    300258.XSHE  20.0204    9.2312
    603360.XSHG  20.0549   40.1861
    300382.XSHE  20.0974  -47.8644
    300485.XSHE  20.1273   27.4275
    600731.XSHG  20.1301   20.4888
    ……
    

    测试使用过滤条件limit过滤股票:

    def init(context):
        # 在context中保存全局变量
        # context.s1 = "000001.XSHE"
        pass
    
    # before_trading函数会在每天策略交易开始前被调用,当天只会被调用一次
    def before_trading(context):
        pass
    
    def handle_bar(context, bar_dict):
        # 获取财务数据,默认是获取所有A股的股票财务数据
        # 创建一个查询语句
        q = query(
            fundamentals.eod_derivative_indicator.pe_ratio,
            fundamentals.eod_derivative_indicator.pcf_ratio
        ).filter(
            fundamentals.eod_derivative_indicator.pe_ratio > 20,
            fundamentals.eod_derivative_indicator.pcf_ratio < 50
        ).order_by(
            fundamentals.eod_derivative_indicator.pe_ratio # 默认按照升序排序,降序使用 fundamentals.eod_derivative_indicator.pe_ratio.asc
        ).limit(10)
        fund = get_fundamentals(q) # 回测不需要传入日期,默认是当天的数据
        logger.info(fund.T)
    
    # after_trading函数会在每天策略交易结束后被调用,当天只会被调用一次
    def after_trading(content):
        pass
    

    测试结果:

    2019-12-02 09:31:00  INFO              pe_ratio pcf_ratio
    600113.XSHG  20.0129   21.9759
    600676.XSHG  20.0165   10.1316
    300258.XSHE  20.0204    9.2312
    603360.XSHG  20.0549   40.1861
    300382.XSHE  20.0974  -47.8644
    300485.XSHE  20.1273   27.4275
    600731.XSHG  20.1301   20.4888
    000761.XSHE  20.1325    3.8861
    000411.XSHE  20.1383   17.2282
    600271.XSHG  20.1523    19.327
    2019-12-02 09:32:00  INFO              pe_ratio pcf_ratio
    600113.XSHG  20.0129   21.9759
    600676.XSHG  20.0165   10.1316
    300258.XSHE  20.0204    9.2312
    ……
    

    测试在指定股票池中(沪深300)过滤股票:

    def init(context):
        # 获取沪深300股票池中的股票
        context.hs300_index_components_list = index_components("000300.XSHG")
    
    # before_trading函数会在每天策略交易开始前被调用,当天只会被调用一次
    def before_trading(context):
        pass
    
    def handle_bar(context, bar_dict):
        # 获取财务数据,默认是获取所有A股的股票财务数据
        # 创建一个查询语句
        q = query(
            fundamentals.eod_derivative_indicator.pe_ratio,
            fundamentals.eod_derivative_indicator.pcf_ratio
        ).filter(
            fundamentals.eod_derivative_indicator.pe_ratio > 20,
            fundamentals.eod_derivative_indicator.pcf_ratio < 50
        ).order_by(
            fundamentals.eod_derivative_indicator.pe_ratio # 默认按照升序排序,降序使用 fundamentals.eod_derivative_indicator.pe_ratio.asc
        ).filter(
            fundamentals.stockcode.in_(context.hs300_index_components_list)
        ).limit(10)
        fund = get_fundamentals(q) # 回测不需要传入日期,默认是当天的数据
        logger.info(fund.T)
    
    # after_trading函数会在每天策略交易结束后被调用,当天只会被调用一次
    def after_trading(content):
        pass
    

    测试结果:

    2019-12-02 09:31:00  INFO              pcf_ratio pe_ratio
    600271.XSHG    19.327  20.1523
    601633.XSHG    4.3186  20.2625
    002001.XSHE   12.5034  20.3645
    601021.XSHG   12.7549  20.4143
    002202.XSHE   15.6682  20.5027
    600030.XSHG    4.4997  20.5932
    000423.XSHE   21.8234  20.6055
    600109.XSHG    9.5708  21.1123
    000166.XSHE   -8.5859  21.2636
    601881.XSHG   42.3332  21.3651
    2019-12-02 09:32:00  INFO              pcf_ratio pe_ratio
    600271.XSHG    19.327  20.1523
    601633.XSHG    4.3186  20.2625
    ……
    

    通过财务数据选股票,不会每天都去获取数据,因为可能获取的股票在近几天是同样的。可以每隔一周、一个月获取一些符合条件的股票。这里可以使用scheduler定时器获取数据,每天运行使用scheduler.run_daily,每周运行使用scheduler.run_weekly,每月运行scheduler.run_monthly。但是,这三个定时器函数只能在init函数中使用

    scheduler.run_daily(function):每天运行一次的function,只能在init中使用。

    注意:init 函数初始化后,如果定时器设置了每月在第一个交易日执行,那么第一个交易日执行 before_trading 函数后,再执行 get_data 函数,最后再执行 after_trading 函数。没有设置定时器的交易日不运行 get_data 函数,只会先后运行before_trading、after_trading函数。

    参数类型注释
    functionfunction使传入的function每日运行,function函数一定要包含并且只能包含 context 和 bar_dict 两个输入参数

    每天运行一次的定时器:

    def init(context):
        # 获取沪深300股票池中的股票
        context.hs300_index_components_list = index_components("000300.XSHG")
        # 定义一个按天运行一次的定时器
        scheduler.run_daily(get_data)
    
    def get_data(context, bar_dict):
        # 按月查询财务数据
        # q = query() # 默认是获取这个月第一天的财务数据
        q = query(
            fundamentals.eod_derivative_indicator.pb_ratio
            ).filter(
                fundamentals.eod_derivative_indicator.pb_ratio > 30
            ).filter(
                fundamentals.stockcode.in_(context.hs300_index_components_list)
            )
        fund = get_fundamentals(q)
        logger.info(fund)
    
    # before_trading函数会在每天策略交易开始前被调用,当天只会被调用一次
    def before_trading(context):
        pass
    
    def handle_bar(context, bar_dict):
       pass
    
    # after_trading函数会在每天策略交易结束后被调用,当天只会被调用一次
    def after_trading(content):
        pass
    

    测试结果:

    2020-02-03 09:31:00  INFO           002607.XSHE
    pb_ratio     40.7768
    2020-02-04 09:31:00  INFO           002607.XSHE
    pb_ratio     36.6894
    2020-02-05 09:31:00  INFO           002607.XSHE
    pb_ratio     40.3632
    2020-02-06 09:31:00  INFO           002607.XSHE
    pb_ratio     40.7525
    2020-02-07 09:31:00  INFO           002607.XSHE
    pb_ratio     43.7937
    2020-02-10 09:31:00  INFO           002607.XSHE
    pb_ratio     42.1636
    2020-02-11 09:31:00  INFO           002607.XSHE
    pb_ratio     42.3583
    2020-02-12 09:31:00  INFO           002607.XSHE
    pb_ratio     42.8205
    2020-02-13 09:31:00  INFO           002607.XSHE
    pb_ratio     42.5529
    

    scheduler.run_monthly(function, tradingday=t):每月运行一次的function,只能在init中使用。

    注意:tradingday的负数表示倒数,tradingday表示交易日,如果某月只有三个交易日,则此月的tradingday=3与tradingday=-1相同。

    参数类型注释
    functionfunction使传入的 function 每日交易开始前运行,function函数一定要包含并且只能包含 context 和 bar_dict 两个输入参数
    tradingdayint范围为 [-23,1],[1,23]。例如:1代表每月第一个交易日。-1代表每月倒数第一个交易日,用户必须指定

    每月运行一次的定时器:

    def init(context):
        # 获取沪深300股票池中的股票
        context.hs300_index_components_list = index_components("000300.XSHG")
        # 定义一个按月运行的定时器
        # 每月只运行一次并指定第一个交易日
        scheduler.run_monthly(get_data, tradingday=1)
    
    def get_data(context, bar_dict):
        # 按月查询财务数据
        # q = query() # 默认是获取这个月第一天的财务数据
        q = query(
            fundamentals.eod_derivative_indicator.pb_ratio
            ).filter(
                fundamentals.eod_derivative_indicator.pb_ratio > 30
            ).filter(
                fundamentals.stockcode.in_(context.hs300_index_components_list)
            )
        fund = get_fundamentals(q)
        logger.info(fund)
    
    # before_trading函数会在每天策略交易开始前被调用,当天只会被调用一次
    def before_trading(context):
        pass
    
    def handle_bar(context, bar_dict):
       pass
    
    # after_trading函数会在每天策略交易结束后被调用,当天只会被调用一次
    def after_trading(content):
        pass
    

    测试结果:

    2020-01-02 09:31:00  INFO           002607.XSHE
    pb_ratio     43.5018
    2020-02-03 09:31:00  INFO           002607.XSHE
    pb_ratio     40.7768
    
    2.4 回测交易接口

    ➢ 交易函数API

    order_shares(id_or_ins, amount, style=MarketOrder()):指定股数交易。落指定股数的买/卖单是最常见的落单方式之一,如有需要落单类型当做一个参量传入,如果忽略掉落单类型,那么默认是市价单(market order)

    参数类型注释
    id_or_insstr或instrument对象股票代码。order_book_id或symbol或instrument对象,用户必须指定。
    amountint需要落单的股数。正数代表买入,负数代表卖出。
    styleOrderType订单类型,默认是市价单。目前支持的订单类型有:MarketOrder()和LimitOrder(limit_price),LimitOrder是用于设置限价单的

    指定股数交易测试:

    def init(context):
        context.s1 = "000001.XSHE"
    
    # before_trading函数会在每天策略交易开始前被调用,当天只会被调用一次
    def before_trading(context):
        pass
    
    def handle_bar(context, bar_dict):
        # 开始编写你的主要算法逻辑
        # 进行交易
        order_shares(context.s1, 1000) 
    
    # after_trading函数会在每天策略交易结束后被调用,当天只会被调用一次
    def after_trading(content):
        pass
    

    测试结果:
    在这里插入图片描述
    在这里插入图片描述
    order_lots(id_or_ins, amount, style=OrderType):指定手数发送买卖单。如果有需要落单类型当做一个参量传入,如果忽略掉落单类型,那么默认是市价单。

    参数类型注释
    id_or_insstr或instrument对象order_book_id或symbol或instrument对象,用户必须指定
    amountfloat多少手的数目。正数表示买入,负数表示卖出,用户必须指定
    styleOrderType订单类型,默认是市价单。目前支持的订单类型有MarkOrder和LimitOrder(limit_price)

    指定手数交易测试:

    def init(context):
        context.s1 = "000001.XSHE"
    
    # before_trading函数会在每天策略交易开始前被调用,当天只会被调用一次
    def before_trading(context):
        pass
    
    def handle_bar(context, bar_dict):
        # 开始编写你的主要算法逻辑
        # 进行交易,10手股票
        order_lots(context.s1, 10) # 等价于order_shares(context, 1000)
    
    # after_trading函数会在每天策略交易结束后被调用,当天只会被调用一次
    def after_trading(content):
        pass
    

    测试结果:
    在这里插入图片描述
    order_value(id_or_ins, cash_amount, style=OrderType):指定价值交易。使用想要花费金钱买入或卖出想要的股票,正数表示买入,负数表示卖出(暂不支持卖空)。股票的股数总是会被调整成对应的100的倍数。当提交一个卖单时,该方法代表的意义是希望通过卖出该股票套现的金额。如果金额超出了所持有股票的价值,那么将卖出所有股票。如果金额不足,该 API 将不会创建发送订单。

    参数类型注释
    id_or_insstr或instrument对象order_book_id
    cash_amountfloat需要花费现金购买或卖出证券的数目。正数代表买入,负数代表卖出,用户必须指定。
    styleOrderType订单类型,默认是市价单。目前支持的订单类型有MarkOrder和LimitOrder(limit_price)

    指定价值交易测试:

    def init(context):
        context.s1 = "000001.XSHE"
    
    # before_trading函数会在每天策略交易开始前被调用,当天只会被调用一次
    def before_trading(context):
        pass
    
    def handle_bar(context, bar_dict):
        # 开始编写你的主要算法逻辑
        # 指定价值交易测试,每笔成交量与成交价的乘积(每笔的金额)要小于¥1600
        order_value(context.s1, 1600)
    
    # after_trading函数会在每天策略交易结束后被调用,当天只会被调用一次
    def after_trading(content):
        pass
    

    测试结果:
    在这里插入图片描述
    order_target_percent(id_or_ins, percent, style=OrderType):按照目标比例下单。买入或卖出证券以正确调整该证券的仓位到占有一个指定的投资组合的目标百分比(暂不支持卖空)。需要计算一个应该调整的仓位。position_to_adjust = target_position - current_position投资组合的价值等于所有已有仓位的价值和剩余现金的总和。如果得到的position_to_adjust是正数,那么会买入该证券,否则会卖出该证券。如果资金不足,不会创建发送订单。

    如果投资组合中有了平安银行股票的仓位,并且占据目前投资组合的10%的价值,那么以下代码会买入平安银行股票最终使其占据投资组合价值的15%。
    order_target_percent('000001.XSHE', 0.15)

    指定目标比例下单测试:

    def init(context):
        context.s1 = "000001.XSHE"
    
    # before_trading函数会在每天策略交易开始前被调用,当天只会被调用一次
    def before_trading(context):
        pass
    
    def handle_bar(context, bar_dict):
        # 开始编写你的主要算法逻辑
        order_target_percent(context.s1, 0.25)
    
    # after_trading函数会在每天策略交易结束后被调用,当天只会被调用一次
    def after_trading(content):
        pass
    

    测试结果:
    在这里插入图片描述

    如果股票涨了,就会卖出部分股票,保证使平安银行股票的价值占据投资组合的15%。同理,如果有跌,就会买如部分股票。

    order_target_value(id_or_ins, cach_amount, style=OrderType):买入或卖出并且自动调整该证券的仓位到一个目标价值(暂不支持卖空)。如果还没有任何该证券的仓位,那么会买入全部目标值的证券。如果一斤有该证券的仓位,则会买入或卖出该证券的现有仓库和目标仓位的价值差值的数目的证券。需要注意,如果资金不足,该API将不会创建发送订单。

    参数类型注释
    id_or_insstr或instrument对象order_book_id
    cash_amountfloat最终的该证券仓位目标价值
    styleOrderType订单类型,默认是市价单。目前支持的订单类型有MarkOrder和LimitOrder(limit_price)

    例:如果现在的投资组合中持有价值3000元的平安银行股票的仓位并且设置目标值为10000元,以下代码范例会发送价值7000的平安银行的买单到市场。

    指定目标价值下单测试:

    def init(context):
        context.s1 = "000001.XSHE"
    
    # before_trading函数会在每天策略交易开始前被调用,当天只会被调用一次
    def before_trading(context):
        pass
    
    def handle_bar(context, bar_dict):
        # 开始编写你的主要算法逻辑
        # 指定目标价值下单
        order_target_value(context.s1, 5000)
    
    # after_trading函数会在每天策略交易结束后被调用,当天只会被调用一次
    def after_trading(content):
        pass
    

    测试结果:
    在这里插入图片描述
    ➢ 交易注意事项

    以下情况,交易会被回测平台自动拒单:

    • 可用资金不足
    • 下单数量不足一手
    • 下单价格超过当日涨跌停板限制(一般按照默认回测的收盘价)
    • 当前可卖(可平)仓位不足
    • 股票当日停牌
    • 合约已经退市(到期)或尚未上市

    默认每日回测:每日收盘价去进行买入。

    ➢ 市价单和限价单

    撮合机制:回测平台支持的撮合方式有两种,一种是当前收盘价,即当前bar发单,以当前bar收盘价作为参考价撮合。一种是开盘价,即当前bar发单,以下一个bar开盘价作为参考价撮合。

    市价单:目的是为了快速成交,当前市价是多少,买入或卖出就是多少。默认是以市价单去买卖股票。

    限价单:挂单的方式,例如:如果当时的市价是100,我们指定100.8卖出,99.8买入。,以预定的价格去成交,一般很少去用。

    滑点:目的是在回测中使用,在模拟和实盘交易是不需要滑点。为了更好地模拟实际交易中订单对市场的冲击,引入滑点。若设置将在一定程度上使最后的成交价“恶化”,也就是买得更贵、卖得更便宜。这里滑点的方式是按照最后成加价的一定比例进行恶化。例如:设置滑点为0.1,如果原本买入交易的成交价是10元,则设置之后成交价将变成10.1元,也就是买得更贵。

    卖空:如果是股票,当天买不可以当天卖,是不允许卖空的,而期货是允许卖空。

    ➢ 投资组合

    投资组合是由投资人或金融机构所持有的股票、债券、金融衍生品等组成的集合,目的是分散风险。查看投资组合的信息:

    def init(context):
        context.s1 = '000001.XSHE'
    
    # before_trading函数会在每天策略交易开始前被调用,当天只会被调用一次
    def before_trading(context):
        pass
    
    def handle_bar(context, bar_dict):
        # 开始编写你的主要算法逻辑
        order_target_percent(context.s1, 0.1)
        # 查看账户中的可用资金,投资组合的可用资金,为子账户可用资金的加和
        print('投资组合的可用资金', context.portfolio.cash)
        # 查看投资组合的当前市场价值,为子账户市场价值的加和
        print('投资组合的当前市场价值', context.portfolio.market_value)
        # 查看总权益,为子账户总权益的加和 
        print('投资组合的总价值', context.portfolio.total_value)
    
    # after_trading函数会在每天策略交易结束后被调用,当天只会被调用一次
    def after_trading(content):
        pass
    

    在这里插入图片描述
    我们还可以查看当前所持仓的股票和指定股票的仓位等信息:

    def init(context):
        # 平安银行股票代码
        context.s1 = '000001.XSHE'
        # 万科股票代码
        context.s2 = '000002.XSHE'
    
    # before_trading函数会在每天策略交易开始前被调用,当天只会被调用一次
    def before_trading(context):
        pass
    
    def handle_bar(context, bar_dict):
        # 开始编写你的主要算法逻辑
        order_target_percent(context.s1, 0.1)
        order_target_percent(context.s2, 0.1)
        # 买入交易了之后,投资组合就会发生变化,不仅表现在资金上,而且表现在仓位上
        # 查看所持仓位的股票
        print(context.portfolio.positions.keys())
        # 查看指定股票的股数
        print('平安银行的仓位数:', context.portfolio.positions[context.s1].quantity)
        print(' 万科的仓位数:', context.portfolio.positions[context.s2].quantity)
        # 打印股票资金账户信息
        print(context.stock_account)
        # 查看账户中的可用资金,投资组合的可用资金,为子账户可用资金的加和
        print('投资组合的可用资金', context.portfolio.cash)
        # 查看投资组合的当前市场价值,为子账户市场价值的加和
        print('投资组合的当前市场价值', context.portfolio.market_value)
        # 查看总权益,为子账户总权益的加和 
        print('投资组合的总价值', context.portfolio.total_value)
        print('--------------------------')
    # after_trading函数会在每天策略交易结束后被调用,当天只会被调用一次
    def after_trading(content):
        pass
    

    日志:

    2020-01-02  INFO  ['000001.XSHE', '000002.XSHE']
    2020-01-02  INFO  平安银行的仓位数: 5900
    2020-01-02  INFO   万科的仓位数: 3000
    2020-01-02  INFO  StockAccount({'positions': ['000002.XSHE', '000001.XSHE'], 'margin': 197213.0, 'frozen_cash': 0.0, 'market_value': 197213.0, 'total_value': 984052.608, 'cash': 786839.608, 'trading_pnl': -15777.000000000015, 'position_pnl': 0, 'transaction_cost': 170.39200000000002, 'daily_pnl': -15947.392000000014, 'dividend_receivable': 0, 'type': 'STOCK', 'total_cash': 786839.608})
    2020-01-02  INFO  投资组合的可用资金 786839.608
    2020-01-02  INFO  投资组合的当前市场价值 197213.0
    2020-01-02  INFO  投资组合的总价值 984052.608
    2020-01-02  INFO  --------------------------
    2020-01-03  WARN  订单创建失败: 下单量为0
    2020-01-03  INFO  ['000001.XSHE', '000002.XSHE']
    2020-01-03  INFO  平安银行的仓位数: 5730
    2020-01-03  INFO   万科的仓位数: 3000
    2020-01-03  INFO  StockAccount({'positions': ['000002.XSHE', '000001.XSHE'], 'margin': 194591.39999999997, 'frozen_cash': 0.0, 'market_value': 194591.39999999997, 'total_value': 984051.91946, 'cash': 789460.5194600001, 'trading_pnl': -292.05999999999995, 'position_pnl': 298.99999999997704, 'transaction_cost': 7.62854, 'daily_pnl': -0.6885400000228401, 'dividend_receivable': 0, 'type': 'STOCK', 'total_cash': 789460.5194600001})
    2020-01-03  INFO  投资组合的可用资金 789460.5194600001
    2020-01-03  INFO  投资组合的当前市场价值 194591.39999999997
    2020-01-03  INFO  投资组合的总价值 984051.91946
    2020-01-03  INFO  --------------------------
    ……
    

    在这里插入图片描述

    2.5 策略评价指标

    ➢ 收益指标

    回测收益率: 策略在期限内的收益率。

    回 测 收 益 率 = 期 末 投 资 组 合 总 权 益 − 期 初 投 资 组 合 权 益 期 初 投 资 组 合 总 权 益 回测收益率=\frac{期末投资组合总权益-期初投资组合权益}{期初投资组合总权益} =
    基础收益: 参考的标准,市场表现情况来作为标准来看我们的策略。回测收益比基准收益大,则策略表现越好。默认以HS300的总体表现来作为基准,也就是说我们的基准要比沪深300的基准要更好一些。

    回测年化收益: 如果不足一年,会根据当前几个月份的收益表现来计算一年可能的收益。我们一般以年化收益率取比较的策略的

    年 化 收 益 率 = ( 1 + R ) 1 t − 1 年化收益率=(1+R)^\frac{1}{t}-1 =(1+R)t11
    t = 策 略 运 行 累 计 自 然 日 数 量 365 t=\frac{策略运行累计自然日数量}{365} t=365
    R = 累 计 收 益 率 R=累计收益率 R=

    对于股票来讲,年化收益达到 15~30% 已近是非常好的策略了,年化收益率越高越好。

    ➢ 风险指标

    最大回撤: 最大回撤比率越小越好,最好保持在10%~30%之间。

    夏普比率: 与无风险利率进行比较。夏普比率越大,说明单位风险所获得的风险回报越高。举例而言,假如国债的回报是4%,而您的投资组合预期回报是16%,您的投资组合的标准偏差是5%,那么用16%-4%,可以得出12%(代表您超出无风险投资的回报),再用12%÷5%=2.4,代表投资者风险每增长1%,换来的是2.4%的多余收益。夏普比率越大,说明单位风险所获得的风险回报越高。

    夏普比率越高越好,达到1.5及其以上已经是很好的结果。

    我们一般关注回测收益、基准收益、回测年化收益和基准年化收益以及最大回撤和夏普比率。

    2.6 实现第一个股票策略

    需求:选股和调仓。选股要求获取市盈率大于50且小于65、营业总收入前10的股票。调仓要求每日调仓,将所有的资金平摊到这10个股票的购买策略中,一次性卖出所有不符合条件的股票(昨天有今天没有的股票)。一般回测的是5~10年之间的数据:

    第一个股票策略:

    # 可以自己import我们平台支持的第三方python模块,比如pandas、numpy等。
    # 选股:获取市盈率大于50且小于65、营业总收入前10的股票
    # 买卖:将所有的资金平摊到这10个股票的购买策略中,一次性卖出所有不符合条件的股票
    # 调仓:这里按月调仓
    
    # 在这个方法中编写任何的初始化逻辑。context对象将会在你的算法策略的任何方法之间做传递。
    def init(context):
        # 在context中保存全局变量
        # context.s1 = "000001.XSHE"
        # 交易日是每月的1号
        scheduler.run_monthly(get_data, tradingday=1)
    
    def get_data(context, bar_dict):
        # 选股
        q = query(
            fundamentals.eod_derivative_indicator.pe_ratio,
            fundamentals.income_statement.revenue
        ).filter(
            fundamentals.eod_derivative_indicator.pe_ratio > 50,
            fundamentals.eod_derivative_indicator.pe_ratio < 65 # 也可以分开过滤
        ).order_by(
            fundamentals.income_statement.revenue.desc()
        ).limit(10)
        fund = get_fundamentals(q)
        # logger.info(fund.T)
        # logger.info(type(fund))
        context.stock_list = fund.T.index
        # logger.info(context.stock_list)
    
    # before_trading此函数会在每天策略交易开始前被调用,当天只会被调用一次
    def before_trading(context):
        pass
    
    # 你选择的证券的数据更新将会触发此段逻辑,例如日或分钟历史数据切片或者是实时数据切片更新
    def handle_bar(context, bar_dict):
        # 开始编写你的主要的算法逻辑
    
        # bar_dict[order_book_id] 可以拿到某个证券的bar信息 
        # context.portfolio 可以拿到现在的投资组合信息
    
        # 使用order_shares(id_or_ins, amount)方法进行落单
    
        # TODO: 开始编写你的算法吧!
        # 查看仓位信息
        # logger.info(context.portfolio.positions) # list类型
        # 先判断仓位是否有股票,再判断旧的持有的股票是否在新的股票池中,如果没有则卖出
        if len(context.portfolio.positions) != 0:
            for stock_item in context.portfolio.positions:
                # 如果旧的持有的股票不在新的股票池中则卖出
                if stock_item not in context.stock_list:
                    order_target_percent(stock_item, 0)
        # 买入每日更新的股票池中的新增加的股票
        # 等比例买入,投资组合总价值的百分比平分10份
        for stock_item in context.stock_list:
            order_target_percent(stock_item, 0.1)
    
    # after_trading函数会在每天交易结束后被调用,当天只会被调用一次
    def after_trading(context):
        pass
    

    回测结果:
    在这里插入图片描述
    在这里插入图片描述
    如果不太理想,可以进一步调优,可以选择在沪深300中的股票:

    # 可以自己import我们平台支持的第三方python模块,比如pandas、numpy等。
    # 选股:获取市盈率大于50且小于65、营业总收入前10的股票
    # 买卖:将所有的资金平摊到这10个股票的购买策略中,一次性卖出所有不符合条件的股票
    # 调仓:这里按月调仓
    # 调优:过滤HS300的股票
    
    # 在这个方法中编写任何的初始化逻辑。context对象将会在你的算法策略的任何方法之间做传递。
    def init(context):
        # 定义选股范围
        context.hs300 = index_components('000300.XSHG')
        # 交易日是每月的1号
        scheduler.run_monthly(get_data, tradingday=1)
    
    def get_data(context, bar_dict):
        # 选股
        q = query(
            fundamentals.eod_derivative_indicator.pe_ratio,
            fundamentals.income_statement.revenue
        ).filter(
            fundamentals.eod_derivative_indicator.pe_ratio > 50,
            fundamentals.eod_derivative_indicator.pe_ratio < 65 # 也可以分开过滤
        ).order_by(
            fundamentals.income_statement.revenue.desc()
        ).filter(
            fundamentals.stockcode.in_(context.hs300)
        ).limit(10)
        fund = get_fundamentals(q)
        # logger.info(fund.T)
        # logger.info(type(fund))
        context.stock_list = fund.T.index
        # logger.info(context.stock_list)
    
    # before_trading此函数会在每天策略交易开始前被调用,当天只会被调用一次
    def before_trading(context):
        pass
    
    # 你选择的证券的数据更新将会触发此段逻辑,例如日或分钟历史数据切片或者是实时数据切片更新
    def handle_bar(context, bar_dict):
        # 开始编写你的主要的算法逻辑
    
        # bar_dict[order_book_id] 可以拿到某个证券的bar信息 
        # context.portfolio 可以拿到现在的投资组合信息
    
        # 使用order_shares(id_or_ins, amount)方法进行落单
    
        # TODO: 开始编写你的算法吧!
        # 查看仓位信息
        # logger.info(context.portfolio.positions) # list类型
        # 先判断仓位是否有股票,再判断旧的持有的股票是否在新的股票池中,如果没有则卖出
        if len(context.portfolio.positions) != 0:
            for stock_item in context.portfolio.positions:
                # 如果旧的持有的股票不在新的股票池中则卖出
                if stock_item not in context.stock_list:
                    order_target_percent(stock_item, 0)
        # 买入每日更新的股票池中的新增加的股票
        # 等比例买入,投资组合总价值的百分比平分10份
        for stock_item in context.stock_list:
            order_target_percent(stock_item, 0.1)
    
    # after_trading函数会在每天交易结束后被调用,当天只会被调用一次
    def after_trading(context):
        pass
    

    回测结果(效果好了一些):
    在这里插入图片描述

    3. 多因子策略
    3.1 股票量化策略介绍
    展开全文
  • 量化中的机器学习简述

    千次阅读 2019-06-24 17:54:20
    人工智能,特别是机器学习,在最近几年大出风头,无人驾驶汽车,阿尔法狗战胜人类最强棋手,演唱会人脸识别抓捕逃犯,手机多国语言在线翻译,这一切一切无不给我们带来深深的震撼,可以说人工智能将在不久的未来引来...

    在这里插入图片描述
    人工智能,特别是机器学习,在最近几年大出风头,无人驾驶汽车,阿尔法狗战胜人类最强棋手,演唱会人脸识别抓捕逃犯,手机多国语言在线翻译,这一切一切无不给我们带来深深的震撼,可以说人工智能将在不久的未来引来巨大的爆发式增长,对我们每个人的生活带来深刻的影响。

    既然机器学习这么厉害,那么是不是可以让机器帮我们预测市场、选股票,买卖股票,我们只需要坐着看收益就好了,为什么现实不是这样的呢?

    这一节就简单总结一下量化投资中的我们对机器学习需要了解的基本概念。后面再逐个研究算法的实际应用。

    1、机器学习在量化投资领域的现状是怎么样的呢?

    一句话总结:

    机器学习是当前量化投资的一个重要的方向,但是它的效果并不比其他方向的策略更好。

    为什么机器学习在投资领域并无明显优势?
    这个现象在国内国外都是一样,相比之下,国外用机器学习做量化的会比国内多一些。我认为有两个方面原因:

    • 一方面是人才结构决定。机器学习领域的顶级专家,几乎没有投入到量化投资领域的。对机器学习或者说人工智能领域的大牛来说,本身就可以在Google、微软、BAT等大公司获得领导岗位,也可以较容易的自己融资创业,量化投资这种高风险的事情对他们没有吸引力。
    • 另一方面是金融学科性质决定的。金融分析属于非实验性科学,因此无法进行对照实验,虽然存在大量的金融交易数据,但是无法通过设计实验来控制自变量的变化、通过重复性试验来检验提出的假设(比如说机器学习发现的某种选股模式)。如此的数据分析得到的大多是看似显著但实际上是欺骗式的模式(尤其对样本外数据),这个现象称作数据迁就(data
      snooping)。

    2、人工智能、机器学习、深度学习什么关系?
    在这里插入图片描述
    补充:

    • 我们通常说的神经网络,也属于深度学习的范畴。
    • 机器学习中除了深度学习,还有强化学习这样的类别,主要用于电子游戏方面。

    3、怎么理解传统算法和机器学习算法的区别?

    什么是机器学习?
    机器学习是人工智能的一个分支。它的核心就是学习能力。用逻辑化的语言来描述就是:

    通过n个样本数据(训练样本),预测出未知数据(测试样本)的属性。

    它和传统算法的主要差别就是:学习能力,也叫做泛化能力

    • 在传统编程中,开发人员要对程序进行硬编码,对于如何达到结果,需要开发人员自己很清楚。
    • 在机器学习中,是机器去从数据中学习,开发人员未必知道机器是怎么达到结果的。能举一反三,从数据中自我学习,是机器学习算法的主要特性。

    比如:预测股价这个问题,在传统算法中,基本认为是不可行的。但是在机器学习算法中,确是有较大成功概率的。

    4、机器学习包含哪些分类?

    从大体上,我们将机器学习分为监督学习和无监督学习。

    • **监督学习:**训练样本中的“特性”feature对应目标的“标签”labels,通常用来解决以下两类问题:
      分类问题,样本标签属于两类或多类。这通常是离散的数据。
      回归问题,样本标签包括一个或多个连续变量。这通常是连续的数据。

    • **无监督学习:**训练样本的属性不包含对应的“标签”,通常是聚类问题。

    **说明:**从量化投资的角度,我们用得较多的都是监督学习。

    更详细的模型分类如下图:
    在这里插入图片描述

    说明:

    • 有些算法既能够用于处理分类问题,也能用于处理回归的问题,比如支持向量机、决策树等。
    • “降维”算是一种特殊的应用,可以是无监督学习,其实也可以用于监督学习的。

    5、机器学习的基本流程是什么样的?

    就如同人类学习某种技能需要持续练习一样,机器学习某种规律也需要大量的数据进行训练。从开始获取数据、训练机器学习模型到最终模型投入应用,通常需要遵循一些固定的流程。

    下图展示了机器学习的基本框架,主要步骤包括:数据获取、特征提取、数据转换、模型训练、模型选择和模型预测。
    在这里插入图片描述

    6、机器学习的模型怎么选择?

    在模型训练中,针对不同的问题,我们选择什么样的机器学习方法呢,这里列举一些简单的例子:

    • 如果数据中包含特征标签,希望学习特征和标签之间的对应关系,那么可以采用监督学习的方法;
    • 如果没有标签,希望探索特征自身的规律,那么可以采用非监督学习
      如果学习任务由一系列行动和对应的奖赏组成,那么可以采用强化学习
    • 如果需要预测的标签是分类变量,比如预测股票上涨还是下跌,那么可以采用分类方法
    • 如果标签是连续的数值变量,比如预测股票具体涨多少,那么可以采用回归方法
    • 另外,样本和特征的个数,数据本身的特点,这些都决定了最终选择哪一种机器学习方法。

    7、机器学习中有哪些重要的概念?

    在进行模型建立的时候,我们有三种数据集:训练集、验证集、测试集

    • 训练集Training set:用来训练模型的,通常需要的数据量很大。可以理解为机器学习过程中的课本。
    • 验证集Validation set:是用来做模型选择(model selection)、参数优化的,即做模型的最终优化及确定的。可以理解为机器学习过程中的模拟考试。
    • 测试集Test set:纯粹是为了测试已经训练好的模型的泛化(generalization)能力。这既是对机器学习成果的考试了。

    在评价模型效果的时候,有欠拟合、正常拟合和过拟合三种情况:

    • 欠拟合:采用了较少的参数或模型过于简单,训练得到的效果就比较差
    • 正常拟合:采用合适数量的参数和合适复杂度的模型
    • 过拟合:采用过多的参数和过于复杂的模型,模型依赖数据,离开测试集后表现较差,即模型预测效果较差。

    8、机器学习在量化投资中怎么用?

    有人觉得这个问题很奇怪,一点都不。我们要做的是交易系统,要做的是量化投资,不论机器学习还是技术分析都只是工具。那么很自然就会有这样几种用法:

    • 第一个当然是直接用用一个机器学习的模型策略来实现交易系统
    • 第二种方式用机器学习与其他策略结合,增加额外的过滤器
    • 第三种是发挥机器学习算法的优势,把它作为工具,给其他量化策略进行参数优化
    展开全文
  • 我们已经知道,监督学习主要就是分类和回归两种方法。本文以支持向量机(support vector machine,SVM)来说明,如何采取机器学习中回归...这在传统量化中是根本不可能实现的,在机器学习领域却能达到50%以上的胜率。

    我们已经知道,监督学习主要就是分类和回归两种方法。本文以支持向量机(support vector machine,SVM)来说明,如何采取机器学习中回归方法来预测股票价格。这在传统量化中是根本不可能实现的,在机器学习领域却能达到50%以上的胜率。

    1、支持向量机

    支持向量机
    支持向量机是一种监督学习算法,可用于分类和回归问题,如支持分类的 SVC和支持回归的SVR。这是20世纪90年代被开发出来的,直到现在,都是高性能算法的首选,在机器学习领域有极为广泛的应用。

    核心思想
    算法的核心思想是寻找最能将特征分离到不同域的超平面。它的理论根据就是,任何一个P维物体(空间)都可以被一个P-1 维的超平面分成两部分,就像我们可以用刀(二维平面)将西瓜(三维物体)分成两半。

    术语概念
    直接看图吧,我们要图中将红蓝点分开,应该怎么办吧呢。
    在这里插入图片描述

    决策边界
    如图所示,红点和蓝点分别代表两类样本,二维空间中的超平面就是图中的黑色直线。如果一条直线可以让两类样本中的点到这条直线的最短距离取最大值,一般认为这条直线就是最稳定的分界线,在机器学习中我们称之为“决策边界”;
    支持向量:而决定这条直线的点往往是由少数几个支撑点决定的,这些点称为支持向量。就是如下图中红线和蓝线穿过的点。而支持向量与决策边界之间的距离就叫做边距。

    sklearn中如何使用
    这里我们使用的是SVR,直接从sklearn中引用SVR模块就可以了

    from sklearn import svm
    sk_model =svm.SVR(kernel='linear')
    

    这里只有一个关键参数,就是核(kernel)

    • 线性核
    • 多项式核
    • 高斯核

    算法预测的原理
    1)如果用机器学习的语言表述,我们根据已知的“特征”x1 和“标签”y ,通过“训练”得到一个反映两者线性关系的模型。
    2)如果这种关系在未来一段时间内能够延续,那么任意给出一个股票当前时刻的特征因子x1,我们就可以“预测”该股票未来时刻的价格 ?̂ = ?0 +?1?1。
    3)根据已有的特征和标签训练模型,使用新的特征进行预测,两者构成了监督学习最核心的两个环节。

    2、策略描述

    标的选择:沪深300指数
    训练数据:2011~2016年共7年的日线数据
    预测数据:基于训练出的模型,预测2017,2018,2019年每天的涨跌

    数据描述
    在这里插入图片描述
    这个日线数据有以下的字段:
    【ts_code】 股票或基金的代码,上证股票SH结尾,深证股票以SZ结尾
    【trade_date】 交易日期
    【open】 开盘价
    【high】 最高价
    【low】 最低价
    【close】 收盘价
    【change】 涨跌幅,复权之后的真实涨跌幅,保证准确

    策略实现描述

    1. 计算当日~前20日的滚动收盘价,作为我们这里的特征,共21个特征
    2. 采用SVM中的SVR线性回归模型来进行训练
    3. 训练好模型后就可以用来预测第二天的收盘价
    4. 通过将预测到的明日收盘价来和明日开盘价比较,就可以得到涨跌预测
    5. 然后我们根据预测结果计算策略收益,用图形展示出来

    3、代码实现

    代码的基本实现步骤:

    1.准备数据

    index_data,features_train,labels_train= getStockData(“000300.SH”,20,‘20110101’,‘20161231’)

    2.训练模型

    sk_model = trainModel(features_train,labels_train)

    3.验证测试集

    index_test, features_test, labels_test = getStockData(“000300.SH”,20, ‘20170101’, ‘20171231’) predictData(sk_model,features_test,
    labels_test,index_test)

    下面是各个函数的具体实现
    #数据获取和处理

      def getStockData(ts_code,bar_num,start_date,end_date):
                #1.读取数据
                index_data =  pd.read_csv(ts_code+'.csv',parse_dates=['trade_date'])   #parse_dates
                #选取字段
                index_data = index_data[['trade_date','close','open']]
                #按日期排序
                index_data.sort_values(by='trade_date', inplace=True)
                #设置日期索引
                index_data.set_index('trade_date', inplace=True)
                
                #2.特征处理
                #这里以当日收盘价和之前n天的收盘价作为特征
                for i in range(1,bar_num+1):
                    index_data['close_'+str(i)] = index_data['close'].shift(i)            
                #去掉前面的空值
                index_data = index_data[bar_num:]
            
                #3.按日期截取
                index_data = index_data[(index_data.index>pd.to_datetime(start_date))&(index_data.index<pd.to_datetime(end_date))]
            
                #特征数据
                features_data = index_data[[x for x in index_data.columns if 'close' in x]]
                #标签数据
                # 回归问题的标签就是预测的股价,所以下一天的收盘价就是前一天的标签;
                labels_data = index_data['close'].shift(-1)  
                 # 进行训练的数据里不能有nan值,因为这一个值对整体影响可以忽略,可以删除也可以填充,这里采用的填充
                labels_data.fillna(method='ffill', inplace=True) 
            
                return  index_data,features_data,labels_data
    

    模型训练

    def trainModel(features_train,label_train):
        #选择模型
        sk_model =svm.SVR(kernel='linear')
        #训练模型(执行大概需要几分钟时间)
        print("开始训练=========>")
        sk_model.fit(features_train,label_train)
        print("<========= 训练结束")
        return sk_model      
    

    预测价格和计算收益

    def predictData(sk_model,features_data,labels_data,base_data):
        #准备用列表方式构造新dataframe
        date_line = list(labels_data.index.strftime("%Y-%m-%d"))  # 日期序列 将timestamp转换成string
        next_close = list(labels_data)                 #明日的收盘价
        current_close = list(features_data['close'])   #取今日的收盘价
        next_open = list(base_data['open'].shift(-1))  #取明天的开盘价
        
        #预测价格
        predict = sk_model.predict(features_data)
    
        #训练结果评分
        # score = sk_model.score(predict, labels_data)
        # print('预测得分:%.4f'%score)
    
        # 预测的明日收盘价,转换成list
        predict = list(predict)
    
        #构造新的dataframe
        index_data = pd.DataFrame({'date': date_line, 'next_close': next_close,'next_predict':predict,'close':current_close,'next_open':next_open})
        print(index_data.head())
        print(index_data.columns)
    
        #计算持仓
        index_data['position'] = np.where(index_data['next_predict']>index_data['next_open']*(1+0.002),1,0)   #这里设置2/1000的滑点
    
        #模型收益计算和可视化
        index_data['PL'] = np.where(index_data['position']==1,(index_data['next_close']-index_data['next_open'])/index_data['next_open'],0)
        print(index_data.head())
        index_data['strategy'] = (index_data['PL'].shift(1) + 1).cumprod()
        index_data['baseline'] = (index_data['next_close'].pct_change() + 1).cumprod()
        index_data.dropna(inplace=True)
        print(index_data.head())
    
        # 绘制图形
        plt.plot(index_data['strategy'])
        plt.plot(index_data['baseline'])
        plt.legend(loc='best')
        # plt.savefig('1.jpg')
        plt.show()
    

    4、策略效果

    我们用的2011~2016年数据训练好的模型进行预测,下面看先一下对各个时期的预测结果。
    1)对训练数据(2011~2016年)的测试
    在这里插入图片描述
    说明:这结果好到爆有没有,当然,这是训练数据,再好都没有意义的

    2)对2017年数据测试
    在这里插入图片描述
    说明:这个效果也很不错,虽然收益率跟直接持有差不多,但是够平滑

    3)对2018年数据测试
    在这里插入图片描述
    说明:这个效果就很明显了,在大盘大幅下跌的情况下保持了正收益。

    5、总结

    总的来看,这个策略效果还是不错的,但是要注意,只是这样的策略是完全无法用于实战的,本文只是展示了程序实现的逻辑和流程。
    1)一方面,完全没有考虑交易费用、滑点等损耗。
    2)另一方面,单纯用价格预测价格,特征太单一了,可靠性不高。

    扩展练习

    • 选取长度的特征或不同的特征组合
    • 不用线性核,采用多项式核或高斯核
    • 不用支持向量回归,改用其他的回归算法
    展开全文
  • 一、算法交易 利用自动化平台,执行预先设置的一系列规则完成交易行为。 二、量化交易的优势 (一)历史数据评估 (二)执行高效 (三)无主观情绪输入 (四)可度量评价 ...(三)机器学习/人工智能 六、深
  • 机器学习深度学习-量化交易实战项目班视频6.7G Python
  • 机器学习的最新进展正在许多行业中找到商业应用,尤其是金融行业。 本文重点介绍金融的核心功能之一——投资流程中的应用。 这包括回报预测、风险建模和投资组合构建。 该研究通过对近期文献的广泛回顾来评估当前的...
  • 机器学习量化分析学习
  • 机器学习量化投资:避不开的那些事(3)-21页.pdf
  • 机器学习量化投资:避不开的那些事(2)-15页.pdf
  • 机器学习量化投资中的应用

    千次阅读 2020-06-02 09:32:07
    (一)监督学习:对未来事件预测 1、回归——预测连续型目标变量 (1)、OLS 回归 OLS 回归的目标是:求误差的最小平方和。对于线性回归模型, 最小二乘法有解析解: 对于非线性回归而言,最小二乘没有解析解,...
  • 机器学习量化交易-第三课 课件
  • 机器学习量化投资

    千次阅读 2019-05-30 14:47:46
    机器学习任务中,如果使用测试集正确率为依据来调整模型,容易出现过拟合的现象,使得泛化误差很大。通常做法是交叉验证(Cross Validation),根据划分验证集上的平均结果来调整模型,不要过分关心测试集上的结果...
  • 文章目录p21 因子数据的标准化处理p22 市值中心化处理介绍p23 案例:市值中性化实现以及回测选股结果p24 市值中心化结果总结分析p25 总结 平台:...rice quant ipynb p21 因子数据的标准化处理 ...
  • 第4课课件。机器学习量化交易第四课
  • 线上量化交易平台就是为量化投资的策略开发者提供工具、回测模拟、实盘和交流社区的地方。其中最早的是2011年在美国成立的Quantopian。中国的首选平台就是聚宽,其他还有优矿和京东量化。本文档教你十行代码入门量化...
  • 这是一篇对前面部分内容的一个总结,利用机器学习从0到1开发量化选股策略。本篇文章没有代码,只是从文字角度叙述策略开发的流程。 目前有很多量化回测的平台可以供大家开发策略,但使用这些回测平台有个弊端。其...
  • p=17 Python机器学习量化交易 —————————————————— 照着视频码出来的原代码是这样的: # 可以自己import我们平台支持的第三方python模块,比如pandas、numpy等。 # 在HS300,选出市值比较小的10...
  • 夫血肉之身,尚然有数;义理之身,岂不能格天。太甲曰:天作孽,犹可违;自作孽,不可活。诗云:永言配命,自求多福。孔先生算汝不登科第,不生子者,此天作之...前面9篇博文对量化交易的各种图形绘制以及计算公式已经.
  • 【Python量化】使用机器学习预测股票交易信号

    千次阅读 多人点赞 2021-03-05 10:24:13
    01引言近年来,随着技术的发展,机器学习和深度学习在金融资产量化研究上的应用越来越广泛和深入。目前,大量数据科学家在Kaggle网站上发布了使用机器学习/深度学习模型对股票、期货、比特币等...
  • 机器学习之PQ量化算法

    千次阅读 2020-05-25 15:44:05
    什么是PQ量化算法 PQ算法属于一种经典的ANN(approximate nearest neighbor,近似最近邻算法)算法,ANN不是寻找最近邻向量,而是退而求其次寻找近似最近邻向量。所以必然会带来一些误差,为了尽量减少误差,很多...
  • 量化投资与机器学习英文版,主要讲alpha策略如何构建
  • 机器学习量化交易实战 Lecture 03机器学习量化交易实战 Lecture 03
  • 本文原作者:甘泉,经授权后发布。 一、多因子选股背景 量化交易策略无非三点:择时、选股、仓控。择时为短期套利交易策略,选股为中长期交易策略,目标是在中长期跑赢指数、获取市场超额收益率...机器学习量化...
  • 机器学习量化投资:避不开的那些事(1)-20页.pdf
  • 量化投资”是指投资者使用数理分析、计算机编程技术、金融工程建模等方式,通过对样本数据进行集中比对处理,找到数据之间的关系,制定量化策略,并使用编写的软件程序来执行交易,...
  • 手动从无穷多个因子中筛选出几个因子显然不太现实,现在网上的主流思想都是使用线性回归模型以及机器学习模型从众多的因子中筛选出有效因子。 一般投资者构建多因子模型的思路如下: 首先根据自己的喜好人工...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 44,363
精华内容 17,745
关键字:

机器学习量化