4

I have a DataFrame that contains price/volume data on an intraday basis:

time                  price    volume   
2015-04-15 10:10:00   10       500    
2015-04-15 10:20:00   15       100    
2015-04-15 10:30:00   20       70
2015-04-15 10:30:00   etc      etc

I need to get a standard price - volume chart, where the top chart contains the prices (a regular line), and the bottom chart contains the volume (a bar chart).

Both charts should share the same axis, of course.

So far, I have come up with:

plt.figure(figsize=(20,15))          
    
ax1=plt.subplot2grid((2,2),(0,0),colspan=2)
ax2=plt.subplot2grid((2,2),(1,0),colspan=2)

ax2.xaxis.set_major_locator(HourLocator(interval=3))
ax2.xaxis.set_major_formatter(DateFormatter('%H:%M'))

data.ix['2015-10-01': '2015-10-02','price'].plot(ax=ax1)
data.ix['2015-10-01': '2015-10-02','volume'].plot(ax=ax2, kind='bar')

But I get super-dense tick labels for the bar charts (the chart is unusable).

How can I simply specify to have minor ticks every hours, and major ticks every 3 hours (so that the chart is still readable)?

Trenton McKinney
  • 56,955
  • 33
  • 144
  • 158
ℕʘʘḆḽḘ
  • 18,566
  • 34
  • 128
  • 235
  • 1
    Do you want one figure with bars and lines, or do you want two figures stacked, but with only the bottom one's axis marked? If the style you're looking for is standard, maybe you can provide a link to an example of what you're talking about. – ASGM May 13 '16 at 14:54
  • whatever is easiest for you. As long as the chat is readable and we can specify where the hourly ticks are. – ℕʘʘḆḽḘ May 13 '16 at 15:18
  • look here for an idea http://www.marketsmith.com/stock-charts/daily-stock-charts/ – ℕʘʘḆḽḘ May 13 '16 at 15:19
  • actually the volume chart does not even need to be a real bart chart, it can have some vertical lines as long as the height of the lines correspond to the volume. – ℕʘʘḆḽḘ May 13 '16 at 15:41

1 Answers1

8

There are some challenges with pandas.plot.bar() and DateTimeIndex that are discussed for instance here. The following:

import matplotlib as mpl
import matplotlib.pyplot as plt

plt.style.use('ggplot')
import pandas as pd
import numpy as np
from datetime import datetime

n = 100
idx = pd.date_range(start=datetime(2016, 1, 1, 10), freq='10Min', periods=n)
data = pd.DataFrame(data={'price': np.cumsum([0.0001] * n + np.random.random(n)),
                          'volume': np.random.randint(low=100, high=10000, size=n)}, index=idx)

fig, ax = plt.subplots(nrows=2, sharex=True, figsize=(15,8))

ax[0].plot(data.index, data.price)
ax[1].bar(data.index, data.volume, width=1/(5*len(data.index)))

xfmt = mpl.dates.DateFormatter('%H:%M')
ax[1].xaxis.set_major_locator(mpl.dates.HourLocator(interval=3))
ax[1].xaxis.set_major_formatter(xfmt)

ax[1].xaxis.set_minor_locator(mpl.dates.HourLocator(interval=1))
ax[1].xaxis.set_minor_formatter(xfmt)

ax[1].get_xaxis().set_tick_params(which='major', pad=25)

fig.autofmt_xdate()
plt.show()

produces the below result. Notice that falling back to matplotlib requires some fiddling with the width parameter in ax[1].bar(). For minorticks, you may want to look here for more detailed formatting options, esp. re skipping intervals to avoid overlap.

enter image description here

Community
  • 1
  • 1
Stefan
  • 41,759
  • 13
  • 76
  • 81
  • excellent ! thanks Stefan. And if I also want minor ticks every hour, should I just use `ax[1].xaxis.set_minor_locator(mpl.dates.HourLocator(interval=1))` ? – ℕʘʘḆḽḘ May 13 '16 at 17:12
  • 1
    See update with `minorticks` and a link on how to adjust formatting. – Stefan May 13 '16 at 17:27