import pandas as pd
import numpy as np
import statsmodels.formula.api as smf

# =============================================================================
# Objective: run the Fixed Design bootstrap without volatility scaling
# generate the fixed-design bootstrap t-values for four cases
# i.    predictive regression with lagged volatiliaty scaled excess return
# ii.   predictive regression with lagged volatiliaty scaled excess return's sign
# iii.  predictive regression with cumulative volatiliaty scaled excess return
# iv.   predictive regression with cumulative volatiliaty scaled excess return' sign
# =============================================================================

# =============================================================================
# create the lagged volatiliaty scaled excess returns,  
# cumulative volatiliaty scaled excess returns,
# and their signs
# =============================================================================

ret=pd.read_excel('#Asset_Return.xlsx','Sheet1')
ret=ret[ret['YM']>=198501]# make sure all returns are after 198501

ret['RF']=ret['Rf']+1#capital RF is the gross risk free rate
ret['Return']=ret['ExRet']+ret['RF']

ret_summary=pd.DataFrame()
for i in range(1,56):
    ret_sub=ret[ret['ID']==i]    
    #get the lag excess return
    ret_sub['ExRet_l0']=ret_sub['ExRet'].shift(0)
    ret_sub['ExRet_l1']=ret_sub['ExRet'].shift(1)
    ret_sub['ExRet_l2']=ret_sub['ExRet'].shift(2)
    ret_sub['ExRet_l3']=ret_sub['ExRet'].shift(3)
    ret_sub['ExRet_l4']=ret_sub['ExRet'].shift(4)
    ret_sub['ExRet_l5']=ret_sub['ExRet'].shift(5)
    ret_sub['ExRet_l6']=ret_sub['ExRet'].shift(6)
    ret_sub['ExRet_l7']=ret_sub['ExRet'].shift(7)
    ret_sub['ExRet_l8']=ret_sub['ExRet'].shift(8)
    ret_sub['ExRet_l9']=ret_sub['ExRet'].shift(9)
    ret_sub['ExRet_l10']=ret_sub['ExRet'].shift(10)
    ret_sub['ExRet_l11']=ret_sub['ExRet'].shift(11)

    ret_sub['ExRet_f1']=ret_sub['ExRet'].shift(-1)
    #get the cumulative excess return 
    ret_sub['ExRetCum1']=ret['ExRet']
    ret_sub['ExRetCum2']=(pd.rolling_apply(ret_sub['Return'],2,lambda x : x.prod())-pd.rolling_apply(ret_sub['RF'],2,lambda x : x.prod()))/2
    ret_sub['ExRetCum3']=(pd.rolling_apply(ret_sub['Return'],3,lambda x : x.prod())-pd.rolling_apply(ret_sub['RF'],3,lambda x : x.prod()))/3
    ret_sub['ExRetCum4']=(pd.rolling_apply(ret_sub['Return'],4,lambda x : x.prod())-pd.rolling_apply(ret_sub['RF'],4,lambda x : x.prod()))/4
    ret_sub['ExRetCum5']=(pd.rolling_apply(ret_sub['Return'],5,lambda x : x.prod())-pd.rolling_apply(ret_sub['RF'],5,lambda x : x.prod()))/5
    ret_sub['ExRetCum6']=(pd.rolling_apply(ret_sub['Return'],6,lambda x : x.prod())-pd.rolling_apply(ret_sub['RF'],6,lambda x : x.prod()))/6
    ret_sub['ExRetCum7']=(pd.rolling_apply(ret_sub['Return'],7,lambda x : x.prod())-pd.rolling_apply(ret_sub['RF'],7,lambda x : x.prod()))/7
    ret_sub['ExRetCum8']=(pd.rolling_apply(ret_sub['Return'],8,lambda x : x.prod())-pd.rolling_apply(ret_sub['RF'],8,lambda x : x.prod()))/8
    ret_sub['ExRetCum9']=(pd.rolling_apply(ret_sub['Return'],9,lambda x : x.prod())-pd.rolling_apply(ret_sub['RF'],9,lambda x : x.prod()))/9
    ret_sub['ExRetCum10']=(pd.rolling_apply(ret_sub['Return'],10,lambda x : x.prod())-pd.rolling_apply(ret_sub['RF'],10,lambda x : x.prod()))/10
    ret_sub['ExRetCum11']=(pd.rolling_apply(ret_sub['Return'],11,lambda x : x.prod())-pd.rolling_apply(ret_sub['RF'],11,lambda x : x.prod()))/11
    ret_sub['ExRetCum12']=(pd.rolling_apply(ret_sub['Return'],12,lambda x : x.prod())-pd.rolling_apply(ret_sub['RF'],12,lambda x : x.prod()))/12

    ret_summary=pd.concat([ret_summary,ret_sub.iloc[12:]])#drop the first 12 variables
    
