白银MACD计算异常求助:MACD线与信号线远高于0轴问题排查
白银MACD指标计算异常排查求助

我采用EMA指标计算MACD,公式如下:
MACD line = EMA(price array, n1) - EMA(price array, n2) MACD signal = EMA(MACD line, n3) Histogram = MACD line - MACD Signal
具体实现代码如下:
import numpy as np import pandas as pd import os import matplotlib.pyplot as plt def EMA(close_price_arr, n): a = 2/(n + 1) EMA_n = np.empty((1, len(close_price_arr))) for i in range(len(close_price_arr)): if i < n - 1: # 创建无法计算EMA的NaN值后续处理 EMA_n[0, i] = 'NaN' if i >= n - 1: # 计算EMA的分子和分母 for j in range(n): nominator_ema += close_price_arr[i - j] * (1-a)**(j) denominator_ema += (1 - a)**(j) nominator_ema += close_price_arr[i - j] * (1-a)**(j) denominator_ema += (1 - a)**n EMA_n[0, i] = nominator_ema / denominator_ema nominator_ema = 0 denominator_ema = 0 return EMA_n def MACD(price_arr, n1, n2, n3): EMA_n1 = EMA(close_price_arr=price_arr, n=n1) EMA_n2 = EMA(close_price_arr=price_arr, n=n2) MACD_unor = EMA_n1 - EMA_n2 x, y = MACD_unor.shape MACD_unor_trans = np.reshape(MACD_unor,y) Signal_line_EMA_n3 = EMA(close_price_arr=MACD_unor_trans, n=n3) histogram = MACD_unor - Signal_line_EMA_n3 return MACD_unor, Signal_line_EMA_n3, histogram # 指定文件路径 FILE = 'TVC_SILVER, 5.csv' FOLDER = 'src' PROJECT_ROOT_DIR = '.' csv_path = os.path.join(PROJECT_ROOT_DIR, FOLDER, FILE) # 读取CSV数据 price_data = pd.read_csv(csv_path, delimiter=',') price_data_copy = price_data.copy() price_data_nodate = price_data.copy().drop('time', axis=1) price_data_np = price_data_nodate.to_numpy(dtype='float32') close_price = price_data_np[:, 3] MACD_main, MACD_signal, histogram = MACD(price_arr=close_price, n1=12, n2=26, n3=9) plt.plot(MACD_main[0, :], label='MACD main 12,26') plt.plot(MACD_signal[0, :], label='MACD signal 9') x_bar, y_bar = histogram.shape ypos = np.arange(y_bar) plt.bar(ypos, histogram[0, :], label='MACD histogram') plt.grid() plt.legend() plt.show()
我不清楚哪里出现了错误导致图表异常,希望能得到排查问题的建议。
排查建议及修正方案
1. 修复EMA函数变量初始化问题
在i >= n-1分支中,进入j循环前未初始化nominator_ema和denominator_ema,直接使用+=会触发未定义变量错误,需在j循环前添加初始化:
if i >= n - 1: nominator_ema = 0 denominator_ema = 0 # 计算EMA的分子和分母 for j in range(n): nominator_ema += close_price_arr[i - j] * (1-a)**(j) denominator_ema += (1 - a)**(j)
2. 删除多余的累加操作
j循环结束后额外添加的两行代码属于重复计算,会导致EMA结果严重偏离正确值,必须删除:
# 以下两行是错误的,直接删除 nominator_ema += close_price_arr[i - j] * (1-a)**(j) denominator_ema += (1 - a)**n
3. 修正NaN赋值方式
使用字符串'NaN'填充numpy数组会导致类型混乱,应改为numpy原生的np.nan:
if i < n - 1: EMA_n[0, i] = np.nan
4. 改用标准递归EMA计算逻辑
当前窗口加权的EMA实现不符合行业标准,标准MACD使用递归式EMA计算,效率更高且结果准确,推荐替换EMA函数为:
def EMA(close_price_arr, n): a = 2 / (n + 1) ema = np.full(len(close_price_arr), np.nan) # 初始值取前n个收盘价的简单平均 ema[n-1] = np.mean(close_price_arr[:n]) # 递归计算后续EMA值 for i in range(n, len(close_price_arr)): ema[i] = a * close_price_arr[i] + (1 - a) * ema[i-1] return ema
5. 简化数组维度处理
修正后的EMA返回一维数组,MACD函数可简化为:
def MACD(price_arr, n1, n2, n3): EMA_n1 = EMA(close_price_arr=price_arr, n=n1) EMA_n2 = EMA(close_price_arr=price_arr, n=n2) MACD_unor = EMA_n1 - EMA_n2 Signal_line_EMA_n3 = EMA(close_price_arr=MACD_unor, n=n3) histogram = MACD_unor - Signal_line_EMA_n3 return MACD_unor, Signal_line_EMA_n3, histogram
6. 简化绘图代码
一维数组可直接用于绘图,无需额外维度转换:
plt.plot(MACD_main, label='MACD main 12,26') plt.plot(MACD_signal, label='MACD signal 9') plt.bar(np.arange(len(histogram)), histogram, label='MACD histogram') plt.grid() plt.legend() plt.show()
内容的提问来源于stack exchange,提问作者Puchatek Kubuś
相关产品推荐
相关产品推荐

