Getting started with Matplotlib

Getting started with Matplotlib

Source: Introduction to Matplotlib and basic line

translator: Flying dragon

agreement: CC BY-NC-SA 4.0

Chapter 1 Introduction to Matplotlib

Welcome to the Python 3+ Matplotlib series of tutorials. In this series, we will cover many aspects of the Matplotlib data visualization module. Matplotlib can create most types of charts, such as bar chart, scatter chart, bar chart, pie chart, stack chart, 3D chart and map chart.

First, in order to actually use Matplotlib, we need to install it.

If you have installed a later version of Python, you should be able to open CMD Exe or terminal, and then execute:

pip install matplotlib

Note: if the short command above does not work, you may need to execute C: / Python 34 / scripts / PIP install Matplotlib.

If you import matplotlib, you will receive errors like "unnamed module" and module name, which means you still need to install the module. A common problem is the lack of a module called six. This means you need to use pip to install six.

Alternatively, you can go to Matplotlib Org and download the appropriate version for installation by visiting the download page. Remember, because your operating system is 64 bit, you don't necessarily need a 64 bit version of Python. If you're not going to try 64 bit, you can use 32 bit. Open IDLE and read the top. If it says you are 64 bits, you are 64 bits. If it says 32 bits, you are 32 bits. Once you install python, you're ready to write any logic you want. I like to program with IDLE, but you can use whatever you like.

import matplotlib.pyplot as plt

This line imports the integrated pyplot, which we will use throughout the series. We import pyplot into plt, which is the traditional practice of python programs using pylot.

plt.plot([1,2,3],[5,7,4])

Next, we call the of plot Plot method draws some coordinates. This Plot requires many parameters, but the first two are 'x' and 'y' coordinates, which we put into the list. This means that according to these lists, we have three coordinates: 1,5,2,7 and 3,4.

plt.plot "draws" this drawing in the background, but after drawing everything we want, when we are ready, we need to bring it to the screen.

plt.show()

In this way, a graphic should pop up. If not, sometimes it can pop up, or you may get an error. Your chart should look like this:

 

This window is a matplotlib window that allows us to view, interact with and access our graphics. You can hover over the chart and see the coordinates usually in the lower right corner. You can also use the button. They may be in different positions, but in the figure above, these buttons are in the lower left corner.

Home

 

Once you start browsing your chart, the home button will help you. If you want to return to the original view, you can click it. Clicking this button will not take effect until you browse the chart.

Forward/Back

 

These buttons can be used like the forward and backward buttons in the browser. You can click these to move back to your previous position or move forward again.

Pan (Pan)

 

You can click the pan button, then click and drag your chart.

Zoom

 

The zoom button allows you to click it, and then click and drag out the square area to zoom in. Zoom in requires left click and drag. You can also right-click and drag to zoom out.

Configure Subplots

 

This button allows you to configure various spacing options for graphics and drawings. Click it to pop up:

 

Each blue bar is a slider that allows you to adjust the inner margin. Some of them now have no effect because there are no other subgraphs. The first four values adjust the margin of the drawing to the edge of the window. Then wspace and hspace correspond to the horizontal or vertical spacing of multiple subgraphs when you draw them.

Save

 

This button allows you to save the drawing in various forms.

So this is a quick introduction to matplotlib, which we will cover more later.

Chapter II legend, title and label

In this tutorial, we will discuss the legend, title and label in Matplotlib. In many cases, graphics can be self-evident, but it is very necessary for graphics to have titles, labels and legends on axis fields to explain what each line is.

Note: Axes refers to the area surrounded by two coordinate Axes.

Start here:

import matplotlib.pyplot as plt

x = [1,2,3]
y = [5,7,4]

x2 = [1,2,3]
y2 = [10,14,12]

In this way, we can draw two lines. Next:

plt.plot(x, y, label='First Line')
plt.plot(x2, y2, label='Second Line')

Here, we draw what we have seen, but this time we add another parameter label. This allows us to specify a name for the line, which we can later display in the legend. Our remaining codes are:

plt.xlabel('Plot Number')
plt.ylabel('Important var')
plt.title('Interesting Graph\nCheck it out')
plt.legend()
plt.show()

Use PLT Xlabel and PLT Ylabel, we can create labels for these corresponding axes. Next, we can use PLT Title create the title of the diagram, and then we can use PLT Legend() generates the default legend. The results are shown as follows:

 

Chapter III bar chart and histogram

In this tutorial, we will cover bar charts and histograms. Let's start with the bar chart:

import matplotlib.pyplot as plt

plt.bar([1,3,5,7,9],[5,2,7,8,2], label="Example one")

plt.bar([2,4,6,8,10],[8,6,2,5,6], label="Example two", color='g')
plt.legend()
plt.xlabel('bar number')
plt.ylabel('bar height')

plt.title('Epic Graph\nAnother Line! Whoa')

plt.show()

plt.bar creates a bar chart for us. If you don't explicitly choose a color, all the bars will look the same even if you make multiple pictures. This gives us the opportunity to use a new Matplotlib customization option. You can use colors in any type of drawing, such as g for green, b for blue, r for red, and so on. You can also use hexadecimal color codes, such as #191970.

 

Next, we will explain the histogram. Histograms are very similar to bar charts and tend to show distribution by grouping sections together. This example may be the grouping of age, or the score of the test. We don't show the age of each group, but according to 20 ~ 25, 25 ~ 30 Wait to show age. Here is an example:

import matplotlib.pyplot as plt

population_ages = [22,55,62,45,21,22,34,42,42,4,99,102,110,120,121,122,130,111,115,112,80,75,65,54,44,43,42,48]

bins = [0,10,20,30,40,50,60,70,80,90,100,110,120,130]

plt.hist(population_ages, bins, histtype='bar', rwidth=0.8)

plt.xlabel('x')
plt.ylabel('y')
plt.title('Interesting Graph\nCheck it out')
plt.legend()
plt.show()

The resulting chart is:

 

For PLT Hist, you first need to put all the values, and then specify which bucket or container to put. In our example, we plotted a bunch of ages and wanted to show them in 10-year increments. We set the width of the bar to 0.8, but if you want to make the bar wider or narrower, you can choose another width.

Chapter IV scatter diagram

Next, we will introduce the scatter diagram. Scatter charts are usually used to compare two variables to find correlation or grouping. If you draw in three dimensions, there are three.

Some sample codes of scatter chart:

import matplotlib.pyplot as plt

x = [1,2,3,4,5,6,7,8]
y = [5,2,4,2,1,4,5,2]

plt.scatter(x,y, label='skitscat', color='k', s=25, marker="o")

plt.xlabel('x')
plt.ylabel('y')
plt.title('Interesting Graph\nCheck it out')
plt.legend()
plt.show()

The result is:

 

plt.scatter not only allows us to draw x and y, but also allows us to determine the color, size and type of markers used. There are a number of tag options, see Matplotlib tag document All options in.

Chapter V stacking diagram

In this Matplotlib data visualization tutorial, we will introduce how to create a stack diagram. The stack chart is used to show the relationship of "part to whole" over time. The stack chart is basically similar to a pie chart, but changes over time.

Let's consider a situation. We have 24 hours a day. We want to see how we spend our time. We divide our activities into: sleeping, eating, working and playing.

We assume that we will track it within 5 days, so our initial data will be as follows:

import matplotlib.pyplot as plt

days = [1,2,3,4,5]

sleeping = [7,8,6,11,7]
eating =   [2,3,4,3,2]
working =  [7,8,7,2,2]
playing =  [8,5,7,8,13]

Therefore, our x-axis will include day variables, i.e. 1, 2, 3, 4 and 5. The various components of the date are then saved in their respective activities. Draw them like this:

plt.stackplot(days, sleeping,eating,working,playing, colors=['m','c','r','k'])

plt.xlabel('x')
plt.ylabel('y')
plt.title('Interesting Graph\nCheck it out')
plt.show()
 

Here, we can at least see how we spend our time in color. The problem is that if we don't look back at the code, we don't know what color is. The next problem is that for polygons, we can't actually add "labels" to the data. Therefore, in any place where there is more than a line with a filled or stacked diagram like this, we cannot mark a specific part in an inherent way. This should not stop programmers. We can solve this problem:

import matplotlib.pyplot as plt

days = [1,2,3,4,5]

sleeping = [7,8,6,11,7]
eating =   [2,3,4,3,2]
working =  [7,8,7,2,2]
playing =  [8,5,7,8,13]


plt.plot([],[],color='m', label='Sleeping', linewidth=5)
plt.plot([],[],color='c', label='Eating', linewidth=5)
plt.plot([],[],color='r', label='Working', linewidth=5)
plt.plot([],[],color='k', label='Playing', linewidth=5)

plt.stackplot(days, sleeping,eating,working,playing, colors=['m','c','r','k'])

plt.xlabel('x')
plt.ylabel('y')
plt.title('Interesting Graph\nCheck it out')
plt.legend()
plt.show()
 

What we do here is draw some blank lines and give them the same color and correct labels that match our stacking diagram. We also set their line width to 5, making the lines appear wider in the legend. Now, we can easily see how we spend our time.

Chapter VI pie chart

Pie charts are much like stacked charts, except that they are at a certain point in time. In general, pie charts are used to display parts. For the overall situation, they are usually in%. Fortunately, Matplotlib handles slice size and everything. We just need to provide values.

import matplotlib.pyplot as plt

slices = [7,2,2,13]
activities = ['sleeping','eating','working','playing']
cols = ['c','m','r','b']

plt.pie(slices,
        labels=activities,
        colors=cols,
        startangle=90,
        shadow= True,
        explode=(0,0.1,0,0),
        autopct='%1.1f%%')

plt.title('Interesting Graph\nCheck it out')
plt.show()
 

In PLT In pie, we need to specify "slice", which is the relative size of each part. Then, we specify the color list of the corresponding slice. Next, we can choose to specify the "starting angle" of the figure. This allows you to start drawing anywhere. In our example, we chose a 90 degree angle for the pie chart, which means that the first part is a vertical line. Next, we can choose to add a character size shadow to the drawing, and then we can even use explode to pull out a slice.

We have a total of four slices, so for explode, if we don't want to pull out any slices, we pass in 0,0,0,0. If we want to pull out the first slice, we pass in 0.1,0,0,0.

Finally, using autopct, we choose to place the percentage on the chart.

Chapter 7 loading data from file

Many times we want to draw data in files. There are many types of files and many methods that you can use to extract data from files for graphing. Here, we will show several methods. First, we will load the CSV file using the built-in CSV module, and then we will show how to load the file using NumPy (third-party module).

import matplotlib.pyplot as plt
import csv

x = []
y = []

with open('example.txt','r') as csvfile:
    plots = csv.reader(csvfile, delimiter=',')
    for row in plots:
        x.append(int(row[0]))
        y.append(int(row[1]))

plt.plot(x,y, label='Loaded from file!')
plt.xlabel('x')
plt.ylabel('y')
plt.title('Interesting Graph\nCheck it out')
plt.legend()
plt.show()
 

Here, we open the sample file, which contains the following data:

1,5
2,3
3,4
4,7
5,4
6,3
7,5
8,7
9,4
10,4

Next, we use the csv module to read the data. The csv reader automatically splits the file by line, and then splits the data in the file using the separator we choose. In our example, this is a comma. Note: csv module and csv reader do not need files, which are literally the same csv file. It can be any simple text file with delimited data.

Once we do this, we store the elements with index 0 in the x list and the elements with index 1 in the y list. After that, we are all set up, ready to draw, and then display the data.

Although it is completely normal to use the CSV module, it may be more meaningful for us to use the NumPy module to load our files and data. If you don't have NumPy, you need to follow the steps below to get it. For more information on installing modules, see pip tutorial . Most people should be able to open the command line and execute pip install numpy.

If not, please refer to the tutorial in the link.

Once you have installed NumPy, you can write the following code:

import matplotlib.pyplot as plt
import numpy as np

x, y = np.loadtxt('example.txt', delimiter=',', unpack=True)
plt.plot(x,y, label='Loaded from file!')

plt.xlabel('x')
plt.ylabel('y')
plt.title('Interesting Graph\nCheck it out')
plt.legend()
plt.show()

The result should be the same chart. Later, when we load the data, we can use NumPy to do more work for us, but this is the future of the tutorial. Just like the csv module doesn't need a special one Like csv, the loadtext function does not require the file to be a txt file, which can be a csv, which can even be a python list object.

Chapter 8 loading data from the network

In addition to loading data from files, another popular data source is the Internet. We can load data from the Internet in various ways, but for us, we just simply read the source code of the website and separate the data through simple splitting.

import matplotlib.pyplot as plt
import numpy as np
import urllib
import matplotlib.dates as mdates


def graph_data(stock):

    stock_price_url = 'http://chartapi.finance.yahoo.com/instrument/1.0/'+stock+'/chartdata;type=quote;range=10y/csv'

    source_code = urllib.request.urlopen(stock_price_url).read().decode()

    stock_data = []
    split_source = source_code.split('\n')

    for line in split_source:
        split_line = line.split(',')
        if len(split_line) == 6:
            if 'values' not in line:
                stock_data.append(line)

There are many steps. First, we see import. pyplot imported as usual, then numpy, then urllib for accessing the Internet, and then matplotlib Dates, as mdates, is useful for converting date stamps into dates that matplotlib understands.

Next, we begin to build our graph_data function. Here, we first define the web address containing stock data. After that, we write some urllib code to access the URL, and then use read reads the source code, and then we continue to decode the data. If you use Python 2, you don't have to use decode.

Then, we define an empty list, which is where we will place the stock data, and we also start to use split_ The source variable splits the data with a newline character.

Now, if you look at the source code and replace + stock + in the URL with stock, like AAPL, you can see that most of the page data is indeed stock pricing information, but there are some header information that we need to filter out. To do this, we use some basic filters, check them to ensure that there are six data points per row, and then ensure that the term values is not in the row.

Now, we have parsed the data and are ready. We will use NumPy:

date, closep, highp, lowp, openp, volume = np.loadtxt(stock_data,
                                                      delimiter=',',
                                                      unpack=True,
                                                      # %Y = full year. 2015
                                                      # %y = partial year 15
                                                      # %m = number month
                                                      # %d = number day
                                                      # %H = hours
                                                      # %M = minutes
                                                      # %S = seconds
                                                      # 12-06-2014
                                                      # %m-%d-%Y
                                                      converters={0: bytespdate2num('%Y%m%d')})

What we do here is to use numpy's loadtext function and deconstruct these six elements into six variables. The first parameter here is stock_data, this is the data we loaded. Then, we specify delimiter (comma here), and then we specify that we really want to unpack variables here, not a variable, but the set of variables we define. Finally, we use the optional converters parameter to specify the element we want to convert (0) and what we intend to do. We pass a function called bytesdate2num, which doesn't exist yet, but we'll write it next.

Chapter 9 time stamp conversion

The focus of this tutorial is to convert dates from the Yahoo finance API to dates that Matplotlib understands. To implement it, we need to write a new function, bytestupdate2num.