for i in range(0,12):
    new_name='ExRetSign_l'+str(i)
    old_name='ExRet_l'+str(i)
    ret_summary[new_name]=np.where(ret_summary[old_name]>=0,1,np.where(ret_summary[old_name]<0,-1,np.nan))

    new_name='ExRetCumSign'+str(i+1)
    old_name='ExRetCum'+str(i+1)
    ret_summary[new_name]=np.where(ret_summary[old_name]>=0,1,np.where(ret_summary[old_name]<0,-1,np.nan))

# =============================================================================
# first demean the lhs variable and rhs variable
# =============================================================================
ret_Demean=pd.DataFrame()

for i in range(1,56):
    ret_sub=ret_summary[ret_summary['ID']==i]
    ret_sub['DemeanExRet_f1']=ret_sub['ExRet_f1']-ret_sub['ExRet'].mean()
    for j in range(0,12):
        ret_sub['DemeanExRet_l'+str(j)]=ret_sub['ExRet_l'+str(j)]-ret_sub['ExRet'].mean()
        ret_sub['DemeanExRetSign_l'+str(j)]=ret_sub['ExRetSign_l'+str(j)]-ret_sub['ExRetSign_l0'].mean()
        ret_sub['DemeanExRetCum'+str(j)]=ret_sub['ExRetCum'+str(j+1)]-ret_sub['ExRetCum'+str(j+1)].mean()
        ret_sub['DemeanExRetCumSign'+str(j)]=ret_sub['ExRetCumSign'+str(j+1)]-ret_sub['ExRetCumSign'+str(j+1)].mean()

    ret_Demean=pd.concat([ret_Demean,ret_sub])


# =============================================================================
# run the demean regression
# =============================================================================
for i in range(0,12):
    ret_Demean['alpha_Lag'+str(i)]=np.nan
    ret_Demean['beta_Lag'+str(i)]=np.nan
    ret_Demean['alpha_LagSign'+str(i)]=np.nan
    ret_Demean['beta_LagSign'+str(i)]=np.nan
    ret_Demean['alpha_Cum'+str(i)]=np.nan
    ret_Demean['beta_Cum'+str(i)]=np.nan
    ret_Demean['alpha_CumSign'+str(i)]=np.nan
    ret_Demean['beta_CumSign'+str(i)]=np.nan


