1.15 重叠因子:WMA加权移动平均线(Weighted Moving Average, WMA)概念与Python实战
加权移动平均线(Weighted Moving Average, WMA)是一种重要的技术分析工具,它通过对不同时期的价格数据赋予不同的权重来计算平均值。WMA给予最近期数据最高的权重,权重随着时间的推移线性递减,这种特性使其能够更快地反应价格变化,同时保持一定的平滑效果。
0. 本栏目因子汇总表
1. 因子简述
加权移动平均线(Weighted Moving Average, WMA)是一种重要的技术分析工具,它通过对不同时期的价格数据赋予不同的权重来计算平均值。WMA给予最近期数据最高的权重,权重随着时间的推移线性递减,这种特性使其能够更快地反应价格变化,同时保持一定的平滑效果。
2. 因子计算逻辑
WMA的计算公式如下:
W M A t = ∑ i = 0 n − 1 ( n − i ) × C l o s e t − i ∑ i = 0 n − 1 ( n − i ) = n × C l o s e t + ( n − 1 ) × C l o s e t − 1 + . . . + 1 × C l o s e t − n + 1 n ( n + 1 ) 2 W M A f a c t o r = C l o s e − W M A σ n ( C l o s e ) \begin{align*} WMA_t &= \frac{\sum_{i=0}^{n-1} (n-i) \times Close_{t-i}}{\sum_{i=0}^{n-1} (n-i)} \\ &= \frac{n \times Close_t + (n-1) \times Close_{t-1} + ... + 1 \times Close_{t-n+1}}{\frac{n(n+1)}{2}} \\ WMA_{factor} &= \frac{Close - WMA}{\sigma_n(Close)} \end{align*} WMAtWMAfactor=∑i=0n−1(n−i)∑i=0n−1(n−i)×Closet−i=2n(n+1)n×Closet+(n−1)×Closet−1+...+1×Closet−n+1=σn(Close)Close−WMA
其中:
- n为移动平均周期
- Close_{t-i}为t-i时刻的收盘价
- σ_n(Close)为n周期收盘价的滚动标准差
3. 因子应用场景
-
趋势跟踪:
- 价格上穿WMA,做多信号
- 价格下穿WMA,做空信号
-
趋势确认:
- WMA斜率反映趋势强度
- WMA形态判断趋势持续性
-
价格回归:
- WMA作为价格回归目标
- 用于均值回归策略
-
市场分析:
- 多周期WMA组合分析
- 判断市场结构变化
4. 因子优缺点
优点:
- 反应灵敏:对近期价格变化敏感
- 权重合理:线性递减权重直观合理
- 噪音适中:比SMA更敏感但比EMA更稳定
- 计算简单:实现容易,计算量小
缺点:
- 滞后存在:虽然比SMA小但仍有滞后
- 权重固定:线性权重可能不适合所有市场
- 震荡敏感:容易在震荡市产生假信号
- 极端影响:近期极端值影响较大
5. 因子代码实现
def WMA_factor(df, n=20):
"""
计算加权移动平均线(WMA)因子
参数:
df (DataFrame): 输入数据
- code: 证券代码,如'600036.SH'
- date: 日期,格式为'YYYY-MM-DD'
- close: 收盘价
n (int): 移动平均周期,默认20
返回:
DataFrame: 包含原有列和WMA因子值,理论取值范围(-∞,+∞),实际大多在[-3,3]之间
注意:
1. 返回数据包含所有输入列
2. 新增WMA列为因子值
3. date列保持原有字符串格式'YYYY-MM-DD'
4. 数据将按code分组、date倒序排列
"""
import numpy as np
import pandas as pd
# 创建副本避免修改原始数据
df_copy = df.copy()
# 检查code格式
valid_codes = df_copy['code'].str.match(r'^(?:\d{6}\.(SH|SZ)|[A-Z]+/[A-Z]+|\w+\.(IB|CFE|US))$')
if not valid_codes.all():
raise ValueError("Invalid code format found")
# 检查date格式
valid_dates = df_copy['date'].str.match(r'^\d{4}-\d{2}-\d{2}$')
if not valid_dates.all():
raise ValueError("Invalid date format found, expected 'YYYY-MM-DD'")
# 排序(使用字符串比较)
df_copy = df_copy.sort_values(['code', 'date'], ascending=[True, False])
# 按code分组计算
def calculate_wma(group):
close = group['close'].values
# 计算线性权重
weights = np.arange(1, n + 1)
weights = weights / weights.sum()
# 计算WMA
wma = np.zeros_like(close)
for i in range(len(close)):
if i < n:
window = close[:i+1]
w = weights[-(i+1):]
w = w / w.sum()
wma[i] = np.sum(window * w)
else:
wma[i] = np.sum(close[i-n+1:i+1] * weights)
# 计算n周期滚动标准差
rolling_std = pd.Series(close).rolling(window=n).std().values
# 计算因子值:使用滚动标准差标准化的价格偏离度
# 处理标准差为0的情况
group['WMA'] = np.where(
rolling_std != 0,
(close - wma) / rolling_std,
0
)
return group
df_copy = df_copy.groupby('code', group_keys=False).apply(calculate_wma)
# 按照最终要求重新排序并重置索引
df_copy = df_copy.sort_values(['code', 'date'], ascending=[True, False]).reset_index(drop=True)
return df_copy
测试数据:
6. 因子取值范围及其含义
WMA因子的取值范围理论上是(-∞,+∞),但实际上大多数值会落在[-3,3]区间内:
- 取值 > 2:表示价格显著高于WMA(超过2个标准差),强烈超买信号
- 取值在(1,2]之间:表示价格高于WMA一个标准差以上,偏多信号
- 取值在[-1,1]之间:表示价格在WMA一个标准差范围内波动,震荡区间
- 取值在[-2,-1)之间:表示价格低于WMA一个标准差以上,偏空信号
- 取值 < -2:表示价格显著低于WMA(超过2个标准差),强烈超卖信号
7. 因子函数参数建议
- n (移动平均周期):
- 默认值:20
- 建议范围:[10, 40]
- 参数说明:决定移动平均的计算周期
- 选择建议:
- 日线数据建议使用:
- 短期:10-15天
- 中期:20-30天
- 长期:30-40天
- 小时线数据建议使用8-20
- 分钟线数据建议使用5-15
- 高波动市场使用较短周期
- 低波动市场使用较长周期
- 日线数据建议使用:
更多推荐
所有评论(0)