def bytespdate2num(fmt, encoding='utf-8'):
    strconverter = mdates.strpdate2num(fmt)
    def bytesconverter(b):
        s = b.decode(encoding)
        return strconverter(s)
    return bytesconverter

This function accepts the data, decodes the data based on the encoding, and then returns it.

Apply this to the rest of our program:

import matplotlib.pyplot as plt
import numpy as np
import urllib
import matplotlib.dates as mdates

def bytespdate2num(fmt, encoding='utf-8'):
    strconverter = mdates.strpdate2num(fmt)
    def bytesconverter(b):
        s = b.decode(encoding)
        return strconverter(s)
    return bytesconverter
    

def graph_data(stock):

    stock_price_url = 'http://chartapi.finance.yahoo.com/instrument/1.0/'+stock+'/chartdata;type=quote;range=10y/csv'
    source_code = urllib.request.urlopen(stock_price_url).read().decode()
    stock_data = []
    split_source = source_code.split('\n')
    for line in split_source:
        split_line = line.split(',')
        if len(split_line) == 6:
            if 'values' not in line and 'labels' not in line:
                stock_data.append(line)

    date, closep, highp, lowp, openp, volume = np.loadtxt(stock_data,
                                                          delimiter=',',
                                                          unpack=True,
                                                          # %Y = full year. 2015
                                                          # %y = partial year 15
                                                          # %m = number month
                                                          # %d = number day
                                                          # %H = hours
                                                          # %M = minutes
                                                          # %S = seconds
                                                          # 12-06-2014
                                                          # %m-%d-%Y
                                                          converters={0: bytespdate2num('%Y%m%d')})

    plt.plot_date(date, closep,'-', label='Price')
 
    plt.xlabel('Date')
    plt.ylabel('Price')
    plt.title('Interesting Graph\nCheck it out')
    plt.legend()
    plt.show()


graph_data('TSLA')

If you draw TSLA, the result graph should look like this:

 

Chapter 10 basic customization

In the Matplotlib tutorial, we will discuss some possible chart customization. In order to start modifying subgraphs, we must define them. We'll talk about them soon, but there are two main ways to define and construct subgraphs. For now, we'll only use one of them, but we'll explain them soon.

Now we modify the graph_data function:

def graph_data(stock):

    fig = plt.figure()
    ax1 = plt.subplot2grid((1,1), (0,0))

In order to modify the chart, we need to reference it, so we store it in the variable fig. Then we define ax1 as a subgraph on the graph. We use subplot2grid here, which is one of the two main methods to obtain subgraphs. We'll discuss these things in depth, but for now, you should see that we have two tuples that provide (1,1) and (0,0). 1,1 indicates that this is a 1 × 1 grid. Then 0,0 indicates that the "starting point" of this subgraph will be 0,0.

Next, get and parse the data through the code we have written:

stock_price_url = 'http://chartapi.finance.yahoo.com/instrument/1.0/'+stock+'/chartdata;type=quote;range=10y/csv'
source_code = urllib.request.urlopen(stock_price_url).read().decode()
stock_data = []
split_source = source_code.split('\n')
for line in split_source:
    split_line = line.split(',')
    if len(split_line) == 6:
        if 'values' not in line and 'labels' not in line:
            stock_data.append(line)

date, closep, highp, lowp, openp, volume = np.loadtxt(stock_data,
                                                      delimiter=',',
                                                      unpack=True,
                                                      converters={0: bytespdate2num('%Y%m%d')})

Next, we plot the data as follows:

ax1.plot_date(date, closep,'-', label='Price')

Now, since we are drawing the date, we may find that if we zoom in, the date will move horizontally. However, we can customize these scale labels, such as:

for label in ax1.xaxis.get_ticklabels():
    label.set_rotation(45)

This will rotate the label diagonally. Next, we can add a grid:

ax1.grid(True)

Then, for other things, we keep the default, but we may also need to adjust the drawing slightly because the date runs outside the chart. Remember the configure subplots button we discussed in the first tutorial? We can not only configure the charts in this way, but also configure them in the code. The following is how we set these parameters:

plt.subplots_adjust(left=0.09, bottom=0.20, right=0.94, top=0.90, wspace=0.2, hspace=0)

Now, in order to prevent us from leaving you somewhere, here is the complete code:

import matplotlib.pyplot as plt
import numpy as np
import urllib
import matplotlib.dates as mdates

def bytespdate2num(fmt, encoding='utf-8'):
    strconverter = mdates.strpdate2num(fmt)
    def bytesconverter(b):
        s = b.decode(encoding)
        return strconverter(s)
    return bytesconverter
    

def graph_data(stock):

    fig = plt.figure()
    ax1 = plt.subplot2grid((1,1), (0,0))
    
    stock_price_url = 'http://chartapi.finance.yahoo.com/instrument/1.0/'+stock+'/chartdata;type=quote;range=10y/csv'
    source_code = urllib.request.urlopen(stock_price_url).read().decode()
    stock_data = []
    split_source = source_code.split('\n')
    for line in split_source:
        split_line = line.split(',')
        if len(split_line) == 6:
            if 'values' not in line and 'labels' not in line:
                stock_data.append(line)

    date, closep, highp, lowp, openp, volume = np.loadtxt(stock_data,
                                                          delimiter=',',
                                                          unpack=True,
                                                          converters={0: bytespdate2num('%Y%m%d')})

    ax1.plot_date(date, closep,'-', label='Price')
    for label in ax1.xaxis.get_ticklabels():
        label.set_rotation(45)
    ax1.grid(True)#, color='g', linestyle='-', linewidth=5)

    plt.xlabel('Date')
    plt.ylabel('Price')
    plt.title('Interesting Graph\nCheck it out')
    plt.legend()
    plt.subplots_adjust(left=0.09, bottom=0.20, right=0.94, top=0.90, wspace=0.2, hspace=0)
    plt.show()


graph_data('TSLA')

The result is:

 

Chapter XI Unix time

In this Matplotlib tutorial, we will show how to handle the conversion of unix timestamp, and then draw the date stamp in the graph. Using the Yahoo Finance API, you will notice that if you use a large time interval, such as 1y (one year), you will get the date stamp we have been using, but if you use 10d (10 days), on the contrary, you will get the unix time stamp.

unix time is the number of seconds after January 1, 1970. It is a standardized time representation across programs. In other words, Matplotlib does not welcome unix timestamps. Here is how you can use Matplotlib to handle unix time:

import matplotlib.pyplot as plt
import numpy as np
import urllib
import datetime as dt
import matplotlib.dates as mdates

def bytespdate2num(fmt, encoding='utf-8'):
    strconverter = mdates.strpdate2num(fmt)
    def bytesconverter(b):
        s = b.decode(encoding)
        return strconverter(s)
    return bytesconverter
    

def graph_data(stock):

    fig = plt.figure()
    ax1 = plt.subplot2grid((1,1), (0,0))
    
    stock_price_url = 'http://chartapi.finance.yahoo.com/instrument/1.0/'+stock+'/chartdata;type=quote;range=10d/csv'
    source_code = urllib.request.urlopen(stock_price_url).read().decode()
    stock_data = []
    split_source = source_code.split('\n')
    for line in split_source:
        split_line = line.split(',')
        if len(split_line) == 6:
            if 'values' not in line and 'labels' not in line:
                stock_data.append(line)

    date, closep, highp, lowp, openp, volume = np.loadtxt(stock_data,
                                                          delimiter=',',
                                                          unpack=True)
    dateconv = np.vectorize(dt.datetime.fromtimestamp)
    date = dateconv(date)
    
##    date, closep, highp, lowp, openp, volume = np.loadtxt(stock_data,
##                                                          delimiter=',',
##                                                          unpack=True,
##                                                          converters={0: bytespdate2num('%Y%m%d')})

    ax1.plot_date(date, closep,'-', label='Price')
    for label in ax1.xaxis.get_ticklabels():
        label.set_rotation(45)
    ax1.grid(True)#, color='g', linestyle='-', linewidth=5)

    plt.xlabel('Date')
    plt.ylabel('Price')
    plt.title('Interesting Graph\nCheck it out')
    plt.legend()
    plt.subplots_adjust(left=0.09, bottom=0.20, right=0.94, top=0.90, wspace=0.2, hspace=0)
    plt.show()


graph_data('TSLA')

So here, what we do is write unix time and comment out our previous code, because we save it for later use. The main differences here are:

dateconv = np.vectorize(dt.datetime.fromtimestamp)
date = dateconv(date)

Here, we convert the time stamp to the date stamp, and then convert it to the time that Matplotlib wants.

Now, for some reason, my unix time has another row of data containing six elements, and it contains the term label. Therefore, in our for loop for parsing data, we will add another check for you:

for line in split_source:
    split_line = line.split(',')
    if len(split_line) == 6:
        if 'values' not in line and 'labels' not in line:
            stock_data.append(line)

Now your chart should look like this:

 

The reason for all the flat lines here is that the market is closed. With this short-term data, we can get intraday data. So there are many points when the transaction is open, and then there is no when the market is closed, then there is a pile, and then there is No.

Chapter 12 color and filling

In this tutorial, we will introduce some more customizations, such as color and line filling.

The first change we need to make is PLT Change the title to the stock variable.

plt.title(stock)

Now, let's introduce how to change the label color. We can do this by modifying our axis object:

ax1.xaxis.label.set_color('c')
ax1.yaxis.label.set_color('r')

If we run it, we'll see that the label changes color, just like in words.

Next, we can specify a specific number for the axis to be displayed instead of automatic selection like this:

ax1.set_yticks([0,25,50,75])

Next, I want to introduce filling. What filling does is fill in the color between the variable and a value you choose. For example, we can:

ax1.fill_between(date, 0, closep)

So here, our code is:

import matplotlib.pyplot as plt
import numpy as np
import urllib
import datetime as dt
import matplotlib.dates as mdates

def bytespdate2num(fmt, encoding='utf-8'):
    strconverter = mdates.strpdate2num(fmt)
    def bytesconverter(b):
        s = b.decode(encoding)
        return strconverter(s)
    return bytesconverter
    

def graph_data(stock):

    fig = plt.figure()
    ax1 = plt.subplot2grid((1,1), (0,0))
    
    stock_price_url = 'http://chartapi.finance.yahoo.com/instrument/1.0/'+stock+'/chartdata;type=quote;range=10y/csv'
    source_code = urllib.request.urlopen(stock_price_url).read().decode()
    stock_data = []
    split_source = source_code.split('\n')
    for line in split_source:
        split_line = line.split(',')
        if len(split_line) == 6:
            if 'values' not in line and 'labels' not in line:
                stock_data.append(line)

    
    date, closep, highp, lowp, openp, volume = np.loadtxt(stock_data,
                                                          delimiter=',',
                                                          unpack=True,
                                                          converters={0: bytespdate2num('%Y%m%d')})

    ax1.fill_between(date, 0, closep)

    for label in ax1.xaxis.get_ticklabels():
        label.set_rotation(45)
    ax1.grid(True)#, color='g', linestyle='-', linewidth=5)
    ax1.xaxis.label.set_color('c')
    ax1.yaxis.label.set_color('r')
    ax1.set_yticks([0,25,50,75])

    plt.xlabel('Date')
    plt.ylabel('Price')
    plt.title(stock)
    plt.legend()
    plt.subplots_adjust(left=0.09, bottom=0.20, right=0.94, top=0.90, wspace=0.2, hspace=0)
    plt.show()


graph_data('EBAY')

The result is:

 

One problem with filling is that we may end up covering everything. We can solve it with transparency:

ax1.fill_between(date, 0, closep)

Let's fill in the conditions now. Let's assume that the starting position of the chart is where we start buying eBay. Here, if the price is lower than this price, we can fill up to the original price, and then if it exceeds the original price, we can fill down. We can do this:

ax1.fill_between(date, closep[0], closep)

Will generate:

 

If we want to use red and green padding to show gains / losses, then compared with the original price, green padding is used for rising (Note: the color of foreign stock markets is opposite to that of domestic stock markets), and red padding is used for falling? no problem! We can add a where parameter as follows:

ax1.fill_between(date, closep, closep[0],where=(closep > closep[0]), facecolor='g', alpha=0.5)

Here, we fill in the area between the current price and the original price, where the current price is higher than the original price. We give it a green foreground because it's a rise, and we use tiny transparency.

We still can't label polygon data (such as filling), but we can implement empty lines as before, so we can:

ax1.plot([],[],linewidth=5, label='loss', color='r',alpha=0.5)
ax1.plot([],[],linewidth=5, label='gain', color='g',alpha=0.5)

ax1.fill_between(date, closep, closep[0],where=(closep > closep[0]), facecolor='g', alpha=0.5)
ax1.fill_between(date, closep, closep[0],where=(closep < closep[0]), facecolor='r', alpha=0.5)

This gives us some padding, as well as empty lines for handling labels, which we intend to display in the legend. The complete code here is:

import matplotlib.pyplot as plt
import numpy as np
import urllib
import datetime as dt
import matplotlib.dates as mdates

def bytespdate2num(fmt, encoding='utf-8'):
    strconverter = mdates.strpdate2num(fmt)
    def bytesconverter(b):
        s = b.decode(encoding)
        return strconverter(s)
    return bytesconverter
    

def graph_data(stock):

    fig = plt.figure()
    ax1 = plt.subplot2grid((1,1), (0,0))
    
    stock_price_url = 'http://chartapi.finance.yahoo.com/instrument/1.0/'+stock+'/chartdata;type=quote;range=10y/csv'
    source_code = urllib.request.urlopen(stock_price_url).read().decode()
    stock_data = []
    split_source = source_code.split('\n')
    for line in split_source:
        split_line = line.split(',')
        if len(split_line) == 6:
            if 'values' not in line and 'labels' not in line:
                stock_data.append(line)

    date, closep, highp, lowp, openp, volume = np.loadtxt(stock_data,
                                                          delimiter=',',
                                                          unpack=True,
                                                          converters={0: bytespdate2num('%Y%m%d')})

    ax1.plot_date(date, closep,'-', label='Price')

    ax1.plot([],[],linewidth=5, label='loss', color='r',alpha=0.5)
    ax1.plot([],[],linewidth=5, label='gain', color='g',alpha=0.5)

    ax1.fill_between(date, closep, closep[0],where=(closep > closep[0]), facecolor='g', alpha=0.5)
    ax1.fill_between(date, closep, closep[0],where=(closep < closep[0]), facecolor='r', alpha=0.5)
    
    for label in ax1.xaxis.get_ticklabels():
        label.set_rotation(45)
    ax1.grid(True)#, color='g', linestyle='-', linewidth=5)
    ax1.xaxis.label.set_color('c')
    ax1.yaxis.label.set_color('r')
    ax1.set_yticks([0,25,50,75])

    plt.xlabel('Date')
    plt.ylabel('Price')
    plt.title(stock)
    plt.legend()
    plt.subplots_adjust(left=0.09, bottom=0.20, right=0.94, top=0.90, wspace=0.2, hspace=0)
    plt.show()


