前面我們討論過(guò)"C#實(shí)現(xiàn)加權(quán)平均法",今天我們繼續(xù)研究另外一種【移動(dòng)加權(quán)平均法】。
在時(shí)間序列分析、股票數(shù)據(jù)處理、工業(yè)信號(hào)平滑等場(chǎng)景中,移動(dòng)平均(Moving Average) 是最常見(jiàn)的平滑技術(shù)之一。相比簡(jiǎn)單移動(dòng)平均(SMA),移動(dòng)加權(quán)平均(WMA) 會(huì)給更靠近當(dāng)前時(shí)刻的數(shù)據(jù)分配更高的權(quán)重,能更敏銳地反映趨勢(shì)變化。
本文會(huì)深入了解如下內(nèi)容:
- ? 使用 C# 編寫(xiě)一個(gè)通用的 WMA 實(shí)現(xiàn)
什么是移動(dòng)加權(quán)平均(WMA)?
移動(dòng)加權(quán)平均(Weighted Moving Average, WMA)與簡(jiǎn)單移動(dòng)平均(Simple Moving Average, SMA)的區(qū)別在于:
- ? SMA 是把窗口內(nèi)的值等權(quán)重平均;
- ? WMA 則對(duì)窗口內(nèi)的值分配不同的權(quán)重,通常是離當(dāng)前點(diǎn)越近,權(quán)重越大。
舉個(gè)例子:
- ? 對(duì)于長(zhǎng)度為 5 的窗口,權(quán)重可能是 [1, 2, 3, 4, 5],最新值乘以 5,最舊值乘以 1。
算法思路
對(duì)于一個(gè)時(shí)間序列:
- 1. 定義窗口大小
n
,以及對(duì)應(yīng)的權(quán)重列表 [w1, w2, ..., wn]
- 2. 從頭到尾滑動(dòng)窗口,每個(gè)位置計(jì)算:
- 3. 對(duì)每個(gè)位置輸出對(duì)應(yīng)的 WMA。
C# 實(shí)現(xiàn)示例
下面是一份使用 .NET 6/C# 10 的 WMA 完整示例:
using System;
using System.Collections.Generic;
using System.Linq;
namespaceWeightedMovingAverageDemo
{
classProgram
{
static void Main(string[] args)
{
// 原始數(shù)據(jù)序列
List<double> data = new() { 10, 20, 30, 40, 50, 60, 70, 80, 90, 100 };
// 設(shè)置窗口大小
int windowSize = 3;
// 設(shè)置權(quán)重(例如 1, 2, 3,離當(dāng)前位置越近權(quán)重越大)
List<double> weights = new() { 1, 2, 3 };
List<double> result = CalculateWeightedMovingAverage(data, windowSize, weights);
Console.WriteLine("移動(dòng)加權(quán)平均結(jié)果:");
Console.WriteLine(string.Join(", ", result.Select(x => x.ToString("F2"))));
}
/// <summary>
/// 計(jì)算移動(dòng)加權(quán)平均數(shù)
/// </summary>
static List<double> CalculateWeightedMovingAverage(List<double> data, int windowSize, List<double> weights)
{
if (weights.Count != windowSize)
thrownew ArgumentException("權(quán)重?cái)?shù)量必須等于窗口大小。");
List<double> result = new();
for (int i = 0; i <= data.Count - windowSize; i++)
{
double weightedSum = 0;
double weightSum = weights.Sum();
for (int j = 0; j < windowSize; j++)
{
weightedSum += data[i + j] * weights[j];
}
result.Add(weightedSum / weightSum);
}
return result;
}
}
}
代碼解析
1?? 輸入數(shù)據(jù)
- ?
data
:原始時(shí)間序列,如傳感器數(shù)據(jù)、股價(jià)等。 - ?
windowSize
:滑動(dòng)窗口大小。 - ?
weights
:自定義權(quán)重列表,元素個(gè)數(shù)必須與窗口大小一致。
2?? 算法核心
- ? 外層循環(huán):從頭到尾滑動(dòng)窗口。
- ? 內(nèi)層循環(huán):窗口內(nèi)每個(gè)值乘以權(quán)重累加。
- ? 用加權(quán)和除以權(quán)重之和,得出 WMA。
3?? 返回值
- ? 返回一個(gè)新的列表,長(zhǎng)度是
data.Count - windowSize + 1
。
輸出結(jié)果
輸入數(shù)據(jù):
10, 20, 30, 40, 50, 60, 70, 80, 90, 100
窗口大小:3
權(quán)重:[1, 2, 3]
輸出:
---解釋?zhuān)?/span>
- ? 第一個(gè)窗口
(10,20,30)
=> (10×1 + 20×2 + 30×3)/6 = 23.33 - ? 第二個(gè)窗口
(20,30,40)
=> (20×1 + 30×2 + 40×3)/6 = 33.33
?? 小結(jié)
本篇演示了:
- ? 移動(dòng)加權(quán)平均的核心原理
- ? 使用 C# 編寫(xiě)通用實(shí)現(xiàn)
- ? 靈活設(shè)置權(quán)重,提升趨勢(shì)檢測(cè)的靈敏度
在工業(yè)生產(chǎn)、金融數(shù)據(jù)分析、實(shí)時(shí)信號(hào)濾波等場(chǎng)景,都可以直接使用此實(shí)現(xiàn),或者把它封裝為工具類(lèi)。
閱讀原文:原文鏈接
該文章在 2025/7/18 10:46:16 編輯過(guò)