<jupyter_start><jupyter_text>Stock market returns as a leading indicator of a countrys GDP growth Stock market returns are known to be a leading indicator of a countries BNP. In this project, I want to test this claim. I pull data on the GDP growth rate from the World Bank database and data on the stock market prices from Yahoo Finance. I do that for four different countries, Germany, Japan, France, and Belgium in the period from 1992 to 2021. Then I make a simple linear regression on $$ {GDP}_t = \beta_0 + \beta_1 stock\:return_{t-1} + \epsilon_t $$and test the $H_0$ of $\beta_1$ being significantly different from zero. Furthermore, I test the opposite claim of stock market return being a lagging indicator, by estimating $$ {stock\:return}_t = \beta_0 + \beta_1 GDP_{t-1} + \epsilon_t $$with the same $H_0$.<jupyter_code># import packages
import numpy as np
import pandas as pd
from pandas_datareader import data as pdr 
from pandas_datareader import wb
import matplotlib.pyplot as plt
import ipywidgets as widgets
from scipy import stats
import dataproject as dp

# Setting graphic style
plt.style.use('seaborn-whitegrid')

# autoreload modules when code is run
%load_ext autoreload
%autoreload 2<jupyter_output><empty_output><jupyter_text>Pulling data from APIs First, I make a dictionary with the tickercodes and country codes for the countries of interest.<jupyter_code># a. Setting initial values

# i. Creating dictionary
country_dict = {'Germany' : {'ticker':'^GDAXI', 'countrycode':'DE'},
             'Japan' : {'ticker':'^N225', 'countrycode':'JP'},
             'France': {'ticker':'^FCHI', 'countrycode':'FR'},
             'Belgium': {'ticker':'^BFX', 'countrycode':'BE'}
            }

# ii. Setting period
start_year = 1992
end_year = 2021<jupyter_output><empty_output><jupyter_text>Then I pull data from the World Bank and from Yahoo Finance.<jupyter_code># b. Pulling data

# i. Creating a list of country codes for World Bank API use.
countrycodes = []
for i in country_dict:
    countrycodes.append(country_dict[i]['countrycode'])

# ii Pulling data from World bank 
GDP_data = wb.download(indicator='NY.GDP.MKTP.KD.ZG', country=countrycodes, start=start_year, end=end_year)
GDP_data.rename(columns = {'NY.GDP.MKTP.KD.ZG':'GDP'}, inplace=True) # Setting name of the variabe to 'GDP'
GDP_data = GDP_data.reindex(index=GDP_data.index[::-1]) # Reverse order such that starting years are the first ones

# iii Pulling data from yahoo Finance and put it into a seperate dataframe.
countries = country_dict.keys()
stocks = pd.DataFrame()
start = str(start_year)+'-01-01'
end = str(end_year+1)+'-01-01' # adding one year to get data for the whole ending year

for i in countries:
    stocks[i+'_price'] = pdr.get_data_yahoo(country_dict[i]['ticker'], start, end, interval='m')['Adj Close']<jupyter_output><empty_output><jupyter_text>As the stock data are the monthly prices of each indicies, I calculate the yearly return and add it to a dataframe similar to the one containing GDP-data.<jupyter_code># c. Transforming monthly price data into yearly return data

# i. Creating an multi-column dataframe similar to GDP_data
return_data = dp.multi_column(countries, GDP_data)

# iii. Transforming the the montly price data to yearly return data and add it to return_data.
return_data['return']=0 # adding a column for returns
for i in countries:
    for j in range(0,len(GDP_data.loc[i].index.values)):
        return_data.loc[i,GDP_data.loc[i].index.values[j]]= ( (stocks[i+'_price'][(j+1)*12]/stocks[i+'_price'][j*12]) - 1)*100<jupyter_output><empty_output><jupyter_text>Explore each data set In this section, I explore each data set, by calling a simple .decribe() function, and creating a bar plot on GDP rate and stock returns respectively.<jupyter_code># a. Summary statistics on yealy GDP rate 
GDP_data.groupby('country').describe()<jupyter_output><empty_output><jupyter_text>In the table above, we see that Belgium has had the highest average GDP growth, while Japan has had the lowest average growth. The minimum for all countries comes from the year 2020 and COVID-lockdowns. Here France has the lowest minimum with an almost 8% decrease in GDP, while the other three countries experienced around 5.7% decrease.<jupyter_code># b. Summary statistics on yearly stock return data
return_data.groupby('country').describe()<jupyter_output><empty_output><jupyter_text>In the table above we see that Germany has had the highest average yearly stock market return, with almost double that of France and Belgium and triple that of Japan.<jupyter_code># c. Split, apply and combine each data set to add the mean.
GDP_mean = GDP_data.groupby('country')['GDP'].agg('mean')
GDP_mean.name = 'GDP_mean'
GDP_data = GDP_data.join(GDP_mean,on = 'country', how='left')

