65.9K
CodeProject 正在变化。 阅读更多。
Home

C++ 包装器类用于计算移动平均值

starIconstarIconstarIconstarIconstarIcon

5.00/5 (2投票s)

2009年4月28日

CPOL

3分钟阅读

viewsIcon

47921

downloadIcon

753

C++ 包装器类用于计算移动平均值

引言

有时您需要计算某个数量的移动平均值。在本文中,我将描述帮助您计算移动平均值的包装类。有多种方法可以计算移动平均值,例如简单移动平均值、加权移动平均值和指数移动平均值。由于时间限制,我只实现了前两种。

背景

维基百科上有一篇关于移动平均线的好文章:Wikipedia。但是,我将在这里简单介绍一下。

当您测量平均值时,您正在测量整个数据范围内数量的平均值。有时,仅测量最后 N 个样本值的平均值是有用的。例如,交易者可能想知道某只股票过去七天的平均价格,并且他/她每天都想要这个值。这将通过计算移动平均值来完成。每次将新样本添加到数据中时,我们需要丢弃最旧的样本,将新样本添加到数据中并计算平均值。

加权移动平均值是简单移动平均值的修改版本,其中可以根据应用或分析为每个样本分配权重。通常,最近的样本被分配最高的权重,而最近最远的样本被分配最低的权重。

指数加权移动平均值是加权移动平均值的另一种版本,其中权重呈指数增加或减少。

我有两个 C++ 包装类 - CSimpleMovingAverage 用于简单移动平均,CWeightedMovingAverage 用于加权移动平均。这两个类都派生自 CMovingAverage,因此它们提供统一的接口。这样,有人可以将更复杂的移动平均值添加到“库”中。

Using the Code

为了使用 CSimpleMovingAverageCWeightedMovingAverage,您必须首先像这样创建对象

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* 中,我编写了一个最简单的测试用例,我用它来验证代码的正确性。当我在数据中包含负样本值时,我得到了加权移动平均线的奇怪值。我不确定这是代码中的错误还是预期结果?

历史

  • 2009 年 4 月 28 日:初始发布
© . All rights reserved.