Option pricing on binomial tree. Graphical representation.

One of the techniques to price the option is the Cox-Ross-Rubinstein model (1979). In this post I’m gonna show how to graphically represent it on the graph using networkX library. First, create the graph with the appropriate structure.

import networkx as nx
import matplotlib.pyplot as plt
G=nx.Graph()
for i in range(0,N+1):
    for j in range(1,i+2):
        if i<N:
            G.add_edge((i,j),(i+1,j))# with edges being added, nodes are created authomatically
            G.add_edge((i,j),(i+1,j+1))

If we draw it now, we won’t get the picture from the book on option pricing. We also need to set the coordinate for each node.

posG={}#dictionary with nodes position
for node in G.nodes():
    posG[node]=(node[0],N+2+node[0]-2*node[1])# write the coordinates of nodes
nx.draw(G,pos=posG)#draw the graph

You should obtain this picture:
Binomial tree graph

We can also put the stock prices and payoffs on the picture. You can look up all the formula in some standard book like J.Hull “Options, Futures and Other Derivative”.
I took the options parameter from an example from this book (chapter 11.4 “A put example”):

European put option:
S=50 (current stock price)
K=52 (strike price)
r=5% p.a.
T=2 (years)
up=1.2
down=0.8 (i.e. in the next period the price either goes up by 20% or goes down by 20 %)
N=2 (periods)

Here is what I produced (nodes with non-zero payoffs are painted green):
example from Hull, chapter 11.4

I’m not gonna bore with formula implementation, so you can download the source code for this example here.

Hello financial world!

Welcome to the blog “Finance with Python“! Here I’m gonna post some finance related information, applications, workarounds etc using Python.

I thought that a good thing to start off would be some kind of “Hello world” example. So, I came up with idea to show how to prototype fast an application that shows some financial data.

We’re gonna see how to build a simple GUI (“Hello financial world!”) that shows the line graph of some stock for some period with the functionality of regenerating the graph given the new stock.

Our GUI (just in case, Graphical User Interface) consists of

  • the entry field for the stock’s name (like “GOOG” for Google)
  • two buttons, the first, to add a stock to the graph and the second to put it alone on the graph
  • the graph itself

Following software needs to be installed before running the example:

  1. You need to install Python on your PC (I used version 2.7)
  2. Then install numpy package.
  3. Save the code from Python API For Yahoo Finance Stock Data as ystockquote.py in your Python’s site-packages directory.
  4. Add the following function to ystockquote.py:
    def get_historical_open_prices(symbol, start_date, end_date):
        """ Example of calling the function:
          import ystockquote as yq
          x,y=yq.get_historical_open_prices('GOOG', '20110715', '20110801')
          yq.plot_data('GOOG',y,x)
        """
        prices=[]
        dates=[]
        data=get_historical_prices(symbol, start_date, end_date)
        for line in data:
            prices.append(line[0])
            dates.append(line[1])
        dates=dates[1:]
        prices=prices[1:]
        dates.reverse()
        prices.reverse()
        return prices, dates
    

Otherwise, you can just download the ystockquote.py file I’m using.

Below is the code that generates our app, the code is overcommented to make it clear what is going on, then we look at some snapshots.

#!/usr/apps/Python/bin/python
# 1. Import the required packages
import matplotlib
matplotlib.use('TkAgg')
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from matplotlib.figure import Figure
from Tkinter import *

# You can replace 'ystockquote' package with matplotlib.quote_historical_yahoo. However, you need to rewrite some part of the code in this case
import ystockquote as yq

# 2. Define some functions
def add_plot(axe,symbol):
    """
    This function adds a line to the plot. This function is called by:
        1. initialization
        2. by pushing the "Add" button
        3. By new_plot function
    Handled parameters:
    axe - is a subplot of the matplotlib figure
    symbol - is of a Tkinter StringVar() type.
    """
    x,y=yq.get_historical_open_prices(symbol.get(), '20111025', '20111104')# get the data from YAHOO
    t=range(len(y))#unfortunately, with matplotlib it's not possible to plot against non-numerical data directly
    #That's why we create a list with numerical values that map to the data range. Later, we replace them back.
    axe.plot(t,y)#plot stock prices
    axe.set_xlabel('time')#Set the label for the x axis
    axe.set_ylabel('dollars')#Set the label for the y axis
    axe.set_xticklabels(x,rotation=45)#Put the dates on the x axis and rotate them 45 degrees for a better representation
    axe.set_title('Dynamics of '+symbol.get()+ " shares in the period \n from " +x[0]+' to '+x[-1])#Set the title
    updatePlot()#Update existing plot

def new_plot(axe,symbol):
    """
    This functions clears the plot before adding a new line. This function is called by pushing the "New" button
    """
    axe.clear()#clear the plot
    add_plot(axe,symbol)#put on it the required stock

def updatePlot():
    """
    This function updates the plot in the window after it was changed.
    """
    if 'dataPlot' in globals():#if the plot was already embedded into the main window, update it
        global dataPlot
        dataPlot.show()
    else:
        pass

# 3. Create a window for the prototype
#------------------
master = Tk()
master.title("Hello financial world!")
#-------------------
symbol=StringVar()
symbol.set('GOOG')# we initialize our prototype with Google stock data

# 3a. Now, we put some buttons and entries to our prototype
#-----------------------------------------
# Create a frame for the entry and buttons
frame = Frame(master, height=16, width=16)# creates frame
frame.pack()# packs it into the main window
# Entry field:
entry=Entry(frame, textvariable=symbol,text=symbol.get())#This line creates the entry field
entry.pack()# This line packs it into the window
# 'Add' and 'New' buttons:
compute_add = Button(frame, text='Add', command=lambda:add_plot(a,symbol))# Pushing the button, calls the function add_plot
compute_add.pack(side='right');
compute_new = Button(frame, text='New', command=lambda:new_plot(a,symbol))
compute_new.pack(side='right');

#--------------------------------------------
# 4. Generate the plot and embed it into our app window
#-------------------------------------------------------------------------------
f = Figure(figsize=(5,4), dpi=100)
a = f.add_subplot(111)
add_plot(a,symbol)#Put on the plot the data of the Google stock.

dataPlot = FigureCanvasTkAgg(f, master=master)#Put the plot into the prototype window
dataPlot.show()
dataPlot.get_tk_widget().pack(side=TOP, fill=BOTH, expand=1)
#-------------------------------------------------------------------------------
# 5. Final step: generate GUI
master.mainloop()

PlotTkYahoo.py

Now, run the code and you should see something like this:

Initialized with Google stock

The application is initialized with the information on the Google stock.
Now, let’s type GM (abbreviation for “General Motors”) in the entry field and push the “New” button. Now we see the line graph of the General Motors stock.

Put General Motors stock instead

Finally, let’s add Microsoft stock line keeping General Motors on the graph. To get it done, type MSFT (abbreviation for “Microsoft”) in the entry field and push on the “Add” button. You should obtain the result on the picture below.

Add Microsoft stock

There are a lot of straight-forward improvement (put the name of the stock on the line, implement GUI as class, replace the abbreviations with companies names etc), the idea was, however, to create a “Hello world!” example.
Even though, our code ended up to have more than 80 lines, half of them are blanks and comment lines. If we remove them and merge some lines together (for example, often there’s no need to list the pack() command on the separate line) we would end up with ca. 40 lines that is small enough for such an app.