matplotlib.finance.candlestick_ohlc 每小时绘制带有时间间隔和适当 xticklabels 的盘中 1 分钟条形数据

matplotlib.finance.candlestick_ohlc plot intraday 1min bar data with time breaks and proper xticklabels at every hour

问题是:

我想绘制一只股票的盘中 1 分钟 OHLC 柱。 每日交易时段由若干段交易时段组成。以下列出:

交易日期:2017/09/14

包括交易时间: 2017/09/13 21:00 - 23:00, 2017/09/14 9:00 - 10:15, 10:30 - 11:30, 13:30 - 15:00.

如你所见,如果我直接使用candlestick_ohlc,就会有间隙。

现在,如果我将 1 分钟的数据作为数据帧。我如何绘制烛台图,在任何柱之间没有间隙(例如,10:15 和 10:30 柱之间没有间隙),并且让 xticklabels 仅在每小时显示主要刻度,如 [= 55=、23:00、10:00 和每 15 分钟的小滴答声,如 21:15、21:30、21:45 等

这是我的数据框在 1 个交易日的样子的图片:

您可以在这里生成一些具有类似形式的伪数据:

def generate_pseudo_data():
    # datetime index data
    idx = pd.date_range('2017-09-13 21:01:00',
                        '2017-09-13 23:00:00', freq='1min')
    idx = idx.append(pd.date_range('2017-09-14 09:01:00',
                                   '2017-09-14 10:15:00', freq='1min'))
    idx = idx.append(pd.date_range('2017-09-14 10:31:00',
                                   '2017-09-14 11:30:00', freq='1min'))
    idx = idx.append(pd.date_range('2017-09-14 13:31:00',
                                   '2017-09-14 15:00:00', freq='1min'))

    # OHLC
    inc = np.random.randint(-2, 3, size=idx.shape).cumsum()
    opens = 3500 + inc
    closes = opens + np.random.randint(-3, 3, idx.shape)
    range_max = np.max(np.concatenate([opens.reshape(-1, 1),
                                       closes.reshape(-1, 1)], axis=1), axis=1)
    highs = range_max + np.random.randint(0, 5, size=idx.shape)
    range_min = np.min(np.concatenate([opens.reshape(-1, 1),
                                       closes.reshape(-1, 1)], axis=1), axis=1)
    lows = range_min - np.random.randint(0, 5, size=idx.shape)
    bar_df = pd.DataFrame({'open': opens, 'high': highs, 'low': lows,
                           'close': closes}, index=idx)
    return bar_df

我在matplotlib.finance模块中看到,有candlestic2_ohlc,还有candlestick_ohlc。 我的第一个尝试是使用 candlestick2_ohlc,因为它不需要数字 datetime 参数,因为它会弄乱带有许多间隙的条形图。 我没有任何差距,但我无法按照我想要的方式制作 xticklabels,因为我现在不知道如何将 datetimeIndex 信息传递给 xticklabels。

这是我首先尝试的: 基本上从这个post学到了:

from datetime import datetime, time

import pandas as pd
import numpy as np

import matplotlib as mpl
import matplotlib.pyplot as plt
from matplotlib.finance import candlestick2_ohlc, candlestick_ohlc
import matplotlib.dates as mdates
from matplotlib import ticker

bar_df = generate_pseudo_data()
fig, ax = plt.subplots()
figManager = plt.get_current_fig_manager()
figManager.window.showMaximized()

candlestick2_ohlc(ax, bar_df.open, bar_df.high, bar_df.low, bar_df.close,
                  width=0.6, colorup='r', colordown='c', alpha=1)
xdate = bar_df.index
def mydate(x, pos):
    try:
        return xdate[int(x)]
    except IndexError:
        return ''

ax.xaxis.set_major_formatter(ticker.FuncFormatter(mydate))
# Everything works fine up to now.
# However the xticklabels are not exactly at 22:00, 23:00, etc.
# And no minor tick labels set up at 21:15, 21:30, 21:45, etc.

# I tried either one of the command below, but both failed with no xticklabels
# showed up.

ax.xaxis.set_major_locator(mdates.HourLocator())
ax.xaxis.set_major_locator(mdates.MinuteLocator(byminute=[0, 15, 30, 45],
                                                interval=1))

# This one works because it only tells xticklabels to have at most
# 8 tick labels, but no info about where the xticklabels should be.
ax.xaxis.set_major_locator(ticker.MaxNLocator(8))

请帮忙。

目前您正在根据其索引绘制数据。 但是,如果您想使用 matplotlib.dates 定位器和格式化程序,则需要在轴上绘制日期。 使用 candlestick2_ohlc 是不可能的。相反,您需要使用 candlestick_ohlc 函数。其实这也是中对你link的问题说的。 但是,使用实际日期不允许合并片段,除非可能在不同的子图中绘制,请参阅 ☼broken axes example

因此这里的解决方案可能是继续绘制索引并将刻度设置到与所需刻度标签对应的位置。

xdate = bar_df.index
def mydate(x, pos):
    try:
        return xdate[int(x)]
    except IndexError:
        return ''
# create date ranges of possible dates to show as major and minor ticklabels
major_dr = pd.date_range('2017-09-13 21:00:00','2017-09-14 15:00:00', freq='60min')
minor_dr = pd.date_range('2017-09-13 21:00:00','2017-09-14 15:00:00', freq='15min')
# calculate positions of the above dates inside the dataframe index
major_ticks = np.isin(xdate, major_dr).nonzero()[0] 
minor_ticks = np.isin(xdate, minor_dr).nonzero()[0]
# use those positions to put ticks at
ax.xaxis.set_major_locator(ticker.FixedLocator(major_ticks))
ax.xaxis.set_minor_locator(ticker.FixedLocator(minor_ticks))
ax.minorticks_on()
ax.xaxis.set_major_formatter(ticker.FuncFormatter(mydate))
fig.autofmt_xdate()

结果看起来像

这读起来很混乱,但据我所知,这就是问题所要求的。