graph_data('EBAY')

Now our result is:

 

Chapter XIII border and horizontal line

Welcome to another customization tutorial, where we use Matplotlib to discuss borders and horizontal lines. Sometimes what you might want to do is change the color of the borders, or even delete them altogether.

The border of a graph is basically the boundary of the graph, in which there are scale lines and other things. To change the color of the border, you can do something like this:

ax1.spines['left'].set_color('c')

Here, we refer to our border dictionary to indicate that we need to adjust the left border, and then we use set_ The color method sets the color to 'c', which is cyan.

What if we want to delete all borders? We can do this:

ax1.spines['right'].set_visible(False)
ax1.spines['top'].set_visible(False)

This is a very similar code, removing the right and top borders.

It's hard to see that we changed the color of the left border, so let's make it obvious by changing the lineweight:

ax1.spines['left'].set_linewidth(5)

Now, the left border has become a very thick and conspicuous cyan. Finally, what if we want to modify the scale parameters? If we don't want black dates, we want some orange dates? no problem!

ax1.tick_params(axis='x', colors='#f06215')

Now our date is orange! Next, let's see how we draw a horizontal line. Of course you can draw a new set of data you create into a horizontal line, but you don't need to. You can:

ax1.axhline(closep[0], color='k', linewidth=5)

So here, our whole code is:

import matplotlib.pyplot as plt
import numpy as np
import urllib
import datetime as dt
import matplotlib.dates as mdates

def bytespdate2num(fmt, encoding='utf-8'):
    strconverter = mdates.strpdate2num(fmt)
    def bytesconverter(b):
        s = b.decode(encoding)
        return strconverter(s)
    return bytesconverter
    

def graph_data(stock):

    fig = plt.figure()
    ax1 = plt.subplot2grid((1,1), (0,0))
    
    stock_price_url = 'http://chartapi.finance.yahoo.com/instrument/1.0/'+stock+'/chartdata;type=quote;range=10y/csv'
    source_code = urllib.request.urlopen(stock_price_url).read().decode()
    stock_data = []
    split_source = source_code.split('\n')
    for line in split_source:
        split_line = line.split(',')
        if len(split_line) == 6:
            if 'values' not in line and 'labels' not in line:
                stock_data.append(line)

    
    date, closep, highp, lowp, openp, volume = np.loadtxt(stock_data,
                                                          delimiter=',',
                                                          unpack=True,
                                                          converters={0: bytespdate2num('%Y%m%d')})

    ax1.plot_date(date, closep,'-', label='Price')
    ax1.plot([],[],linewidth=5, label='loss', color='r',alpha=0.5)
    ax1.plot([],[],linewidth=5, label='gain', color='g',alpha=0.5)
    ax1.axhline(closep[0], color='k', linewidth=5)
    ax1.fill_between(date, closep, closep[0],where=(closep > closep[0]), facecolor='g', alpha=0.5)
    ax1.fill_between(date, closep, closep[0],where=(closep < closep[0]), facecolor='r', alpha=0.5)
    
    for label in ax1.xaxis.get_ticklabels():
        label.set_rotation(45)
    ax1.grid(True)
    #ax1.xaxis.label.set_color('c')
    #ax1.yaxis.label.set_color('r')
    ax1.set_yticks([0,25,50,75])

    ax1.spines['left'].set_color('c')
    ax1.spines['right'].set_visible(False)
    ax1.spines['top'].set_visible(False)
    ax1.spines['left'].set_linewidth(5)

    ax1.tick_params(axis='x', colors='#f06215')

    
    

    plt.xlabel('Date')
    plt.ylabel('Price')
    plt.title(stock)
    plt.legend()
    plt.subplots_adjust(left=0.09, bottom=0.20, right=0.94, top=0.90, wspace=0.2, hspace=0)
    plt.show()


graph_data('ebay')

The result is:

 

Chapter XIV OHLC K-line diagram

In the Matplotlib tutorial, we will introduce how to create a K-line diagram of on, high, low and off (OHLC) in Matplotlib. These charts are used to display time series stock price information in a simplified form. To implement it, we first need to import some modules:

import matplotlib.ticker as mticker
from matplotlib.finance import candlestick_ohlc

We introduced ticker, which allows us to modify the ticker information at the bottom of the chart. Then we start from Matplotlib Introducing Candlestick into finance module_ OHLC function.

Now, we need to organize our data to work with matplotlib. If you just join us, we get the following data:

stock_price_url = 'http://chartapi.finance.yahoo.com/instrument/1.0/'+stock+'/chartdata;type=quote;range=1m/csv'
source_code = urllib.request.urlopen(stock_price_url).read().decode()
stock_data = []
split_source = source_code.split('\n')
for line in split_source:
    split_line = line.split(',')
    if len(split_line) == 6:
        if 'values' not in line and 'labels' not in line:
            stock_data.append(line)


date, closep, highp, lowp, openp, volume = np.loadtxt(stock_data,
                                                      delimiter=',',
                                                      unpack=True,
                                                      converters={0: bytespdate2num('%Y%m%d')})

Now we need to build a Python list where each element is data. We can modify our loadtext function so that it does not deconstruct, but then we still want to refer to specific data points. We can solve this problem, but we may end up with only two separate data sets. To do this, we do the following:

x = 0
y = len(date)
ohlc = []

while x < y:
    append_me = date[x], openp[x], highp[x], lowp[x], closep[x], volume[x]
    ohlc.append(append_me)
    x+=1

With this, we now store the ohlc data list into our variable ohlc. Now we can draw it like this:

candlestick_ohlc(ax1, ohlc)

The chart should look like this:

 

Unfortunately, the datetime data on the x-axis is not in the form of a date stamp. We can deal with it:

ax1.xaxis.set_major_formatter(mdates.DateFormatter('%Y-%m-%d'))

In addition, red / black coloring is not the best choice in my opinion. We should use green for rising and red for falling. To this end, we can:

candlestick_ohlc(ax1, ohlc, width=0.4, colorup='#77d879', colordown='#db3f3f')

Finally, we can set the x tag to the number we want, like this:

ax1.xaxis.set_major_locator(mticker.MaxNLocator(10))

Now, the complete code is as follows:

import matplotlib.pyplot as plt
import matplotlib.dates as mdates
import matplotlib.ticker as mticker
from matplotlib.finance import candlestick_ohlc

import numpy as np
import urllib
import datetime as dt


def bytespdate2num(fmt, encoding='utf-8'):
    strconverter = mdates.strpdate2num(fmt)
    def bytesconverter(b):
        s = b.decode(encoding)
        return strconverter(s)
    return bytesconverter
    

def graph_data(stock):

    fig = plt.figure()
    ax1 = plt.subplot2grid((1,1), (0,0))
    
    stock_price_url = 'http://chartapi.finance.yahoo.com/instrument/1.0/'+stock+'/chartdata;type=quote;range=1m/csv'
    source_code = urllib.request.urlopen(stock_price_url).read().decode()
    stock_data = []
    split_source = source_code.split('\n')
    for line in split_source:
        split_line = line.split(',')
        if len(split_line) == 6:
            if 'values' not in line and 'labels' not in line:
                stock_data.append(line)

    
    date, closep, highp, lowp, openp, volume = np.loadtxt(stock_data,
                                                          delimiter=',',
                                                          unpack=True,
                                                          converters={0: bytespdate2num('%Y%m%d')})

    x = 0
    y = len(date)
    ohlc = []

    while x < y:
        append_me = date[x], openp[x], highp[x], lowp[x], closep[x], volume[x]
        ohlc.append(append_me)
        x+=1


    candlestick_ohlc(ax1, ohlc, width=0.4, colorup='#77d879', colordown='#db3f3f')

    for label in ax1.xaxis.get_ticklabels():
        label.set_rotation(45)

    ax1.xaxis.set_major_formatter(mdates.DateFormatter('%Y-%m-%d'))
    ax1.xaxis.set_major_locator(mticker.MaxNLocator(10))
    ax1.grid(True)
    

    plt.xlabel('Date')
    plt.ylabel('Price')
    plt.title(stock)
    plt.legend()
    plt.subplots_adjust(left=0.09, bottom=0.20, right=0.94, top=0.90, wspace=0.2, hspace=0)
    plt.show()


graph_data('EBAY')

The result is:

 

Also note that we removed most ax1 changes from the previous tutorial.

Chapter 15 style

In this Matplotlib tutorial, we will discuss styles. The style we use for Matplotlib is very similar to CSS (cascading style sheets) for HTML pages. As you can see here, all our changes to the graph will be superimposed, and we currently have only one axis field. We can use for loops to at least reduce the amount of code, but we can also use these styles in Matplotlib.

The idea of the style page is to write a custom style to a file, and then, in order to use these changes and apply them to the drawing, all you need to do is import the style and then use the specific style. In this way, let's assume that you find yourself always changing the various elements of the graph. You don't have to write 25 ~ 200 lines of custom code for each chart, just write it into a style, load the style, and apply all these changes in two lines! Let's start.

from matplotlib import style

Next, we specify the style to use. Matplotlib already has several styles.

We can use styles like this:

style.use('ggplot')
 

In addition to the title, the color of the label is gray, and the background of the axis field is light gray. We can immediately distinguish that the font is different. We also notice that the grid is actually a solid white line. Our K-line chart remains unchanged, mainly because we customize it afterwards. When you load a style, the changes take effect, but if you write new custom code after you load the style, your changes also take effect.

Because we try to show the style module, but let's continue, draw a few lines and comment out the K-line diagram for the time being:

#candlestick_ohlc(ax1, ohlc, width=0.4, colorup='#77d879', colordown='#db3f3f')
ax1.plot(date,closep)
ax1.plot(date,openp)

Will generate:

 

It's much better than the default value!

Another example of a style is fivethirtyeight:

 

You can view all available styles in this way:

print(plt.style.available)

I here it provides ['bmh ',' dark_background ',' ggplot ',' fivethirtyeight ',' grayscale '].

Let's try dark_background:

style.use('dark_background')
 

Now, what if you want to make your own style? First, you need to find the style directory. To implement it, if you know where it is, you can go to your matplotlib directory, or you can find it. If you don't know how to find the directory, you can do the following:

print(plt.__file__)

This will at least tell you the location of the pyplot module.

In the matplotlib directory, you need to look for MPL data. You need to find style there, then lib. My path is C: \ package \ lib \ Python style on Windows.

It should show all the available mplstyle file. You can edit, copy or rename them, and then modify them there to what you want. Then, whatever you name it mplstyle files should be placed in style In use.

Chapter 16 real time chart

In this Matplotlib tutorial, we will introduce how to create a real-time update chart, which can be updated when the data source is updated. You may want to use this to plot real-time stock pricing data, or you can connect the sensor to the computer and display the sensor real-time data. To do this, we use the animation function of Matplotlib.

First:

import matplotlib.pyplot as plt
import matplotlib.animation as animation
from matplotlib import style

Here, the only new import is Matplotlib animation as animation. This is a module that allows us to animate graphics after display.

Next, we'll add some code you're familiar with. If you've been following this series:

style.use('fivethirtyeight')

fig = plt.figure()
ax1 = fig.add_subplot(1,1,1)

Now let's write the animation function:

def animate(i):
    graph_data = open('example.txt','r').read()
    lines = graph_data.split('\n')
    xs = []
    ys = []
    for line in lines:
        if len(line) > 1:
            x, y = line.split(',')
            xs.append(x)
            ys.append(y)
    ax1.clear()
    ax1.plot(xs, ys)

What we do here is build the data and then draw it. Note that we do not call PLT show(). We read data from a sample file, which reads as follows:

1,5
2,3
3,4
4,7
5,4
6,3
7,5
8,7
9,4
10,4

We open the above file, then store each line, divide it into xs and ys with commas, and we will draw it. then:

ani = animation.FuncAnimation(fig, animate, interval=1000)
plt.show()

We run the animation, put the animation into the chart (fig), and run the animation function of animate. Finally, we set an interval of 1000 milliseconds or 1 second.

The results of running this chart should generate the chart as usual. Then, you should be able to update example with the new coordinates Txt file. Doing so will generate an automatically updated chart as follows:

 

Chapter 17 notes and texts

In this tutorial, we will discuss how to add text to Matplotlib graphics. We can do this in two ways. One is to place the text somewhere on the chart. The other is to specially annotate the drawings on the chart to attract attention.

The starting code here is tutorial 15, which is here:

import matplotlib.pyplot as plt
import matplotlib.dates as mdates
import matplotlib.ticker as mticker
from matplotlib.finance import candlestick_ohlc
from matplotlib import style

import numpy as np
import urllib
import datetime as dt

style.use('fivethirtyeight')
print(plt.style.available)

print(plt.__file__)


def bytespdate2num(fmt, encoding='utf-8'):
    strconverter = mdates.strpdate2num(fmt)
    def bytesconverter(b):
        s = b.decode(encoding)
        return strconverter(s)
    return bytesconverter
    

def graph_data(stock):

    fig = plt.figure()
    ax1 = plt.subplot2grid((1,1), (0,0))
    
    stock_price_url = 'http://chartapi.finance.yahoo.com/instrument/1.0/'+stock+'/chartdata;type=quote;range=1m/csv'
    source_code = urllib.request.urlopen(stock_price_url).read().decode()
    stock_data = []
    split_source = source_code.split('\n')
    for line in split_source:
        split_line = line.split(',')
        if len(split_line) == 6:
            if 'values' not in line and 'labels' not in line:
                stock_data.append(line)

    
    date, closep, highp, lowp, openp, volume = np.loadtxt(stock_data,
                                                          delimiter=',',
                                                          unpack=True,
                                                          converters={0: bytespdate2num('%Y%m%d')})

    x = 0
    y = len(date)
    ohlc = []

    while x < y:
        append_me = date[x], openp[x], highp[x], lowp[x], closep[x], volume[x]
        ohlc.append(append_me)
        x+=1


    candlestick_ohlc(ax1, ohlc, width=0.4, colorup='#77d879', colordown='#db3f3f')

    for label in ax1.xaxis.get_ticklabels():
        label.set_rotation(45)

    ax1.xaxis.set_major_formatter(mdates.DateFormatter('%Y-%m-%d'))
    ax1.xaxis.set_major_locator(mticker.MaxNLocator(10))
    ax1.grid(True)
    

    plt.xlabel('Date')
    plt.ylabel('Price')
    plt.title(stock)
    plt.subplots_adjust(left=0.09, bottom=0.20, right=0.94, top=0.90, wspace=0.2, hspace=0)
    plt.show()


graph_data('ebay')

So here is the OHLC K-line diagram of eBay of Yahoo Finance API. The first thing we want to explain here is to add text to the graph.

font_dict = {'family':'serif',
             'color':'darkred',
             'size':15}
ax1.text(date[10], closep[1],'Text Example', fontdict=font_dict)

Here, we need to do something. First, we use ax1 Textadd text. We use our data to give the location of this text in coordinates. First give the coordinates of the text, and then give the actual text to be placed. Next, we use the fontdict parameter to add a data dictionary to use the font used. In our font dictionary, we change the font to serif, the color to "crimson", and then change the font size to 15. This will all apply to the text on our chart as follows:

 

