Grr
Grr

Reputation: 16109

Issue with rotating x tick labels in matplotlib subplots

I am having an issue getting my x axis tick labels to rotate. I have tried following the matplotlib documentation for axes.set_xticklabels() using ax1.set_xticklables(labels, rotation=45). I have tried using plt.setp per this post but still havent been able to successfully rotate the labels. For reference my code is as follows:

import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import datetime 

print("Enter a symbol:")
symbol = input()
symbol = symbol.upper()
print("Enter an interval:")
interval = input()
print("You entered: " + symbol)

# Obtain minute bars of symbol from Google Finance for the last ten days

bars = pd.read_csv(r'http://www.google.com/finance/getprices?i={}&p=10d&f=d,o,h,l,c,v&df=cpct&q={}'.format(interval, symbol), sep=',', engine='python', skiprows=7, header=None, names=['Date', 'Close', 'High', 'Low', 'Open', 'Volume'])

bars['Date'] = bars['Date'].map(lambda x: int(x[1:]) if x[0] == 'a' else int(x))
bars['Date'] = bars['Date'].map(lambda u: u * 60 if u < 400 else u)
threshold = 24000
bars['Timestamp'] = bars[bars['Date']>threshold].loc[:, 'Date']
bars['Timestamp'] = bars['Timestamp'].fillna(method='ffill')
bars['Date'] = bars.apply(lambda x: x.Date + x.Timestamp if x.Date < threshold else x.Date, axis=1)
bars.drop('Timestamp', axis=1, inplace=True)
bars['Date'] = bars['Date'].map(lambda v: datetime.datetime.fromtimestamp(v) if v < 25000 else datetime.datetime.fromtimestamp(v))

# Plot equity curve
fig = plt.figure()
fig.patch.set_facecolor('white') # Set the outer color to white
ax1 = fig.add_subplot(211, ylabel='Price in $')
ax1.set_xticklabels(bars['Date'], rotation=45)

# Plot the DIA closing price overlaid with the moving averages
bars['Close'].plot(ax=ax1, color='r', lw=2.)
signals[['short_mavg', 'long_mavg']].plot(ax=ax1,lw=2.)

# Plot the "buy" trades agains DIA
ax1.plot(signals.ix[signals.positions == 1.0].index, signals.short_mavg[signals.positions == 1.0], '^', markersize=10, color='m')
ax1.plot(signals.ix[signals.positions == 2.0].index, signals.short_mavg[signals.positions == 2.0], '^', markersize=10, color='m')

# Plot the "sell" trades against AAPL
ax1.plot(signals.ix[signals.positions == -1.0].index, signals.short_mavg[signals.positions == -1.0], 'v', markersize=10, color='b')
ax1.plot(signals.ix[signals.positions == -2.0].index, signals.short_mavg[signals.positions == -2.0], 'v', markersize=10, color='b')

# Plot the equity curve in dollars
ax2 = fig.add_subplot(212, xticklabels=bars['Date'], ylabel='Portfolio value in $')
ax2.set_xticklabels(bars['Date'], rotation=45)
returns['total'].plot(ax=ax2, lw=2.)

# Plot the "buy" and "sell" trades against the equity curve
ax2.plot(returns.ix[signals.positions == 1.0].index, returns.total[signals.positions == 1.0], '^', markersize=10, color='m')
ax2.plot(returns.ix[signals.positions == -1.0].index, returns.total[signals.positions == -1.0], 'v', markersize=10, color='b')
ax2.plot(returns.ix[signals.positions == 2.0].index, returns.total[signals.positions == 2.0], '^', markersize=10, color='m')
ax2.plot(returns.ix[signals.positions == -2.0].index, returns.total[signals.positions == -2.0], 'v', markersize=10, color='b')

# Plot the figure
fig.savefig("C:/users/gph/desktop/tradingalgorithm/30_60EMA_cross_backtest.png")

bars['Date'] is a dataframe column imported from a csv on my machine, but you could replicate a smaller version of it with the segment of code in the top of the example.

Upvotes: 1

Views: 4051

Answers (1)

Grr
Grr

Reputation: 16109

So after a bit of tinkering I figured this out on my own. For some reason with Pandas 0.17 and matplotlib 1.5 trying to plot lines with df['column'].plot(ax=ax#) prevents me being able to control the formatting of the axis. Furthermore what i was doing with ax1.set_xticklabels(bars['Date'], rotation=45) was incorrect in that it was setting the ticklabels to the entirety of the 'Date' column and only displaying the first few based on the number of ticks.

What i ended up doing was following the advice of this post, converting the 'Date' from numpy.datetime64 (not friendly with matplotlib) to a float days format, and create a new column 'Dates' with this value. Then a list of unique days is created and converted to ISO date format.

dates = [md.date2num(t) for t in bars.Date]
bars['Dates'] = dates
days = np.unique(np.floor(bars['Dates']), return_index=True)
iso_days= []
for n in np.arange(len(days[0])):
    iso_days.append(datetime.date.isoformat(md.num2date(days[0][n]))) 

The rest was pretty simple, I made a few changes to the way I called subplots() and set sharex=True for looks.

# Plot two subplots to assess trades and equity curve. 
fig, (ax1, ax2) = plt.subplots(, 1, sharex=True)
fig.patch.set_facecolor('white') # Set the outer color to white
ax1.set_ylabel('Price in $')
# Plot the DIA closing price overlaid with the moving averages
ax1.set_xticks(days[1])

ax1.plot(bars.index, bars['Close'], color='r', lw=2.)
ax1.plot(bars.index, signals['short_mavg'], 'b', bars.index, signals['long_mavg'], 'g',lw=2.)

# Plot the "buy" trades agains DIA
ax1.plot(signals.ix[signals.positions == 1.0].index, signals.short_mavg[signals.positions == 1.0], '^', markersize=10, color='m')
ax1.plot(signals.ix[signals.positions == 2.0].index, signals.short_mavg[signals.positions == 2.0], '^', markersize=10, color='m')

# Plot the "sell" trades against AAPL
ax1.plot(signals.ix[signals.positions == -1.0].index, signals.short_mavg[signals.positions == -1.0], 'v', markersize=10, color='b')
ax1.plot(signals.ix[signals.positions == -2.0].index, signals.short_mavg[signals.positions == -2.0], 'v', markersize=10, color='b')

# Plot the equity curve in dollars
ax2.set_ylabel('Portfolio value in $')
ax2.plot(bars.index, returns.total, lw=2.)
ax2.set_xticklabels(iso_days, rotation=45, horizontalalignment='right')

# Plot the "buy" and "sell" trades against the equity curve
ax2.plot(returns.ix[signals.positions == 1.0].index, returns.total[signals.positions == 1.0], '^', markersize=10, color='m')
ax2.plot(returns.ix[signals.positions == -1.0].index, returns.total[signals.positions == -1.0], 'v', markersize=10, color='b')
ax2.plot(returns.ix[signals.positions == 2.0].index, returns.total[signals.positions == 2.0], '^', markersize=10, color='m')
ax2.plot(returns.ix[signals.positions == -2.0].index, returns.total[signals.positions == -2.0], 'v', markersize=10, color='b')

# Plot the figure
plt.tight_layout()
plt.show()
fig.savefig("C:/users/gph/desktop/tradingalgorithm/{}_{}EMA_cross_backtest.png".format(short_window, long_window))

It Worked!

Upvotes: 1

Related Questions