MACD,全称是Moving Average Convergence Divergence,即移动平均聚散指标,是一种常用的技术分析指标,用于判断股票价格趋势的强度、方向、动能以及可能的反转点。 它是根据指数移动平均线(EMA)的收敛和发散情况计算出来的。
1. 基本概念:
-
EMA (Exponential Moving Average): 指数移动平均线。它对近期的价格赋予更高的权重,因此比简单移动平均线 (SMA) 更能快速地反映价格变化。
-
DIF (Difference): 差离值,也称为快线。 它是短期EMA和长期EMA之差。 DIF = EMA(12) - EMA(26), 默认情况下,短期EMA周期为12天,长期EMA周期为26天。
-
DEA (Difference Exponential Average): 离差平均值,也称为慢线或信号线。 它是DIF的EMA。 DEA = EMA(DIF, 9),默认情况下,DEA的周期为9天。
-
MACD柱状图 (Histogram): 也称为MACD柱或能量柱。 它是DIF和DEA之差。 MACD柱 = DIF - DEA。 MACD柱围绕零轴波动。
2. 计算公式:
MACD的计算涉及多个步骤:
-
计算EMA(12)和EMA(26): 使用指数移动平均公式计算12日EMA和26日EMA。
-
EMA(当日) = α * 收盘价(当日) + (1 - α) * EMA(昨日)
-
α = 2 / (N + 1),其中N是周期数 (例如,12日EMA的α = 2 / (12 + 1) = 0.1538)
-
-
计算DIF: DIF = EMA(12) - EMA(26)
-
计算DEA: DEA = EMA(DIF, 9), 使用DIF的值计算9日EMA。
-
计算MACD柱: MACD柱 = DIF - DEA
3. 指标解读和使用方法:
-
DIF和DEA的交叉:
-
金叉: DIF线上穿DEA线,是买入信号,表明短期趋势强于长期趋势,股价可能上涨。
-
死叉: DIF线下穿DEA线,是卖出信号,表明短期趋势弱于长期趋势,股价可能下跌。
-
-
MACD柱:
-
MACD柱在零轴之上: 表明多头力量强于空头力量,股价趋势向上。MACD柱向上增长,表明上涨动能增强;MACD柱向上减小,表明上涨动能减弱。
-
MACD柱在零轴之下: 表明空头力量强于多头力量,股价趋势向下。MACD柱向下增长(负值越来越大),表明下跌动能增强;MACD柱向下减小(负值越来越小),表明下跌动能减弱。
-
-
零轴穿越:
-
DIF和DEA都在零轴之上: 市场处于多头市场,趋势向上。
-
DIF和DEA都在零轴之下: 市场处于空头市场,趋势向下。
-
-
背离: 当股价的走势与MACD指标的走势相反时,可能预示着趋势反转。
-
顶背离: 股价创新高,而MACD未能创新高,预示下跌风险。
-
底背离: 股价创新低,而MACD未能创新低,预示上涨机会。
-
-
数值大小: DIF和DEA的数值越大,表明趋势越强。
4. MACD指标的优缺点:
-
优点:
-
能够有效地识别趋势,尤其是在中长线趋势的判断上。
-
能够过滤掉一些虚假信号,相对稳定。
-
-
缺点:
-
反应相对滞后,不如KDJ等指标灵敏。
-
在震荡行情中,容易发出错误信号。
-
对参数设置有一定的依赖性。
-
5. 使用注意事项:
-
结合其他指标: MACD指标最好与其他技术指标(如RSI、均线等)结合使用,以提高准确性。
-
考虑市场环境: 在不同的市场环境下,MACD指标的有效性会有所不同。
-
参数设置: 可以根据不同的股票或市场,适当调整MACD指标的参数。常用的参数是(12, 26, 9),也可以尝试其他参数。
-
不要孤立使用: 不要只依赖MACD指标来做决策,要综合考虑基本面、消息面等因素。
-
注意风险控制: 任何技术指标都不能保证100%的准确率,所以要做好风险控制,设置止损位。
-
关注MACD柱状图变化: MACD柱状图能更直观的显示动能变化,有助于更早的发现趋势变化。
总结:
MACD指标是一种非常重要的趋势跟踪指标,它通过分析EMA的收敛和发散情况来判断市场趋势。 虽然MACD指标存在一些局限性,但在实际应用中,如果与其他指标结合使用,并结合基本面和市场环境进行分析,可以有效地提高投资决策的准确性。 同样重要的是要记住风险管理,设置止损,并根据自己的风险承受能力进行投资。
附: python分析代码和输出图
import akshare as ak
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.dates as mdates
from mplfinance.original_flavor import candlestick_ohlc
# 获取港股日线数据
def get_hk_stock_data(symbol):
df = ak.stock_hk_daily(symbol=symbol, adjust="qfq")
return df
# 模拟主力资金净流入
def calculate_main_net_inflow(df, threshold=100000):
"""
模拟主力资金净流入
:param df: 包含成交量和成交额的数据
:param threshold: 大单阈值(单位:港元)
:return: 主力资金净流入
"""
# 检查列名
print("数据列名:", df.columns)
# 计算成交额(成交额 = 收盘价 × 成交量)
df['turnover'] = df['close'] * df['volume']
# 假设主力资金为大单(成交额超过阈值)
df['main_inflow'] = df.apply(lambda row: row['turnover'] if row['turnover'] > threshold else 0, axis=1)
df['main_outflow'] = df.apply(lambda row: row['turnover'] if row['turnover'] < -threshold else 0, axis=1)
# 计算主力资金净流入
df['main_net_inflow'] = df['main_inflow'] - df['main_outflow']
return df
# 计算KDJ指标
def calculate_kdj(df, n=9, m1=3, m2=3):
"""
计算KDJ指标
:param df: 包含高、低、收盘价的数据
:param n: KDJ的周期
:param m1: K值的平滑周期
:param m2: D值的平滑周期
:return: 包含K、D、J值的数据
"""
low_list = df['low'].rolling(n, min_periods=1).min()
high_list = df['high'].rolling(n, min_periods=1).max()
rsv = (df['close'] - low_list) / (high_list - low_list) * 100
df['K'] = rsv.ewm(alpha=1/m1, adjust=False).mean()
df['D'] = df['K'].ewm(alpha=1/m2, adjust=False).mean()
df['J'] = 3 * df['K'] - 2 * df['D']
return df
# 计算MACD指标
def calculate_macd(df, short_window=12, long_window=26, signal_window=9):
"""
计算MACD指标
:param df: 包含收盘价的数据
:param short_window: 短期EMA的周期
:param long_window: 长期EMA的周期
:param signal_window: 信号线的周期
:return: 包含MACD、信号线和柱状图的数据
"""
df['EMA_short'] = df['close'].ewm(span=short_window, adjust=False).mean()
df['EMA_long'] = df['close'].ewm(span=long_window, adjust=False).mean()
df['MACD'] = df['EMA_short'] - df['EMA_long']
df['Signal'] = df['MACD'].ewm(span=signal_window, adjust=False).mean()
df['Histogram'] = df['MACD'] - df['Signal']
return df
# 计算移动平均线
def calculate_moving_averages(df):
"""
计算5日、10日、20日、30日和60日移动平均线
:param df: 包含收盘价的数据
:return: 包含移动平均线的数据
"""
df['MA_5'] = df['close'].rolling(window=5).mean()
df['MA_10'] = df['close'].rolling(window=10).mean()
df['MA_20'] = df['close'].rolling(window=20).mean()
df['MA_30'] = df['close'].rolling(window=30).mean()
df['MA_60'] = df['close'].rolling(window=60).mean()
return df
# 标注KDJ的金叉和死叉
def mark_kdj_crossings(ax, df):
"""
在KDJ图上标注金叉和死叉
:param ax: KDJ图的轴
:param df: 包含K、D值的数据
"""
# 金叉:K线向上穿过D线
golden_cross = (df['K'].shift(1) < df['D'].shift(1)) & (df['K'] > df['D'])
# 死叉:K线向下穿过D线
death_cross = (df['K'].shift(1) > df['D'].shift(1)) & (df['K'] < df['D'])
# 标注金叉
for date, k in df[golden_cross][['date', 'K']].values:
ax.annotate('金叉', xy=(date, k), xytext=(date, k + 5),
arrowprops=dict(facecolor='red', shrink=0.05), fontsize=8, color='red')
# 标注死叉
for date, k in df[death_cross][['date', 'K']].values:
ax.annotate('死叉', xy=(date, k), xytext=(date, k - 5),
arrowprops=dict(facecolor='green', shrink=0.05), fontsize=8, color='green')
# 标注MACD的金叉和死叉
def mark_macd_crossings(ax, df):
"""
在MACD图上标注金叉和死叉
:param ax: MACD图的轴
:param df: 包含MACD和Signal值的数据
"""
# 金叉:MACD线向上穿过Signal线
golden_cross = (df['MACD'].shift(1) < df['Signal'].shift(1)) & (df['MACD'] > df['Signal'])
# 死叉:MACD线向下穿过Signal线
death_cross = (df['MACD'].shift(1) > df['Signal'].shift(1)) & (df['MACD'] < df['Signal'])
# 标注金叉
for date, macd in df[golden_cross][['date', 'MACD']].values:
ax.annotate('金叉', xy=(date, macd), xytext=(date, macd + 0.1),
arrowprops=dict(facecolor='red', shrink=0.05), fontsize=8, color='red')
# 标注死叉
for date, macd in df[death_cross][['date', 'MACD']].values:
ax.annotate('死叉', xy=(date, macd), xytext=(date, macd - 0.1),
arrowprops=dict(facecolor='green', shrink=0.05), fontsize=8, color='green')
# 绘制日 K 线图、主力资金净流入、KDJ和MACD
def plot_candlestick_with_indicators(df):
# 创建画布和子图
fig, (ax1, ax2, ax3, ax4) = plt.subplots(4, 1, figsize=(14, 16), gridspec_kw={'height_ratios': [2, 1, 1, 1]})
# 准备蜡烛图数据
df['date'] = pd.to_datetime(df['date'])
df['date'] = df['date'].map(mdates.date2num) # 将日期转换为 matplotlib 格式
ohlc_data = df[['date', 'open', 'high', 'low', 'close']]
# 绘制日 K 线图
candlestick_ohlc(ax1, ohlc_data.values, width=0.6, colorup='red', colordown='green', alpha=0.8)
ax1.xaxis_date() # 设置 x 轴为日期格式
ax1.set_title('Daily Candlestick Chart with Main Net Inflow, KDJ, and MACD')
ax1.set_ylabel('Price')
ax1.grid(True)
# 绘制移动平均线
ax1.plot(df['date'], df['MA_5'], label='MA 5', color='blue', linewidth=1)
ax1.plot(df['date'], df['MA_10'], label='MA 10', color='orange', linewidth=1)
ax1.plot(df['date'], df['MA_20'], label='MA 20', color='green', linewidth=1)
ax1.plot(df['date'], df['MA_30'], label='MA 30', color='purple', linewidth=1)
ax1.plot(df['date'], df['MA_60'], label='MA 60', color='brown', linewidth=1)
ax1.legend()
# 绘制主力资金净流入
ax2.bar(df['date'], df['main_net_inflow'], color=np.where(df['main_net_inflow'] > 0, 'red', 'green'))
ax2.xaxis_date()
ax2.set_ylabel('Main Net Inflow')
ax2.grid(True)
# 绘制KDJ指标
ax3.plot(df['date'], df['K'], label='K', color='blue')
ax3.plot(df['date'], df['D'], label='D', color='orange')
ax3.plot(df['date'], df['J'], label='J', color='purple')
ax3.xaxis_date()
ax3.set_ylabel('KDJ')
ax3.legend()
ax3.grid(True)
# 标注KDJ的金叉和死叉
mark_kdj_crossings(ax3, df)
# 绘制MACD指标
ax4.plot(df['date'], df['MACD'], label='MACD', color='blue')
ax4.plot(df['date'], df['Signal'], label='Signal', color='red')
ax4.bar(df['date'], df['Histogram'], label='Histogram', color=np.where(df['Histogram'] > 0, 'green', 'red'))
ax4.xaxis_date()
ax4.set_ylabel('MACD')
ax4.legend()
ax4.grid(True)
# 标注MACD的金叉和死叉
mark_macd_crossings(ax4, df)
# 调整布局
plt.tight_layout()
plt.show()
# 示例调用
if __name__ == "__main__":
# 港股代码(例如:02477 对应的是腾讯控股)
symbol = "01810" # 港股代码,不需要加 .HK 后缀
# 获取数据
df = get_hk_stock_data(symbol)
# 按日期排序(确保数据按时间升序排列)
df = df.sort_values('date', ascending=True)
# 只保留最近一年的数据
df['date'] = pd.to_datetime(df['date'])
df = df[df['date'] >= pd.Timestamp.now() - pd.Timedelta(days=365)]
# 模拟主力资金净流入
df = calculate_main_net_inflow(df)
# 计算KDJ指标
df = calculate_kdj(df)
# 计算MACD指标
df = calculate_macd(df)
# 计算移动平均线
df = calculate_moving_averages(df)
# 绘制日 K 线图、主力资金净流入、KDJ和MACD
plot_candlestick_with_indicators(df)