Get the "Applied Data Science Edge"!

The ViralML School

Fundamental Market Analysis with Python - Find Your Own Answers On What Is Going on in the Financial Markets

Web Work

Python Web Work - Prototyping Guide for Maker

Use HTML5 Templates, Serve Dynamic Content, Build Machine Learning Web Apps, Grow Audiences & Conquer the World!

Hot off the Press!

The Little Book of Fundamental Market Indicators

My New Book: "The Little Book of Fundamental Analysis: Hands-On Market Analysis with Python" is Out!

PMI Correlated to the 10-Year Yields? Yes, A PMI Proxy Any Time, Any Day!

Introduction

A PMI Proxy Any Time, Any Day! If this is true, this could come in handy when you need a quick estimate mid-month. Let's roll up our sleeves and find out.



If you liked it, please share it:

Code

ViralML-Hands-US-ISM-Manufacturing-And-10-Year-Yields
In [2]:
from IPython.display import Image
Image(filename='viralml-book.png')
Out[2]:

Fundamental and Technical Indicators - Hands-On Market Analysis

Companion book: "The Little Book of Fundamental Market Indicators":

https://amzn.to/2DERG3d

More at:

https://www.viralml.com/

The US ISM manufacturing headline series is closely correlated with yields ( CS is using ISM as a macro momentum proxy here)

Data

Purchasing Managers' Index - PMI Composite Index https://www.quandl.com/data/ISM/MAN_PMI-PMI-Composite-Index

Treasury Yield Curve Rates https://www.quandl.com/data/USTREASURY/YIELD-Treasury-Yield-Curve-Rates

In [8]:
%matplotlib inline
import matplotlib
import matplotlib.pyplot as plt
import io, base64, os, json, re 
import pandas as pd
import numpy as np
import datetime
import warnings
warnings.filterwarnings('ignore')
In [9]:
path_to_market_data = '/Users/manuel/Documents/financial-research/market-data/2019-07-20/'

# create an MACD indicators
def MACD(df, feature, fast=9, medium=12, long=26):
    # WARNING - Feed data in ascending order only (i.e. first row should be your oldest print)
    
    tmp_df = df.copy()
    
    
    tmp_df['EXP1'] = tmp_df[feature].ewm(span=medium, adjust=False).mean()
    tmp_df['EXP2'] = tmp_df[feature].ewm(span=long, adjust=False).mean()
    tmp_df['MACD'] = tmp_df['EXP1']-tmp_df['EXP2']
    tmp_df['EXP3'] = tmp_df['MACD'].ewm(span=fast, adjust=False).mean()
    tmp_df['MACD_Hist'] = tmp_df['MACD'] - tmp_df['EXP3']
    
    return tmp_df

Data

In [45]:
# Purchasing Managers' Index - PMI 

pmi_df = pd.read_csv(path_to_market_data + 'ISM-MAN_PMI.csv')
pmi_df['Date'] = pd.to_datetime(pmi_df['Date'])
print(np.min(pmi_df['Date'] ),np.max(pmi_df['Date'] ))
pmi_df = pmi_df.sort_values('Date', ascending=True) # sort in ascending date order
pmi_df['PMI_pct_change'] = pmi_df['PMI'].pct_change()
pmi_df.tail()
1948-01-01 00:00:00 2019-06-01 00:00:00
Out[45]:
Date PMI PMI_pct_change
4 2019-02-01 54.2 -0.042403
3 2019-03-01 55.3 0.020295
2 2019-04-01 52.8 -0.045208
1 2019-05-01 52.1 -0.013258
0 2019-06-01 51.7 -0.007678
In [46]:
# Treasury Yield Curve Rates
rates_df = pd.read_csv(path_to_market_data + 'USTREASURY-YIELD.csv')
rates_df['Date'] = pd.to_datetime(rates_df['Date']) 
print(np.min(rates_df['Date'] ),np.max(rates_df['Date'] ))
rates_df = rates_df.sort_values('Date', ascending=True) # sort in ascending date order
rates_df['10_YR_pct_change'] = rates_df['10 YR'].pct_change()
rates_df.tail()
1990-01-02 00:00:00 2019-07-22 00:00:00
Out[46]:
Date 1 MO 2 MO 3 MO 6 MO 1 YR 2 YR 3 YR 5 YR 7 YR 10 YR 20 YR 30 YR 10_YR_pct_change
4 2019-07-16 2.16 2.17 2.15 2.06 2.00 1.87 1.84 1.88 2.00 2.13 2.42 2.63 0.019139
3 2019-07-17 2.13 2.14 2.14 2.04 1.95 1.83 1.80 1.83 1.94 2.06 2.35 2.57 -0.032864
2 2019-07-18 2.11 2.12 2.05 2.01 1.90 1.77 1.74 1.78 1.89 2.04 2.34 2.56 -0.009709
1 2019-07-19 2.11 2.16 2.06 2.03 1.94 1.80 1.77 1.80 1.91 2.05 2.35 2.57 0.004902
0 2019-07-22 2.13 2.16 2.09 2.08 1.95 1.80 1.77 1.80 1.92 2.05 2.36 2.58 0.000000

