在金融分析、统计学和其他领域,移动平均是一种常用的数据平滑技术,用于分析数据的趋势和模式。本文将介绍如何使用C++实现简单移动平均和加权移动平均的计算工具。
移动平均是一种统计方法,用于计算一组数据的平均值,但只关注最近N个数据点。例如,交易员可能对过去七天某股票的平均价格感兴趣,并希望每天都能得到这个值。这就是通过计算移动平均来实现的。每当有新的样本数据加入时,就需要丢弃最旧的样本,添加新的样本,并重新计算平均值。
加权移动平均是简单移动平均的改进版本,其中每个样本可以根据应用或分析的需要分配不同的权重。通常,最近的样本被赋予最高的权重,而最不最近的样本被赋予最低的权重。
指数加权移动平均是加权移动平均的另一种版本,其中权重以指数方式增加或减少。
实现了两个C++包装类:
这两个类都继承自CMovingAverage,以便它们提供统一的接口。这样,用户可以方便地向“库”中添加更复杂的移动平均计算方法。
要使用CSimpleMovingAverage或CWeightedMovingAverage,首先需要像这样创建对象:
CSimpleMovingAverage movingAvgCtr;
这两个类实现了两个非常直观的方法:
virtual void AddSample(const float a_fSample) = 0;
virtual float GetAverage() const = 0;
默认情况下,类将计算最近10个样本的平均值。如果想有一个更大的样本间隔,可以将所需的样本大小传递给构造函数:
CSimpleMovingAverage movingAvgCtr(20);
现在,要开始获取平均值,需要使用AddSample方法添加样本:
movingAvgCtr.AddSample(44.5);
可以随时使用GetAverage()方法获取移动平均值。
在内部,样本使用STL队列容器进行维护。由于在获得N个样本后需要丢弃最近的样本并添加新的样本,发现队列的push、pop、front和back操作在编码时非常直观。
编写这段代码的原因是,当需要它时,在网上找不到任何C++代码。知道这些类在某些方面有所欠缺。在CWeightedMovingAverage中,将最近的样本赋予最高的权重,但有人可能想要反过来,将最不最近的样本赋予最高的权重(为什么?这取决于应用,不幸的是,对统计学的理解不够,所以不知道)。当然,指数移动平均也没有包含在库中。
一个弱点是写的自动化测试用例不够多。在main.cpp中,编写了一个最小化的测试用例,用来验证代码的正确性。当在数据中包含负样本值时,得到了加权移动平均的奇怪值。不确定这是否是代码中的bug,还是预期的结果?