user6972
user6972

Reputation: 911

Python Pyplot unix timestamp on axis with candlestick plot

I've tried to go through some of the answers about plotting timestamps as strings using pyplot, but none of the answers quite address my situation.

Here is a sample of what I am trying to do with the data organized as [timestamp, open,close , max, min, avg, volume]. The candlestick works fine, but I'm trying to add in the x-axis for showing datetimes.

I understand I need to convert them to a datetime object for the formatter to work, but I'm not sure what is the best way to accomplish this with this type of plot. This is what I have now:

results=[[1388893323, 24.309684210526317, 24.302, 24.309684210526317, 24.261, 24.2828875, 172.1496], [1388893203, 24.301997222222223, 24.2501, 24.301997222222223, 24.2501, 24.28035104166669, 198.16475999999997], 
[1388893083, 24.2501, 24.311, 24.311, 24.2501, 24.276614722222227, 1002.402654], 
[1388892963, 24.311, 24.311, 24.37764285714286, 24.311, 24.313886785714317, 111.5695297]]

xfmt = DateFormatter('%Y-%m-%d %H:%M:%S')

fig, ax = plt.subplots()
fig.subplots_adjust(bottom=0.2)
ax.xaxis.set_major_formatter(xfmt)

candlestick(ax, results, width=20)

ax.xaxis_date()
ax.autoscale_view()
plt.setp( plt.gca().get_xticklabels(), rotation=45, horizontalalignment='right')

plt.show()

Which produces an error I believe is related to not being a datetime object:

  File "sma.py", line 27, in <module>
    plt.setp( plt.gca().get_xticklabels(), rotation=45, horizontalalignment='right')
  File "/usr/lib/pymodules/python2.7/matplotlib/axes.py", line 2530, in get_xticklabels
    self.xaxis.get_ticklabels(minor=minor))
  File "/usr/lib/pymodules/python2.7/matplotlib/axis.py", line 1109, in get_ticklabels
    return self.get_majorticklabels()
  File "/usr/lib/pymodules/python2.7/matplotlib/axis.py", line 1093, in get_majorticklabels
    ticks = self.get_major_ticks()
  File "/usr/lib/pymodules/python2.7/matplotlib/axis.py", line 1191, in get_major_ticks
    numticks = len(self.get_major_locator()())
  File "/usr/lib/pymodules/python2.7/matplotlib/dates.py", line 749, in __call__
    self.refresh()
  File "/usr/lib/pymodules/python2.7/matplotlib/dates.py", line 758, in refresh
    dmin, dmax = self.viewlim_to_dt()
  File "/usr/lib/pymodules/python2.7/matplotlib/dates.py", line 530, in viewlim_to_dt
    return num2date(vmin, self.tz), num2date(vmax, self.tz)
  File "/usr/lib/pymodules/python2.7/matplotlib/dates.py", line 289, in num2date
    if not cbook.iterable(x): return _from_ordinalf(x, tz)
  File "/usr/lib/pymodules/python2.7/matplotlib/dates.py", line 203, in _from_ordinalf
    dt = datetime.datetime.fromordinal(ix)
ValueError: year is out of range

I'm new to python and I've tried a few things that don't seem to work. How do I resolve this problem?


I tried remapping as suggested and it seems to be working:

results=[[1388897101, 24.52, 24.51, 24.52, 24.51, 24.51562500000004, 58.848754], [1388896981, 24.51, 24.54544, 24.54544, 24.51, 24.521243333333334, 44.292754], [1388896861, 24.546877777777777, 24.5, 24.575633333333332, 24.5, 24.523650277777747, 71.937206], [1388896741, 24.5, 24.5, 24.5, 24.5, 24.5, 27.362592], [1388896621, 24.5, 24.516213513513513, 24.516213513513513, 24.5, 24.504934459459466, 87.731023]]

i=0;
for data in results:
    results[i][0] = epoch2num(data[0])
    i+=1

results=[[735238.19792824076, 24.52, 24.51, 24.52, 24.51, 24.51562500000004, 58.848754], [735238.19653935183, 24.51, 24.54544, 24.54544, 24.51, 24.521243333333334, 44.292754], [735238.19515046291, 24.546877777777777, 24.5, 24.575633333333332, 24.5, 24.523650277777747, 71.937206], [735238.1937615741, 24.5, 24.5, 24.5, 24.5, 24.5, 27.362592], [735238.19237268518, 24.5, 24.516213513513513, 24.516213513513513, 24.5, 24.504934459459466, 87.731023]]

But the scale on the x-axis covers months instead of just just a few hours of data. How do you adjust the scale for dates?

Upvotes: 2

Views: 2584

Answers (1)

falsetru
falsetru

Reputation: 368964

matplotlib use different number for time, according to matplotlib.dates documentation:

Matplotlib provides sophisticated date plotting capabilities, standing on the shoulders of python datetime, the add-on modules pytz and dateutils. datetime objects are converted to floating point numbers which represent time in days since 0001-01-01 UTC, plus 1. For example, 0001-01-01, 06:00 is 1.25, not 0.25.

You need to convert epoch timestamp using matplotlib.dates.epoch2num:

results=[
    ...
]
for data in results:
    data[0] = epoch2num(data[0]) # <---

Upvotes: 4

Related Questions