In [12]:
import matplotlib.pyplot as plt
from __future__ import print_function
import statsmodels.api as sm
import numpy as np
import pandas as pd
import pandas.io.data as web
import datetime as dt
from math import log
%matplotlib inline
start = dt.datetime(1980, 10, 1) # start date
end = dt.datetime(2016, 3, 1) # end date
codes = ['MTSDS133FMS'] # Federal Deficit/Surplus
fred = web.DataReader(codes, 'fred', start, end)
fred.plot()
url = "http://ichart.finance.yahoo.com/table.csv?s=^GSPC&d=5&e=1&f=2016&g=m&a=9&b=1&c=1980&ignore=.csv" #S&P500
data = pd.read_csv(url)
dataframe = data.set_index('Date')
dataframe = dataframe.iloc[::-1]
dataframe[[5]].plot()
Out[12]:
I’m going to adjust labels on both graphs and also the time axis on the S&P graph:
In [15]:
DATES = [dt.datetime.strptime(date, '%Y-%m-%d').date() for date in dataframe.index]
fred.plot()
plt.legend( ('Federal Surplus or Deficit',), loc=0 ,shadow=True)
plt.axhline(0, color='black')
plt.show()
fig, ax = plt.subplots()
plt.plot(DATES, dataframe[[5]], label='S&P500')
legend = ax.legend(loc='upper center', shadow=True)
plt.grid()
plt.show()
In [16]:
#Here I'm adding the deficit column, lagged by 2 months.
df2 = pd.concat([fred,fred[:2]])
df2 = df2[[0]].shift(+2)
df2 = df2.set_index(dataframe.index)
dataframe['Def'] = df2['MTSDS133FMS']
dataframe = dataframe.fillna(value=0)
dataframe.tail()
Out[16]:
In [17]:
darr = np.array(dataframe['Def'])
dmean = pd.rolling_mean(darr, 24, min_periods=0) #rolling mean of deficit
myInt = 10000 #dividing deficit/surplus for 10,000
REDDE = [x / myInt for x in dmean]
fig, ax = plt.subplots()
plt.plot(DATES, REDDE, label='Deficit/Surplus factor')
plt.axhline(0, color='black')
legend = ax.legend(loc='lower center', shadow=True)
plt.show()
arr = np.array(dataframe['Adj Close']) #rolling mean of standard deviation of S&P500 to compute the Z-Score
std_err = pd.rolling_std(arr, 24, min_periods=1)
rmean = pd.rolling_mean(arr, 24, min_periods=1) #rolling mean of S&P500 to compute Z-Score
ZSP = (-(dataframe['Adj Close']-rmean))/std_err #computing the Z-score for S&P
fig, ax = plt.subplots()
plt.plot(DATES, ZSP, label='S&P factor (Z-Score)')
plt.axhline(0, color='black')
legend = ax.legend(loc='upper center', shadow=True)
plt.show()
FCItest = (ZSP+REDDE)/2 #computing my Financial Conditions Indicator, dividing by 2 to get the average
fig, ax = plt.subplots()
plt.plot(DATES, FCItest, label='FCI test INDICATOR')
plt.axhline(0, color='black')
legend = ax.legend(loc='lower center', shadow=True)
plt.show()
fig, ax= plt.subplots(figsize=(18,10)) #plotting S&P and FCI together
plt.plot(DATES, dataframe['Adj Close'], label='S&P')
plt.plot(DATES, FCItest*500, label='FCI test indicator')
legend = ax.legend(loc='lower center', shadow=True)
plt.grid()
plt.axhline(0, color='black')
plt.show()
The FCI I created gives very interesting insights about the stock market. We see the FCI values becoming positive during recessions and negative when the economy is doing well. Therefore it tells us when a recession is approaching and when it’s over. Someone might notice that my FCI doesn’t revert during the Early 1990s Recession, which lasted 8 months just like Early 2000 recession following the .com bubble. However, just like in 1987, the indicator gets very close to the 0 x-axis so we know the market is in a correction area. This confirms that the smaller the deficit, the higher the probability of a bear market and/or a recession. When there is a surplus, the consequences are pretty clear. The huge surplus in the early 2000’s was actually the main reason why a great economy ended.
In [18]:
SP = dataframe['Adj Close'].tolist()
r = 0.629 #I assign the value of 0.66 (2/3) to my deficit indicator
PREDDE = [x * r for x in REDDE]
fig, ax = plt.subplots()
plt.plot(DATES, PREDDE, label='Deficit/Surplus factor')
plt.axhline(0, color='black')
legend = ax.legend(loc='lower center', shadow=True)
plt.show()
FCI = (ZSP+PREDDE)/2 #computing my final Financial Conditions Indicator, dividing by 2 to get the average
fig, ax = plt.subplots()
plt.plot(DATES, FCI, label='FCI INDICATOR')
plt.axhline(0, color='black')
legend = ax.legend(loc='lower center', shadow=True)
plt.show()
In [19]:
STRAT = [1,1,1,1]
for i in range(4, len(FCI)):
x = STRAT[i-1]
if i>4: #starting from month 5 just so we can start in January 1981
if (FCI[i-2] < 0) and (FCI[i-1] < 0) :
if (SP[i]) > (SP[i-1]):
j = x*((SP[i])/(SP[i-1]))
STRAT.append(j)
else:
j = x*((SP[i])/(SP[i-1]))
STRAT.append(j)
elif (FCI[i-2] < 0) and (FCI[i-1] > 0) :
if (SP[i]) > (SP[i-1]):
j = x*(1-((SP[i])/(SP[i-1])-1))
STRAT.append(j)
else:
j = x*(1-((SP[i])/(SP[i-1])-1))
STRAT.append(j)
elif (FCI[i-2] > 0) and (FCI[i-1] < 0) :
if (SP[i]) > (SP[i-1]):
j = x*((SP[i])/(SP[i-1]))
STRAT.append(j)
else:
j = x*((SP[i])/(SP[i-1]))
STRAT.append(j)
else:
if (SP[i]) > (SP[i-1]):
j = x*(1-((SP[i])/(SP[i-1])-1))
STRAT.append(j)
else:
j = x*(1-((SP[i])/(SP[i-1])-1))
STRAT.append(j)
else:
if (SP[i]) > (SP[i-1]):
j = x*((SP[i])/(SP[i-1]))
STRAT.append(j)
else:
j = x*((SP[i])/(SP[i-1]))
STRAT.append(j)
cumret = [1,1,1,1]
for i in range(4,len(SP)):
x = SP[3]
y = SP[0+i]
ret = y/x
cumret.append(ret)
pass
r = 5
FCIX5 = [x * r for x in FCI] #times 5 just to to make the graph clear, what is important is the sign (positive or negative)
fig, ax= plt.subplots(figsize=(18,10))
plt.grid()
plt.plot(DATES, FCIX5, label='FCI INDICATOR')
plt.plot(DATES, STRAT, label='Model (cumulative return)')
plt.plot(DATES, cumret, label='S&P (cumulative return)')
legend = ax.legend(loc='upper center', shadow=True)
plt.axhline(0, color='black')
plt.show()
logSP = [log(y,10) for y in cumret]
logSTRAT = [log(y,10) for y in STRAT]
fig, ax= plt.subplots(figsize=(18,10))
plt.plot(DATES, logSP, label='Log S&P (cumulative return)')
plt.plot(DATES, logSTRAT, label='Log Model (cumulative return)')
legend = ax.legend(loc='upper center', shadow=True)
plt.grid()
plt.axhline(0, color='black')
plt.show()
In [20]:
RETSP=[0,0,0,0]
RETFCI=[0,0,0,0]
DIFF=[]
for i in range(4,len(FCI)):
y = cumret[i]/cumret[i-1]-1
RETSP.append(y)
for i in range(4,len(FCI)):
t = STRAT[i]/STRAT[i-1]-1
RETFCI.append(t)
fig, ax= plt.subplots(figsize=(18,7))
plt.axhline(0, color='black')
plt.plot(DATES, RETSP, label='S&P return')
plt.plot(DATES, RETFCI, label='FCI return')
legend = ax.legend(loc='upper center', shadow=True)
plt.show()
for i in range(0, len(FCI)):
h = RETFCI[i]-RETSP[i]
DIFF.append(h)
fig, ax= plt.subplots(figsize=(18,7))
plt.plot(DATES, DIFF, label='(FCI-S&P return)')
legend = ax.legend(loc='upper center', shadow=True)
plt.show()
C=[] #this is ugly but I like to keep lists ready, just in case..
S=[]
D=[]
T=[]
MEANSP=[]
MEANFCI=[]
STDEVSP=[]
STDEVFCI=[]
SHARPESP=[]
SHARPEFCI=[]
for i in range(0, len(FCI)): #computing mean and st.dev. from first observation to get the Sharpe Ratio for the S&P500
C.append(RETSP[i])
d = np.average(C)
MEANSP.append(d)
for i in range(0, len(FCI)):
S.append(RETSP[i])
e = np.std(S)
STDEVSP.append(e)
for i in range(0,len(FCI)):
f = MEANSP[i]*12/(STDEVSP[i]*np.sqrt(12))
SHARPESP.append(f)
pass
for i in range(0, len(FCI)): #computing mean and st.dev. from first observation to get the Sharpe Ratio for my model
D.append(RETFCI[i])
d = np.average(D)
MEANFCI.append(d)
for i in range(0, len(FCI)):
T.append(RETFCI[i])
g = np.std(T)
STDEVFCI.append(g)
for i in range(0,len(FCI)):
f = MEANFCI[i]*12/(STDEVFCI[i]*np.sqrt(12))
SHARPEFCI.append(f)
fig, ax= plt.subplots(figsize=(18,7))
plt.axhline(0, color='black')
plt.axhline(1, color='red')
plt.axhline(0.5, color='red')
plt.plot(DATES, SHARPESP, label='S&P Sharpe Ratio (0 risk-free rate)')
plt.plot(DATES, SHARPEFCI, label='FCI Sharpe Ratio (0 risk-free rate)')
legend = ax.legend(loc='upper center', shadow=True)
plt.show() #plotting both cumulative Sharpe Ratios (since 1981)
fig, ax= plt.subplots(figsize=(18,10))
plt.plot(DATES, PREDDE, label='Deficit/Surplus factor')
plt.plot(DATES, FCIX5, label='FCI INDICATOR')
plt.plot(DATES, cumret, label='S&P (cumulative return)')
plt.axhline(0, color='black')
plt.axhline(-5, color='red')
legend = ax.legend(loc='upper center', shadow=True)
plt.grid()
plt.show() #plotting Deficit/Surplus and cumulative return for S&P
In [21]:
#some more statistics
covariance = np.cov(RETSP,RETFCI)[0][1]
variance = np.var(RETSP)
beta = covariance / variance
print("Beta is %.2f" %beta) #Beta
annret = 12*MEANFCI[-1]*100
annstdev = np.sqrt(12)*STDEVFCI[-1]*100
rf = 4
sr = (annret-rf)/annstdev #Sharpe Ratio FCI
print("The average Annual Return of my strategy is %.2f%%" %annret)
print("The average Standard Deviation of my strategy is %.2f%%" %annstdev)
print("Therefore, with a risk-free rate of 4%%, the Sharpe Ratio is %.2f" %sr)
annretsp = 12*MEANSP[-1]*100
annstdevsp = np.sqrt(12)*STDEVSP[-1]*100
rf = 4
srsp = (annretsp-rf)/annstdevsp #Sharpe Ratio S&P500
print("The average Annual Return of the S&P 500 is %.2f%%" %annretsp)
print("The average Standard Deviation of the S&P 500 is %.2f%%" %annstdevsp)
print("Therefore, with a risk-free rate of 4%%, the Sharpe Ratio of the S&P 500 is %.2f" %srsp)
In [22]:
import seaborn as sns
rettt = np.array(RETSP)
fccc = np.array(RETFCI)
VIO=pd.DataFrame(rettt)
VIO["fccc"] = fccc
VIO.columns = ['S&P', 'FCI']
VIO.index=dataframe.index
sns.violinplot(data=VIO) #over 35 years
Out[22]:
In [23]:
VIOO = VIO.iloc[316:340,0:2] #during the 2008 recession
sns.violinplot(data=VIOO)
Out[23]:
In [259]:
dta=pd.Series(logSP) #use "arr" instead of "logSP" for the S&P data (before taking logs)
dta.index = pd.DatetimeIndex(start='1980-10-01', end='2016-05-01', freq='MS')
res = sm.tsa.ARIMA(dta, (1, 1, 1)).fit() #ARIMA(1,1,1) in this case
fig, ax = plt.subplots(figsize=(20,10))
ax = dta.ix['2007-01-01':].plot(ax=ax)
fig = res.plot_predict(399, 435, dynamic=False, ax=ax, plot_insample=False) #plotting forecast from Jan 2014
plt.show()