for i in range(0,12):
    new_name='DemeanExRet_l'+str(i)
    regression=ret_Demean[['YM','DemeanExRet_f1',new_name]].dropna()
    form="DemeanExRet_f1 ~ DemeanExRet_l"+str(i)+'-1'
    result=smf.ols(formula=form, data=regression).fit(cov_type='cluster',cov_kwds={'groups': regression['YM']},use_t=True)
    beta_Lag=result.params[0]
    ret_Demean['epsilon_Lag'+str(i)]=result.resid
    
    new_name='DemeanExRetSign_l'+str(i)
    regression=ret_Demean[['YM','DemeanExRet_f1',new_name]].dropna()
    form="DemeanExRet_f1 ~ DemeanExRetSign_l"+str(i)+'-1'
    result=smf.ols(formula=form, data=regression).fit(cov_type='cluster',cov_kwds={'groups': regression['YM']},use_t=True)
    beta_LagSign=result.params[0]
    ret_Demean['epsilon_LagSign'+str(i)]=result.resid

    new_name='DemeanExRetCum'+str(i)
    regression=ret_Demean[['YM','DemeanExRet_f1',new_name]].dropna()
    form="DemeanExRet_f1 ~ DemeanExRetCum"+str(i)+'-1'
    result=smf.ols(formula=form, data=regression).fit(cov_type='cluster',cov_kwds={'groups': regression['YM']},use_t=True)
    beta_Cum=result.params[0]
    ret_Demean['epsilon_Cum'+str(i)]=result.resid

    new_name='DemeanExRetCumSign'+str(i)
    regression=ret_Demean[['YM','DemeanExRet_f1',new_name]].dropna()
    form="DemeanExRet_f1 ~ DemeanExRetCumSign"+str(i)+'-1'
    result=smf.ols(formula=form, data=regression).fit(cov_type='cluster',cov_kwds={'groups': regression['YM']},use_t=True)
    beta_CumSign=result.params[0]
    ret_Demean['epsilon_CumSign'+str(i)]=result.resid

    for j in range(1,56):
        ret_sub=ret_Demean[ret_Demean['ID']==j]
        ret_Demean['beta_Lag'+str(i)]=beta_Lag
        ret_Demean['beta_LagSign'+str(i)]=beta_LagSign
        ret_Demean['beta_Cum'+str(i)]=beta_Cum
        ret_Demean['beta_CumSign'+str(i)]=beta_CumSign       
        
        ret_Demean['alpha_Lag'+str(i)].loc[ret_sub.index]=ret_sub['ExRet'].mean()-beta_Lag*ret_sub['ExRet'].mean()
        ret_Demean['alpha_LagSign'+str(i)].loc[ret_sub.index]=ret_sub['ExRet'].mean()-beta_LagSign*ret_sub['ExRetSign_l0'].mean()
        ret_Demean['alpha_Cum'+str(i)].loc[ret_sub.index]=ret_sub['ExRet'].mean()-beta_Cum*ret_sub['ExRetCum'+str(i+1)].mean()
        ret_Demean['alpha_CumSign'+str(i)].loc[ret_sub.index]=ret_sub['ExRet'].mean()-beta_CumSign*ret_sub['ExRetCumSign'+str(i+1)].mean()

# =============================================================================
# run the Fixed Design bootstrap regression
# =============================================================================

tLag_Fixed=np.empty((10000,12))
tLagSign_Fixed=np.empty((10000,12))
tCum_Fixed=np.empty((10000,12))
tCumSign_Fixed=np.empty((10000,12))


