MACD (Moving Average Convergence / Divergence) - 异同移动平均线
1 公式
3个参数(这3个参数可以根据实际情况自己设定,默认为12,26和9):
- (k)日快速移动平均线
- (m)日慢速移动平均
- (n)日移动平均
EMA(k) = 前一日EMA × (k-1) / (k+1)+今日收盘价 × 2 / (k+1)
EMA(m) = 前一日EMA × (m-1) / (m+1)+今日收盘价 × 2 / (m+1)
DIFF = 今日EMA(k) - 今日EMA(m)
DEA = 前一日DEA × (n-1) / (n+1)+今日DIF × 2 / (n+1)
BAR(MACD) = 2 × (DIFF-DEA)
关键是第一日和第二日的DIFF,DEA和BAR(MACD)是多少:
第一日都为0
DIFF = 0,DEA = 0,BAR(MACD) = 0
第二日
EMA(k) = 前一日收盘价(即第一日收盘价)+(今日收盘价 - 前一日收盘价)× 2 / (k+1)
EMA(m) = 前一日收盘价(即第一日收盘价)+(今日收盘价 - 前一日收盘价)× 2 / (m+1)
DIFF=EMA(k) - EMA(m)
DEA(n) = 0(即前一日DEA(n))+ 今日DIFF × 2 / (n+1)
BAR = 2 × (DIFF - DEA)
第三日就可以按最上面的公式计算了,因为前一日(即第二日)的EMA(k),EMA(m),DEA(n)都已经有了,后面以此类推。
由于计算当天的DIFF,DEA和BAR(MACD)需要前一天的EMA数据,所以除非这些数据是已知的,否则需要从第一天收盘后开始计算,这也是MACD比较麻烦的地方。
根据以上的公式给出代码就不困难了:
元数据的获取使用了Tushare第三方金融数据库,可以见之前的blog:python 经济数据第三方库 tushare 简单试用
2 数据准备
元数据格式是这样的(以沪深300指数为例):
3 计算过程
def emaN(emadays: int, n: int, close: list, lastemaN: list):
"""
计算n日指数移动平均线(EMA)
:param emadays: EMA的计算周期
:param n: 当前计算的天数
:param close: 收盘价列表
:param lastemaN: 上一个EMA值的列表
:return: 当前计算的EMA值
"""
if n == 1:
return 0
elif n == 2:
return close[n-2]+(close[n-1]-close[n-2])*2/(emadays+1)
else:
return lastemaN[n-2]*(emadays-1)/(emadays+1)+close[n-1]*2/(emadays+1)
def diffN(emafast: float, emaslow: float):
"""
计算DIF值,即快速EMA和慢速EMA的差值
:param emafast: 快速EMA值
:param emaslow: 慢速EMA值
:return: DIF值
"""
return emafast-emaslow
def deaN(ma: int, lastdea: list, diff: float, n: int):
"""
计算DEA值,即DIF的指数移动平均线
:param ma: DEA的计算周期
:param lastdea: 上一个DEA值的列表
:param diff: 当前的DIF值
:param n: 当前计算的天数
:return: 当前计算的DEA值
"""
if n == 1:
return 0
elif n == 2:
return lastdea[n-2]+diff*2/(ma+1)
else:
return lastdea[n-2]*(ma-1)/(ma+1)+diff*2/(ma+1)
def macd(diff: float, dea: float):
"""
计算MACD值,即DIF和DEA差值的2倍
:param diff: 当前的DIF值
:param dea: 当前的DEA值
:return: MACD值
"""
return 2*(diff-dea)
def calculate_MACD(df: pd.DataFrame, fast_ma: int, slow_ma: int, ma: int):
"""
计算MACD指标,并将结果添加到DataFrame中
:param df: 包含交易数据的DataFrame,必须包含'trade_date'和'close'列
:param fast_ma: 快速EMA的计算周期
:param slow_ma: 慢速EMA的计算周期
:param ma: DEA的计算周期
:return: 包含MACD指标计算结果的DataFrame
"""
# sort by date
sort_df = df.sort_values('trade_date')
# create list to save result
EMA_fast = []
EMA_slow = []
DIFF = []
DEA = []
MACDN = []
# get close prices
close = sort_df['close']
# need to be calculated
# cal ema,diff,dea,macd
for i in range(1, close.count() + 1):
# print(i)
ema10 = emaN(emadays=fast_ma, n=i, close=close, lastemaN=EMA_fast)
# print("ema10=" + str(ema10))
EMA_fast.insert(i, ema10)
ema22 = emaN(emadays=slow_ma, n=i, close=close, lastemaN=EMA_slow)
# print("ema22=" + str(ema22))
EMA_slow.insert(i, ema22)
diff = diffN(ema10, ema22)
# print("diff=" + str(diff))
DIFF.insert(i, diff)
dea = deaN(ma=ma, lastdea=DEA, diff=diff, n=i)
# print("dea=" + str(dea))
DEA.insert(i, dea)
# print(DEA)
macdN = macd(diff, dea)
MACDN.insert(i, macdN)
# insert result to dataframe
sort_df['ema' + str(fast_ma)] = EMA_fast
sort_df['ema' + str(slow_ma)] = EMA_slow
sort_df['diff' + str(fast_ma)] = DIFF
sort_df['dea' + str(slow_ma)] = DEA
sort_df['macd' + str(ma)] = MACDN
return sort_df
4 结果:
最后的3列数据就是我们想要获得的数据,可以与任意股票软件中的数据对比,完全一致
到此,完成计算。