复制利用谷歌趋势量化金融市场的交易行为
这是发表于《自然》的一篇论文:
Quantifying Trading Behavior in Financial Markets Using Google Trends.
翻译为:利用谷歌趋势量化金融市场的交易行为。
第一部分介绍了 Pandas 的基础知识以及如何使用它来分析财务数据。
在第二部分,我们将重申这些概念,通过应用它们来重现最近发表的一篇关于使用谷歌趋势搜索量搜索特定术语的论文(例如 ‘debt’(债务))来预测市场走势。有几个单元格是空的,供您填写。
此外,我们将看到如何使用 Pandas 测试实际的交易策略并计算其性能。
先导入所有需要的包
import datetime # 日期时间库
import numpy as np # 数组数学库
import pandas as pd # numpy的数据分析工具,建议0.19版本以上
import pandas_datareader as pdr # 原pandas.io,一般用作财经工具,建议0.8.1以上
import matplotlib.pyplot as plt # 绘图库,最常用的可视化工具之一
import tushare as ts # 财经数据接口包
import matplotlib as mpl # 绘图库,最常用的可视化工具之一
再调整一下
mpl.rc('figure', figsize=(8, 7))
Tobias Preis
非常好心地向我提供了这份出版物中使用的数据。有许多谷歌趋势搜索词,但在这里我们将只使用 ‘debt’ 。
data = pd.read_csv('data/GoogleTrendsData.csv', index_col='Date', parse_dates=True)
data.head()
djia debt
Date
2004-01-14 10485.18 0.210000
2004-01-22 10528.66 0.210000
2004-01-28 10702.51 0.210000
2004-02-04 10499.18 0.213333
2004-02-11 10579.03 0.200000
接下来构图:
data.plot(subplots=True)
----------result----------
array([<matplotlib.axes._subplots.AxesSubplot object at 0x000001E772A065F8>,
<matplotlib.axes._subplots.AxesSubplot object at 0x000001E774D32320>],
dtype=object)
plt.show()
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yQb4EJEB-1586415134516)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20200403153733407.png)]
作者通过形成移动平均线并测试当前值是否与过去3周的移动平均线相交,来检测搜索量在任何给定的周内是否相对增加或减少。
我们先来计算移动平均线。
data['debt_mavg'] = pd.rolling_mean(data.debt, 3)
data.head()
----------result----------
djia debt debt_mavg
Date
2004-01-14 10485.18 0.210000 NaN
2004-01-22 10528.66 0.210000 NaN
2004-01-28 10702.51 0.210000 0.210000
2004-02-04 10499.18 0.213333 0.211111
2004-02-11 10579.03 0.200000 0.207778
因为我们想看看当前值高于均线的前述几个星期,所以我们必须将移动平均时间序列向前移动一下。
data['debt_mavg'] = data.debt_mavg.shift(1)
data.head(10)
----------result----------
djia debt debt_mavg
Date
2004-01-14 10485.18 0.210000 NaN
2004-01-22 10528.66 0.210000 NaN
2004-01-28 10702.51 0.210000 NaN
2004-02-04 10499.18 0.213333 0.210000
2004-02-11 10579.03 0.200000 0.211111
2004-02-19 10714.88 0.203333 0.207778
2004-02-25 10609.62 0.200000 0.205555
2004-03-03 10678.14 0.200000 0.201111
2004-03-10 10529.48 0.196667 0.201111
2004-03-17 10102.89 0.196667 0.198889
生成命令信号
摘要:
“我们使用谷歌趋势来确定n(t - 1)
对特定的搜索项进行了多少次搜索,比如第t - 1
周的债务,谷歌将周定义为在周日结束,与在此期间谷歌上执行的搜索总数相关。”
并且
“我们实现这个策略通过出售道琼斯工业指数的收盘价p (t)的第一个交易日周t,如果Δn (t−1,Δt) > 0,和购买道琼斯工业指数的价格p (t(1)第一个交易日结束时的下周。[…]。如果Δn (t−1,Δt) < 0,那么我们购买道琼斯工业指数的收盘价p (t)的第一个交易日周t和出售道琼斯工业指数的价格p (t 1)在未来一周的第一个交易日。”
data['order'] = 0
data['order'][data.debt > data.debt_mavg] = -1 # Short if search volume goes up relative to mavg.
data['order'][data.debt < data.debt_mavg] = 1 # Long if search volume goes down relative to mavg.
data.head(10)
----------result----------
djia debt debt_mavg order
Date
2004-01-14 10485.18 0.210000 NaN 0
2004-01-22 10528.66 0.210000 NaN 0
2004-01-28 10702.51 0.210000 NaN 0
2004-02-04 10499.18 0.213333 0.210000 -1
2004-02-11 10579.03 0.200000 0.211111 1
2004-02-19 10714.88 0.203333 0.207778 1
2004-02-25 10609.62 0.200000 0.205555 1
2004-03-03 10678.14 0.200000 0.201111 1
2004-03-10 10529.48 0.196667 0.201111 1
2004-03-17 10102.89 0.196667 0.198889 1
计算回报
data['ret_djia'] = data.djia.pct_change()
data.head()
----------result----------
djia debt debt_mavg order ret_djia
Date
2004-01-14 10485.18 0.210000 NaN 0 NaN
2004-01-22 10528.66 0.210000 NaN 0 0.004147
2004-01-28 10702.51 0.210000 NaN 0 0.016512
2004-02-04 10499.18 0.213333 0.210000 -1 -0.018998
2004-02-11 10579.03 0.200000 0.211111 1 0.007605
第 t 周的收益与第 t-1 周有关。然而,我们在第 t 周买入,然后在 t+1 周卖出,因此 我们必须通过提高回报率来进行调整。
data['ret_djia'] = data['ret_djia'].shift(-1)
data.head()
----------result----------
djia debt debt_mavg order ret_djia
Date
2004-01-14 10485.18 0.210000 NaN 0 0.004147
2004-01-22 10528.66 0.210000 NaN 0 0.016512
2004-01-28 10702.51 0.210000 NaN 0 -0.018998
2004-02-04 10499.18 0.213333 0.210000 -1 0.007605
2004-02-11 10579.03 0.200000 0.211111 1 0.012841
作者使用的算法是在每周一做出做多或做空道琼斯的决定。过了这个星期,我们退出所有的仓位( 如果我们渴望,就卖;如果我们做空,就买 ),然后做出一个新的交易决定。
ret
列包含每周回报。因此,如果我们在第 t
周买,在第 t+1
周卖,我们就得到了第 t+1
周的回报。相反,如果我们在第 t
周做空,在第 t+1
周买回,我们得到的是 t+1
周的负回报。
# 计算我们的策略回报
data['ret_google'] = data.order * data.ret_djia
data.head(10)
----------result----------
djia debt debt_mavg order ret_djia ret_google
Date
2004-01-14 10485.18 0.210000 NaN 0 0.004147 0.000000
2004-01-22 10528.66 0.210000 NaN 0 0.016512 0.000000
2004-01-28 10702.51 0.210000 NaN 0 -0.018998 -0.000000
2004-02-04 10499.18 0.213333 0.210000 -1 0.007605 -0.007605
2004-02-11 10579.03 0.200000 0.211111 1 0.012841 0.012841
2004-02-19 10714.88 0.203333 0.207778 1 -0.009824 -0.009824
2004-02-25 10609.62 0.200000 0.205555 1 0.006458 0.006458
2004-03-03 10678.14 0.200000 0.201111 1 -0.013922 -0.013922
2004-03-10 10529.48 0.196667 0.201111 1 -0.040514 -0.040514
2004-03-17 10102.89 0.196667 0.198889 1 -0.003775 -0.003775
现在我们只需要计算复利。当我们把赚来的钱进行再投资时,回报实际上不是把它们加起来计算的,而是用它们的累计乘积计算的:
i t = ( i t − 1 + i t − 1 ⋅ r t ) = ( 1 + r t ) ⋅ i t − 1 , i 0 = 1 i_t = (i_{t-1} + i_{t-1} \cdot r_t) = (1 + r_t) \cdot i_{t-1}, \quad i_0 = 1 it=(it−1+it−1⋅rt)=(1+rt)⋅it−1,i0=1
plt.figure(figsize=(10, 3))
(1 + data.ret_google).cumprod().plot()
plt.ylabel('Portfolio value')
----------result----------
Text(0, 0.5, 'Portfolio value')
plt.show()
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SqfGC5Z5-1586415134517)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20200403175525081.png)]
限制
我们已经看到, Pandas
可以非常灵活而强大地处理时间序列财务数据。
使用一些基本的金融数学,我们甚至可以实现一个简单的回测。
然而,如果我们真的想在现实世界中运行这个我们在这里忽略了的策略,就会涉及到很多复杂性:
- 容易产生误差
- 没有考虑交易成本
- 我们自己的订单对价格的影响。
- 预测偏差: 我们可以获得整个历史,这使得我们很容易使用我们无法获得的信息。
因此,为了真正正确地反测试一个策略,我们需要模拟所有这些东西。