前言
歡迎關注dotnet研習社,前面我們討論過"C#實現加權平均法",今天我們繼續研究另外一種【移動加權平均法】。
在時間序列分析、股票數據處理、工業信號平滑等場景中,移動平均(Moving Average) 是最常見的平滑技術之一。相比簡單移動平均(SMA),移動加權平均(WMA) 會給更靠近當前時刻的數據分配更高的權重,能更敏銳地反映趨勢變化。
本文會深入了解如下內容:
- 快速理解 WMA 的原理
- 使用 C# 編寫一個通用的 WMA 實現
- 提供完整示例和代碼解析
什么是移動加權平均(WMA)?
移動加權平均(Weighted Moving Average, WMA)與簡單移動平均(Simple Moving Average, SMA)的區別在于:
- SMA 是把窗口內的值等權重平均;
- WMA 則對窗口內的值分配不同的權重,通常是離當前點越近,權重越大。
舉個例子:
- 對于長度為 5 的窗口,權重可能是 [1, 2, 3, 4, 5],最新值乘以 5,最舊值乘以 1。
算法思路
對于一個時間序列:
-
定義窗口大小
n
,以及對應的權重列表[w1, w2, ..., wn]
-
從頭到尾滑動窗口,每個位置計算:
WMAt=∑i=1nxt?i+1?wi∑i=1nwi WMA_t = \frac{\sum_{i=1}^{n} x_{t-i+1} \cdot w_i}{\sum_{i=1}^{n} w_i} WMAt?=∑i=1n?wi?∑i=1n?xt?i+1??wi??
-
對每個位置輸出對應的 WMA。
C# 實現示例
下面是一份使用 .NET 6/C# 10 的 WMA 完整示例:
using System;
using System.Collections.Generic;
using System.Linq;namespace WeightedMovingAverageDemo
{class Program{static void Main(string[] args){// 原始數據序列List<double> data = new() { 10, 20, 30, 40, 50, 60, 70, 80, 90, 100 };// 設置窗口大小int windowSize = 3;// 設置權重(例如 1, 2, 3,離當前位置越近權重越大)List<double> weights = new() { 1, 2, 3 };List<double> result = CalculateWeightedMovingAverage(data, windowSize, weights);Console.WriteLine("移動加權平均結果:");Console.WriteLine(string.Join(", ", result.Select(x => x.ToString("F2"))));}/// <summary>/// 計算移動加權平均數/// </summary>static List<double> CalculateWeightedMovingAverage(List<double> data, int windowSize, List<double> weights){if (weights.Count != windowSize)throw new ArgumentException("權重數量必須等于窗口大小。");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?? 輸入數據
data
:原始時間序列,如傳感器數據、股價等。windowSize
:滑動窗口大小。weights
:自定義權重列表,元素個數必須與窗口大小一致。
2?? 算法核心
- 外層循環:從頭到尾滑動窗口。
- 內層循環:窗口內每個值乘以權重累加。
- 用加權和除以權重之和,得出 WMA。
3?? 返回值
- 返回一個新的列表,長度是
data.Count - windowSize + 1
。
輸出結果
輸入數據:
10, 20, 30, 40, 50, 60, 70, 80, 90, 100
窗口大小:3
權重:[1, 2, 3]
輸出:
解釋:
- 第一個窗口
(10,20,30)
=> (10×1 + 20×2 + 30×3)/6 = 23.33 - 第二個窗口
(20,30,40)
=> (20×1 + 30×2 + 40×3)/6 = 33.33 - 以此類推。
🏁 小結
本篇演示了:
- 移動加權平均的核心原理
- 使用 C# 編寫通用實現
- 靈活設置權重,提升趨勢檢測的靈敏度
在工業生產、金融數據分析、實時信號濾波等場景,都可以直接使用此實現,或者把它封裝為工具類。