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!


Sign up for my newsletter and get my free intro class:

Peer 6-9 Months Into the Future with the CLI - a World Economic Health Leading Indicator

Introduction

Let's look at an incredible indicator called the CLI, Composite Leading Indicators (but I am dubbing it the World Economic Economic Leading Health Index). It purportedly can foretell turns in the economy 6-9 months in advance according to the OECD's brochure. It is made up of business confidence surveys, manufacturing orders, and inventories levels, share prices, trading trends, etc.



If you liked it, please share it:

Code

ViralML - Composite Leading Indicators Series
In [9]:
from IPython.display import Image
Image(filename='cli-thumbnail.png', width='80%')
Out[9]:

World Economic Health Indicator:

OECD: Composite Leading Indicators (CLI)

https://www.economy.com/dismal/indicators/definition/oecd_cli

Established in 1961, the Organisation for Economic Co-operation and Development (OECD) is composed of 30 member nations. The OECD acts as a forum to coordinate economic policies and promote growth and stability. The OECD Composite Leading Indicators are selected from a wide range of key short-term economic indicators (170 in total, or between 5 and 10 for each country), which reflect different sectors of the economy, and provide a gauge of future economic activity.

https://data.oecd.org/leadind/composite-leading-indicator-cli.htm

S&P 500 (^GSPC)

https://finance.yahoo.com/quote/%5EGSPC

Direct pull:

https://stats.oecd.org/sdmx-json/data/DP_LIVE/OECD.CLI.../OECD?contentType=csv&detail=code&separator=comma&csv-lang=en

And just for fun, try pulling somthing from Google Trends

In [61]:
%matplotlib inline
import matplotlib
import matplotlib.pyplot as plt
import io, base64, os, json, re, math
import pandas as pd
import numpy as np
import datetime
import warnings
warnings.filterwarnings('ignore')
In [77]:
## Building a good world representation of the CLI
cli_df = pd.read_csv('DP_LIVE_19012020143246784.csv')
set(cli_df['LOCATION'])
Out[77]:
{'CHN', 'OECD', 'RUS'}
In [78]:
cli_df.head()
Out[78]:
LOCATION INDICATOR SUBJECT MEASURE FREQUENCY TIME Value Flag Codes
0 CHN CLI AMPLITUD LTRENDIDX M 1990-01 96.02216 NaN
1 CHN CLI AMPLITUD LTRENDIDX M 1990-02 95.74557 NaN
2 CHN CLI AMPLITUD LTRENDIDX M 1990-03 95.52505 NaN
3 CHN CLI AMPLITUD LTRENDIDX M 1990-04 95.35284 NaN
4 CHN CLI AMPLITUD LTRENDIDX M 1990-05 95.21412 NaN
In [79]:
import calendar
full_date_list = []
for tm in cli_df['TIME']:
    year = int(tm.split('-')[0])
    month = int(tm.split('-')[1])
    full_date_list.append(tm + '-' + str(calendar.monthrange(year, month)[1]))

cli_df['Date'] = full_date_list
cli_df['Date'] = pd.to_datetime(cli_df['Date'])
cli_df = cli_df[['Date', 'LOCATION', 'Value']]
cli_df = cli_df.sort_values('Date', ascending=True)
print(min(cli_df['Date']), max(cli_df['Date']))
cli_df.tail()
1961-06-30 00:00:00 2019-11-30 00:00:00
Out[79]:
Date LOCATION Value
357 2019-10-31 CHN 99.18159
1386 2019-10-31 RUS 99.69604
358 2019-11-30 CHN 99.30731
1060 2019-11-30 OECD 99.25119
1387 2019-11-30 RUS 99.75460
In [80]:
# min date for each location
for ct in set(cli_df['LOCATION']):
    print(ct)
    cli_tmp = cli_df[cli_df['LOCATION']==ct]
    print(np.min(cli_tmp['Date']))
CHN
1990-01-31 00:00:00
OECD
1961-06-30 00:00:00
RUS
1992-09-30 00:00:00
In [67]:
cli_df = cli_df[cli_df['Date'] >= '1992-09-30']
cli_df = cli_df[['Date', 'Value']]
cli_df = cli_df.groupby('Date').mean().reset_index()
In [68]:
cli_df.head()
Out[68]:
Date Value
0 1992-09-30 101.600053
1 1992-10-31 101.555863
2 1992-11-30 101.503577
3 1992-12-31 101.448503
4 1993-01-31 101.392197

Load S&P 500 Index for Comparison and Data Exploration