Great. What we can do next is annotate a specific drawing. We hope to do so to give more information. In the case of eBay, maybe we want to explain a specific drawing or give some information about what happened. In the case of stock price, there may be some news that will affect the price. You can annotate where the news comes from, which will help explain pricing changes.

ax1.annotate('Bad News!',(date[9],highp[9]),
             xytext=(0.8, 0.9), textcoords='axes fraction',
             arrowprops = dict(facecolor='grey',color='grey'))

Here, we use ax1 Annotate. We first pass the text we want to annotate, and then pass the coordinates we want the annotation to point to. We do this because when we annotate, we can draw lines and arrows pointing to specific points. Next, we specify the location of xytext. It can be like the coordinate position we use for text placement, but let's show another example. It can be an axis field decimal, so we use 0.8 and 0.9. This means that the position of the text is 80% of the x-axis and 90% of the y-axis. In this way, if we move the chart, the text will remain in the same position.

Executing it generates:

 

According to the time you study this tutorial, the points you point to may be different. This is just an example of annotation. There are some reasonable ideas, that is, why we need to annotate something.

When the chart starts, try clicking the pan button (Blue Cross) and then moving the chart. You will see that the text remains stationary, but the arrow follows and continues to point to the specific point we want. That's cool!

The complete code of the last chart:

import matplotlib.pyplot as plt
import matplotlib.dates as mdates
import matplotlib.ticker as mticker
from matplotlib.finance import candlestick_ohlc
from matplotlib import style

import numpy as np
import urllib
import datetime as dt

style.use('fivethirtyeight')
print(plt.style.available)

print(plt.__file__)


def bytespdate2num(fmt, encoding='utf-8'):
    strconverter = mdates.strpdate2num(fmt)
    def bytesconverter(b):
        s = b.decode(encoding)
        return strconverter(s)
    return bytesconverter
    

def graph_data(stock):

    fig = plt.figure()
    ax1 = plt.subplot2grid((1,1), (0,0))
    
    stock_price_url = 'http://chartapi.finance.yahoo.com/instrument/1.0/'+stock+'/chartdata;type=quote;range=1m/csv'
    source_code = urllib.request.urlopen(stock_price_url).read().decode()
    stock_data = []
    split_source = source_code.split('\n')
    for line in split_source:
        split_line = line.split(',')
        if len(split_line) == 6:
            if 'values' not in line and 'labels' not in line:
                stock_data.append(line)

    
    date, closep, highp, lowp, openp, volume = np.loadtxt(stock_data,
                                                          delimiter=',',
                                                          unpack=True,
                                                          converters={0: bytespdate2num('%Y%m%d')})

    x = 0
    y = len(date)
    ohlc = []

    while x < y:
        append_me = date[x], openp[x], highp[x], lowp[x], closep[x], volume[x]
        ohlc.append(append_me)
        x+=1


    candlestick_ohlc(ax1, ohlc, width=0.4, colorup='#77d879', colordown='#db3f3f')
  
    for label in ax1.xaxis.get_ticklabels():
        label.set_rotation(45)

    ax1.xaxis.set_major_formatter(mdates.DateFormatter('%Y-%m-%d'))
    ax1.xaxis.set_major_locator(mticker.MaxNLocator(10))
    ax1.grid(True)
    ax1.annotate('Bad News!',(date[9],highp[9]),
                 xytext=(0.8, 0.9), textcoords='axes fraction',
                 arrowprops = dict(facecolor='grey',color='grey'))
    
##    # Text placement example:
##    font_dict = {'family':'serif',
##                 'color':'darkred',
##                 'size':15}
##    ax1.text(date[10], closep[1],'Text Example', fontdict=font_dict)

    plt.xlabel('Date')
    plt.ylabel('Price')
    plt.title(stock)
    #plt.legend()
    plt.subplots_adjust(left=0.09, bottom=0.20, right=0.94, top=0.90, wspace=0.2, hspace=0)
    plt.show()


graph_data('ebay')

Now, using annotations, we can do some other things, such as annotating the final price of the stock chart. That's what we're going to do next.

Chapter 18 notes the final price of the stock chart

In this Matplotlib tutorial, we will show an example of how to track the last price of a stock by annotating it to the right of the axis field, as many charting applications do.

Although people like to see historical prices in their Real-time charts, they also want to see the latest prices. What most applications do is annotate the last price at the y-axis height of the price, then highlight it, and move it slightly in the box as the price changes. Using our recent annotation tutorial, we can add a bbox.

Our core code is:

bbox_props = dict(boxstyle='round',fc='w', ec='k',lw=1)

ax1.annotate(str(closep[-1]), (date[-1], closep[-1]),
             xytext = (date[-1]+4, closep[-1]), bbox=bbox_props)

We use ax1 Annotate to place the string value of the last price. We don't use it here, but we specify the point to be annotated as the last point on the graph. Next, we use xytext to place our text in a specific location. We specify its y coordinate as the Y coordinate of the last point, and the x coordinate as the x coordinate of the last point, plus several points. We do this to move it out of the chart. It's enough to put the text outside the graph, but now it's just floating text.

We use the bbox parameter to create a box around the text. We use bbox_props creates an attribute dictionary that contains a box style, followed by a white (w) foreground color, a black (k) border color, and a lineweight of 1. For more box styles, see matplotlib annotation document.

Finally, the annotation moves to the right, requiring us to use subplots_adjust to create some new spaces:

plt.subplots_adjust(left=0.11, bottom=0.24, right=0.87, top=0.90, wspace=0.2, hspace=0)

The complete code here is as follows:

import matplotlib.pyplot as plt
import matplotlib.dates as mdates
import matplotlib.ticker as mticker
from matplotlib.finance import candlestick_ohlc
from matplotlib import style

import numpy as np
import urllib
import datetime as dt

style.use('fivethirtyeight')
print(plt.style.available)

print(plt.__file__)


def bytespdate2num(fmt, encoding='utf-8'):
    strconverter = mdates.strpdate2num(fmt)
    def bytesconverter(b):
        s = b.decode(encoding)
        return strconverter(s)
    return bytesconverter


def graph_data(stock):

    fig = plt.figure()
    ax1 = plt.subplot2grid((1,1), (0,0))

    stock_price_url = 'http://chartapi.finance.yahoo.com/instrument/1.0/'+stock+'/chartdata;type=quote;range=1m/csv'
    source_code = urllib.request.urlopen(stock_price_url).read().decode()
    stock_data = []
    split_source = source_code.split('\n')
    for line in split_source:
        split_line = line.split(',')
        if len(split_line) == 6:
            if 'values' not in line and 'labels' not in line:
                stock_data.append(line)


    date, closep, highp, lowp, openp, volume = np.loadtxt(stock_data,
                                                          delimiter=',',
                                                          unpack=True,
                                                          converters={0: bytespdate2num('%Y%m%d')})

    x = 0
    y = len(date)
    ohlc = []

    while x < y:
        append_me = date[x], openp[x], highp[x], lowp[x], closep[x], volume[x]
        ohlc.append(append_me)
        x+=1


    candlestick_ohlc(ax1, ohlc, width=0.4, colorup='#77d879', colordown='#db3f3f')

    for label in ax1.xaxis.get_ticklabels():
        label.set_rotation(45)

    ax1.xaxis.set_major_formatter(mdates.DateFormatter('%Y-%m-%d'))
    ax1.xaxis.set_major_locator(mticker.MaxNLocator(10))
    ax1.grid(True)

    bbox_props = dict(boxstyle='round',fc='w', ec='k',lw=1)

    ax1.annotate(str(closep[-1]), (date[-1], closep[-1]),
                 xytext = (date[-1]+3, closep[-1]), bbox=bbox_props)


##    # Annotation example with arrow
##    ax1.annotate('Bad News!',(date[11],highp[11]),
##                 xytext=(0.8, 0.9), textcoords='axes fraction',
##                 arrowprops = dict(facecolor='grey',color='grey'))
##
##    
##    # Font dict example
##    font_dict = {'family':'serif',
##                 'color':'darkred',
##                 'size':15}
##    # Hard coded text
##    ax1.text(date[10], closep[1],'Text Example', fontdict=font_dict)

    plt.xlabel('Date')
    plt.ylabel('Price')
    plt.title(stock)
    #plt.legend()
    plt.subplots_adjust(left=0.11, bottom=0.24, right=0.87, top=0.90, wspace=0.2, hspace=0)
    plt.show()


graph_data('EBAY')

The result is:

 

Chapter 19 sub chart

In this Matplotlib tutorial, we will discuss subgraphs. There are two main ways to work with subgraphs, which are used to create multiple charts on the same chart. Now, we'll start with a clean code. If you've been following this tutorial, make sure to keep the old code, or you can review the code of the previous tutorial at any time.

First, let's use styles to create our chart, and then create a function to randomly create sample plots:

import random
import matplotlib.pyplot as plt
from matplotlib import style

style.use('fivethirtyeight')

fig = plt.figure()

def create_plots():
    xs = []
    ys = []

    for i in range(10):
        x = i
        y = random.randrange(10)

        xs.append(x)
        ys.append(y)
    return xs, ys

Now let's start using add_ The subplot method creates a subplot:

ax1 = fig.add_subplot(221)
ax2 = fig.add_subplot(222)
ax3 = fig.add_subplot(212)

It works by using three numbers: numRows, numCols, and plotNum.

Therefore, 221 represents the first position of two rows and two columns. 222 is the second position of two rows and two columns. Finally, 212 is the second position in two rows and one column.

2x2: 

+-----+-----+
|  1  |  2  |
+-----+-----+
|  3  |  4  |
+-----+-----+

2x1: 

+-----------+
|     1     |
+-----------+
|     2     |
+-----------+

Translator's note: the original text is wrong here, and the translation has been changed.

Note: 221 is an abbreviation. It is only valid when the number of rows multiplied by the number of columns is less than 10. Otherwise, it should be written as 2,2,1.

The result of this code is:

 

This is add_subplot. Try some configurations that you think might be interesting, and then try add_subplot create them until you are satisfied.

Next, let's introduce another method, which is subplot2grid.

Delete or comment out other domain definitions, and then add:

ax1 = plt.subplot2grid((6,1), (0,0), rowspan=1, colspan=1)
ax2 = plt.subplot2grid((6,1), (1,0), rowspan=4, colspan=1)
ax3 = plt.subplot2grid((6,1), (5,0), rowspan=1, colspan=1)

So, add_subplot can't let us make one plot cover multiple locations. But this new subplot2grid can. Therefore, subplot2grid works by first passing a tuple, which is a grid shape. We passed (6,1), which means that the whole chart is divided into six rows and one column. The next tuple is the starting point in the upper left corner. For ax1, this is 0,0, so it starts at the top. Next, we can optionally specify rowspan and colspan. This is the number of rows and columns occupied by the axis field.

6x1: 

          colspan=1
(0,0)   +-----------+
        |    ax1    | rowspan=1
(1,0)   +-----------+
        |           |
        |    ax2    | rowspan=4
        |           |
        |           |
(5,0)   +-----------+
        |    ax3    | rowspan=1
        +-----------+

The result is:

 

Obviously, we have some overlapping problems here, and we can adjust the subgraph to deal with it.

Again, try to conceive subgraphs of various configurations and make them with subplot2grid until you are satisfied!

We will continue to use subplot2grid and apply it to the code we have gradually established, which we will continue in the next tutorial.

Chapter 20 applies subgraphs to our charts

In this Matplotlib tutorial, we will process the code of our previous tutorial and implement the subgraph configuration in the previous tutorial. Our starting code is as follows:

import matplotlib.pyplot as plt
import matplotlib.dates as mdates
import matplotlib.ticker as mticker
from matplotlib.finance import candlestick_ohlc
from matplotlib import style

import numpy as np
import urllib
import datetime as dt

style.use('fivethirtyeight')
print(plt.style.available)

print(plt.__file__)


def bytespdate2num(fmt, encoding='utf-8'):
    strconverter = mdates.strpdate2num(fmt)
    def bytesconverter(b):
        s = b.decode(encoding)
        return strconverter(s)
    return bytesconverter


def graph_data(stock):

    fig = plt.figure()
    ax1 = plt.subplot2grid((1,1), (0,0))

    stock_price_url = 'http://chartapi.finance.yahoo.com/instrument/1.0/'+stock+'/chartdata;type=quote;range=1m/csv'
    source_code = urllib.request.urlopen(stock_price_url).read().decode()
    stock_data = []
    split_source = source_code.split('\n')
    for line in split_source:
        split_line = line.split(',')
        if len(split_line) == 6:
            if 'values' not in line and 'labels' not in line:
                stock_data.append(line)


    date, closep, highp, lowp, openp, volume = np.loadtxt(stock_data,
                                                          delimiter=',',
                                                          unpack=True,
                                                          converters={0: bytespdate2num('%Y%m%d')})

    x = 0
    y = len(date)
    ohlc = []

    while x < y:
        append_me = date[x], openp[x], highp[x], lowp[x], closep[x], volume[x]
        ohlc.append(append_me)
        x+=1


    candlestick_ohlc(ax1, ohlc, width=0.4, colorup='#77d879', colordown='#db3f3f')

    for label in ax1.xaxis.get_ticklabels():
        label.set_rotation(45)

    ax1.xaxis.set_major_formatter(mdates.DateFormatter('%Y-%m-%d'))
    ax1.xaxis.set_major_locator(mticker.MaxNLocator(10))
    ax1.grid(True)

    bbox_props = dict(boxstyle='round',fc='w', ec='k',lw=1)

    ax1.annotate(str(closep[-1]), (date[-1], closep[-1]),
                 xytext = (date[-1]+4, closep[-1]), bbox=bbox_props)


##    # Annotation example with arrow
##    ax1.annotate('Bad News!',(date[11],highp[11]),
##                 xytext=(0.8, 0.9), textcoords='axes fraction',
##                 arrowprops = dict(facecolor='grey',color='grey'))
##
##    
##    # Font dict example
##    font_dict = {'family':'serif',
##                 'color':'darkred',
##                 'size':15}
##    # Hard coded text
##    ax1.text(date[10], closep[1],'Text Example', fontdict=font_dict)

    plt.xlabel('Date')
    plt.ylabel('Price')
    plt.title(stock)
    #plt.legend()
    plt.subplots_adjust(left=0.11, bottom=0.24, right=0.90, top=0.90, wspace=0.2, hspace=0)
    plt.show()


graph_data('EBAY')

One major change is to modify the definition of the axis domain:

ax1 = plt.subplot2grid((6,1), (0,0), rowspan=1, colspan=1)
plt.title(stock)
ax2 = plt.subplot2grid((6,1), (1,0), rowspan=4, colspan=1)
plt.xlabel('Date')
plt.ylabel('Price')
ax3 = plt.subplot2grid((6,1), (5,0), rowspan=1, colspan=1)

