It is hard to see the last datapoint on the chart when it is right next to the y-axis. I would like to create some space between my last data point and the right y-axis. Any idea how to create this space?
import pandas as pd
import numpy as np
import yfinance as yf
import pandas_datareader as pdr
import datetime as dt
import matplotlib.pyplot as plt
##Get stock price data
ticker = '^GSPC, AAPL'
#get data from YFinance
df = yf.download(ticker, period = "max" , interval = "1d")['Adj Close']
#Convert the 'Date' Index to 'Date' Column
df.reset_index(inplace=True)
df['GSPCpctchange'] = (df['^GSPC'] / df['^GSPC'].shift(1))-1
df['AAPLpctchange'] = (df['AAPL'] / df['AAPL'].shift(1))-1
df['10_percent_R'] = df['GSPCpctchange'].rolling(10).corr(df['AAPLpctchange'])
df['10_price_R'] = df['^GSPC'].rolling(10).corr(df['AAPL'])
df['Date'] = pd.to_datetime(df['Date'], format = '%Y/%m/%d')
# Assign this as index
df.set_index(['Date'], inplace=True)
#Chart S&P500 and AAPL 10D R on one chart
plt.style.use('classic')
fig, ax1 = plt.subplots(figsize=(13,9))
ax2 = ax1.twinx()
fig.suptitle('S&P500 10D Correlation with AAPL', fontsize=16)
ax1.set_xlabel('Date')
ax1.set_ylabel('S&P500', color="blue")
ax1.tick_params(axis='y', labelcolor="blue")
ax1.plot(df.loc['2019-01-01':'2021-02-27','^GSPC'], linewidth=3, color="blue")
ax2.set_ylabel('10D AAPL Correlation', color="navy") # we already handled the x-label with ax1
ax2.tick_params(axis='y', labelcolor="navy")
ax2.plot(df.loc['2019-01-01':'2021-02-27','10_percent_R'], color="orange")
ax2.plot(df.loc['2019-01-01':'2021-02-27','10_price_R'], color="navy")
ax1.grid()
plt.legend(['Percent R','Price R'], loc="upper left")
You can try like this:
ax1.set_xlim(['2019-01-01', '2021-03-01'])
Related
I'm trying to figure out how to plot an X-axis with hourly precision (the index column has hourly values) as is in my dataframe. Currently, it just labels each month. I want one label for each Y point “close values column”.
My code now:
import matplotlib.pyplot as plt
from matplotlib import dates as mpl_dates
import pandas as pd
data = pd.read_csv('C:/Users/renat/.spyder-py3/1H data new.csv', index_col=0, parse_dates=True)
data.index = pd.to_datetime(data.index, format='%Y-%m-%d %H:%M:%S')
plt.figure(figsize=(80, 8))
plt.plot_date(data.index,data['close'], linestyle='solid',xdate=True, marker=None)
plt.gcf().autofmt_xdate()
date_format = mpl_dates.DateFormatter('%Y-%m-%d %H')
plt.gca().xaxis.set_major_formatter(date_format)
plt.title('Price Chart for TEST')
plt.xlabel('Date')
plt.ylabel('Price ($)')
plt.show()
Thanks to #r-begginers's comment I am able to achieve what I want. My finished code to print financial data with hourly labels for the X axis is as follows:
import matplotlib.pyplot as plt
from matplotlib import dates as mpl_dates
import pandas as pd
data = pd.read_csv('C:/Users/renat/.spyder-py3/1H data new.csv', index_col=0, parse_dates=True)
data.index = pd.to_datetime(data.index, format='%Y-%m-%d %H:%M:%S')
plt.figure(figsize=(100, 8))
plt.plot_date(data.index,data['close'], linestyle='solid',xdate=True, marker=None)
days = mpl_dates.DayLocator(interval=1)
days_fmt = mpl_dates.DateFormatter('%Y-%m-%d %H:%M')
plt.gca().xaxis.set_major_locator(days)
plt.gca().xaxis.set_major_formatter(days_fmt)
plt.grid()
plt.xticks(rotation=90, fontsize=6)
plt.title('Price Chart for TEST')
plt.xlabel('Date')
plt.ylabel('Price ($)')
plt.show()
I've simply replaced the three lines that were related to the formatting of the x-axis.
In:
hours = mpl_dates.HourLocator(interval=1)
hours_fmt = mpl_dates.DateFormatter('%H')
plt.gca().xaxis.set_major_locator(hours)
plt.gca().xaxis.set_major_formatter(hours_fmt)
Out:
plt.gcf().autofmt_xdate()
date_format = mpl_dates.DateFormatter('%Y-%m-%d %H')
plt.gca().xaxis.set_major_formatter(date_format)
I've also made some other changes, but they are not relevant to the question.
Thanks again to #r-begginers for pointing me in this direction.
When I want to use axvspan to fill the dates, It fills wrong area. I think it reversed axvspans. The reason for the problem may be the dataframe that I imported from World Bank. How can I fix it? Thank you.
import matplotlib.pyplot as plt
import matplotlib
from pandas_datareader import wb
import seaborn as sns
import pandas as pd
import datetime
start = datetime.datetime (2000,1,1)
end = datetime.datetime (2021,5,1)
ind = ['FM.LBL.BMNY.ZG',
'FR.INR.DPST'
]
df = wb.download(indicator=ind, country='CHN', start=start, end=end).dropna();df.reset_index(inplace=True)
df.columns = ['Country',
'Year',
'Broad money growth (annual %) - China',
'Deposit interest rate (%)'
]
df=df.sort_values(by='Year', ascending=True)
axes= df.plot(x='Year',subplots=True, figsize=(20,12), layout=(1,2), colormap='summer', legend=True)
for ax, col in zip(axes.flatten(), df.columns):
ax.axvspan('2007-1-12', '2009-6-1', color='teal', alpha=0.5,
label='2008 Crisis')
ax.axvspan('2019-12-1', '2020-2-1', color='orange', alpha=0.5,
label='Pandemic')
ax.set_title(col)
axes[0,0].set_title('Broad money growth (annual %) - China')
axes[0,0].invert_xaxis()
axes[0,0].legend(loc='upper left')
axes[0,0].set_ylabel('Percent(Annual)')
axes[0,0].invert_xaxis()
axes[0,1].set_title('Deposit interest rate (%)')
axes[0,1].invert_xaxis()
axes[0,1].legend(loc='upper left')
axes[0,1].set_ylabel('Percent(Annual)')
axes[0,1].invert_xaxis()
plt.suptitle("Financial Sector in China",fontweight="bold")
plt.show()
Correcting xaxis dtype in pandas.plot to correct vspan locations
The year column in df is an object not an int, so the xlim is (-1, 21) and the labels are formatted on top of those index locations. Therefore, when you go to place your vspan, the x location entered does not match those of the x axis. To fix this, simply make your year column an int and make your vspan in terms of years as ints.
import matplotlib.pyplot as plt
import matplotlib
from pandas_datareader import wb
import seaborn as sns
import pandas as pd
import datetime
import matplotlib.ticker as ticker
start = datetime.datetime (2000,1,1)
end = datetime.datetime (2021,5,1)
ind = ['FM.LBL.BMNY.ZG',
'FR.INR.DPST'
]
df = wb.download(indicator=ind, country='CHN', start=start, end=end).dropna();df.reset_index(inplace=True)
df.columns = ['Country',
'Year',
'Broad money growth (annual %) - China',
'Deposit interest rate (%)'
]
df=df.sort_values(by='Year', ascending=True)
df['Year'] = df['Year'].astype(int)
axes= df.plot(x='Year',subplots=True, figsize=(15,5), layout=(1,2), colormap='summer', legend=True)
for ax, col in zip(axes.flatten(), df.columns):
ax.axvspan(2007, 2009, color='teal', alpha=0.5, label='2008 Crisis')
ax.axvspan(2019, 2020, color='orange', alpha=0.5, label='Pandemic')
ax.set_title(col)
ax.set_xlim(2000, 2021)
ax.xaxis.set_major_locator(ticker.MultipleLocator(2))
axes[0,0].set_title('Broad money growth (annual %) - China')
axes[0,0].legend(loc='upper left')
axes[0,0].set_ylabel('Percent(Annual)')
axes[0,1].set_title('Deposit interest rate (%)')
axes[0,1].legend(loc='upper left')
axes[0,1].set_ylabel('Percent(Annual)')
plt.suptitle("Financial Sector in China",fontweight="bold")
This code gives plot of candlesticks with moving averages but the x-axis is in index, I need the x-axis in dates.
What changes are required?
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from mpl_finance import candlestick2_ohlc
#date format in data-> dd-mm-yyyy
nif = pd.read_csv('data.csv')
#nif['Date'] = pd.to_datetime(nif['Date'], format='%d-%m-%Y', utc=True)
mavg = nif['Close'].ewm(span=50).mean()
mavg1 = nif['Close'].ewm(span=13).mean()
fg, ax1 = plt.subplots()
cl = candlestick2_ohlc(ax=ax1,opens=nif['Open'],highs=nif['High'],lows=nif['Low'],closes=nif['Close'],width=0.4, colorup='#77d879', colordown='#db3f3f')
mavg.plot(ax=ax1,label='50_ema')
mavg1.plot(color='k',ax=ax1, label='13_ema')
plt.legend(loc=4)
plt.subplots_adjust(left=0.09, bottom=0.20, right=0.94, top=0.90, wspace=0.2, hspace=0)
plt.show()
Output:
I also had a lot of "fun" with this in the past... Here is one way of doing it using mdates:
import pandas as pd
import pandas_datareader.data as web
import datetime as dt
import matplotlib.pyplot as plt
from matplotlib.finance import candlestick_ohlc
import matplotlib.dates as mdates
ticker = 'MCD'
start = dt.date(2014, 1, 1)
#Gathering the data
data = web.DataReader(ticker, 'yahoo', start)
#Calc moving average
data['MA10'] = data['Adj Close'].rolling(window=10).mean()
data['MA60'] = data['Adj Close'].rolling(window=60).mean()
data.reset_index(inplace=True)
data['Date']=mdates.date2num(data['Date'].astype(dt.date))
#Plot candlestick chart
fig = plt.figure()
ax1 = fig.add_subplot(111)
ax2 = fig.add_subplot(111)
ax3 = fig.add_subplot(111)
ax1.xaxis_date()
ax1.xaxis.set_major_formatter(mdates.DateFormatter('%d-%m-%Y'))
ax2.plot(data.Date, data['MA10'], label='MA_10')
ax3.plot(data.Date, data['MA60'], label='MA_60')
plt.ylabel("Price")
plt.title(ticker)
ax1.grid(True)
plt.legend(loc='best')
plt.xticks(rotation=45)
candlestick_ohlc(ax1, data.values, width=0.6, colorup='g', colordown='r')
plt.show()
Output:
Hope this helps.
Simple df:
Using plotly:
import plotly.figure_factory
fig = plotly.figure_factory.create_candlestick(df.open, df.high, df.low, df.close, dates=df.ts)
fig.show()
will automatically parse the ts column to be displayed correctly on x.
Clunky workaround here, derived from other post (if i can find again, will reference). Using a pandas df, plot by index and then reference xaxis tick labels to date strings for display. Am new to python / matplotlib, and this this solution is not so flexible, but it works basically. Also using a pd index for plotting removes the blank 'weekend' daily spaces on market price data.
Matplotlib xaxis index as dates
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from mpl_finance import candlestick2_ohlc
from mpl_finance import candlestick_ohlc
%matplotlib notebook # for Jupyter
# Format m/d/Y,Open,High,Low,Close,Adj Close,Volume
# csv data does not include NaN, or 'weekend' lines,
# only dates from which prices are recorded
DJIA = pd.read_csv('yourFILE.csv') #Format m/d/Y,Open,High,
Low,Close,Adj Close,Volume
print(DJIA.head())
fg, ax1 = plt.subplots()
cl =candlestick2_ohlc(ax=ax1,opens=DJIA['Open'],
highs=DJIA['High'],lows=DJIA['Low'],
closes=DJIA['Close'],width=0.4, colorup='#77d879',
colordown='#db3f3f')
ax1.set_xticks(np.arange(len(DJIA)))
ax1.set_xticklabels(DJIA['Date'], fontsize=6, rotation=-90)
plt.show()
I have written the code below to visualise a joyplot. When trying to change the x axis labels using axes.set_xticks, I get the error: AttributeError: 'list' object has no attribute 'set_xticks'
import joypy
import pandas as pd
from matplotlib import pyplot as plt
data = pd.DataFrame.from_records([['twitter', 1],
['twitter', 6],
['wikipedia', 1],
['wikipedia', 3],
['indymedia', 1],
['indymedia', 9]], columns=['platform','day'])
# Get number of days in the dataset
numdays = max(set(data['day'].tolist()))
# Generate date strings from a manually set start date
start_date = "2010-01-01"
dates = pd.date_range(start_date, periods=numdays)
dates = [str(date)[:-9] for date in dates]
fig, axes = joypy.joyplot(data,by="platform")
axes.set_xticks(range(numdays)); axes.set_xticklabels(dates)
plt.show()
The expected output should look something like the following but with the dates from dates as ticklabels.
Since joypy.joyplot(..) returns a tuple of figure, axes and axes should be list of axes, you probably want to set the labels for the last axes,
axes[-1].set_xticks(range(numdays))
axes[-1].set_xticklabels(dates)
To make date plots with python matplotlib do you should use plot_date function.
fig, ax = plt.subplots()
ax.plot_date(dates, data1, '-')
I put the complete example in pastebin, follow the link:
https://pastebin.com/sVPUZaeM
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from matplotlib.dates import DateFormatter
from random import randrange, random
from datetime import datetime
#generate date list
start_date = np.datetime64('2010-01-01').astype(datetime)
numdays = 10
dates = pd.date_range(start_date, periods=numdays)
#Generate data example
data1 = [(random()+idx)**1.2 for idx in range(len(dates))]
data2 = [(random()+idx)**1.5 for idx in range(len(dates))]
#plot
fig, ax = plt.subplots()
ax.plot_date(dates, data1, '-')
ax.plot_date(dates, data2, '-')
#set the label for x and y and title
plt.title('Matplot lib dates wc example')
plt.xlabel('Dates')
plt.ylabel('Random values example')
#date format
ax.fmt_xdata = DateFormatter('%Y%m%d')
ax.grid(True)
fig.autofmt_xdate()
plt.show()
Python version tested successfully: 2.7.12
This code generates: this follow plot
trying to plot a candlestick serie after importing datas from yahoo-finance. I'm using python 2.7
I have already a serie plotted and I want to add the same one as candlestick but I don't see how I can do that :
import matplotlib.pyplot as plt
from matplotlib.finance import candlestick2_ohlc
#Reset the index to remove Date column from index
df_ohlc = data.reset_index()
#Naming columns
df_ohlc.columns = ["Date","Open","High",'Low',"Close", "Adj Close", "Volume"]
#Normal plot
ax1 = plt.subplot()
ax1.plot(df_ohlc["Date"], df_ohlc["Close"], label = "Price", color="blue", linewidth=2.0)
#Candle plot
candlestick2_ohlc(ax1,df_ohlc['Open'],df_ohlc['High'],df_ohlc['Low'],df_ohlc['Close'],width=0.6)
If I plot candlestick alone, it looks fine but the x axis is a list of integers.
If I plot candlestick alone after converting df_ohlc["Date"] to float then reconverting to datetime, it plots the serie with the correct x axis but there are gaps on the weekend even if the serie isn't defined for these dates.
Is there a way to plot both series at the same time ? I'm planning to add more series like moving average, OLS, Bollinger etc...
You can remove weekend gaps and make human-readable dates xticklabels in this way. Note that, this script is written in python 3 and there may be some differences from python 2.
import quandl
import numpy as np
from mpl_finance import candlestick_ohlc
import matplotlib.pyplot as plt
# getting data and modifying it to remove gaps at weekends
r = quandl.get('WIKI/AAPL', start_date='2016-01-01', end_date='2017-11-10')
date_list = np.array(r.index.to_pydatetime())
plot_array = np.zeros([len(r), 5])
plot_array[:, 0] = np.arange(plot_array.shape[0])
plot_array[:, 1:] = r.iloc[:, :4]
# plotting candlestick chart
fig, ax = plt.subplots()
num_of_bars = 100 # the number of candlesticks to be plotted
candlestick_ohlc(ax, plot_array[-num_of_bars:], colorup='g', colordown='r')
ax.margins(x=0.0, y=0.1)
ax.yaxis.tick_right()
x_tick_labels = []
ax.set_xlim(right=plot_array[-1, 0]+10)
ax.grid(True, color='k', ls='--', alpha=0.2)
# setting xticklabels actual dates instead of numbers
indices = np.linspace(plot_array[-num_of_bars, 0], plot_array[-1, 0], 8, dtype=int)
for i in indices:
date_dt = date_list[i]
date_str = date_dt.strftime('%b-%d')
x_tick_labels.append(date_str)
ax.set(xticks=indices, xticklabels=x_tick_labels)
plt.show()
I really need more information about your code and your dataframe, but you can use this example to do a candlestick
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.ticker as mticker
from matplotlib.finance import candlestick_ohlc
import matplotlib.dates as mdates
import datetime as dt
#Reset the index to remove Date column from index
df_ohlc = df.reset_index()
#Naming columns
df_ohlc.columns = ["Date","Open","High",'Low',"Close", "Adj Close", "Volume"]
#Converting dates column to float values
df_ohlc['Date'] = df_ohlc['Date'].map(mdates.date2num)
#Making plot
fig = plt.figure()
fig.autofmt_xdate()
ax1 = plt.subplot2grid((6,1), (0,0), rowspan=6, colspan=1)
#Converts raw mdate numbers to dates
ax1.xaxis_date()
plt.xlabel("Date")
print(df_ohlc)
#Making candlestick plot
candlestick_ohlc(ax1,df_ohlc.values,width=1, colorup='g', colordown='k',alpha=0.75)
plt.ylabel("Price")
plt.legend()
plt.show()