In [69]:
# load the S&P 500
sp500_raw = pd.read_csv('^GSPC.csv')
sp500_raw.tail()
Out[69]:
Date Open High Low Close Adj Close Volume
23111 2020-01-06 3217.550049 3246.840088 3214.639893 3246.280029 3246.280029 3674070000
23112 2020-01-07 3241.860107 3244.909912 3232.429932 3237.179932 3237.179932 3420380000
23113 2020-01-08 3238.590088 3267.070068 3236.669922 3253.050049 3253.050049 3720890000
23114 2020-01-09 3266.030029 3275.580078 3263.669922 3274.699951 3274.699951 3638390000
23115 2020-01-10 3281.810059 3282.989990 3260.860107 3265.350098 3265.350098 1631680402
In [70]:
sp500_raw = sp500_raw[['Date','Adj Close']]
sp500_raw['Date'] = pd.to_datetime(sp500_raw['Date'])
sp500_raw = sp500_raw.sort_values('Date', ascending=True) 
print(min(sp500_raw['Date']), max(sp500_raw['Date']))
sp500_raw.head()
1927-12-30 00:00:00 2020-01-10 00:00:00
Out[70]:
Date Adj Close
0 1927-12-30 17.660000
1 1928-01-03 17.760000
2 1928-01-04 17.719999
3 1928-01-05 17.549999
4 1928-01-06 17.660000

Plot both together

In [71]:
sp500_tmp = sp500_raw.copy()
sp500_tmp = sp500_tmp[sp500_tmp['Date'] >= '1992-09-30']

fig, ax = plt.subplots(figsize=(16, 10))
plt.plot(sp500_tmp['Date'], sp500_tmp['Adj Close'], label='SP500', 
         color='green')
plt.legend(loc='lower left')
second_axis = ax.twinx()
plt.plot(cli_df['Date'], cli_df['Value'], label='CLI', 
         color='blue')
second_axis.axhline(y=100, color='gray')
plt.title('CLI-World vs SP&500')
plt.legend(loc='upper left')
plt.grid()
In [72]:
google_trends = pd.read_csv('google-trends-refi-rates.csv', skiprows=1)
google_trends.head()
Out[72]:
Month refinance: (Worldwide) interest rates: (Worldwide)
0 2004-01 29 72
1 2004-02 29 78
2 2004-03 35 86
3 2004-04 25 100
4 2004-05 21 90
In [73]:
import calendar
full_date_list = []
for tm in google_trends['Month']:
    year = int(tm.split('-')[0])
    month = int(tm.split('-')[1])
    full_date_list.append(tm + '-' + str(calendar.monthrange(year, month)[1]))

google_trends['Date'] = full_date_list
google_trends['Date'] = pd.to_datetime(google_trends['Date'])
google_trends = google_trends[['Date', 'refinance: (Worldwide)', 'interest rates: (Worldwide)']]
print(min(google_trends['Date']), max(google_trends['Date']))
google_trends.tail()
2004-01-31 00:00:00 2020-01-31 00:00:00
Out[73]:
Date refinance: (Worldwide) interest rates: (Worldwide)
188 2019-09-30 35 67
189 2019-10-31 31 61
190 2019-11-30 28 54
191 2019-12-31 27 48
192 2020-01-31 34 56
In [74]:
cli_tmp = cli_df.copy()
cli_tmp = cli_tmp[cli_tmp['Date'] >= '2004-01-31']

fig, ax = plt.subplots(figsize=(16, 10))
plt.plot(google_trends['Date'], 
         google_trends['refinance: (Worldwide)'],
         label='Refinance', 
         color='blue')

plt.legend(loc='lower left')
second_axis = ax.twinx()
plt.plot(google_trends['Date'], 
         google_trends['interest rates: (Worldwide)'], 
         label='Interest Rates', 
         color='green')

plt.legend(loc='upper left')

third_axis = ax.twinx()
plt.plot(cli_tmp['Date'], cli_tmp['Value'], label='CLI', 
         color='black')
second_axis.axhline(y=100, color='gray')
plt.title('CLI-World vs Google Trends')
plt.legend(loc='upper right')
plt.grid()

Show Notes

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

Let's look at an incredible indicator called the CLI, Composite Leading Indicators (but I am dubbing it the World Economic Economic Leading Health Index). It purportedly can foretell turns in the economy 6-9 months in advance according to the OECD's brochure. It is made up of business confidence surveys, manufacturing orders, and inventories levels, share prices, trading trends, etc.