for n in range(0,10000):
    size=len(ret_Demean)
    ret_Demean['vera']=np.random.uniform(0,1,size)
    ret_Demean['vera']=np.where(ret_Demean['vera']>=0.5,1,-1)
    
    for i in range(0,12):
    
        ret_Demean['star_Lag'+str(i)]=ret_Demean['alpha_Lag'+str(i)]+ret_Demean['beta_Lag'+str(i)]*ret_Demean['ExRet_l'+str(i)]+ret_Demean['vera']*ret_Demean['epsilon_Lag'+str(i)]
        ret_Demean['star_LagSign'+str(i)]=ret_Demean['alpha_LagSign'+str(i)]+ret_Demean['beta_LagSign'+str(i)]*ret_Demean['ExRetSign_l'+str(i)]+ret_Demean['vera']*ret_Demean['epsilon_LagSign'+str(i)]
        ret_Demean['star_Cum'+str(i)]=ret_Demean['alpha_Cum'+str(i)]+ret_Demean['beta_Cum'+str(i)]*ret_Demean['ExRetCum'+str(i+1)]+ret_Demean['vera']*ret_Demean['epsilon_Cum'+str(i)]
        ret_Demean['star_CumSign'+str(i)]=ret_Demean['alpha_CumSign'+str(i)]+ret_Demean['beta_CumSign'+str(i)]*ret_Demean['ExRetCumSign'+str(i+1)]+ret_Demean['vera']*ret_Demean['epsilon_CumSign'+str(i)]

        mean=pd.DataFrame(ret_Demean.groupby(['ID'])['star_Lag'+str(i),'star_LagSign'+str(i),'star_Cum'+str(i),'star_CumSign'+str(i)].mean())
        mean.columns=['Mean_Lag','Mean_LagSign','Mean_Cum','Mean_CumSign']
        mean['ID']=mean.index
        
        ret_DemeanStar=pd.merge(ret_Demean,mean,on='ID',how='left')
        ret_DemeanStar['Demean_star_Lag'+str(i)]=ret_DemeanStar['star_Lag'+str(i)]-ret_DemeanStar['Mean_Lag']
        ret_DemeanStar['Demean_star_LagSign'+str(i)]=ret_DemeanStar['star_LagSign'+str(i)]-ret_DemeanStar['Mean_LagSign']
        ret_DemeanStar['Demean_star_Cum'+str(i)]=ret_DemeanStar['star_Cum'+str(i)]-ret_DemeanStar['Mean_Cum']
        ret_DemeanStar['Demean_star_CumSign'+str(i)]=ret_DemeanStar['star_CumSign'+str(i)]-ret_DemeanStar['Mean_CumSign']
        
        regression=ret_DemeanStar[['YM',"Demean_star_Lag"+str(i),"DemeanExRet_l"+str(i)]].dropna()
        form="Demean_star_Lag"+str(i)+" ~ DemeanExRet_l"+str(i)+'-1'
        result=smf.ols(formula=form, data=regression).fit(cov_type='cluster',cov_kwds={'groups': regression['YM']},use_t=True)
        tLag_Fixed[n,i]=result.tvalues[0]

        regression=ret_DemeanStar[['YM',"Demean_star_LagSign"+str(i),"DemeanExRetSign_l"+str(i)]].dropna()
        form="Demean_star_LagSign"+str(i)+" ~ DemeanExRetSign_l"+str(i)+'-1'
        result=smf.ols(formula=form, data=regression).fit(cov_type='cluster',cov_kwds={'groups': regression['YM']},use_t=True)
        tLagSign_Fixed[n,i]=result.tvalues[0]

        regression=ret_DemeanStar[['YM',"Demean_star_Cum"+str(i),"DemeanExRetCum"+str(i)]].dropna()
        form="Demean_star_Cum"+str(i)+" ~ DemeanExRetCum"+str(i)+'-1'
        result=smf.ols(formula=form, data=regression).fit(cov_type='cluster',cov_kwds={'groups': regression['YM']},use_t=True)
        tCum_Fixed[n,i]=result.tvalues[0]

        regression=ret_DemeanStar[['YM',"Demean_star_CumSign"+str(i),"DemeanExRetCumSign"+str(i)]].dropna()
        form="Demean_star_CumSign"+str(i)+" ~ DemeanExRetCumSign"+str(i)+'-1'
        result=smf.ols(formula=form, data=regression).fit(cov_type='cluster',cov_kwds={'groups': regression['YM']},use_t=True)
        tCumSign_Fixed[n,i]=result.tvalues[0]


Table5_Fixed=pd.DataFrame(columns=['Lag','Lag_Sign','Cum','Cum_Sign'],index=np.arange(1,13))

for i in range(1,13):
    Table5_Fixed.loc[[i],['Lag']]=np.percentile(tLag_Fixed[:,i-1],97.5)
    Table5_Fixed.loc[[i],['Lag_Sign']]=np.percentile(tLagSign_Fixed[:,i-1],97.5)
    Table5_Fixed.loc[[i],['Cum']]=np.percentile(tCum_Fixed[:,i-1],97.5)
    Table5_Fixed.loc[[i],['Cum_Sign']]=np.percentile(tCumSign_Fixed[:,i-1],97.5)

pd.DataFrame.to_csv(Table5_Fixed,'Table5_Fixed.csv')
