【问题标题】:mplfinance xaxis ticks every n minutes, but not if datapoint doesn't existmplfinance xaxis 每 n 分钟滴答一次,但如果数据点不存在则不会
【发布时间】:2025-11-27 19:45:01
【问题描述】:

检查我不是在这里重新发明*,对于 mplfinance,我希望每 15 分钟在 x 轴上显示一次刻度,但前提是数据存在。

直接绘制到 mplfinance(没有 returnfig=True),除了 xaxis 值没有时间对齐之外,该图还可以,它们取决于数据框的第一个元素,即使用的时间。

为了尝试让它每小时都有网格/刻度,我有以下代码,当我的数据集中有预期的熊猫索引时,它可以正常工作:

start_date = pd.to_datetime('2021-12-21 04:00').tz_localize('America/New_York')
end_date = pd.to_datetime('2021-12-21 19:55').tz_localize('America/New_York')
df5trimmed = df5.truncate(before=start_date, after=end_date)    
                    
ticks = pd.date_range(start_date, end_date, freq='15T')
ticklocations = [ df5trimmed.index.get_loc(tick) for tick in ticks ]
ticklabels = [ tick.time().strftime('%H:%M') for tick in ticks ]

fig, axlist = mpf.plot(df5trimmed,style='yahoo', addplot=plotsToAdd, figsize=(48,24), 
                       type='candlestick', volume=True, xrotation=0,
                       tight_layout=True, returnfig=True)

axlist[-2].xaxis.set_ticks(ticklocations)
axlist[-2].set_xticklabels(ticklabels)

然而,预期它会在迭代器 df5trimmed.index.get_loc(tick) for tick in ticks 期间使用 index not found 爆炸,而此时 pandaframe 中不存在该滴答的数据。

请注意,在17:00 密钥访问尝试期间,它下面的数据中的不连续性会爆炸,因为它在我的数据中不存在:

基本上我希望绘制与 n 分钟对齐的线(在下面的示例中为 15 分钟),但前提是它存在而不是其他情况(如果它不存在,我可以将条形放在旁边彼此)...总而言之,在流动性(会有数据点的地方)的常规交易时间内,滴答声@ 08:15, 08:30。

在 mplfinance 中是否有一个参数可以做到这一点?

我想要实现的目标

以下内容来自交易视图,请注意在正常交易时间内每 15 分钟对齐的时间刻度以及几乎整个情节。

附加信息 - 源数据和绘制的内容

下面使用this csv data,并直接绘制到mplfinance,你可以看到时间刻度与我得到04:00, 06:25, 08:10, 09:50等的小时不一致:

import mplfinance as mpf
import pandas as pd
import datetime

df5trimmed = pd.read_csv('https://pastebin.com/raw/SgpargBb', index_col=0, parse_dates=True)
fig, axlist = mpf.plot(df5trimmed,style='yahoo', figsize=(48,24), type='candlestick', volume=True, xrotation=0, tight_layout=True, returnfig=True)

# Display:
mpf.show()

【问题讨论】:

  • 哪行代码引发了index not found 异常?另外,尝试设置show_nontrading=True(而不是自己设置set_ticks),因为这可能会使滴答声对你来说是一个很好的频率。最后,如果您可以提供您的数据的 csv 文件,以便其他人可以轻松复制,这将使其他人更容易帮助您找到解决方案。
  • 嗨丹尼尔,谢谢你的回复,我交易 show_nontrading=True 没有区别,我已经用最后的代码和文件参考更新了我的问题,我得到了什么,并澄清了我是什么寻找。非常感谢您的帮助。

标签: python mplfinance


【解决方案1】:

我使用以下代码添加刻度,但前提是它们存在 - 我怀疑编写此代码的更好方法,因此可以将其作为替代答案重新发布。

我的下一次迭代将是使文本具有 0 度旋转,并且在标签被另一个标签覆盖时不会混乱。

import mplfinance as mpf
import pandas as pd
import datetime

def getTimestampTickFrequency(df):
    # get most common interval in minutes
    mode = df.index.to_series().diff().astype('timedelta64[m]').astype('Int64').mode()[0]
    
    if mode==5:
        return 15, 3 # for 5 minutes, tick every 15 mins
    elif mode==15:
        return 60, 12 # for 15 minute data, tick every hour
    elif mode==120:
        return 240, 48 # for hourly data, tick every 2 hours
    
    return mode

def getTickLocationsAndLabels(df):
    tickLocations = []
    tickLabels = []
    
    tickFrequencyMinutes, samplesBetweenTicks = getTimestampTickFrequency(df)
    entireTickRange = pd.date_range(start=df.index[0], end=df.index[-1], freq=f'{tickFrequencyMinutes}T')
    prevTimestamp = df.index[0]
    
    # get indexes of data frame that match the ticks, if they exist
    for tick in entireTickRange:
        print(tick)
        try:
            found = df.index.get_loc(tick)
            currentTimestamp = df.index[found] 
            timestampDifference = (currentTimestamp - prevTimestamp).total_seconds() / 60
            
            print(f'Delta last time stamp = {timestampDifference}')
            #if timestampDifference <= tickFrequencyMinutes:
            tickLocations.append(found)
            tickLabels.append(tick.time().strftime('%H:%M'))
            
            prevTimestamp = currentTimestamp
        except KeyError:            
            pass # ignore
            
    return tickLocations, tickLabels

