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

特斯拉股票K线图EMA线与主图分离问题咨询

问题:EMA线与K线主图分离无法对齐

运行代码后,本应叠加在特斯拉股票K线图上的4条EMA线与主图出现分离,无法对齐显示。

EMA线与主图分离的截图

原测试代码如下:

import yfinance as yf
import mplfinance as mpf
import matplotlib.pyplot as plt
import matplotlib.patches as mpatches
import pandas as pd

# Dates to get stock data
start_date = "2010-07-01"
end_date = "2023-06-17"

# Fetch Tesla stock data
tesla_data = yf.download("TSLA", start=start_date, end=end_date)
tesla_weekly_data = tesla_data.resample("W").agg(
    {"Open": "first", "High": "max", "Low": "min", "Close": "last", "Volume": "sum"}
).dropna()

# Get the latest closing price
latest_price = tesla_weekly_data['Close'][-1]

# Create additional plot
close_price = tesla_weekly_data['Close']
apd = mpf.make_addplot(close_price, color='cyan', width=2)

# Calculate the EMA with different lengths
ema_lengths = [8, 13, 21, 55]
ema_colors = ['blue', 'green', 'yellow', 'red']
ema_lines = []
for length, color in zip(ema_lengths, ema_colors):
    ema_line = tesla_weekly_data['Close'].ewm(span=length, adjust=False).mean()
    ema_lines.append(ema_line)

# Plot the candlestick chart with EMA lines
fig, axes = mpf.plot(tesla_weekly_data,
                     type='candle',
                     addplot=apd,
                     style='yahoo',
                     title='Tesla Stock Prices',
                     ylabel='Price',
                     xlabel='Date',
                     volume=True,
                     ylabel_lower='Volume',
                     volume_panel=1,
                     figsize=(16, 8),
                     returnfig=True)

# Move the y-axis labels to the left side
axes[0].yaxis.tick_left()
axes[1].yaxis.tick_left()

# Adjust the position of the y-axis label for price
axes[0].yaxis.set_label_coords(-0.08, 0.5)

# Adjust the position of the y-axis label for volume
axes[1].yaxis.set_label_coords(-0.08, 0.5)

# Set y-axis label for price and volume
axes[0].set_ylabel('Price', rotation=0, labelpad=20)
axes[1].set_ylabel('Volume', rotation=0, labelpad=20)

# Make the legend box
handles = axes[0].get_legend_handles_labels()[0]
red_patch = mpatches.Patch(color='red')
green_patch = mpatches.Patch(color='green')
cyan_patch = mpatches.Patch(color='cyan')
handles = handles[:2] + [red_patch, green_patch, cyan_patch]
labels = ["Price Up", "Price Down", "Closing Price"]
axes[0].legend(handles=handles, labels=labels)

# Add a box to display the current price
latest_price_text = f"Current Price: ${latest_price:.2f}"
box_props = dict(boxstyle='round', facecolor='white', edgecolor='black', alpha=0.8)
axes[0].text(0.02, 0.95, latest_price_text, transform=axes[0].transAxes,
             fontsize=12, verticalalignment='top', bbox=box_props)

# Add EMA lines
for ema_line, color in zip(ema_lines, ema_colors):
    axes[0].plot(ema_line, color=color)

# Display the chart
plt.show()

问题原因

直接用axes[0].plot()添加EMA线时,matplotlib会将pandas的DatetimeIndex默认转换为从0开始的整数索引绘制,但mplfinance的主图x轴是基于实际日期的坐标系统,两者x轴刻度不匹配,导致EMA线偏移分离。

解决方法

使用mplfinance提供的mpf.make_addplot()方法创建EMA线的绘图对象,将所有需要叠加的线条(收盘价线+EMA线)统一传入mpf.plot()的addplot参数,让mplfinance统一处理坐标轴对齐。

修正后的代码如下:

import yfinance as yf
import mplfinance as mpf
import matplotlib.pyplot as plt
import matplotlib.patches as mpatches
import pandas as pd

# Dates to get stock data
start_date = "2010-07-01"
end_date = "2023-06-17"

# Fetch Tesla stock data
tesla_data = yf.download("TSLA", start=start_date, end=end_date)
tesla_weekly_data = tesla_data.resample("W").agg(
    {"Open": "first", "High": "max", "Low": "min", "Close": "last", "Volume": "sum"}
).dropna()

# Get the latest closing price
latest_price = tesla_weekly_data['Close'][-1]

# Create additional plots: 收盘价线 + 所有EMA线
add_plots = []
# 添加收盘价线
add_plots.append(mpf.make_addplot(tesla_weekly_data['Close'], color='cyan', width=2))

# Calculate the EMA with different lengths and add to add_plots
ema_lengths = [8, 13, 21, 55]
ema_colors = ['blue', 'green', 'yellow', 'red']
for length, color in zip(ema_lengths, ema_colors):
    ema_line = tesla_weekly_data['Close'].ewm(span=length, adjust=False).mean()
    add_plots.append(mpf.make_addplot(ema_line, color=color))

# Plot the candlestick chart with all add plots
fig, axes = mpf.plot(tesla_weekly_data,
                     type='candle',
                     addplot=add_plots,  # 传入所有叠加图对象
                     style='yahoo',
                     title='Tesla Stock Prices',
                     ylabel='Price',
                     xlabel='Date',
                     volume=True,
                     ylabel_lower='Volume',
                     volume_panel=1,
                     figsize=(16, 8),
                     returnfig=True)

# Move the y-axis labels to the left side
axes[0].yaxis.tick_left()
axes[1].yaxis.tick_left()

# Adjust the position of the y-axis label for price
axes[0].yaxis.set_label_coords(-0.08, 0.5)

# Adjust the position of the y-axis label for volume
axes[1].yaxis.set_label_coords(-0.08, 0.5)

# Set y-axis label for price and volume
axes[0].set_ylabel('Price', rotation=0, labelpad=20)
axes[1].set_ylabel('Volume', rotation=0, labelpad=20)

# Make the legend box
handles = axes[0].get_legend_handles_labels()[0]
# 添加EMA线的图例补丁
ema_patches = [mpatches.Patch(color=color, label=f'EMA-{length}') for length, color in zip(ema_lengths, ema_colors)]
red_patch = mpatches.Patch(color='red')
green_patch = mpatches.Patch(color='green')
cyan_patch = mpatches.Patch(color='cyan', label='Closing Price')
handles = handles[:2] + [red_patch, green_patch, cyan_patch] + ema_patches
labels = ["Price Up", "Price Down", "Closing Price"] + [f'EMA-{length}' for length in ema_lengths]
axes[0].legend(handles=handles, labels=labels)

# Add a box to display the current price
latest_price_text = f"Current Price: ${latest_price:.2f}"
box_props = dict(boxstyle='round', facecolor='white', edgecolor='black', alpha=0.8)
axes[0].text(0.02, 0.95, latest_price_text, transform=axes[0].transAxes,
             fontsize=12, verticalalignment='top', bbox=box_props)

# Display the chart
plt.show()

内容的提问来源于stack exchange,提问作者Damian

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 13:24:56