Let's Plot it All

In [50]:
cut_off_date = '1995-01-02'

pmi_df_tmp = pmi_df.copy()
rates_df_tmp = rates_df.copy()
 
pmi_df_tmp = pmi_df_tmp[pmi_df_tmp['Date'] >= cut_off_date]
rates_df_tmp = rates_df_tmp[rates_df_tmp['Date'] >= cut_off_date]
In [51]:
# join both datasets together
fig, ax = plt.subplots(figsize=(16, 8))
plt.plot(pmi_df_tmp['Date'], pmi_df_tmp['PMI'] , color='blue', label='PMI')
plt.title('PMI & 10 Year Yield')
plt.legend(loc='lower right')
plt.grid()

# Get new axis
ax2 = ax.twinx()
plt.plot(rates_df_tmp['Date'], rates_df_tmp['10 YR'] , color='black', label='10 YR')
plt.legend(loc='lower left')
 

plt.show()

Join both datasets together

In [52]:
# merge data sets together
# join both datasets together
print('pmi_df.shape():',pmi_df.shape)
print('rates_df.shape():',rates_df.shape)

 
together = pd.merge(rates_df, pmi_df, on= ['Date'], how='left')
 
# last valid observation forward
together = together.fillna(method='ffill')
 

together.tail(20)
pmi_df.shape(): (858, 3)
rates_df.shape(): (7394, 14)
Out[52]:
Date 1 MO 2 MO 3 MO 6 MO 1 YR 2 YR 3 YR 5 YR 7 YR 10 YR 20 YR 30 YR 10_YR_pct_change PMI PMI_pct_change
7374 2019-06-24 2.12 2.13 2.13 2.10 1.92 1.72 1.69 1.75 1.88 2.02 2.33 2.55 -0.024155 52.1 -0.013258
7375 2019-06-25 2.11 2.12 2.12 2.10 1.93 1.71 1.67 1.73 1.86 2.00 2.31 2.53 -0.009901 52.1 -0.013258
7376 2019-06-26 2.11 2.12 2.15 2.12 1.96 1.77 1.74 1.80 1.92 2.05 2.35 2.57 0.025000 52.1 -0.013258
7377 2019-06-27 2.19 2.15 2.14 2.12 1.93 1.74 1.71 1.76 1.88 2.01 2.31 2.52 -0.019512 52.1 -0.013258
7378 2019-06-28 2.18 2.15 2.12 2.09 1.92 1.75 1.71 1.76 1.87 2.00 2.31 2.52 -0.004975 52.1 -0.013258
7379 2019-07-01 2.17 2.16 2.21 2.10 1.94 1.78 1.74 1.79 1.90 2.03 2.34 2.55 0.015000 52.1 -0.013258
7380 2019-07-02 2.21 2.17 2.20 2.09 1.91 1.77 1.71 1.75 1.85 1.98 2.29 2.51 -0.024631 52.1 -0.013258
7381 2019-07-03 2.25 2.20 2.21 2.08 1.91 1.77 1.71 1.74 1.83 1.96 2.25 2.47 -0.010101 52.1 -0.013258
7382 2019-07-05 2.26 2.22 2.23 2.14 1.98 1.87 1.82 1.84 1.93 2.04 2.34 2.54 0.040816 52.1 -0.013258
7383 2019-07-08 2.23 2.24 2.26 2.14 1.99 1.88 1.84 1.86 1.94 2.05 2.32 2.53 0.004902 52.1 -0.013258
7384 2019-07-09 2.22 2.24 2.26 2.15 2.00 1.92 1.88 1.88 1.96 2.07 2.34 2.54 0.009756 52.1 -0.013258
7385 2019-07-10 2.18 2.18 2.20 2.07 1.93 1.82 1.79 1.82 1.93 2.07 2.36 2.57 0.000000 52.1 -0.013258
7386 2019-07-11 2.17 2.17 2.17 2.08 1.97 1.85 1.84 1.88 1.99 2.13 2.42 2.65 0.028986 52.1 -0.013258
7387 2019-07-12 2.16 2.18 2.14 2.07 1.96 1.84 1.81 1.86 1.98 2.12 2.42 2.64 -0.004695 52.1 -0.013258
7388 2019-07-15 2.17 2.19 2.16 2.06 1.95 1.83 1.80 1.84 1.96 2.09 2.39 2.61 -0.014151 52.1 -0.013258
7389 2019-07-16 2.16 2.17 2.15 2.06 2.00 1.87 1.84 1.88 2.00 2.13 2.42 2.63 0.019139 52.1 -0.013258
7390 2019-07-17 2.13 2.14 2.14 2.04 1.95 1.83 1.80 1.83 1.94 2.06 2.35 2.57 -0.032864 52.1 -0.013258
7391 2019-07-18 2.11 2.12 2.05 2.01 1.90 1.77 1.74 1.78 1.89 2.04 2.34 2.56 -0.009709 52.1 -0.013258
7392 2019-07-19 2.11 2.16 2.06 2.03 1.94 1.80 1.77 1.80 1.91 2.05 2.35 2.57 0.004902 52.1 -0.013258
7393 2019-07-22 2.13 2.16 2.09 2.08 1.95 1.80 1.77 1.80 1.92 2.05 2.36 2.58 0.000000 52.1 -0.013258

