4

I tried to follow the matplotlib documentation to create price-volume plot for stocks. I have a question about how to set the major ticks to the first day of each month and minor ticks for each day. I tried to follow http://matplotlib.org/examples/pylab_examples/date_demo2.html, but just could not get it to work. The following is the best I can get for now. Any help?!

#!/usr/bin/env python

import matplotlib.pyplot as plt
from matplotlib.dates import DateFormatter, WeekdayLocator, MonthLocator, DayLocator, MONDAY
from matplotlib.finance import quotes_historical_yahoo, candlestick2, volume_overlay
from matplotlib import gridspec
from matplotlib.dates import num2date, IndexDateFormatter
from matplotlib.ticker import  IndexLocator, FuncFormatter

from operator import itemgetter

# (Year, month, day) tuples suffice as args for quotes_historical_yahoo
date1 = (2010, 2, 1)
date2 = (2011, 2, 1)

symbol = 'TSLA'

quotes = quotes_historical_yahoo(symbol, date1, date2)

if len(quotes) == 0:
    raise SystemExit

ds, opens, closes, highs, lows, volumes = zip(*quotes)

def get_locator():
    """
    the axes cannot share the same locator, so this is a helper
    function to generate locators that have identical functionality
    """
    return IndexLocator(10, 1)

formatter =  IndexDateFormatter(ds, '%b %d %y')

def millions(x, pos):
    'The two args are the value and tick position'
    return '%1.1fM' % (x*1e-6)

def thousands(x, pos):
    'The two args are the value and tick position'
    return '%1.1fK' % (x*1e-3)

millionformatter = FuncFormatter(millions)
thousandformatter = FuncFormatter(thousands)

#fig = plt.figure(figsize=(8, 6)) 

fig = plt.figure()
fig.subplots_adjust(bottom=0.15)
fig.subplots_adjust(hspace=0)
fig.suptitle(symbol, fontsize=24, fontweight='bold')

gs = gridspec.GridSpec(2, 1, height_ratios=[4, 1]) 

ax0 = plt.subplot(gs[0])

#candlestick(ax0, quotes, width=0.6)
candles = candlestick2(ax0, opens, closes, highs, lows, width=1, colorup='g')

ax0.xaxis.set_major_locator( get_locator() )
ax0.xaxis.set_major_formatter(formatter)
ax0.set_ylabel('Price', fontsize=16)

#ax0.xaxis_date()
#ax0.autoscale_view()

ax1 = plt.subplot(gs[1], sharex=ax0)

#vc = volume_overlay3(ax1, quotes, colorup='k', colordown='r', width=4, alpha=1.0)
#volume_overlay(ax1, opens, closes, volumes, colorup='g', alpha=0.5, width=1)
#ax1.set_xticks(ds)

vc = volume_overlay(ax1, opens, closes, volumes, colorup='g', alpha=0.5, width=1)
ax1.add_collection(vc)

#ax1.format_xdata = DateFormatter('%Y-%m-%d')

#maxvolume = max(quotes,key=itemgetter(5))[5]

#ax1.set_ylim([0, maxvolume])

ax1.xaxis.set_major_locator(get_locator())
ax1.xaxis.set_major_formatter(formatter)
ax1.yaxis.set_major_formatter(millionformatter)
ax1.yaxis.tick_right()
ax1.set_ylabel('Volume', fontsize=16)

#ax1.xaxis_date()
#ax1.autoscale_view()

plt.setp(ax0.get_xticklabels(), visible=False)
plt.setp(ax1.get_xticklabels(), rotation=90, horizontalalignment='left')

plt.show()

and the picture I got is as follows: price and volume plot

Victor Gau
  • 191
  • 2
  • 11
  • http://stackoverflow.com/questions/24963711/matplotlib-setting-both-major-and-minor-ticks-forces-same-x-and-y-scale – Srivatsan Jun 17 '15 at 14:17
  • If you're expecting to work with stocks and business data, the pandas library might be handy for you. It uses matplotlib underneath so you'll be learning some general matplotlib syntax, but if panda's defaults are what you want, it's a good place to start. http://stackoverflow.com/questions/12945971/pandas-timeseries-plot-setting-x-axis-major-and-minor-ticks-and-labels?rq=1 – cphlewis Jun 17 '15 at 19:31
  • 2
    Yes, pandas is good for data analysis. But I think I need more than pandas's defaults to create fancy stock plot. – Victor Gau Jun 17 '15 at 20:20

1 Answers1

5

Just for posterity:

import matplotlib.dates as dt
import matplotlib.ticker as ticker
ax.xaxis.set_major_locator(dt.MonthLocator())
ax.xaxis.set_major_formatter(dt.DateFormatter('%d %b'))
ax.xaxis.set_minor_locator(dt.DayLocator())
ax.xaxis.set_minor_formatter(ticker.NullFormatter())
Philipp
  • 4,659
  • 9
  • 48
  • 69