You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

白银MACD指标计算异常排查求助

我的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ś

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.24 08:48:15