<jupyter_start><jupyter_text>0. ETF SelectionWe select the SPDR Gold Shares (GLD) ETF as the gold ETF. It is traded on Nasdaq, the currency is USD.Similarly, we choose the Amundi CAC 40 UCITS ETF-C (C40.PA) as the equity ETF. It will track the CAC 40 index of France. It is traded on Paris Euronext, the currency is EUR.Data source: https://finance.yahoo.com/  1. Data Importing<jupyter_code>import arch
import holidays
import pandas as pd
import numpy as np
from pandas import Series, DataFrame
import matplotlib.pyplot as plt
import seaborn as sns

from statsmodels.tsa.arima.model import ARIMA
from scipy import stats
from datetime import datetime
from nelson_siegel_svensson import NelsonSiegelSvenssonCurve, NelsonSiegelCurve
from nelson_siegel_svensson.calibrate import calibrate_ns_ols, calibrate_nss_ols

%matplotlib inline
gold_df = pd.read_csv("data/SPDR_Gold_Shares_USD.csv")
equity_df = pd.read_csv("data/C40.PA.csv")
treasury_Yield_df = pd.read_csv('data/Treasury_Yield.csv')<jupyter_output><empty_output><jupyter_text>Convert the data into the datetime format and make it the index to query the dataframe easier.<jupyter_code>gold_df["Date"] = pd.to_datetime(gold_df["Date"], format="%Y-%m-%d")
gold_df.set_index("Date", inplace=True)
equity_df["Date"] = pd.to_datetime(equity_df["Date"], format="%Y-%m-%d")
equity_df.set_index("Date", inplace=True)<jupyter_output><empty_output><jupyter_text>Verify that the time range is correct.<jupyter_code>treasury_Yield_df.head()
treasury_Yield_df.tail()
gold_df.head()
gold_df.tail()
equity_df.head()
equity_df.tail()<jupyter_output><empty_output><jupyter_text>One notable difference between gold and equity prices is that we have prices for gold ETF every day of a week while we don't have prices for equity ETF for weekends (Saturday and Sunday). In order to make the analysis comparable, we will drop the prices of gold ETF on Saturday and Sunday before making further preprocessing and analysis. Another difference is that November 28, 2019 is a Bank Holiday in the US market and we don't have the data that day for the gold ETF. In order to calculate the Pearson correlation, we will also drop the data of that day for the equity market to have two time series with the same length.<jupyter_code>gold_df = gold_df[gold_df.index.dayofweek < 5]
gold_df.shape
equity_df = equity_df[equity_df.index != "2019-11-28"]
equity_df.shape<jupyter_output><empty_output><jupyter_text>2. Data Processing We use adjusted close prices to calculate the daily returns. Adjusted close prices are the prices that already take into account stock split and dividends, which reflex more accurate the change of the prices.<jupyter_code>gold_df["Daily Return"] = gold_df["Adj Close"].pct_change(1)
gold_df.head()
equity_df["Daily Return"] = equity_df["Adj Close"].pct_change(1)
equity_df.head()<jupyter_output><empty_output><jupyter_text>3. Data Summaries The value at 2019-10-31 is the statistic for the whole October, likewise, the value at 2019-11-30 is the statistic for November. The daily high minus low and the required statistics of part 7 will also be presented here.<jupyter_code># 3.1
df_Oct = treasury_Yield_df[treasury_Yield_df['Date'].str.contains("Oct")]
average_yield_Oct = np.mean(df_Oct)
print("Average October Yield is \n{}\n".format(average_yield_Oct))

df_Nov = treasury_Yield_df[treasury_Yield_df['Date'].str.contains("Nov")]
average_yield_Nov = np.mean(df_Nov)
print("Average November Yield is \n{}".format(average_yield_Nov))
st_dev_Oct = np.std(df_Oct)
st_dev_NoV = np.std(df_Nov)
print("Standard Deviation for October Yield is \n{}\n".format(st_dev_Oct))
print("Standard Deviation for November Yield is \n{}".format(st_dev_NoV))
gold_df["High minus low"] = gold_df["High"] - gold_df["Low"]
equity_df["High minus low"] = equity_df["High"] - equity_df["Low"]
gold_df.resample('M').mean()
equity_df.resample('M').mean()
gold_df.resample('M').std()
equity_df.resample('M').std()<jupyter_output><empty_output><jupyter_text>4. Graphing<jupyter_code>treasury_Yield_df.set_index('Date').plot(figsize=(10,5), grid=True)
plt.figure(figsize=(12,5))
plt.title('The prices of gold ETF (in USD) and equity ETF (in EUR) in October and November 2019')

ax1 = gold_df["Adj Close"].plot(color='blue', grid=True, label='gold ETF')
ax2 = equity_df["Adj Close"].plot(color='red', grid=True, secondary_y=True, label='equity ETF')

h1, l1 = ax1.get_legend_handles_labels()
h2, l2 = ax2.get_legend_handles_labels()

plt.legend(h1+h2, l1+l2, loc=2)
plt.show()<jupyter_output><empty_output><jupyter_text>5. Fitting the yield curve<jupyter_code>t =np.array([2.0,3.0,5.0,7.0,10.0,30.0])
#avarage yield rate for October 
y = np.array([1.551385,1.527154,1.525115,1.614000,1.701423,2.187269])

curve_fit, status = calibrate_nss_ols(t,y)
NSS_ZC = NelsonSiegelSvenssonCurve.zero(curve_fit,t)
NSS_ZC

