Jovian
⭐️
Sign In
Learn data science and machine learning by building real-world projects on Jovian

Finance Data Project

In this data project we will focus on exploratory data analysis of stock prices. Keep in mind, this project is just meant to practice your visualization and pandas skills, it is not meant to be a robust financial analysis or be taken as financial advice.


** NOTE: This project is extremely challenging because it will introduce a lot of new concepts and have you looking things up on your own (we'll point you in the right direction) to try to solve the tasks issued. Feel free to just go through the solutions lecture notebook and video as a "walkthrough" project if you don't want to have to look things up yourself. You'll still learn a lot that way! **


We'll focus on bank stocks and see how they progressed throughout the financial crisis all the way to early 2016.

Get the Data

In this section we will learn how to use pandas to directly read data from Google finance using pandas!

First we need to start with the proper imports, which we've already laid out for you here.

Note: You'll need to install pandas-datareader for this to work! Pandas datareader allows you to read stock information directly from the internet Use these links for install guidance (pip install pandas-datareader), or just follow along with the video lecture.

The Imports

Already filled out for you.

In [1]:
from pandas_datareader import data, wb
import pandas as pd
import numpy as np
import datetime
%matplotlib inline

Data

We need to get data using pandas datareader. We will get stock information for the following banks:

  • Bank of America
  • CitiGroup
  • Goldman Sachs
  • JPMorgan Chase
  • Morgan Stanley
  • Wells Fargo

** Figure out how to get the stock data from Jan 1st 2006 to Jan 1st 2016 for each of these banks. Set each bank to be a separate dataframe, with the variable name for that bank being its ticker symbol. This will involve a few steps:**

  1. Use datetime to set start and end datetime objects.
  2. Figure out the ticker symbol for each bank.
  3. Figure out how to use datareader to grab info on the stock.

** Use this documentation page for hints and instructions (it should just be a matter of replacing certain values. Use google finance as a source, for example:**

# Bank of America
BAC = data.DataReader("BAC", 'google', start, end)

WARNING: MAKE SURE TO CHECK THE LINK ABOVE FOR THE LATEST WORKING API. "google" MAY NOT ALWAYS WORK.


We also provide pickle file in the article lecture right before the video lectures.

In [2]:
df = pd.read_pickle('all_banks')
In [3]:
df.head()
Out[3]:

** Create a list of the ticker symbols (as strings) in alphabetical order. Call this list: tickers**

In [4]:
tickers = ['BAC', 'C', 'GS', 'JPM', 'MS', 'WFC']

** Use pd.concat to concatenate the bank dataframes together to a single data frame called bank_stocks. Set the keys argument equal to the tickers list. Also pay attention to what axis you concatenate on.**

#because using all_banks data, we don't have to do this step

** Set the column name levels (this is filled out for you):**

In [5]:
df.columns.names = ['Bank Ticker','Stock Info']

** Check the head of the bank_stocks dataframe.**

In [6]:
df.head()
Out[6]:
In [7]:
BAC = df['BAC']
In [8]:
BAC.head()
Out[8]:

EDA

Let's explore the data a bit! Before continuing, I encourage you to check out the documentation on Multi-Level Indexing and Using .xs. Reference the solutions if you can not figure out how to use .xs(), since that will be a major part of this project.

** What is the max Close price for each bank's stock throughout the time period?**

In [9]:
for tick in tickers:
    print(tick, df[tick]['Close'].max())
BAC 54.9 C 564.1 GS 247.92 JPM 70.08 MS 89.3 WFC 58.52
In [10]:
for tick in tickers:
    print(df[tick]['Close'].max())
54.9 564.1 247.92 70.08 89.3 58.52
In [11]:
df.xs(key='Close',axis=1,level='Stock Info').max()
Out[11]:
Bank Ticker
BAC     54.90
C      564.10
GS     247.92
JPM     70.08
MS      89.30
WFC     58.52
dtype: float64

** Create a new empty DataFrame called returns. This dataframe will contain the returns for each bank's stock. returns are typically defined by:**

\[r_t = \frac{p_t - p_{t-1}}{p_{t-1}} = \frac{p_t}{p_{t-1}} - 1\]

In [12]:
returns = pd.DataFrame()

** We can use pandas pct_change() method on the Close column to create a column representing this return value. Create a for loop that goes and for each Bank Stock Ticker creates this returns column and set's it as a column in the returns DataFrame.**

In [13]:
for tick in tickers:
    returns[tick+'Return'] = df[tick]['Close'].pct_change()
returns.head()
Out[13]:

** Create a pairplot using seaborn of the returns dataframe. What stock stands out to you? Can you figure out why?**

In [14]:
import seaborn as sns
sns.pairplot(returns[1:])
Out[14]:
<seaborn.axisgrid.PairGrid at 0x2abce52a370>
Notebook Image
  • See solution for details about Citigroup behavior....

** Using this returns DataFrame, figure out on what dates each bank stock had the best and worst single day returns. You should notice that 4 of the banks share the same day for the worst drop, did anything significant happen that day?**

In [15]:
returns.idxmin()
Out[15]:
BACReturn   2009-01-20
CReturn     2011-05-06
GSReturn    2009-01-20
JPMReturn   2009-01-20
MSReturn    2008-10-09
WFCReturn   2009-01-20
dtype: datetime64[ns]

** You should have noticed that Citigroup's largest drop and biggest gain were very close to one another, did anythign significant happen in that time frame? **

  • See Solution for details
In [16]:
returns.idxmax()
Out[16]:
BACReturn   2009-04-09
CReturn     2011-05-09
GSReturn    2008-11-24
JPMReturn   2009-01-21
MSReturn    2008-10-13
WFCReturn   2008-07-16
dtype: datetime64[ns]

** Take a look at the standard deviation of the returns, which stock would you classify as the riskiest over the entire time period? Which would you classify as the riskiest for the year 2015?**

In [17]:
returns.std()
Out[17]:
BACReturn    0.036650
CReturn      0.179969
GSReturn     0.025346
JPMReturn    0.027656
MSReturn     0.037820
WFCReturn    0.030233
dtype: float64
In [18]:
returns.loc['2015-01-01':'2015-12-31'].std()
Out[18]:
BACReturn    0.016163
CReturn      0.015289
GSReturn     0.014046
JPMReturn    0.014017
MSReturn     0.016249
WFCReturn    0.012591
dtype: float64

** Create a distplot using seaborn of the 2015 returns for Morgan Stanley **

In [19]:
sns.distplot(returns.loc['2015-01-01':'2015-12-31']['MSReturn'], color='green',
            bins=50)
Out[19]:
<matplotlib.axes._subplots.AxesSubplot at 0x2abd17f9310>
Notebook Image

** Create a distplot using seaborn of the 2008 returns for CitiGroup **

In [20]:
sns.distplot(returns.loc['2008-01-01':'2008-12-31']['CReturn'], color='red',
            bins=50)
Out[20]:
<matplotlib.axes._subplots.AxesSubplot at 0x2abd1de06d0>
Notebook Image

More Visualization

A lot of this project will focus on visualizations. Feel free to use any of your preferred visualization libraries to try to recreate the described plots below, seaborn, matplotlib, plotly and cufflinks, or just pandas.

Imports

In [21]:
import matplotlib.pyplot as plt
import seaborn as sns
sns.set_style('whitegrid')
%matplotlib inline

# Optional Plotly Method Imports
import plotly
import cufflinks as cf
cf.go_offline()

** Create a line plot showing Close price for each bank for the entire index of time. (Hint: Try using a for loop, or use .xs to get a cross section of the data.)**

In [22]:
for tick in tickers:
    df[tick]['Close'].plot(label=tick,figsize=(12,4))
plt.legend()
plt.xlim([datetime.date(2006,1,1), datetime.date(2016,12,31)])
Out[22]:
(732312.0, 736329.0)
Notebook Image
In [34]:
df.xs(key='Close',axis=1,level='Stock Info').plot(label=tick,figsize=(12,4))
plt.legend()
plt.xlim([datetime.date(2006,1,1), datetime.date(2016,12,31)])
Out[34]:
(732312.0, 736329.0)
Notebook Image
In [24]:
df.xs(key='Close',axis=1,level='Stock Info').iplot()

Moving Averages

Let's analyze the moving averages for these stocks in the year 2008.

** Plot the rolling 30 day average against the Close Price for Bank Of America's stock for the year 2008**

In [25]:
plt.figure(figsize=(12,4))
BAC['Close'].loc["2008-01-01":'2009-01-01'].rolling(window=30).mean().plot(label='30 day Mov Avg')
BAC['Close'].loc["2008-01-01":'2009-01-01'].plot(label='BAC Close')
plt.legend()
plt.xlim([datetime.date(2008,1,1), datetime.date(2009,1,1)])
Out[25]:
(733042.0, 733408.0)
Notebook Image

** Create a heatmap of the correlation between the stocks Close Price.**

In [26]:
correlation = df.xs(key='Close',axis=1,level='Stock Info').corr()
sns.heatmap(correlation,annot=True,cmap='coolwarm')
Out[26]:
<matplotlib.axes._subplots.AxesSubplot at 0x2abd50f5730>
Notebook Image

** Optional: Use seaborn's clustermap to cluster the correlations together:**

In [27]:
sns.clustermap(correlation,annot=True,cmap='coolwarm')
Out[27]:
<seaborn.matrix.ClusterGrid at 0x2abd3972490>
Notebook Image

Part 2 (Optional)

In this second part of the project we will rely on the cufflinks library to create some Technical Analysis plots. This part of the project is experimental due to its heavy reliance on the cuffinks project, so feel free to skip it if any functionality is broken in the future.

** Use .iplot(kind='candle) to create a candle plot of Bank of America's stock from Jan 1st 2015 to Jan 1st 2016.**

In [28]:
correlation.head()
Out[28]:
In [29]:
correlation.iplot(kind='heatmap',colorscale='rdylbu')
In [30]:
bac15 = BAC[['Open','High','Low','Close']].loc['2015-01-01':'2016-01-01']
bac15.iplot(kind='candle')

** Use .ta_plot(study='sma') to create a Simple Moving Averages plot of Morgan Stanley for the year 2015.**

In [31]:
df['MS']['Close'].loc['2015-01-01':'2016-01-01'].ta_plot(study='sma',periods=[13,21,55])

Use .ta_plot(study='boll') to create a Bollinger Band Plot for Bank of America for the year 2015.

In [32]:
BAC['Close'].loc['2015-01-01':'2016-01-01'].ta_plot(study='boll')

Great Job!

Definitely a lot of more specific finance topics here, so don't worry if you didn't understand them all! The only thing you should be concerned with understanding are the basic pandas and visualization oeprations.