确定稳态向量,马尔科夫链(Markov chain)被用来表示至少有两个状态的系统。有关马尔科夫链的详细信息,请参阅 http://en.wikipedia.org/wiki/Markov_chain。此类系统t时刻的状态仅取决于t-1时刻的状态。系统的当前状态在这些状态之间随机地切换。如果把一支股票的股价变动情况定义为一个马尔科夫链,并定义持平F、上涨U和下跌D这三个状态,则我们可以根据当日收盘价确定其稳态。
在未来某个时刻之后,或者从理论上讲经过无限长时间之后,马尔科夫链系统的状态将不再改变。这个状态被称为稳态。随机矩阵包含了状态之间转移的概率。把随机矩阵A应用于稳态,状态将保持不变,用数学符号表示如下:
也可以把稳态看作特征值为1的特征向量。
具体步骤
现在我们需要先获取数据。
- 获取一年的数据。
获取数据的一种办法是使用Matplotlib(如有必要,请参阅1.5节)。我们将获取从现在算起一年内的数据,相关代码如下。
- 选取收盘价。
我们已经从雅虎财经频道获得了需要的历史数据。这些数据被表示为一个由元组构成的列表,但我们只关心元组中包含的收盘价。历史数据列表的例子如下。
元组中的第一个元素代表日期,后面依次是开盘价、最高价、最低价和收盘价,最后一个元素是成交量。可以用如下方式选择收盘价。
收盘价是每个元组中的第五个数。现在我们获得了一个由大约253个收盘价构成的列表。
- 确定状态数组。
使用NumPy的diff
函数获得两个相邻交易日的收盘价差,进而确定状态数组。状态数组中的每个状态由价差的符号决定。当NumPy的sign
函数的输入参数为负值、正值和零时,其返回结果分别为-1、1和0。
- 初始化随机矩阵。
对于每一次状态转换,其起始状态和结束状态都有三种可能。例如,如果起始状态为U,则可能切换到:
- 状态U
- 状态F
- 状态D
使用NumPy的zeros
函数,对随机矩阵进行初始化。
- 选取每一种符号对应的起始状态索引。
代码现在变得有点复杂了,我们不得不使用循环语句。对每一种可能的符号,使用NumPy的where
函数选取其对应的起始状态索引。这里的k
是一个平滑常数,后面将讨论其作用。
- 平滑处理和随机矩阵。
给定起始状态,可以对每种类型转换发生的次数进行计数。把计数结果除以该起始状态对应的总的转换次数,就能获得随机矩阵中相应的转换概率。顺便说一下,这不是最佳的做法,因为可能会造成过拟合。
在现实生活中,相邻的两个交易日的收盘价有可能相同。但对于易变的股票市场而言,这种可能性很小。对于转换次数为零的情况,一种应对方法是使用加法平滑。基本思路是在转换次数上加一个常数,从而避免出现概率为0的情况。计算随机矩阵中各个元素的代码如下。
上述代码的功能是,对每一种可能的转换类型,基于转换发生的次数和加法平滑技术,计算其转换概率。
使用AAPL(苹果公司)的数据和平滑常数k=1
,得到如下随机矩阵。
- 特征值和特征向量。
为了能得到特征值和特征向量,我们需要使用NumPy的linalg
模块和eig
函数。
eig
函数返回的是一个特征值数组和一个特征向量数组。
选择特征值1对应的特征向量。
现在我们只对特征值1对应的特征向量感兴趣。实际上,特征值可能不会精确地等于1,因此应该设立一个误差边界。可以寻找取值介于0.9和1.1之间的特征值对应的特征向量的索引,代码如下。
本章的完整代码如下。
这段代码的输出结果如下所示。
小结
我们没有对得到的特征向量进行归一化处理。因为我们在处理概率问题,所以特征向量中的各个元素取值之和应该为1。本例介绍了diff
、sign
和eig
函数,它们的功能描述如下。
函数 | 功能描述 |
---|---|
diff |
计算离散差分,默认计算一阶差分 |
sign |
返回数组元素的符号 |
eig |
返回数组的特征值和特征向量 |