Now, ax2 is the stock price data we are actually plotting. The top and bottom charts will be used as indicator information.

In our code for drawing data, we need to change ax1 to ax2:

candlestick_ohlc(ax2, ohlc, width=0.4, colorup='#77d879', colordown='#db3f3f')

for label in ax2.xaxis.get_ticklabels():
    label.set_rotation(45)

ax2.xaxis.set_major_formatter(mdates.DateFormatter('%Y-%m-%d'))
ax2.xaxis.set_major_locator(mticker.MaxNLocator(10))
ax2.grid(True)

bbox_props = dict(boxstyle='round',fc='w', ec='k',lw=1)

ax2.annotate(str(closep[-1]), (date[-1], closep[-1]),
             xytext = (date[-1]+4, closep[-1]), bbox=bbox_props)

After the change, the code is:

import matplotlib.pyplot as plt
import matplotlib.dates as mdates
import matplotlib.ticker as mticker
from matplotlib.finance import candlestick_ohlc
from matplotlib import style

import numpy as np
import urllib
import datetime as dt

style.use('fivethirtyeight')
print(plt.style.available)

print(plt.__file__)


def bytespdate2num(fmt, encoding='utf-8'):
    strconverter = mdates.strpdate2num(fmt)
    def bytesconverter(b):
        s = b.decode(encoding)
        return strconverter(s)
    return bytesconverter


def graph_data(stock):

    fig = plt.figure()
    ax1 = plt.subplot2grid((6,1), (0,0), rowspan=1, colspan=1)
    plt.title(stock)
    ax2 = plt.subplot2grid((6,1), (1,0), rowspan=4, colspan=1)
    plt.xlabel('Date')
    plt.ylabel('Price')
    ax3 = plt.subplot2grid((6,1), (5,0), rowspan=1, colspan=1)


    stock_price_url = 'http://chartapi.finance.yahoo.com/instrument/1.0/'+stock+'/chartdata;type=quote;range=1m/csv'
    source_code = urllib.request.urlopen(stock_price_url).read().decode()
    stock_data = []
    split_source = source_code.split('\n')
    for line in split_source:
        split_line = line.split(',')
        if len(split_line) == 6:
            if 'values' not in line and 'labels' not in line:
                stock_data.append(line)


    date, closep, highp, lowp, openp, volume = np.loadtxt(stock_data,
                                                          delimiter=',',
                                                          unpack=True,
                                                          converters={0: bytespdate2num('%Y%m%d')})

    x = 0
    y = len(date)
    ohlc = []

    while x < y:
        append_me = date[x], openp[x], highp[x], lowp[x], closep[x], volume[x]
        ohlc.append(append_me)
        x+=1


    candlestick_ohlc(ax2, ohlc, width=0.4, colorup='#77d879', colordown='#db3f3f')

    for label in ax2.xaxis.get_ticklabels():
        label.set_rotation(45)

    ax2.xaxis.set_major_formatter(mdates.DateFormatter('%Y-%m-%d'))
    ax2.xaxis.set_major_locator(mticker.MaxNLocator(10))
    ax2.grid(True)

    bbox_props = dict(boxstyle='round',fc='w', ec='k',lw=1)

    ax2.annotate(str(closep[-1]), (date[-1], closep[-1]),
                 xytext = (date[-1]+4, closep[-1]), bbox=bbox_props)


##    # Annotation example with arrow
##    ax1.annotate('Bad News!',(date[11],highp[11]),
##                 xytext=(0.8, 0.9), textcoords='axes fraction',
##                 arrowprops = dict(facecolor='grey',color='grey'))
##
##    
##    # Font dict example
##    font_dict = {'family':'serif',
##                 'color':'darkred',
##                 'size':15}
##    # Hard coded text
##    ax1.text(date[10], closep[1],'Text Example', fontdict=font_dict)


    #
    #plt.legend()
    plt.subplots_adjust(left=0.11, bottom=0.24, right=0.90, top=0.90, wspace=0.2, hspace=0)
    plt.show()


graph_data('EBAY')

The result is:

 

Chapter 21 more index data

In this Matplotlib tutorial, we introduced adding some simple functions to calculate the data so that we can fill our axis field. One is simple moving average, the other is simple price HML calculation.

These new functions are:

def moving_average(values, window):
    weights = np.repeat(1.0, window)/window
    smas = np.convolve(values, weights, 'valid')
    return smas

def high_minus_low(highs, lows):
    return highs-lows

You don't need to focus too much on understanding the working principle of moving average. We just calculate it from the sample data so that you can learn more about custom Matplotlib.

We also want to define some values for the moving average at the top of the script:

MA1 = 10
MA2 = 30

Next, in our graph_ In the data function:

ma1 = moving_average(closep,MA1)
ma2 = moving_average(closep,MA2)
start = len(date[MA2-1:])

h_l = list(map(high_minus_low, highp, lowp))

Here, we calculate two moving means and HML.

We also define a "starting point". Because we want our data to be in line. For example, a 20 day moving average requires 20 data points. This means that we can't really calculate the moving average of 20 days on day 5. Therefore, when we calculate the moving average, we will lose some data. To handle the subtraction of this data, we use the starting variable to calculate how much data we should have. Here, we can safely use [- start:] to plot the moving average, and if we want, carry out the above steps for all plots to arrange the data.

Next, we can draw the HML on ax1 by:

ax1.plot_date(date,h_l,'-')

Finally, we can add the moving average to ax3 in this way:

ax3.plot(date[-start:], ma1[-start:])
ax3.plot(date[-start:], ma2[-start:])

Our complete code, including increasing the time range we use:

import matplotlib.pyplot as plt
import matplotlib.dates as mdates
import matplotlib.ticker as mticker
from matplotlib.finance import candlestick_ohlc
from matplotlib import style

import numpy as np
import urllib
import datetime as dt

style.use('fivethirtyeight')
print(plt.style.available)

print(plt.__file__)

MA1 = 10
MA2 = 30

def moving_average(values, window):
    weights = np.repeat(1.0, window)/window
    smas = np.convolve(values, weights, 'valid')
    return smas

def high_minus_low(highs, lows):
    return highs-lows


def bytespdate2num(fmt, encoding='utf-8'):
    strconverter = mdates.strpdate2num(fmt)
    def bytesconverter(b):
        s = b.decode(encoding)
        return strconverter(s)
    return bytesconverter
    

def graph_data(stock):

    fig = plt.figure()
    ax1 = plt.subplot2grid((6,1), (0,0), rowspan=1, colspan=1)
    plt.title(stock)
    ax2 = plt.subplot2grid((6,1), (1,0), rowspan=4, colspan=1)
    plt.xlabel('Date')
    plt.ylabel('Price')
    ax3 = plt.subplot2grid((6,1), (5,0), rowspan=1, colspan=1)
    
    
    stock_price_url = 'http://chartapi.finance.yahoo.com/instrument/1.0/'+stock+'/chartdata;type=quote;range=1y/csv'
    source_code = urllib.request.urlopen(stock_price_url).read().decode()
    stock_data = []
    split_source = source_code.split('\n')
    for line in split_source:
        split_line = line.split(',')
        if len(split_line) == 6:
            if 'values' not in line and 'labels' not in line:
                stock_data.append(line)

    
    date, closep, highp, lowp, openp, volume = np.loadtxt(stock_data,
                                                          delimiter=',',
                                                          unpack=True,
                                                          converters={0: bytespdate2num('%Y%m%d')})

    x = 0
    y = len(date)
    ohlc = []

    while x < y:
        append_me = date[x], openp[x], highp[x], lowp[x], closep[x], volume[x]
        ohlc.append(append_me)
        x+=1

    ma1 = moving_average(closep,MA1)
    ma2 = moving_average(closep,MA2)
    start = len(date[MA2-1:])

    h_l = list(map(high_minus_low, highp, lowp))

    ax1.plot_date(date,h_l,'-')


    candlestick_ohlc(ax2, ohlc, width=0.4, colorup='#77d879', colordown='#db3f3f')
  
    for label in ax2.xaxis.get_ticklabels():
        label.set_rotation(45)

    ax2.xaxis.set_major_formatter(mdates.DateFormatter('%Y-%m-%d'))
    ax2.xaxis.set_major_locator(mticker.MaxNLocator(10))
    ax2.grid(True)
    
    bbox_props = dict(boxstyle='round',fc='w', ec='k',lw=1)
    
    ax2.annotate(str(closep[-1]), (date[-1], closep[-1]),
                 xytext = (date[-1]+4, closep[-1]), bbox=bbox_props)

    
##    # Annotation example with arrow
##    ax2.annotate('Bad News!',(date[11],highp[11]),
##                 xytext=(0.8, 0.9), textcoords='axes fraction',
##                 arrowprops = dict(facecolor='grey',color='grey'))
##
##    
##    # Font dict example
##    font_dict = {'family':'serif',
##                 'color':'darkred',
##                 'size':15}
##    # Hard coded text 
##    ax2.text(date[10], closep[1],'Text Example', fontdict=font_dict)



    ax3.plot(date[-start:], ma1[-start:])
    ax3.plot(date[-start:], ma2[-start:])


    plt.subplots_adjust(left=0.11, bottom=0.24, right=0.90, top=0.90, wspace=0.2, hspace=0)
    plt.show()


graph_data('EBAY')

The code effect is shown in the figure below:

 

Chapter 22 custom filling, trimming and clearing

Welcome to another Matplotlib tutorial! In this tutorial, we will clear the chart and then make some customization.

Our current code is:

import matplotlib.pyplot as plt
import matplotlib.dates as mdates
import matplotlib.ticker as mticker
from matplotlib.finance import candlestick_ohlc
from matplotlib import style

import numpy as np
import urllib
import datetime as dt

style.use('fivethirtyeight')
print(plt.style.available)

print(plt.__file__)

MA1 = 10
MA2 = 30

def moving_average(values, window):
    weights = np.repeat(1.0, window)/window
    smas = np.convolve(values, weights, 'valid')
    return smas

def high_minus_low(highs, lows):
    return highs-lows


def bytespdate2num(fmt, encoding='utf-8'):
    strconverter = mdates.strpdate2num(fmt)
    def bytesconverter(b):
        s = b.decode(encoding)
        return strconverter(s)
    return bytesconverter
    

def graph_data(stock):

    fig = plt.figure()
    ax1 = plt.subplot2grid((6,1), (0,0), rowspan=1, colspan=1)
    plt.title(stock)
    ax2 = plt.subplot2grid((6,1), (1,0), rowspan=4, colspan=1)
    plt.xlabel('Date')
    plt.ylabel('Price')
    ax3 = plt.subplot2grid((6,1), (5,0), rowspan=1, colspan=1)
    
    
    stock_price_url = 'http://chartapi.finance.yahoo.com/instrument/1.0/'+stock+'/chartdata;type=quote;range=1y/csv'
    source_code = urllib.request.urlopen(stock_price_url).read().decode()
    stock_data = []
    split_source = source_code.split('\n')
    for line in split_source:
        split_line = line.split(',')
        if len(split_line) == 6:
            if 'values' not in line and 'labels' not in line:
                stock_data.append(line)

    
    date, closep, highp, lowp, openp, volume = np.loadtxt(stock_data,
                                                          delimiter=',',
                                                          unpack=True,
                                                          converters={0: bytespdate2num('%Y%m%d')})

    x = 0
    y = len(date)
    ohlc = []

    while x < y:
        append_me = date[x], openp[x], highp[x], lowp[x], closep[x], volume[x]
        ohlc.append(append_me)
        x+=1

    ma1 = moving_average(closep,MA1)
    ma2 = moving_average(closep,MA2)
    start = len(date[MA2-1:])

    h_l = list(map(high_minus_low, highp, lowp))

    ax1.plot_date(date,h_l,'-')


    candlestick_ohlc(ax2, ohlc, width=0.4, colorup='#77d879', colordown='#db3f3f')
  
    for label in ax2.xaxis.get_ticklabels():
        label.set_rotation(45)

    ax2.xaxis.set_major_formatter(mdates.DateFormatter('%Y-%m-%d'))
    ax2.xaxis.set_major_locator(mticker.MaxNLocator(10))
    ax2.grid(True)
    
    bbox_props = dict(boxstyle='round',fc='w', ec='k',lw=1)
    
    ax2.annotate(str(closep[-1]), (date[-1], closep[-1]),
                 xytext = (date[-1]+4, closep[-1]), bbox=bbox_props)

    
##    # Annotation example with arrow
##    ax2.annotate('Bad News!',(date[11],highp[11]),
##                 xytext=(0.8, 0.9), textcoords='axes fraction',
##                 arrowprops = dict(facecolor='grey',color='grey'))
##
##    
##    # Font dict example
##    font_dict = {'family':'serif',
##                 'color':'darkred',
##                 'size':15}
##    # Hard coded text 
##    ax2.text(date[10], closep[1],'Text Example', fontdict=font_dict)



    ax3.plot(date[-start:], ma1[-start:])
    ax3.plot(date[-start:], ma2[-start:])


    plt.subplots_adjust(left=0.11, bottom=0.24, right=0.90, top=0.90, wspace=0.2, hspace=0)
    plt.show()


graph_data('EBAY')

Now I think it's a good idea to add a custom fill to our moving average. Moving averages are often used to illustrate price trends. The idea is that you can calculate a fast and a slow moving average. Generally speaking, moving average is used to make the price "smooth". They always "lag" behind the price, but our idea is to calculate different speeds. The larger the moving average, the slower it will be. So the idea is that if the moving average of "faster" exceeds the average of "slower", the price will rise, which is a good thing. If a faster MA passes below a slower MA, this is a downward trend and is generally considered a bad thing. My idea is to fill between fast and slow MA. The "up" trend is green, and then the down trend is red. The method is as follows:

ax3.fill_between(date[-start:], ma2[-start:], ma1[-start:],
                 where=(ma1[-start:] < ma2[-start:]),
                 facecolor='r', edgecolor='r', alpha=0.5)

ax3.fill_between(date[-start:], ma2[-start:], ma1[-start:],
                 where=(ma1[-start:] > ma2[-start:]),
                 facecolor='g', edgecolor='g', alpha=0.5)

Next, we will encounter some problems that we can solve:

ax3.xaxis.set_major_formatter(mdates.DateFormatter('%Y-%m-%d'))
ax3.xaxis.set_major_locator(mticker.MaxNLocator(10))

for label in ax3.xaxis.get_ticklabels():
    label.set_rotation(45)

plt.setp(ax1.get_xticklabels(), visible=False)
plt.setp(ax2.get_xticklabels(), visible=False)

Here, we cut and paste ax2 date format, and then we set the x scale label to false to remove them!

In the custom axis field, we can also define the following actions for each axis:

fig = plt.figure()
ax1 = plt.subplot2grid((6,1), (0,0), rowspan=1, colspan=1)
plt.title(stock)
ax2 = plt.subplot2grid((6,1), (1,0), rowspan=4, colspan=1)
plt.xlabel('Date')
plt.ylabel('Price')
ax3 = plt.subplot2grid((6,1), (5,0), rowspan=1, colspan=1)

