豪爽的麦片 · 关于任命潘珑方等46人为公证员的公告· 7 月前 · |
多情的烈酒 · 毫不动摇坚持和加强党对一切工作的领导· 9 月前 · |
热心的春卷 · 傅首尔背后的男人,用整片鱼塘圈养的一条“咸鱼 ...· 1 年前 · |
作者:WI
编译:叶别 | 公众号翻译部
近期原创文章:
本文亮点
1、可扩展的基础架构,数据获取方便;
2、Python编程技术应用;
3、编程、计量经济学、强化学习的基础概念;
4、超全策略代码;
本推文会介绍如何在利用股票分钟数据,基于强化学习来做配对交易。包括基本概念和具体实现;这里采用的强化学习方法,是类似多臂老虎机(N-armed bandit)问题。
获取全部代码,见文末
数据获取
▍Tiingo 数据源
Tiingo是一个金融研究平台,提供包括新闻、基本面和股票价格在内的数据。我们可以通过其REST IEX API提取日内股票市场数据,该API从IEX交易所检索到TOPS数据(最高价/最低价/开盘/收盘价)。
举个例子,可以通过访问以下链接来获取苹果公司在2019年1月2号中每5分钟的股价。
https://api.tiingo.com/iex/aapl/prices?startDate=2019-01-02&endDate=2019-01-02&resampleFreq=5min&token=ef79e455ba9b04c3df719407e34f05e1b051b4d6
json返回结果:
为了使任务自动化,我们提供了一个能够在指定历史窗口内获得股票列表的标准化的日内数据的函数。
不足之处有:
1、最多提供1分钟级别的数据;
2、不同股票可以查询到的股价的天数不是固定的,即使指定365天的窗口,也可能只获得几天的数据;
3、不同股票在一天之内可以查询到的时间段也不是固定的(可能某些股票开盘后了才能查到股价);查询速度不是很快。
解决方案:
1、一次只查询一只股票、只查询一天的数据;
2、对查询到的多个时间段的数据,用固定窗口去截断(比如限制每天只取391分钟的数据);
3、异步IO。
Pandas提供了相关工具,可以从Tiingo和其它类似数据集中提取数据,但目前只提取天级别的数据。 虽然API是免费的,不过使用时也请注意调用方法,避免请求过多超出限制。
▍实现
首先注册账号、申请:
token:https://api.tiingo.com/account/api/token
介绍下Data/API.py下面的几个主要函数:
1.生成获取股价数据的url,参数有股票名(ticker),时间(target_date),请求频次(freq),token;
2. 获取json数据:
以上两个函数是放在Data/API.py 文件中的Tiingo 类下面的;可以根据输入不同重复执行。
▍异步IO
上面实现是有局限性的、性能也比较差。 每获取一条数据时,程序会建立API连接、从服务器请求数据、等待响应,重复请求直到完成所有的URL。异步IO的处理方式是不同的,下面这段代码是用异步IO的方式来获取Google和Facebook在20180101到20180131这段时间内的交易数据(每天391分钟数据, 319*24个交易日*2只股票,共约15600条数据)。可以看出, 相比于非异步请求,性能提升了17倍(1.38s->23.58s)。
asyncio是一个使用async / await方式的并发编程的库,asyncio用作多个Python异步框架的基础,这些框架提供高性能的网络和Web服务器、数据库连接库、分布式任务队列等。AsyncIO是单线程的,它使用一个单事件处理器来组织任务分配、以便多个任务可以在其他任务空闲时开始运行。
下面有个官方示例来展示asyncio的思想。
程序地址:
https://python.readthedocs.io/fr/latest/library/asyncio-task.html
https://python.readthedocs.io/fr/latest/library/asyncio-task.html
上面程序中的关键字 async def 将相应的函数定义为可以暂停或恢复执行的协程。 每当任务运行到在关键字 await 处,将回传一个事件控制器( loop ),该事件控制器再唤起另一个任务。 简单来说,这种方式不会浪费等待时间。
在我们的代码中也有类似的方法, _fetch_hist_async 将创建一个事件循环来控制 fetch_data_async 进程( fetch_data_async 是获取日内价格的基础任务); 遇到await时控制器返回到事件循环,即使前一个请求尚未完成,也会触发另一个请求。
_fetch_hist_async in class Tiingo
fetch_data_async in class Tiingo
▍数据存储
把数据用.csv格式保存到STATICS/PRICE目录下。
代码结构
获取全部代码,见文末
配对交易的概念和分析
▍配对交易
配对交易是市场中性策略
Gatev 等人这样描述:
“配对交易的概念非常简单, 找出价格在历史上一起变化的两只股票, 当它们之间的差距扩大时,做多价低者、做空价高者。如果历史重演,价格差距会收敛,套利者会获利。”
这里包含两个方阶段:
1、规则制订阶段:测量股票之间的价格关系,寻找潜在的股票配对。
2、在交易期间,监控股价变动,并根据预定义的规则进行交易。
Krauss (2017) 总结了配对交易的5种类型:距离法,协整方法,时间序列法,随机控制法和其他方法如机器学习、主成分分析、copula等。 本文是把经典的Engle和Granger(1987)协整方法和强化学习算法结合起来的应用 。
这里我们会用时间序列分析中的平稳性的概念, 在金融时间序列中通常用的是弱平稳性(或协方差),并遵从3个准则:
1、随机变量x的均值E[x(t)]: 该均值和时间t独立;
2、方差Var(x(t)):大于0且有限的值、且与时间t独立;
3、协方差Cov(x(t),x(s)):和t-s相关,但与单独的t和s独立。x(t)一般可以是对数股价收益(或差分),而不是价格本身。 如果一个时间序列的一阶差分平稳了,就是所谓的一阶单整I(1)。
虽然有些交易可以从定向投注中获利,但这不是我们关注的, 我们真正想要的是找到一对价格差异或价差始终保持稳定(并且协整)的股票。
▍分析(见EXAMPLE/Analysis.py)
我们抽取了20180101-20180731期间的21只美股的1分钟级别的数据,用.csv格式保存在STATICS/PRICE目录下。对时间段前70%的数据,我们来进行一些分析。
▍Pearson 相关系数
先看下代码:
看下结果:
上图可以看出,最高相关性位于PEP(百事可乐)/PG(保洁)/JNJ(强生)/KO(可口可乐)这四只股票之间。从经济角度来看,可以形成两组配对:JNJ-PG和KO-PEP。 不过需要注意的是高相关性并不一定意味着协整。
▍边缘分布
如果我们画出以上股票对的边缘分布,可以看到线性相关和一些簇的关系。
代码如下:
效果如下:
▍价格图表
我们创建一个函数来绘制样本期间的价格和价差, 价格在开始时重新定为1;其中第二个子图中的th是交易阈值(买点和买点),stop_loss是止损点。
代码如下:
效果如下:
▍协整检验
以下代码计算协整检验的p值,如果p值很小观察协整关系的概率应该相对较高。
代码如下:
但是相关性并不等于协整。即使两对股票的相关性是差不多的,但协整关系的概率差别比较大。
有时我们可以找到相关但不是协整的价格关系。 例如如果两种股票价格随着时间一起上涨,则它们是正相关的; 然而如果这两只股票以不同的速度上涨,价差将继续增长而不是在均衡时振荡,因此是非平稳的。
下面给出一个例子, 用代码通过几何布朗运动(Geometric Brownian Motion)和Cholesky分解模拟两个相关的股票 ,每个包含1000个样本。
可以看到虽然很相关,但是p值却非常大。
画出时间序列上的图:
上图中的第2个子图中显示了价差不断变大,而不是均值回归。
▍协整
1987年Engle和Granger提出的协整理论,虽然一些变量的本身是非平稳序列,但是它们的线性组合却有可能是平稳序列。
这种平稳的线性组合被称为协整方程,且可解释为变量之间的长期稳定的均衡关系。具体地,如果两个I(1)对数股票价格x(1,t)和x(2,t)有协整关系,那么存在一个系数b和一个平稳的时间序列y(t), 使得:
其中a是一个固定常数,y(t)是目标的平稳的价差。 显然,我们可以简单地使用普通最小二乘方法来估计价差y和系数b,通过将x(1,t)来对x(2,t)做回归。
▍协整检验
测试协整的最常用方法是DF方法(Dickey Fuller)或ADF方法(Augmented Dickey Fuller)。
▍单位根和DF检验
对于一个简单的一阶自回归AR(1)模型
其中e(t)是白噪声,t是时间, xt是要检验的变量;如果c=1则说明单位根是存在的。
DF检验是用来测试一个自回归模型是否存在单位根,把上面的回归模型改写为:
c=1也就意味着零假设c-1=0。 我们还可以添加截距或趋势项,并根据假设测试系数等于零的零假设。
▍ADF检验
把DF检验中用到的AR(1)自回归改为高阶自回归AR(p),那么就是ADF检验。
AR(p):
残差形式:
对应的零假设是:
▍实现部分
我们在策略类EGCointegration中实现了上面的分析。 请注意,此处的检验是基于statsmodels.tsa.stattools.coint,在同一库中还有另一个函数statsmodels.tsa.stattools.adfuller是用来用于单元根检验的。
不同之处在于:
1、 coint 实际上是Engle-Granger协整检验,有2个时间序列输入,计算残差、对残差做检验;
2、 adfuller 是一个时间序列的输入,检验的是单变量的单位根。大部分场景下两个检验得出的结论是一致的,但是coint方法实现起来更直观。
强化学习的介绍
▍基础概念
强化学习有两个元素: Agent和环境(Environment)。 环境由具有预定义状态空间(State)的不同状态表示,而Agent学习一个策略(Policy)来确定要在动作空间(Action)中执行哪个动作。 Agent的学习周期可归纳为以下几个阶段:
1、观察环境状态
2、根据现有Policy相应地采取动作
3、收到执行动作的相应奖励(Reward)
4、更新Policy
举个例子,假设一只小狗(Agent)正在学习如何对他主人的命令(环境)作出反应。 它是一只懒狗,只知道如何执行三个命令: