使用卷积计算移动平均值

  CSVComma-Separated Value,逗号分隔值)格式是一种常见的文件格式。NumPy中的loadtxt函数可以方便地读取CSV文件,自动切分字段,并将数据载入NumPy数组。 

  我们以某公司的历史股价数据为例展开叙述。股价数据存储在CSV文件中,第一列为yyyy-mm-dd格式的日期,随后各列依次是收盘价、成交量、开盘价、最高价、最低价。下面为前几行数据: 

  我们只关注股票的收盘价和成交量。我们将收盘价和成交量分别载入到两个数组中:

c, v = np.loadtxt('Stock_Prices.csv', delimiter=',', usecols=(1,2), unpack=True)

  可以看到,数据存储在Stock_Prices.csv文件中,delimiter参数指定了文件中的分隔符为英文逗号 ","usecols的参数为一个元组,以获取第1列和第2列的数据,也就是股票的收盘价和成交量数据。 unpack参数设置为True,意思是分拆存储不同列的数据,即分别将收盘价和成交量的数组赋值给变量cv。 

1. 计算成交量平均价格

  VWAP Volume-Weighted Average Price,成交量加权平均价格)是一个非常重要的经济学量,它代表着金融资产的“平均”价格。某个价格的成交量越高,该价格所占的权重就越大。 VWAP就是以成交量为权重计算出来的加权平均值,常用于算法交易。 

import numpy as np

c, v = np.loadtxt('Stock_Prices.csv', delimiter=',', usecols=(1,2), unpack=True)

vwap = np.average(c, weights = v)

print "VWAP =", vwap

The output is
VWAP = 37.00109716 

我们仅仅调用了average函数,并将v作为权重参数使用,就完成了加权平均值的计算。此外, NumPy中也有计算算术平均值的函数mean。 

2. 计算算数平均值

print "mean =", np.mean(c)

mean = 37.0013015873

3. 简单移动平均线

  简单移动平均线(moving average)通常用于分析时间序列上的数据。为了计算它,我们需要定义一个N个周期的移动窗口,在我们的例子中即N个交易日。我们按照时间序列滑动这个窗口,并计算窗口内数据的均值。 

  移动平均线只需要少量的循环和均值函数即可计算得出,但使用NumPy还有更优的选择——convolve函数。简单移动平均线只不过是计算与等权重的指示函数的卷积,当然,也可以是不等权重的。卷积是分析数学中一种重要的运算,定义为一个函数与经过翻转和平移的另一个函数的乘积的积分。 

  按照如下步骤计算简单移动平均线:

  (1) 使用ones函数创建一个长度为N的元素均初始化为1的数组,然后对整个数组除以N,即可得到权重 

N = int(sys.argv[1])
weights = np.ones(N) / N
print "Weights", weights

  在N = 5时,输出结果如下:
  Weights [ 0.2 0.2 0.2 0.2 0.2]

  (2) 使用这些权重值,调用convolve函数:

  c = np.loadtxt('Stock_Prices.csv', delimiter=',', usecols=(1,), unpack=True)
  ma = np.convolve(weights, c)[N-1:-N+1] 

  (3) 使用Matplotlib进行绘图

    在ipython中运行如下代码: %run  calculate_ma.py  5

import numpy as np
import sys
from matplotlib.pyplot import plot
from matplotlib.pyplot import show

N = int(sys.argv[1])
weights = np.ones(N) / N

c = np.loadtxt('Stock_Prices.csv', delimiter=',', usecols=(1,), unpack=True)
ma = np.convolve(weights, c)[N-1:-N+1]

t = np.arange(N - 1, len(c))
plot(t, c[N-1:], lw=1.0)
plot(t, ma, lw=2.0)
show()

  在下图中,相对较平滑的粗线描绘的是5日移动平均线,而锯齿状的细线描绘的是每天的收盘价。 


  •   序列的基本运算

   在数字信号处理中,序列通常有下面几种运算形式:

1. 序列相加

  序列之间的加法,是指两个序列的同序号的值逐项对应相加。即在同一时刻n,对幅值进行叠加:

  $$y(n)=x_1(n)+x_2(n)$$

 2. 序列乘常数

  一个常数乘以序列,是指该常数乘以序列的每一个值,如:

$$y(n)= k \cdot x(n)$$

  k可以是复数也可以是实数。当k为实数,且k>1时,就是通常所说的放大作用,即把序列x(n)的幅度放大了k倍。

3. 序列相乘

  序列之间的乘法,是指两个序列的同序号的值逐项对应相乘:

$$y(n)=x_1(n) \cdot x_2(n)$$

4. 序列移位

  序列x(n)向右(左)平移,是将序列号减去(加上)m(m>0),如:

$y(n)=x(n-m)$,右移m

$y(n)=x(n+m)$,左移m

  下图中分别表示了原序列x(n)、x(n+2)和x(n-1)的图形。由图可见,x(n+2)表示原序列左移2个单位,通常称序列的超前;x(n-1)表示原序列右移1个单位,通常称序列的延时。 作为实现序列延时的实际离散系统就是移位寄存器或存储器。 

 

 5. 序列翻转

  设序列x(n)用下图a表示,其翻转序列x(-n)用图b表示。x(n)与x(-n)关于纵坐标轴对称。

 6. 序列卷积

  两个序列的线性卷积定义为

 $$x(n)*y(n)=\sum_{k=-\infty}^{\infty}x(k)y(n-k)$$

   其中,符号“*”表示一种特定的运算形式,称作“卷积”。

  卷积运算的求解过程为:

  ①. 将x(n)和y(n)用x(k)和y(k)表示,并将y(k)翻转,形成y(-k);

  ②. 将y(-k)移位n,得到y(n-k)。当n>0时,序列右移;当n<0时,序列左移;

  ③. 将x(k)和y(n-k)相同k的序列值对应相乘后,再相加

  按以上3个步骤可得到卷积结果x(n)*y(n)。

  下面通过图例来说明。如计算序列h(n)与x(n)的卷积y(n),先将坐标n换成坐标m,n成为m坐标中的参变量 

  将x(m)沿纵轴翻转得到x(-m)

  将x(-m)的值每次右移一次,分别得到x(1-m),x(2-m),...,x(n-k)。当n<0时(如n=-1),从图中可以看出此时x(n-m)与h(m)没有相互重叠的区域,则卷积为0。

  当n=0时x(-m)与h(m)在m=0点有重叠,故y(0)不为零。以后随着n的增加x(n-m)逐渐右移,x(n-m)与h(m)相互重叠的值也越来越多。当n=时3时,x(3-m)已有一个值移出h(m)所在的区间。当n>5时,x(n-m)已全部移出h(m)所在的区间,此时卷积y(n)又等于零了。

  卷积y(n)波形图(f)所示:

  可以使用numpy中的convolve函数进行验证:

h = np.ones(3)
x = np.array([0.5,1,1.5,2])
y = np.convolve(h, x)

print y

  卷积运算服从交换律: x(n) * y(n) = y(n) * x(n)

  卷积运算服从加法分配律: y(n) * [x1(n) + x2(n)] = y(n) * x1(n) + y(n) * x2(n)

  卷积也服从结合律:x(n) * h1(n) * h2(n) = [x(n) * h1(n)] * h2(n) = [x(n) * h2(n)] * h1(n) = x(n) *[h1(n) * h2(n)] 

7. 序列的能量

  序列的能量定义为序列各采样值的平方和,即

$$E=\sum_{n=-\infty}^{\infty}|x(n)|^2$$

  序列的能量可以是有限的,如能量信号;也可能是无限的,如功率信号。

 

 

 

 

参考:

移动平均

《数字信号处理及应用》  北京邮电大学出版社

posted @ 2016-12-29 15:51  XXX已失联  阅读(5068)  评论(0编辑  收藏  举报