Next, we can see that our y scale has many numbers, which often overlap each other. We also see that the axes overlap each other. We can do this:

ax1.yaxis.set_major_locator(mticker.MaxNLocator(nbins=5, prune='lower'))

So what happens here is that we modify our y-axis object by first setting nbins to 5. This means that we can display up to five tags. Then we can also "trim" the label, so here, we trim the bottom label, which will make it disappear, so there will be no text overlap now. We may still want to trim the top label of ax2, but here is our source code so far:

Current source code:

import matplotlib.pyplot as plt
import matplotlib.dates as mdates
import matplotlib.ticker as mticker
from matplotlib.finance import candlestick_ohlc
from matplotlib import style

import numpy as np
import urllib
import datetime as dt

style.use('fivethirtyeight')
print(plt.style.available)

print(plt.__file__)

MA1 = 10
MA2 = 30

def moving_average(values, window):
    weights = np.repeat(1.0, window)/window
    smas = np.convolve(values, weights, 'valid')
    return smas

def high_minus_low(highs, lows):
    return highs-lows


def bytespdate2num(fmt, encoding='utf-8'):
    strconverter = mdates.strpdate2num(fmt)
    def bytesconverter(b):
        s = b.decode(encoding)
        return strconverter(s)
    return bytesconverter
    

def graph_data(stock):

    fig = plt.figure()
    ax1 = plt.subplot2grid((6,1), (0,0), rowspan=1, colspan=1)
    plt.title(stock)
    plt.ylabel('H-L')
    ax2 = plt.subplot2grid((6,1), (1,0), rowspan=4, colspan=1)
    plt.ylabel('Price')
    ax3 = plt.subplot2grid((6,1), (5,0), rowspan=1, colspan=1)
    plt.ylabel('MAvgs')
    
    
    stock_price_url = 'http://chartapi.finance.yahoo.com/instrument/1.0/'+stock+'/chartdata;type=quote;range=1y/csv'
    source_code = urllib.request.urlopen(stock_price_url).read().decode()
    stock_data = []
    split_source = source_code.split('\n')
    for line in split_source:
        split_line = line.split(',')
        if len(split_line) == 6:
            if 'values' not in line and 'labels' not in line:
                stock_data.append(line)

    
    date, closep, highp, lowp, openp, volume = np.loadtxt(stock_data,
                                                          delimiter=',',
                                                          unpack=True,
                                                          converters={0: bytespdate2num('%Y%m%d')})

    x = 0
    y = len(date)
    ohlc = []

    while x < y:
        append_me = date[x], openp[x], highp[x], lowp[x], closep[x], volume[x]
        ohlc.append(append_me)
        x+=1

    ma1 = moving_average(closep,MA1)
    ma2 = moving_average(closep,MA2)
    start = len(date[MA2-1:])

    h_l = list(map(high_minus_low, highp, lowp))
    

    ax1.plot_date(date,h_l,'-')
    ax1.yaxis.set_major_locator(mticker.MaxNLocator(nbins=5, prune='lower'))


    candlestick_ohlc(ax2, ohlc, width=0.4, colorup='#77d879', colordown='#db3f3f')
  
    

    
    ax2.grid(True)
    
    bbox_props = dict(boxstyle='round',fc='w', ec='k',lw=1)
    
    ax2.annotate(str(closep[-1]), (date[-1], closep[-1]),
                 xytext = (date[-1]+4, closep[-1]), bbox=bbox_props)

    
##    # Annotation example with arrow
##    ax2.annotate('Bad News!',(date[11],highp[11]),
##                 xytext=(0.8, 0.9), textcoords='axes fraction',
##                 arrowprops = dict(facecolor='grey',color='grey'))
##
##    
##    # Font dict example
##    font_dict = {'family':'serif',
##                 'color':'darkred',
##                 'size':15}
##    # Hard coded text 
##    ax2.text(date[10], closep[1],'Text Example', fontdict=font_dict)



    ax3.plot(date[-start:], ma1[-start:], linewidth=1)
    ax3.plot(date[-start:], ma2[-start:], linewidth=1)
    
    ax3.fill_between(date[-start:], ma2[-start:], ma1[-start:],
                     where=(ma1[-start:] < ma2[-start:]),
                     facecolor='r', edgecolor='r', alpha=0.5)

    ax3.fill_between(date[-start:], ma2[-start:], ma1[-start:],
                     where=(ma1[-start:] > ma2[-start:]),
                     facecolor='g', edgecolor='g', alpha=0.5)
    
    ax3.xaxis.set_major_formatter(mdates.DateFormatter('%Y-%m-%d'))
    ax3.xaxis.set_major_locator(mticker.MaxNLocator(10))

    for label in ax3.xaxis.get_ticklabels():
        label.set_rotation(45)

    plt.setp(ax1.get_xticklabels(), visible=False)
    plt.setp(ax2.get_xticklabels(), visible=False)
    plt.subplots_adjust(left=0.11, bottom=0.24, right=0.90, top=0.90, wspace=0.2, hspace=0)
    plt.show()


graph_data('EBAY')
 

It looks better, but there's still something to clear.

Chapter 23 shared X-axis

In this Matplotlib data visualization tutorial, we will discuss the sharex option, which allows us to share the x-axis between charts. It may be better to think of sharex as "copy X".

Before we start, first we need to do some trimming and set the maximum number of scales on the other axis, as shown below:

ax2.yaxis.set_major_locator(mticker.MaxNLocator(nbins=7, prune='upper'))

as well as

ax3.yaxis.set_major_locator(mticker.MaxNLocator(nbins=4, prune='upper'))

Now, let's share the x-axis between all axis domains. To do this, we need to add it to the axis domain definition:

fig = plt.figure()
ax1 = plt.subplot2grid((6,1), (0,0), rowspan=1, colspan=1)
plt.title(stock)
plt.ylabel('H-L')
ax2 = plt.subplot2grid((6,1), (1,0), rowspan=4, colspan=1, sharex=ax1)
plt.ylabel('Price')
ax3 = plt.subplot2grid((6,1), (5,0), rowspan=1, colspan=1, sharex=ax1)
plt.ylabel('MAvgs')

Above, for ax2 and ax3, we add a new parameter called sharex, and then we say that we want to share the x axis with ax1.

In this way, we can load the chart, and then we can zoom in to a specific point. The result will be as follows:

 

So this means that all axis domains move together along their x axis. That's cool!

Next, let's apply [- start:] to all data, so all axis fields start in the same place. Our final code is:

import matplotlib.pyplot as plt
import matplotlib.dates as mdates
import matplotlib.ticker as mticker
from matplotlib.finance import candlestick_ohlc
from matplotlib import style

import numpy as np
import urllib
import datetime as dt

style.use('fivethirtyeight')
print(plt.style.available)

print(plt.__file__)

MA1 = 10
MA2 = 30

def moving_average(values, window):
    weights = np.repeat(1.0, window)/window
    smas = np.convolve(values, weights, 'valid')
    return smas

def high_minus_low(highs, lows):
    return highs-lows


def bytespdate2num(fmt, encoding='utf-8'):
    strconverter = mdates.strpdate2num(fmt)
    def bytesconverter(b):
        s = b.decode(encoding)
        return strconverter(s)
    return bytesconverter
    

def graph_data(stock):

    fig = plt.figure()
    ax1 = plt.subplot2grid((6,1), (0,0), rowspan=1, colspan=1)
    plt.title(stock)
    plt.ylabel('H-L')
    ax2 = plt.subplot2grid((6,1), (1,0), rowspan=4, colspan=1, sharex=ax1)
    plt.ylabel('Price')
    ax3 = plt.subplot2grid((6,1), (5,0), rowspan=1, colspan=1, sharex=ax1)
    plt.ylabel('MAvgs')
    
    
    stock_price_url = 'http://chartapi.finance.yahoo.com/instrument/1.0/'+stock+'/chartdata;type=quote;range=1y/csv'
    source_code = urllib.request.urlopen(stock_price_url).read().decode()
    stock_data = []
    split_source = source_code.split('\n')
    for line in split_source:
        split_line = line.split(',')
        if len(split_line) == 6:
            if 'values' not in line and 'labels' not in line:
                stock_data.append(line)

    
    date, closep, highp, lowp, openp, volume = np.loadtxt(stock_data,
                                                          delimiter=',',
                                                          unpack=True,
                                                          converters={0: bytespdate2num('%Y%m%d')})

    x = 0
    y = len(date)
    ohlc = []

    while x < y:
        append_me = date[x], openp[x], highp[x], lowp[x], closep[x], volume[x]
        ohlc.append(append_me)
        x+=1

    ma1 = moving_average(closep,MA1)
    ma2 = moving_average(closep,MA2)
    start = len(date[MA2-1:])

    h_l = list(map(high_minus_low, highp, lowp))
    

    ax1.plot_date(date[-start:],h_l[-start:],'-')
    ax1.yaxis.set_major_locator(mticker.MaxNLocator(nbins=4, prune='lower'))


    candlestick_ohlc(ax2, ohlc[-start:], width=0.4, colorup='#77d879', colordown='#db3f3f')
  
    

    ax2.yaxis.set_major_locator(mticker.MaxNLocator(nbins=7, prune='upper'))
    ax2.grid(True)
    
    bbox_props = dict(boxstyle='round',fc='w', ec='k',lw=1)
    
    ax2.annotate(str(closep[-1]), (date[-1], closep[-1]),
                 xytext = (date[-1]+4, closep[-1]), bbox=bbox_props)

    
##    # Annotation example with arrow
##    ax2.annotate('Bad News!',(date[11],highp[11]),
##                 xytext=(0.8, 0.9), textcoords='axes fraction',
##                 arrowprops = dict(facecolor='grey',color='grey'))
##
##    
##    # Font dict example
##    font_dict = {'family':'serif',
##                 'color':'darkred',
##                 'size':15}
##    # Hard coded text 
##    ax2.text(date[10], closep[1],'Text Example', fontdict=font_dict)



    ax3.plot(date[-start:], ma1[-start:], linewidth=1)
    ax3.plot(date[-start:], ma2[-start:], linewidth=1)
    
    ax3.fill_between(date[-start:], ma2[-start:], ma1[-start:],
                     where=(ma1[-start:] < ma2[-start:]),
                     facecolor='r', edgecolor='r', alpha=0.5)

    ax3.fill_between(date[-start:], ma2[-start:], ma1[-start:],
                     where=(ma1[-start:] > ma2[-start:]),
                     facecolor='g', edgecolor='g', alpha=0.5)
    
    ax3.xaxis.set_major_formatter(mdates.DateFormatter('%Y-%m-%d'))
    ax3.xaxis.set_major_locator(mticker.MaxNLocator(10))
    ax3.yaxis.set_major_locator(mticker.MaxNLocator(nbins=4, prune='upper'))

    for label in ax3.xaxis.get_ticklabels():
        label.set_rotation(45)



    plt.setp(ax1.get_xticklabels(), visible=False)
    plt.setp(ax2.get_xticklabels(), visible=False)
    plt.subplots_adjust(left=0.11, bottom=0.24, right=0.90, top=0.90, wspace=0.2, hspace=0)
    plt.show()


graph_data('EBAY')

Next we will discuss how to create multiple y axes.

Chapter 24 multiple Y axes

In this Matplotlib tutorial, we will show how to use multiple Y axes on the same subgraph. In our example, we are interested in drawing stock prices and trading volumes on the same chart and the same subgraph.

To do this, first we need to define a new axis field, but this axis field is ax2 "twins" with only x axis.

This is enough to create a pivot field. We call it ax2v, because this axis field is ax2 plus trading volume.

Now, we define the drawing on the axis field, and we will add:

ax2v.fill_between(date[-start:],0, volume[-start:], facecolor='#0079a3', alpha=0.4)

We fill in between 0 and the current trading volume, give it a blue foreground, and then give it a transparency. We want to apply nether poison in case the trading volume eventually covers other things, so we can still see these two elements.

So far, our code is:

import matplotlib.pyplot as plt
import matplotlib.dates as mdates
import matplotlib.ticker as mticker
from matplotlib.finance import candlestick_ohlc
from matplotlib import style

import numpy as np
import urllib
import datetime as dt

style.use('fivethirtyeight')
print(plt.style.available)

print(plt.__file__)

MA1 = 10
MA2 = 30

def moving_average(values, window):
    weights = np.repeat(1.0, window)/window
    smas = np.convolve(values, weights, 'valid')
    return smas

def high_minus_low(highs, lows):
    return highs-lows


def bytespdate2num(fmt, encoding='utf-8'):
    strconverter = mdates.strpdate2num(fmt)
    def bytesconverter(b):
        s = b.decode(encoding)
        return strconverter(s)
    return bytesconverter
    

def graph_data(stock):

    fig = plt.figure()
    ax1 = plt.subplot2grid((6,1), (0,0), rowspan=1, colspan=1)
    plt.title(stock)
    plt.ylabel('H-L')
    ax2 = plt.subplot2grid((6,1), (1,0), rowspan=4, colspan=1, sharex=ax1)
    plt.ylabel('Price')
    ax2v = ax2.twinx()
    
    ax3 = plt.subplot2grid((6,1), (5,0), rowspan=1, colspan=1, sharex=ax1)
    plt.ylabel('MAvgs')
    
    
    stock_price_url = 'http://chartapi.finance.yahoo.com/instrument/1.0/'+stock+'/chartdata;type=quote;range=1y/csv'
    source_code = urllib.request.urlopen(stock_price_url).read().decode()
    stock_data = []
    split_source = source_code.split('\n')
    for line in split_source:
        split_line = line.split(',')
        if len(split_line) == 6:
            if 'values' not in line and 'labels' not in line:
                stock_data.append(line)

    
    date, closep, highp, lowp, openp, volume = np.loadtxt(stock_data,
                                                          delimiter=',',
                                                          unpack=True,
                                                          converters={0: bytespdate2num('%Y%m%d')})

    x = 0
    y = len(date)
    ohlc = []

    while x < y:
        append_me = date[x], openp[x], highp[x], lowp[x], closep[x], volume[x]
        ohlc.append(append_me)
        x+=1

    ma1 = moving_average(closep,MA1)
    ma2 = moving_average(closep,MA2)
    start = len(date[MA2-1:])

    h_l = list(map(high_minus_low, highp, lowp))
    

    ax1.plot_date(date[-start:],h_l[-start:],'-')
    ax1.yaxis.set_major_locator(mticker.MaxNLocator(nbins=4, prune='lower'))


    candlestick_ohlc(ax2, ohlc[-start:], width=0.4, colorup='#77d879', colordown='#db3f3f')
  
    

    ax2.yaxis.set_major_locator(mticker.MaxNLocator(nbins=7, prune='upper'))
    ax2.grid(True)
    
    bbox_props = dict(boxstyle='round',fc='w', ec='k',lw=1)
    
    ax2.annotate(str(closep[-1]), (date[-1], closep[-1]),
                 xytext = (date[-1]+4, closep[-1]), bbox=bbox_props)