As Percentage Change

In [26]:
# join both datasets together
fig, ax = plt.subplots(figsize=(16, 8))
plt.plot(together['Date'], together['PMI_pct_change'] , color='blue', label='PMI_pct_change')
plt.title('DOW_pct_change, DJTA_pct_change')
plt.plot(together['Date'], together['10_YR_pct_change'], color='green', label='10_YR_pct_change')


plt.axhline(0, color='gray', linewidth=3, linestyle='-.' )
plt.legend()
plt.grid()
plt.show()
In [53]:
fig, ax = plt.subplots(figsize=(16, 8))
plt.plot(together['Date'], together['PMI_pct_change'].rolling(window=1, min_periods=1).mean(), color='blue', label='PMI_pct_change')
plt.title('DOW_pct_change, DJTA_pct_change')
plt.plot(together['Date'], together['10_YR_pct_change'].rolling(window=25, min_periods=1).mean()*10, color='green', label='10_YR_pct_change')


plt.axhline(0, color='gray', linewidth=3, linestyle='-.' )
plt.legend()
plt.grid()
plt.show()
In [54]:
cut_off_date = '2015-01-02'

together_tmp = together.copy()
 
together_tmp = together_tmp[together_tmp['Date'] >= cut_off_date] 
In [55]:
fig, ax = plt.subplots(figsize=(16, 8))
plt.plot(together_tmp['Date'], together_tmp['PMI_pct_change'].rolling(window=1, min_periods=1).mean(), color='blue', label='PMI_pct_change')
plt.title('DOW_pct_change, DJTA_pct_change')
plt.plot(together_tmp['Date'], together_tmp['10_YR_pct_change'].rolling(window=30, min_periods=1).mean()*10, color='green', label='10_YR_pct_change')


plt.axhline(0, color='gray', linewidth=3, linestyle='-.' )
plt.legend()
plt.grid()
plt.show()

Show Notes

(pardon typos and formatting -
these are the notes I use to make the videos)

A PMI Proxy Any Time, Any Day! If this is true, this could come in handy when you need a quick estimate mid-month. Let's roll up our sleeves and find out.