Oct_curve, status = calibrate_nss_ols(t,NSS_ZC)
assert status.success
print(Oct_curve)

t = np.linspace(0,20,100)
plt.plot(t,Oct_curve(t))
plt.show()

#avarage yield rate for November 
t =np.array([2.0,3.0,5.0,7.0,10.0,30.0])
y = np.array([1.616750,1.618042,1.641167,1.736833,1.811625,2.276708])

curve_fit, status = calibrate_nss_ols(t,y)
NSS_ZC = NelsonSiegelSvenssonCurve.zero(curve_fit,t)
NSS_ZC

Nov_curve, status = calibrate_nss_ols(t,NSS_ZC)
assert status.success
print(Nov_curve)

t = np.linspace(0,20,100)
plt.plot(t,Nov_curve(t))
plt.show()<jupyter_output>NelsonSiegelSvenssonCurve(beta0=2.6460791130382035, beta1=-0.7093417256161145, beta2=-1.3222551460581986, beta3=-2.0635765939331834, tau1=1.623812678632114, tau2=5.1802674914969495)<jupyter_text>6. Modelling Prices<jupyter_code>def get_data(df, month, column):
    return df[(df.index >= f"2019-{month:02d}-01") & (df.index < f"2019-{(month+1):02d}-01")][column]<jupyter_output><empty_output><jupyter_text>ARMA model is a specific case of ARIMA model with i = 0, that allows us to use the ARIMA model here.<jupyter_code>def fit_arima(data):
    model = ARIMA(data, order=(3,0,3))
    model_fit = model.fit()
    print(model_fit.summary())
    residuals = pd.DataFrame(model_fit.resid)
    ax1 = residuals.plot(label='residual')
    plt.title("Residuals during the month")
    ax1.get_legend().remove()
    plt.show()
    ax2 = residuals.plot(kind='kde')
    plt.title("Kernel density estimation of the residuals")
    ax2.get_legend().remove()
    plt.show()
df_name = {0: "gold ETF", 1: "equity ETF"}
month_name = {10: "October", 11: "November"}
for index, df in enumerate([gold_df, equity_df]):
    for month in [10, 11]:
        print("-" * 78)
        print("-" * 78)
        print("-" * 78)
        print(f"ARMA model for {df_name[index]} in {month_name[month]}")
        data = get_data(df, month, "Adj Close")
        fit_arima(data)<jupyter_output>------------------------------------------------------------------------------
------------------------------------------------------------------------------
------------------------------------------------------------------------------
ARMA model for gold ETF in October<jupyter_text>7. Modelling Volatility The high minus low for the ETF's prices and their average, as well as the standard deviation of returns are presented in part 3<jupyter_code>def fit_garch(data):
    garch = arch.arch_model(data, vol='garch', p=1, o=0, q=1)
    garch_fitted = garch.fit()
    print(garch_fitted.summary())
for index, df in enumerate([gold_df, equity_df]):
    for month in [10, 11]:
        print("-" * 78)
        print("-" * 78)
        print("-" * 78)
        print(f"GARCH model for {df_name[index]} in {month_name[month]}")
        data = get_data(df, month, "Daily Return")
        data = data.dropna()
        fit_garch(data)<jupyter_output>------------------------------------------------------------------------------
------------------------------------------------------------------------------
------------------------------------------------------------------------------
GARCH model for gold ETF in October
Iteration:      1,   Func. Count:      6,   Neg. LLF: 2211987.449503363
Iteration:      2,   Func. Count:     16,   Neg. LLF: -81.257589920448
Optimization terminated successfully    (Exit mode 0)
            Current function value: -81.25758995275967
            Iterations: 6
            Function evaluations: 16
            Gradient evaluations: 2
                     Constant Mean - GARCH Model Results                      
==============================================================================
Dep. Variable:           Daily Return   R-squared:                      -0.000
Mean Model:             Constant Mean   Adj. R-squared:                 -0.000
Vol Model:                      GARCH   Log-Likelihood:     [...]<jupyter_text>8. Correlation<jupyter_code>corr_oct = stats.pearsonr(gold_df[("2019-10-01" < gold_df.index) & (gold_df.index < "2019-11-01")]["Daily Return"], equity_df[("2019-10-01" < equity_df.index) & (equity_df.index < "2019-11-01")]["Daily Return"])[0]
print(f"The correlation of gold and equity ETFs in October is {corr_oct}")
corr_nov = stats.pearsonr(gold_df[gold_df.index >= "2019-11-01"]["Daily Return"], equity_df[equity_df.index >= "2019-11-01"]["Daily Return"])[0]
print(f"The correlation of gold and equity ETFs in November is {corr_nov}")<jupyter_output>The correlation of gold and equity ETFs in November is -0.4119305823448921
{'fraction_non_alphanumeric': 0.17585948377423155, 'fraction_numerical': 0.05280068544500375, 'mean_word_length': 3.730496453900709, 'pattern_counts': {'":': 0, '<': 51, '<?xml version=': 0, '>': 48, 'https://': 1, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '12', 'dir': 'jupyter-structured-clean-dedup', 'id': '142711', 'license': 'MIT', 'n_tokens_mistral': 3530, 'n_tokens_neox': 3149, 'n_words': 794, 'path': 'Econometrics - Submission 1.ipynb', 'repo_name': 'tqa236/econometrics-WQU', 'size': '9337'}