##    # Annotation example with arrow
##    ax2.annotate('Bad News!',(date[11],highp[11]),
##                 xytext=(0.8, 0.9), textcoords='axes fraction',
##                 arrowprops = dict(facecolor='grey',color='grey'))
##
##    
##    # Font dict example
##    font_dict = {'family':'serif',
##                 'color':'darkred',
##                 'size':15}
##    # Hard coded text 
##    ax2.text(date[10], closep[1],'Text Example', fontdict=font_dict)
    ax2v.fill_between(date[-start:],0, volume[-start:], facecolor='#0079a3', alpha=0.4)
    
    
    ax3.plot(date[-start:], ma1[-start:], linewidth=1)
    ax3.plot(date[-start:], ma2[-start:], linewidth=1)
    
    ax3.fill_between(date[-start:], ma2[-start:], ma1[-start:],
                     where=(ma1[-start:] < ma2[-start:]),
                     facecolor='r', edgecolor='r', alpha=0.5)

    ax3.fill_between(date[-start:], ma2[-start:], ma1[-start:],
                     where=(ma1[-start:] > ma2[-start:]),
                     facecolor='g', edgecolor='g', alpha=0.5)
    
    ax3.xaxis.set_major_formatter(mdates.DateFormatter('%Y-%m-%d'))
    ax3.xaxis.set_major_locator(mticker.MaxNLocator(10))
    ax3.yaxis.set_major_locator(mticker.MaxNLocator(nbins=4, prune='upper'))

    for label in ax3.xaxis.get_ticklabels():
        label.set_rotation(45)



    plt.setp(ax1.get_xticklabels(), visible=False)
    plt.setp(ax2.get_xticklabels(), visible=False)
    plt.subplots_adjust(left=0.11, bottom=0.24, right=0.90, top=0.90, wspace=0.2, hspace=0)
    plt.show()


graph_data('GOOG')

Will generate:

 

Great. So far, it's good. Next, we may want to delete the labels on the new y-axis, and then we may not want the transaction volume to take up too much space. no problem:

first:

ax2v.axes.yaxis.set_ticklabels([])

The y scale label is set to an empty list above, so there will be no labels.

Translator's note: so what is the meaning of adding a new axis after deleting the label? You can draw directly on the original axis field.

Next, we may set the grid to false so that there will be no double grid on the axis field:

ax2v.grid(False)

Finally, in order to process the transaction volume and occupy a lot of space, we can do the following:

ax2v.set_ylim(0, 3*volume.max())

Therefore, this sets the y-axis display range from 0 to 3 times the maximum trading volume. This means that at the highest point, the trading volume can account for up to 33% of the graph. Therefore, increase volume The more multiples of Max, the smaller / less space.

Now, our chart is:

import matplotlib.pyplot as plt
import matplotlib.dates as mdates
import matplotlib.ticker as mticker
from matplotlib.finance import candlestick_ohlc
from matplotlib import style

import numpy as np
import urllib
import datetime as dt

style.use('fivethirtyeight')
print(plt.style.available)

print(plt.__file__)

MA1 = 10
MA2 = 30

def moving_average(values, window):
    weights = np.repeat(1.0, window)/window
    smas = np.convolve(values, weights, 'valid')
    return smas

def high_minus_low(highs, lows):
    return highs-lows


def bytespdate2num(fmt, encoding='utf-8'):
    strconverter = mdates.strpdate2num(fmt)
    def bytesconverter(b):
        s = b.decode(encoding)
        return strconverter(s)
    return bytesconverter
    

def graph_data(stock):

    fig = plt.figure()
    ax1 = plt.subplot2grid((6,1), (0,0), rowspan=1, colspan=1)
    plt.title(stock)
    plt.ylabel('H-L')
    ax2 = plt.subplot2grid((6,1), (1,0), rowspan=4, colspan=1, sharex=ax1)
    plt.ylabel('Price')
    ax2v = ax2.twinx()
    
    ax3 = plt.subplot2grid((6,1), (5,0), rowspan=1, colspan=1, sharex=ax1)
    plt.ylabel('MAvgs')
    
    
    stock_price_url = 'http://chartapi.finance.yahoo.com/instrument/1.0/'+stock+'/chartdata;type=quote;range=1y/csv'
    source_code = urllib.request.urlopen(stock_price_url).read().decode()
    stock_data = []
    split_source = source_code.split('\n')
    for line in split_source:
        split_line = line.split(',')
        if len(split_line) == 6:
            if 'values' not in line and 'labels' not in line:
                stock_data.append(line)

    
    date, closep, highp, lowp, openp, volume = np.loadtxt(stock_data,
                                                          delimiter=',',
                                                          unpack=True,
                                                          converters={0: bytespdate2num('%Y%m%d')})

    x = 0
    y = len(date)
    ohlc = []

    while x < y:
        append_me = date[x], openp[x], highp[x], lowp[x], closep[x], volume[x]
        ohlc.append(append_me)
        x+=1

    ma1 = moving_average(closep,MA1)
    ma2 = moving_average(closep,MA2)
    start = len(date[MA2-1:])

    h_l = list(map(high_minus_low, highp, lowp))
    

    ax1.plot_date(date[-start:],h_l[-start:],'-')
    ax1.yaxis.set_major_locator(mticker.MaxNLocator(nbins=4, prune='lower'))


    candlestick_ohlc(ax2, ohlc[-start:], width=0.4, colorup='#77d879', colordown='#db3f3f')
  
    

    ax2.yaxis.set_major_locator(mticker.MaxNLocator(nbins=7, prune='upper'))
    ax2.grid(True)
    
    bbox_props = dict(boxstyle='round',fc='w', ec='k',lw=1)
    
    ax2.annotate(str(closep[-1]), (date[-1], closep[-1]),
                 xytext = (date[-1]+5, closep[-1]), bbox=bbox_props)

##    # Annotation example with arrow
##    ax2.annotate('Bad News!',(date[11],highp[11]),
##                 xytext=(0.8, 0.9), textcoords='axes fraction',
##                 arrowprops = dict(facecolor='grey',color='grey'))
##
##    
##    # Font dict example
##    font_dict = {'family':'serif',
##                 'color':'darkred',
##                 'size':15}
##    # Hard coded text 
##    ax2.text(date[10], closep[1],'Text Example', fontdict=font_dict)
    
    ax2v.fill_between(date[-start:],0, volume[-start:], facecolor='#0079a3', alpha=0.4)
    ax2v.axes.yaxis.set_ticklabels([])
    ax2v.grid(False)
    ax2v.set_ylim(0, 3*volume.max())



    ax3.plot(date[-start:], ma1[-start:], linewidth=1)
    ax3.plot(date[-start:], ma2[-start:], linewidth=1)
    
    ax3.fill_between(date[-start:], ma2[-start:], ma1[-start:],
                     where=(ma1[-start:] < ma2[-start:]),
                     facecolor='r', edgecolor='r', alpha=0.5)

    ax3.fill_between(date[-start:], ma2[-start:], ma1[-start:],
                     where=(ma1[-start:] > ma2[-start:]),
                     facecolor='g', edgecolor='g', alpha=0.5)
    
    ax3.xaxis.set_major_formatter(mdates.DateFormatter('%Y-%m-%d'))
    ax3.xaxis.set_major_locator(mticker.MaxNLocator(10))
    ax3.yaxis.set_major_locator(mticker.MaxNLocator(nbins=4, prune='upper'))

    for label in ax3.xaxis.get_ticklabels():
        label.set_rotation(45)



    plt.setp(ax1.get_xticklabels(), visible=False)
    plt.setp(ax2.get_xticklabels(), visible=False)
    plt.subplots_adjust(left=0.11, bottom=0.24, right=0.90, top=0.90, wspace=0.2, hspace=0)
    plt.show()


graph_data('GOOG')

Here, we're almost done. The only drawback here is a good illustration. Some lines are obvious, but people may wonder what the parameters of the moving average are. Here we are 10 and 30. Adding custom legends is covered in the next tutorial.

Chapter 25 custom legend

In this Matplotlib tutorial, we will discuss custom legends. We have introduced Basics of adding Legends.

The main problem with legends is that legends often hinder the display of data. Here are a few options. One option is to put the legend outside the axis domain, but we have multiple subgraphs here, which is very difficult. Instead, we'll make the legend a little smaller and then apply a transparency.

First, in order to create a legend, we need to add labels to our data that we want to display on the legend.

ax1.plot_date(date[-start:],h_l[-start:],'-', label='H-L')
...
ax2v.plot([],[], color='#0079a3', alpha=0.4, label='Volume')
...
ax3.plot(date[-start:], ma1[-start:], linewidth=1, label=(str(MA1)+'MA'))
ax3.plot(date[-start:], ma2[-start:], linewidth=1, label=(str(MA2)+'MA'))

Note that we added a tag to the transaction volume by creating an empty behavior. Remember, we can't tag any padding, so that's why we added this blank line.

Now, we can add the legend in the lower right corner through PLT Do the following before show():

ax1.legend()
ax2v.legend()
ax3.legend()

Will generate:

 

Therefore, we can see that the legend still occupies some positions. Let's change the position, size and add transparency:

ax1.legend()
leg = ax1.legend(loc=9, ncol=2,prop={'size':11})
leg.get_frame().set_alpha(0.4)

ax2v.legend()
leg = ax2v.legend(loc=9, ncol=2,prop={'size':11})
leg.get_frame().set_alpha(0.4)

ax3.legend()
leg = ax3.legend(loc=9, ncol=2,prop={'size':11})
leg.get_frame().set_alpha(0.4)

All legends are located at position 9 (upper middle). There are many places to place legends. We can pass in different location numbers for parameters to see where they are located. The ncol parameter allows us to specify the number of columns in the legend. There is only one column here. If there are 2 items in the legend, they will be stacked in one column. Finally, we specify the size to be smaller. After that, we apply a transparency of 0.4 to the entire legend.

Now our result is:

 

The complete code is:

import matplotlib.pyplot as plt
import matplotlib.dates as mdates
import matplotlib.ticker as mticker
from matplotlib.finance import candlestick_ohlc
from matplotlib import style

import numpy as np
import urllib
import datetime as dt

style.use('fivethirtyeight')
print(plt.style.available)

print(plt.__file__)

MA1 = 10
MA2 = 30

def moving_average(values, window):
    weights = np.repeat(1.0, window)/window
    smas = np.convolve(values, weights, 'valid')
    return smas

def high_minus_low(highs, lows):
    return highs-lows


def bytespdate2num(fmt, encoding='utf-8'):
    strconverter = mdates.strpdate2num(fmt)
    def bytesconverter(b):
        s = b.decode(encoding)
        return strconverter(s)
    return bytesconverter
    

def graph_data(stock):

    fig = plt.figure(facecolor='#f0f0f0')
    ax1 = plt.subplot2grid((6,1), (0,0), rowspan=1, colspan=1)
    plt.title(stock)
    plt.ylabel('H-L')
    ax2 = plt.subplot2grid((6,1), (1,0), rowspan=4, colspan=1, sharex=ax1)
    plt.ylabel('Price')
    ax2v = ax2.twinx()
    
    ax3 = plt.subplot2grid((6,1), (5,0), rowspan=1, colspan=1, sharex=ax1)
    plt.ylabel('MAvgs')
    
    
    stock_price_url = 'http://chartapi.finance.yahoo.com/instrument/1.0/'+stock+'/chartdata;type=quote;range=1y/csv'
    source_code = urllib.request.urlopen(stock_price_url).read().decode()
    stock_data = []
    split_source = source_code.split('\n')
    for line in split_source:
        split_line = line.split(',')
        if len(split_line) == 6:
            if 'values' not in line and 'labels' not in line:
                stock_data.append(line)

    
    date, closep, highp, lowp, openp, volume = np.loadtxt(stock_data,
                                                          delimiter=',',
                                                          unpack=True,
                                                          converters={0: bytespdate2num('%Y%m%d')})

    x = 0
    y = len(date)
    ohlc = []

    while x < y:
        append_me = date[x], openp[x], highp[x], lowp[x], closep[x], volume[x]
        ohlc.append(append_me)
        x+=1

    ma1 = moving_average(closep,MA1)
    ma2 = moving_average(closep,MA2)
    start = len(date[MA2-1:])

    h_l = list(map(high_minus_low, highp, lowp))
    

    ax1.plot_date(date[-start:],h_l[-start:],'-', label='H-L')
    ax1.yaxis.set_major_locator(mticker.MaxNLocator(nbins=4, prune='lower'))


    candlestick_ohlc(ax2, ohlc[-start:], width=0.4, colorup='#77d879', colordown='#db3f3f')
  
    

    ax2.yaxis.set_major_locator(mticker.MaxNLocator(nbins=7, prune='upper'))
    ax2.grid(True)
    
    bbox_props = dict(boxstyle='round',fc='w', ec='k',lw=1)
    
    ax2.annotate(str(closep[-1]), (date[-1], closep[-1]),
                 xytext = (date[-1]+4, closep[-1]), bbox=bbox_props)

##    # Annotation example with arrow
##    ax2.annotate('Bad News!',(date[11],highp[11]),
##                 xytext=(0.8, 0.9), textcoords='axes fraction',
##                 arrowprops = dict(facecolor='grey',color='grey'))
##
##    
##    # Font dict example
##    font_dict = {'family':'serif',
##                 'color':'darkred',
##                 'size':15}
##    # Hard coded text 
##    ax2.text(date[10], closep[1],'Text Example', fontdict=font_dict)

    ax2v.plot([],[], color='#0079a3', alpha=0.4, label='Volume')
    ax2v.fill_between(date[-start:],0, volume[-start:], facecolor='#0079a3', alpha=0.4)
    ax2v.axes.yaxis.set_ticklabels([])
    ax2v.grid(False)
    ax2v.set_ylim(0, 3*volume.max())



    ax3.plot(date[-start:], ma1[-start:], linewidth=1, label=(str(MA1)+'MA'))
    ax3.plot(date[-start:], ma2[-start:], linewidth=1, label=(str(MA2)+'MA'))
    
    ax3.fill_between(date[-start:], ma2[-start:], ma1[-start:],
                     where=(ma1[-start:] < ma2[-start:]),
                     facecolor='r', edgecolor='r', alpha=0.5)

    ax3.fill_between(date[-start:], ma2[-start:], ma1[-start:],
                     where=(ma1[-start:] > ma2[-start:]),
                     facecolor='g', edgecolor='g', alpha=0.5)
    
    ax3.xaxis.set_major_formatter(mdates.DateFormatter('%Y-%m-%d'))
    ax3.xaxis.set_major_locator(mticker.MaxNLocator(10))
    ax3.yaxis.set_major_locator(mticker.MaxNLocator(nbins=4, prune='upper'))

    for label in ax3.xaxis.get_ticklabels():
        label.set_rotation(45)



    plt.setp(ax1.get_xticklabels(), visible=False)
    plt.setp(ax2.get_xticklabels(), visible=False)
    plt.subplots_adjust(left=0.11, bottom=0.24, right=0.90, top=0.90, wspace=0.2, hspace=0)

    ax1.legend()
    leg = ax1.legend(loc=9, ncol=2,prop={'size':11})
    leg.get_frame().set_alpha(0.4)
    
    ax2v.legend()
    leg = ax2v.legend(loc=9, ncol=2,prop={'size':11})
    leg.get_frame().set_alpha(0.4)
    
    ax3.legend()
    leg = ax3.legend(loc=9, ncol=2,prop={'size':11})
    leg.get_frame().set_alpha(0.4)
    
    plt.show()
    fig.savefig('google.png', facecolor=fig.get_facecolor())