return_mean = return_data.groupby('country')['return'].agg('mean')
return_mean.name = 'return_mean'
return_data = return_data.join(return_mean,on = 'country', how='left')
# d. create a function for making an interactive dropdown plot
def interactive_dropdown_plot(data, by):
    
    def plot_e(df, country): 

        fig = plt.figure(dpi = 130) # create the figure
        ax = fig.add_subplot(1,1,1)

        ax.bar(data.loc[country].index.values,data.loc[country][by], label= by + ' rate')
        ax.plot(data.loc[country].index.values,data.loc[country][by+'_mean'], color = 'orange', label = 'Average '+by+' rate' )
        ax.tick_params(labelrotation=90)
        ax.set_title(by.upper())
        ax.set_ylabel('Percentage')
        ax.legend()
        plt.show()


    widgets.interact(plot_e, 
        df = widgets.fixed(data),
        country = widgets.Dropdown(description='country',
                                  options = countries,
                                  value = 'Germany')
                    )

# e. Visualize the data from each data set. 
interactive_dropdown_plot(GDP_data, 'GDP')
interactive_dropdown_plot(return_data, 'return')<jupyter_output><empty_output><jupyter_text>Creating the final dataframe for analysis Finally, I merge the two data set and add lagged variables<jupyter_code># a. merging GDP-data and return_data
final_df = pd.merge(GDP_data, return_data, on=['country','year'])

# b. add lagged values of GDP and return
dp.lagging_obs(final_df,'GDP',1)
dp.lagging_obs(final_df,'return',1)

final_df<jupyter_output><empty_output><jupyter_text>Analysis We can now do a regression on the lagged value of $return$ on $GDP$ (and on the lagged value of $GDP$ on $return$), to test the claim of stock market returns being an leading (lagging) indicator of GDP growth. First, I present scatter plots for at visual inspection. The regressand, Y, and the regressor, X, can be changed in the dropdown menu of the plots. Beneath is the results from the linear regression presented, where the p-value determines whether we reject the $H_0$ of no correlation.<jupyter_code># a. Making a function for the scatter plots
def scatter_plot(df,x,y):
    fig = plt.figure(figsize = (10,8)) # create the figure
    for i, country in enumerate(countries):
        ax = fig.add_subplot(2,2,i+1)
        reg_data = df.loc[country][1:] # removing the first observation 
        
        X = reg_data[x]
        Y = reg_data[y]
        
        ax.scatter(X, Y, color='black')
        ax.set_xlabel(x, size = 14)
        ax.set_ylabel(y, size = 14)
        ax.set_title(country, size=16)
        
        m, b = np.polyfit(X, Y, 1) # obtain m (slope) and b(intercept) of linear regression line
        ax.plot(X, m*X+b, color='red')
        
        fig.tight_layout()

widgets.interact(scatter_plot, 
        df = widgets.fixed(final_df),
        x = widgets.Dropdown(description='X',
                                  options = ['return-1','GDP-1'],
                                  value = 'return-1'),
        y = widgets.Dropdown(description='Y',
                                  options = ['GDP','return'],
                                  value = 'GDP')
                    )
# b. Regressions 
# i. Regression of return-1 on GDP
dp.regress(final_df,countries,'return-1','GDP')
# ii. Regression of GDP-1 on return
dp.regress(final_df,countries,'GDP-1','return')<jupyter_output>Germany: Beta1 is -3.865, with a p value of 0.103 and a r-squared value of 0.099.
Japan: Beta1 is -2.475, with a p value of 0.305 and a r-squared value of 0.040.
France: Beta1 is -0.682, with a p value of 0.820 and a r-squared value of 0.002.
Belgium: Beta1 is -1.416, with a p value of 0.640 and a r-squared value of 0.009.
{'fraction_non_alphanumeric': 0.10726033834586467, 'fraction_numerical': 0.01656484962406015, 'mean_word_length': 3.798759864712514, 'pattern_counts': {'":': 0, '<': 36, '<?xml version=': 0, '>': 36, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 7, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '9', 'dir': 'jupyter-structured-clean-dedup', 'id': '228106', 'license': 'MIT', 'n_tokens_mistral': 2826, 'n_tokens_neox': 2629, 'n_words': 907, 'path': 'dataproject/dataproject.ipynb', 'repo_name': 'NumEconCopenhagen/projects-2022-ludvigsen', 'size': '8512'}