df5trimmed = pd.read_csv('https://pastebin.com/raw/SgpargBb', index_col=0, parse_dates=True)
tickLocations, tickLabels = getTickLocationsAndLabels(df5trimmed)
fig, axlist = mpf.plot(df5trimmed,style='yahoo', figsize=(48,24), type='candlestick', volume=True, tight_layout=True, returnfig=True)
axlist[-2].xaxis.set_ticks(tickLocations)
axlist[-2].set_xticklabels(tickLabels)

# Display:
mpf.show()

【讨论】:

    【解决方案2】:

    因此,需要消除由于缺少条形而导致的绘图间隙。

    基本上我希望绘制与 n 分钟对齐的线(在 下面的例子 15 分钟),但前提是它存在而不是其他情况

    从您发布的代码中尝试,但放大前 30 个柱并添加选项 show_nontrading=True:

    import mplfinance as mpf
    import pandas as pd
    import datetime
    
    df5trimmed = pd.read_csv('https://pastebin.com/raw/SgpargBb', index_col=0, parse_dates=True)
    fig, axlist = mpf.plot(df5trimmed[0:30],
                           style='yahoo', 
                           figsize=(48,24), 
                           type='candle', 
                           volume=True, 
                           xrotation=0, 
                           tight_layout=True, 
                           returnfig=True,
                           show_nontrading=True)
    
    # Display:
    mpf.show()
    

    我明白了,这显示了你提到的差距。

    但如果我设置选项 show_nontrading=False

    这将更改为下图,删除了与缺失条对应的间隙。

    这不是你需要的吗?

    【讨论】:

    • 感谢 Marcello 的回复,特别是我希望每 15 分钟在 x 轴上显示一次刻度,但前提是存在数据。如果您在我的“我想要实现的目标”部分下看到来自 Tradingview 的图片,您可以看到带有规则对齐刻度的 x 轴,
    • @morleyc,检查我是否在同一页面中。您有一个具有频率的基础规则时间序列,例如 5 分钟,并且您希望以 15 分钟的间隔绘制它,绘制当时基础 TS 的值。例如,如果您的系列是:11:05:00、11:10:00、11:15:00、11:20:00、11:25:00、11:45:00,并且绘图频率为 15 分钟,然后您将绘制 11:15:00、11:45:00 的值。它是否正确?然后对于缺失值,您有两个选择:是否绘制间隙,后者是您喜欢的。如果是这样,解决方案可能是使用合并。确认,我会告诉你怎么做。
    • 嗨,Marcello,是的,正确的是,只会显示 11:15 和 11:45 的刻度(所有数据点都会被绘制出来,没有间隙)
    【解决方案3】:

    请检查这是否解决了您的问题。我认为是的。

    检查早上 6:00 到早上 7:00 之间的日期范围。在 5:00 和 6:00 之间绘制了几个条形图,并且缺少 6:30。

    import mplfinance as mpf
    import pandas as pd
    import datetime
    import matplotlib.pyplot as plt
    %matplotlib inline
    
    # DATA PREPARATION
    df5 = pd.read_csv('https://pastebin.com/raw/SgpargBb', index_col=0, parse_dates=True)
    start_date = pd.to_datetime('2021-12-21 1:00').tz_localize('America/New_York')
    end_date = pd.to_datetime('2021-12-21 7:00').tz_localize('America/New_York')
    df5trimmed = df5.truncate(before=start_date, after=end_date)
    
    # PLOTTING 
    fig,  axlist= mpf.plot(df5trimmed,
                           style='yahoo', 
                           type='candlestick', 
                           volume=True, 
                           xrotation=0, 
                           figsize=(20,10), 
                           returnfig=True,
                           show_nontrading=False)
    
    # x-tick labeling preparation
    # the frequency can be ajusted but needs to be lower than original data
    idx = pd.date_range(start_date, end_date, freq='30T', tz='America/New_York')
    df_label_idx = pd.DataFrame(index=idx)
    
    # this merge does the trick: the output is the intersection between the lower frequency and the 
    # higher freq time series. The inner option leaves in the output only those rows present in both TS
    # dropping from the lower freq TS those missing periods in the higher freq TS.
    df_label = pd.merge(df_label_idx, df5trimmed, how='inner', left_index=True, right_index=True ).tz_convert('America/New_York')
    
    # Tick labels are generated based on df_label
    tick_labels = list(df_label.index.strftime('%H:%M'))
    ticklocations = [df5trimmed.index.get_loc(tick) for tick in df_label.index ]
    
    axlist[-2].xaxis.set_ticks(ticklocations)
    axlist[-2].set_xticklabels(tick_labels)
    
    mpf.show()
    
    
    print(tick_labels)
    
    df_label
    
    df5trimmed['2021-12-21 05:00:00-05:00':'2021-12-21 07:00:00-05:00']
    

    【讨论】:

      最近更新 更多