Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
590 views
in Technique[技术] by (71.8m points)

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

The problem is:

I want to plot the intraday 1 minute OHLC bars of one stock. The daily trading hour is composed of several segments of trading periods. Which is listed below:

Trade date: 2017/09/14

Included trading hour: 2017/09/13 21:00 - 23:00, 2017/09/14 9:00 - 10:15, 10:30 - 11:30, 13:30 - 15:00.

As you can see, if I just use candlestick_ohlc directly, there will be gaps.

Now if I get 1minute data as a dataframe. How can I plot a candlestick graph, with no gaps between any bars(e.g, no gap between 10:15 and 10:30 bar), and have the xticklabels only displaying the major ticks at every hour, like 22:00, 23:00, 10:00, and minor ticks at every 15 minutes, like 21:15, 21:30, 21:45, etc.

Here is a picture of what my dataframe looks like for 1 trading day: enter image description here

You can generate some pseudo data with similar form here:

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

I saw in matplotlib.finance module, there is candlestic2_ohlc, and candlestick_ohlc. My first trial was to use candlestick2_ohlc since it doesn't require a numerical datetime argument which would mess up the bars with many gaps. I don't get any gaps, but I can't make the xticklabels as what I want because I don't know how to pass the datetimeIndex information to the xticklabels now.

Here is what I have tried first: Basically learnt from this post: how to plot ohlc candlestick with datetime in matplotlib?

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))

The candlestick_ohlc result

Please help.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Currently you are plotting the data against its index. However, if you want to use matplotlib.dates locators and formatters you would need to plot dates on the axes. This is not possible using candlestick2_ohlc. Instead you would need to use candlestick_ohlc function. Actually this is also said in this answer to the question you link to. Using actual dates however, does not allow to merge the sements, other than possibly plotting in different subplots, see ?broken axes example.

So a solution here might be to stay with plotting the index and setting the ticks to the locations that correspond the desired tick labels.

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()

The result would look like

enter image description here

This is reading very confusingly, but to the best of my understanding this is what the question asks for.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...