graph_data('GOOG')

Now we can see the legend, but we can also see any information under the legend. Also note the extra function fig.savefig. This is the way to automatically save the image of the drawing. We can also set the foreground color of the saved graphics so that the background is not white, as shown in our example.

This is the typical Matplotlib diagram I want to show so far. Next, we'll talk about Basemap, which is a Matplotlib extension for drawing geographic locations, and then I'm going to talk about 3D graphics in Matplotlib.

Chapter 26 Basemap geographic mapping

In this Matplotlib tutorial, we will cover the geographic mapping module basemap. Basemap is an extension of Matplotlib.

To use Basemap, we first need to install it. To get Basemap, you can get it here: http://matplotlib.org/basemap/users/download.html , or you can visit http://www.lfd.uci.edu/~gohlke/pythonlibs/.

If you have problems installing Basemap, please check pip installation tutorial.

Once you install Basemap, you can create a map. First, let's project a simple map. To do this, we need to import Basemap and pyplot, create projection, draw at least some contour or data, and then we can display graphics.

from mpl_toolkits.basemap import Basemap
import matplotlib.pyplot as plt

m = Basemap(projection='mill')
m.drawcoastlines()
plt.show()

The result of the above code is as follows:

 

This is done using Miller projection, which is just a lot Basemap projection options one of.

Chapter 27 Basemap customization

In this Matplotlib tutorial, we continue to use the Basemap geographic mapping extension. We'll show you some of the customization options available to us.

First, get our starting code from the previous tutorial:

from mpl_toolkits.basemap import Basemap
import matplotlib.pyplot as plt

m = Basemap(projection='mill')
m.drawcoastlines()
plt.show()

We can start by zooming in to a specific area:

from mpl_toolkits.basemap import Basemap
import matplotlib.pyplot as plt

m = Basemap(projection='mill',
            llcrnrlat = -40,
            llcrnrlon = -40,
            urcrnrlat = 50,
            urcrnrlon = 75)
m.drawcoastlines()
plt.show()

The parameters here are:

  • llcrnrlat - latitude of the lower left corner
  • llcrnrlon - longitude of the lower left corner
  • urcrnrlat - latitude in the upper right corner
  • Upper right corner of longitude crurlon

In addition, the coordinates need to be converted, in which the coordinates of west longitude and south latitude are negative and the coordinates of north latitude and east longitude are positive.

Using these coordinates, Basemap selects the area between them.

 

Next, we will use something similar to:

m.drawcountries(linewidth=2)

This draws the country and uses a line with a line width of 2 to generate a dividing line.

Another option is:

m.drawstates(color='b')

This will draw the state in blue.

You can also perform:

m.drawcounties(color='darkred')

This will draw the country.

So our code is:

from mpl_toolkits.basemap import Basemap
import matplotlib.pyplot as plt

m = Basemap(projection='mill',
            llcrnrlat = -90,
            llcrnrlon = -180,
            urcrnrlat = 90,
            urcrnrlon = 180)

m.drawcoastlines()
m.drawcountries(linewidth=2)
m.drawstates(color='b')
m.drawcounties(color='darkred')

plt.title('Basemap Tutorial')
plt.show()
 

It's hard to say, but we defined the lines of districts and counties in the United States. We can use a magnifying glass to enlarge the Basemap figure. Like other figures, it will generate:

 

Another useful option is the resolution option in the Basemap call.

m = Basemap(projection='mill',
            llcrnrlat = -90,
            llcrnrlon = -180,
            urcrnrlat = 90,
            urcrnrlon = 180,
            resolution='l')

The resolution options are:

  • c - rough
  • l - low
  • h - high
  • f - complete

For higher resolutions, you should zoom in very large, otherwise it may be just a waste.

Another option is to use etopo() to draw terrain, such as:

m.etopo()

Drawing this graph using the drawaccounts method produces:

 

Finally, there is a blue marble version that you can call:

m.bluemarble()

Will generate:

 

Code to date:

from mpl_toolkits.basemap import Basemap
import matplotlib.pyplot as plt

m = Basemap(projection='mill',
            llcrnrlat = -90,
            llcrnrlon = -180,
            urcrnrlat = 90,
            urcrnrlon = 180,
            resolution='l')

m.drawcoastlines()
m.drawcountries(linewidth=2)
##m.drawstates(color='b')
##m.drawcounties(color='darkred')
#m.fillcontinents()
#m.etopo()
m.bluemarble()

plt.title('Basemap Tutorial')
plt.show()

Chapter 28 drawing coordinates in Basemap

Welcome to another Matplotlib Basemap tutorial. In this tutorial, we will show you how to draw individual coordinates and how to connect them in a geographic area.

First, we will start with some basic starting data:

from mpl_toolkits.basemap import Basemap
import matplotlib.pyplot as plt

m = Basemap(projection='mill',
            llcrnrlat = 25,
            llcrnrlon = -130,
            urcrnrlat = 50,
            urcrnrlon = -60,
            resolution='l')

m.drawcoastlines()
m.drawcountries(linewidth=2)
m.drawstates(color='b')

Next, we can draw coordinates, starting with their actual coordinates. Remember that the south latitude and west longitude coordinates need to be converted to negative values. For example, New York City is 40.7127 north latitude and 74.0059 west longitude. We can define these coordinates in our program, such as:

NYClat, NYClon = 40.7127, -74.0059

Then we convert these to the x and y coordinates to be drawn.

xpt, ypt = m(NYClon, NYClat)

Notice here that we have now flipped the coordinate order to lon, lat (latitude, longitude). Coordinates are usually given in lat and lon order. However, in the graph, lat and long are converted to y and X, which we obviously don't need. At some point, you have to flip them. Don't forget this part!

Finally, we can draw the following coordinates:

m.plot(xpt, ypt, 'c*', markersize=15)

There is a cyan star on this chart, with a size of 15. For more tag types, see: Matplotlib tag document.

Next, let's draw another location, Los Angeles, California:

LAlat, LAlon = 34.05, -118.25
xpt, ypt = m(LAlon, LAlat)
m.plot(xpt, ypt, 'g^', markersize=15)

We will draw a green triangle this time:

 

What if we want to connect these blocks? Originally, we can implement it like other Matplotlib diagrams.

First, we save those xpt and ypt coordinates to the list, such as:

xs = []
ys = []

NYClat, NYClon = 40.7127, -74.0059
xpt, ypt = m(NYClon, NYClat)
xs.append(xpt)
ys.append(ypt)
m.plot(xpt, ypt, 'c*', markersize=15)

LAlat, LAlon = 34.05, -118.25
xpt, ypt = m(LAlon, LAlat)
xs.append(xpt)
ys.append(ypt)
m.plot(xpt, ypt, 'g^', markersize=15)

m.plot(xs, ys, color='r', linewidth=3, label='Flight 98')

Will generate:

 

fantastic. Sometimes we need to connect two coordinates on the graph with an arc. How to achieve it?

m.drawgreatcircle(NYClon, NYClat, LAlon, LAlat, color='c', linewidth=3, label='Arc')

Our complete code is:

from mpl_toolkits.basemap import Basemap
import matplotlib.pyplot as plt

m = Basemap(projection='mill',
            llcrnrlat = 25,
            llcrnrlon = -130,
            urcrnrlat = 50,
            urcrnrlon = -60,
            resolution='l')

m.drawcoastlines()
m.drawcountries(linewidth=2)
m.drawstates(color='b')
#m.drawcounties(color='darkred')
#m.fillcontinents()
#m.etopo()
#m.bluemarble()

xs = []
ys = []

NYClat, NYClon = 40.7127, -74.0059
xpt, ypt = m(NYClon, NYClat)
xs.append(xpt)
ys.append(ypt)
m.plot(xpt, ypt, 'c*', markersize=15)

LAlat, LAlon = 34.05, -118.25
xpt, ypt = m(LAlon, LAlat)
xs.append(xpt)
ys.append(ypt)
m.plot(xpt, ypt, 'g^', markersize=15)

m.plot(xs, ys, color='r', linewidth=3, label='Flight 98')
m.drawgreatcircle(NYClon, NYClat, LAlon, LAlat, color='c', linewidth=3, label='Arc')


plt.legend(loc=4)
plt.title('Basemap Tutorial')
plt.show()

The result is:

 

That's all about Basemap. The next chapter is about the 3D drawing of Matplotlib.

Chapter 29 3D drawing

Hello, welcome to the 3D drawing in the Matplotlib tutorial. Matplotlib has built-in 3D graphics, so we don't need to download anything. First, we need to introduce some complete modules:

from mpl_toolkits.mplot3d import axes3d
import matplotlib.pyplot as plt

axes3d is used because it requires different kinds of axis fields in order to actually draw something in 3D. below:

fig = plt.figure()
ax1 = fig.add_subplot(111, projection='3d')

Here, we define the graph as usual, and then we define ax1 as the usual subgraph, but this time we use 3D projection. We need to do this to remind Matplotlib that we need to provide 3D data.

Now let's create some 3D data:

x = [1,2,3,4,5,6,7,8,9,10]
y = [5,6,7,8,2,5,6,3,7,2]
z = [1,2,6,3,2,7,3,3,7,2]

Next, we draw it. First, let's show a simple wireframe example:

ax1.plot_wireframe(x,y,z)

last:

ax1.set_xlabel('x axis')
ax1.set_ylabel('y axis')
ax1.set_zlabel('z axis')

plt.show()

Our complete code is:

from mpl_toolkits.mplot3d import axes3d
import matplotlib.pyplot as plt
from matplotlib import style

style.use('fivethirtyeight')

fig = plt.figure()
ax1 = fig.add_subplot(111, projection='3d')

x = [1,2,3,4,5,6,7,8,9,10]
y = [5,6,7,8,2,5,6,3,7,2]
z = [1,2,6,3,2,7,3,3,7,2]

ax1.plot_wireframe(x,y,z)

ax1.set_xlabel('x axis')
ax1.set_ylabel('y axis')
ax1.set_zlabel('z axis')

plt.show()

The result is (including the style used):

 

These 3D graphics can interact. First, you can click and drag with the left mouse button to move the drawing. You can also right-click and drag to zoom in or out.

Chapter 30 3D scatter diagram

Welcome to another 3D Matplotlib tutorial, which will cover how to draw a 3D scatter diagram.

Drawing a 3D scatter diagram is very similar to the usual scatter diagram and 3D wireframe.

A simple example:

from mpl_toolkits.mplot3d import axes3d
import matplotlib.pyplot as plt
from matplotlib import style

style.use('ggplot')

fig = plt.figure()
ax1 = fig.add_subplot(111, projection='3d')

x = [1,2,3,4,5,6,7,8,9,10]
y = [5,6,7,8,2,5,6,3,7,2]
z = [1,2,6,3,2,7,3,3,7,2]

x2 = [-1,-2,-3,-4,-5,-6,-7,-8,-9,-10]
y2 = [-5,-6,-7,-8,-2,-5,-6,-3,-7,-2]
z2 = [1,2,6,3,2,7,3,3,7,2]

ax1.scatter(x, y, z, c='g', marker='o')
ax1.scatter(x2, y2, z2, c ='r', marker='o')

ax1.set_xlabel('x axis')
ax1.set_ylabel('y axis')
ax1.set_zlabel('z axis')

plt.show()

The result is:

 

Remember that you can change the size and marking of these drawings, just like the usual scatter diagram.

Chapter 31 3D bar chart

In this Matplotlib tutorial, we will introduce 3D bar graphs. 3D bar chart is very unique because it allows us to draw more than 3 dimensions. No, you can't draw more than the third dimension, but you can draw more than three dimensions.

For a bar chart, you need to have the starting point of the bar, the height and width of the bar. But for the 3D bar chart, you have another option, which is the depth of the bar. In most cases, the bar chart starts with the bar plane on the axis, but you can also add another dimension by breaking this constraint. However, we will make it very simple:

from mpl_toolkits.mplot3d import axes3d
import matplotlib.pyplot as plt
import numpy as np
from matplotlib import style
style.use('ggplot')

fig = plt.figure()
ax1 = fig.add_subplot(111, projection='3d')

x3 = [1,2,3,4,5,6,7,8,9,10]
y3 = [5,6,7,8,2,5,6,3,7,2]
z3 = np.zeros(10)

dx = np.ones(10)
dy = np.ones(10)
dz = [1,2,3,4,5,6,7,8,9,10]

ax1.bar3d(x3, y3, z3, dx, dy, dz)


ax1.set_xlabel('x axis')
ax1.set_ylabel('y axis')
ax1.set_zlabel('z axis')

plt.show()

Note here that we must define x, y, and z, followed by the width, height, and depth of the three dimensions. This generates:

 

Chapter 32 summary

Welcome to the final Matplotlib tutorial. Here we will organize the whole series and show a slightly more complex 3D wireframe:

from mpl_toolkits.mplot3d import axes3d
import matplotlib.pyplot as plt
import numpy as np
from matplotlib import style
style.use('ggplot')

fig = plt.figure()
ax1 = fig.add_subplot(111, projection='3d')

x, y, z = axes3d.get_test_data()

print(axes3d.__file__)
ax1.plot_wireframe(x,y,z, rstride = 3, cstride = 3)

ax1.set_xlabel('x axis')
ax1.set_ylabel('y axis')
ax1.set_zlabel('z axis')

plt.show()
 

If you've followed this tutorial from the beginning, you've learned most of what Matplotlib provides. You may not believe it, but Matplotlib can still do many other things! Please continue your study and you can visit Matplotlib at any time Org and view the sample and gallery pages.

If you find yourself using a lot of Matplotlib, please consider donating it to John Hunter Memorial Fund.

Note: drawing method of space surface

# Quadratic paraboloid z = x^2 + y^2
x = np.linspace(-10, 10, 101)
y = x
x, y = np.meshgrid(x, y)
z = x ** 2 + y ** 2
ax = plot.subplot(111, projection='3d')
ax.plot_wireframe(x, y, z)
plot.show()
 
 
# Ball with radius 1
t = np.linspace(0, np.pi * 2, 100)
s = np.linspace(0, np.pi, 100)
t, s = np.meshgrid(t, s)
x = np.cos(t) * np.sin(s)
y = np.sin(t) * np.sin(s)
z = np.cos(s)
ax = plot.subplot(111, projection='3d')
ax.plot_wireframe(x, y, z)
plot.show()
 
 

Tags: plt

Posted by RickChase on Mon, 23 May 2022 06:37:25 +0300