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

mplfinance实时绘图vlines索引异常:垂直线偏移右侧问题

问题:mplfinance实时绘图中垂直线偏移至右侧的原因及解决方法

我在mplfinance的实时绘图上尝试绘制垂直线,当前绘制水平线的代码运行正常:

def animate(ival):
    df =  pd.read_pickle("/Users/user/Workfiles/Python/rp/0.72.0.0/df.pkl")

    ax1.clear()
    mpf.plot(df, ax=ax1, type='candle', ylabel='p', warn_too_much_data=999999999999)

 
    try:
        ax1.hlines(y=price, xmin=df.shape[0]-10, xmax=df.shape[0], color='r', linewidth=1)
    except UnboundLocalError:
        pass

ani = FuncAnimation(fig, animate, interval=100)

mpf.show()

我已获取需标记行的索引存入变量lows_peaks,对应行的时间戳正确,但执行以下代码绘制垂直线时,线条出现在绘图右侧:

for i in df.iloc[lows_peaks].index:
    ax1.vlines(x=i, ymin=df.low.min(), ymax=df.high.max(), color='r', linewidth=1)

附可复现代码:

import pandas as pd
import numpy as np
from matplotlib.animation import FuncAnimation
import mplfinance as mpf

times = pd.date_range(start='2022-01-01', periods=50, freq='ms')

df = pd.DataFrame(np.random.randint(3000, 3100, (50, 1)), columns=['open'])
df['high'] = df.open+5
df['low'] = df.open-2
df['close'] = df.open
df.set_index(times, inplace=True)
lows_peaks = df.low.nsmallest(5).index
print(lows_peaks)

fig = mpf.figure(style="charles",figsize=(7,8))
ax1 = fig.add_subplot(1,1,1)

def animate(ival):
    ax1.clear()
    
    for i in lows_peaks:
        ax1.vlines(x=i, ymin=df.low.min(), ymax=df.high.max(), color='blue', linewidth=3)
    mpf.plot(df, ax=ax1)
    
ani = FuncAnimation(fig, animate, interval=100)

mpf.show()

原因分析

问题核心在于绘图顺序和mplfinance的坐标轴逻辑:

  1. mplfinance绘制K线时,会将x轴转换为从0开始的整数行号,而非原始的时间戳格式。但你先绘制垂直线时用的是原始时间戳,这些时间戳的数值远大于mplfinance实际使用的x轴范围,导致线条被挤到绘图右侧。
  2. 其次,mpf.plot()执行时会重置坐标轴的刻度和范围,覆盖你之前绘制的垂直线的坐标映射关系。

解决方案

调整绘图顺序,先让mplfinance完成K线绘制,再基于它生成的x轴坐标绘制垂直线,两种可靠实现方式如下:

方式一:直接获取时间戳对应的行号

利用df.index.get_loc()直接获取目标时间戳在DataFrame中的行位置(即mplfinance使用的x轴坐标):

import pandas as pd
import numpy as np
from matplotlib.animation import FuncAnimation
import mplfinance as mpf

times = pd.date_range(start='2022-01-01', periods=50, freq='ms')

df = pd.DataFrame(np.random.randint(3000, 3100, (50, 1)), columns=['open'])
df['high'] = df.open+5
df['low'] = df.open-2
df['close'] = df.open
df.set_index(times, inplace=True)
lows_peaks = df.low.nsmallest(5).index

fig = mpf.figure(style="charles",figsize=(7,8))
ax1 = fig.add_subplot(1,1,1)

def animate(ival):
    ax1.clear()
    
    # 先绘制K线,让mplfinance初始化坐标轴
    mpf.plot(df, ax=ax1)
    
    y_min = df.low.min()
    y_max = df.high.max()
    # 获取目标时间戳对应的行号,绘制垂直线
    for date in lows_peaks:
        x_pos = df.index.get_loc(date)
        ax1.vlines(x=x_pos, ymin=y_min, ymax=y_max, color='blue', linewidth=3)
    
ani = FuncAnimation(fig, animate, interval=100)

mpf.show()

方式二:建立时间戳与x坐标的映射

通过坐标轴的刻度标签建立时间戳到x坐标的映射,适合需要自定义刻度的场景:

import pandas as pd
import numpy as np
from matplotlib.animation import FuncAnimation
import mplfinance as mpf

times = pd.date_range(start='2022-01-01', periods=50, freq='ms')

df = pd.DataFrame(np.random.randint(3000, 3100, (50, 1)), columns=['open'])
df['high'] = df.open+5
df['low'] = df.open-2
df['close'] = df.open
df.set_index(times, inplace=True)
lows_peaks = df.low.nsmallest(5).index

fig = mpf.figure(style="charles",figsize=(7,8))
ax1 = fig.add_subplot(1,1,1)

def animate(ival):
    ax1.clear()
    
    # 先绘制K线
    mpf.plot(df, ax=ax1)
    
    # 建立时间戳到x坐标的映射
    xtick_labels = [label.get_text() for label in ax1.get_xticklabels()]
    xtick_dates = pd.to_datetime(xtick_labels, errors='coerce')
    x_pos_map = {date: pos for pos, date in enumerate(df.index) if date in xtick_dates}
    
    y_min = df.low.min()
    y_max = df.high.max()
    # 遍历目标时间戳绘制垂直线
    for date in lows_peaks:
        if date in x_pos_map:
            ax1.vlines(x=x_pos_map[date], ymin=y_min, ymax=y_max, color='blue', linewidth=3)
    
ani = FuncAnimation(fig, animate, interval=100)

mpf.show()

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 21:50:37