
/*  Cem Ertur and Antonio Musolesi, 
"Weak and Strong Cross-Sectional Dependence: a Panel Data Analysis of International Technology Diffusion", 
Journal of Applied Econometrics, forthcoming. */	


/** This gauss code allows the CCE estimation of the equations 16 to 20 in Ertur and  Musolesi (2016) 
corresponding to the first row of tables 4 and 5. It use the code that was made available by Takashi Yamagata 
and that can be found at:
http://www.econ.cam.ac.uk/emeritus/mhp1/ppfiles/CCEgauss6_22Aug08.zip
**/








/************************************************************/
/** Specify the directory and name of the output file      **/ 
/************************************************************/
output file = C:\\out_g7.txt RESET;

/************************************************************/
/** load cross section id, years, y_it, x_it (first sheet) **/ 
/************************************************************/
    /* Specify the range of first raw, variables names */
        vname=xlsreadm("C:\\first.xls","a1:i1",1,"");

    /* Specify the range of the cross section varying regresssors, second raw onwards */
        data=xlsreadm("C:\\first.xls","a2:i817",1,"");

/*****************************************************************/
/** load cross sectionally common variables d_t (second sheet)  **/ 
/*****************************************************************/
/** first of all, specify the number of "d" (except intercept) **/
nb_d=0;

if nb_d /= 0;
     /* Specify the rage of first raw, variables names (SECOND EXCEL SHEET)*/
        dname=xlsreadm("C:\\DT.xls","b1:b1",1,"");
        dname=dname[1,1:nb_d];
    /* Specify the rage of observed common factors z_t (SECOND EXCEL SHEET)*/
        data_d=xlsreadm("C:\\DT.xls","b2:b35",1,"");
endif;
/*****************************************************************/
/** specify the x which would not go for cross section averages **/ 
/*****************************************************************/
/** Column number in Excel (please put "0" if not applicable) **/ 
/** eg, no_xbar = {5 6};                                    **/
    no_xbar = {  };

/*****************************************************************/
/** specify the x and id, which has "zeros" due to normalisation**/
/*****************************************************************/
/** zero_x: Column number in Excel 
    zero_id: the id number
    eg,  zero_x = 5; zero_id = 3;
(zero_x = 0; zero_id = 0 if not applicable) **/
                                                                
    zero_x = 0; zero_id = 0; 

/******************************************************************/
/** Whether the individual CCE estimation results are reported or not */
/*******************************************************************/
report=1; /*** report=0: not reported, report=1:reported at the end */

/** @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ **/
/** Please do not change below, unless you are familiar with gauss programme **/
/** @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ **/

if sumc(sumc(data)).==_dxmiss;"Missing Data Somewhere! This code does not allow it.";end;endif;

idvec_o=data[.,1];
yvec=data[.,2];

idvec={};
tvec={};
starttvec={};
endtvec={};

total=rows(data);

id_i=idvec_o[1];
c_it=1;
do while c_it<=total;
idvec=idvec|id_i;
/**/
    c_t=1;
    starttvec=starttvec|yvec[c_it];
    do while c_t<=100000;

        if c_it==total;
            tvec=tvec|c_t;
            endtvec=endtvec|yvec[c_it];
            goto out;
        endif;

        if idvec_o[c_it+1]==id_i;
            c_t=c_t+1;
            c_it=c_it+1;
        else;
            tvec=tvec|c_t;
            endtvec=endtvec|yvec[c_it];
            goto next;
        endif;
    endo;
    
next:
    
    c_it=c_it+1;
    id_i=idvec_o[c_it];
endo;
out:


miny=minc(starttvec);
maxy=maxc(endtvec);
mint=minc(tvec);
maxt=maxc(tvec);

n=rows(idvec);
ivec=seqa(1,1,n);


/** Cross section averages **/
t_n={};
data_bar={};
c_t=miny;
do while c_t<=maxy;
    data_c_t=selif(data,data[.,2].==c_t);
        data_bar_c_t={};
        ccc=1;
        do while ccc<=cols(data_c_t);
            data_c_t_temp=data_c_t[.,ccc];
            if ccc==zero_x;
            data_c_t_temp=delif(data_c_t,data_c_t[.,1].==zero_id);
            data_bar_c_t=data_bar_c_t~meanc(data_c_t_temp[.,ccc]);
            else;
            data_bar_c_t=data_bar_c_t~meanc(data_c_t_temp);
            endif;
            ccc=ccc+1;
        endo;
    data_bar=data_bar|data_bar_c_t;
    t_n=t_n|rows(data_c_t);
c_t=c_t+1;
endo;

/* choose y */
y = data[.,3];
yname = vname[3];

/* choose x */
x = data[.,4:cols(data)];
xname = vname[4:cols(data)];

/* choose ybar */
ybar=data_bar[.,3];
ybarname=vname[3] $+ "bar";

/* choose z */
if nb_d==0;
data_d=ones(rows(ybar),1);dname="inpt";
else;
data_d=data_d~ones(rows(ybar),1);dname=dname~"inpt";
endif;

/* choose xbar */
nb_no_xbar=cols(no_xbar);
xbar_temp = data_bar[.,4:cols(data)];xbarname_temp = vname[4:cols(data)] $+ "bar";

    /* take away the specified xbar by user **/
    if no_xbar == 0; xbar = xbar_temp;xbarname = xbarname_temp;
    elseif nb_no_xbar==cols(x) and no_xbar /= 0;h_i=data_d~ybar;hname=dname~ybarname;goto noxbar;
    else;
        c_nb=1;
        do while c_nb<=nb_no_xbar;
            xbar_temp[.,no_xbar[c_nb]-3] = ones(rows(xbar_temp),1)*_dxmiss;
            xbarname_temp[no_xbar[c_nb]-3] = _dxmiss;
            c_nb=c_nb+1;
        endo;
    xbar_tempt=xbar_temp';
    xbarname_tempt=xbarname_temp';
    xbar=delif(xbar_tempt,xbar_tempt[.,1].==_dxmiss)';
    xbarname=delif(xbarname_tempt,xbarname_tempt.==_dxmiss)';
endif;

/* form h=(z,ybar,xbar) */
h_i=data_d~ybar~xbar;
hname=dname~ybarname~xbarname;

noxbar:
/* choose z */
    h={};
    i=1;
    do while i<=n;
    h = h|h_i[starttvec[i]-miny+1:endtvec[i]-maxy+maxt,.];
    i=i+1;
    endo;

/*** mean group estimation ***/
if zero_x==0; zero_xx=0;
else; zero_xx=zero_x-3;endif;
if zero_id==0;zero_idx=0;
else; zero_idx=indnv(zero_id,idvec);
endif;
{b_mg,cov_mg,e_mg,inverse_x_x,out_mg,b_vec,se_nw,se,sig_vec}=
mg(yname',(xname~dname)',y,x~h[.,1:cols(data_d)],n,tvec,starttvec-miny+1,endtvec-maxy+maxt,
seqa(miny,maxy,maxt),zero_xx, zero_idx);

{cd_nt,pvalue_cd_nt,meanrho,used}=cdtest(e_mg,n,tvec,starttvec-miny+1,endtvec-maxy+maxt);

{b_fe,cov_fe,sig2_fe,e_fe,se_fe,tvalue_fe,out_fe,ci_vec_fe,sig_i_vec_fe,
cov_fe_rbst_nw_Fe,cov_fe_hs2_fe}=pcceNW((yname~xname~dname)',y, x,h[.,1:cols(data_d)] , n,tvec,starttvec-miny+1,endtvec-maxy+maxt,
seqa(miny,maxy,maxt),cov_mg[1:cols(x),1:cols(x)],b_vec[.,1:cols(x)]);

{b_mg_cce,cov_mg_cce,e_mg_cce,inverse_x_x_cce,out_mg_cce,b_vec_cce,se_nw_cce,se_cce,sig_vec_cce}=
mg(yname',(xname~hname)',y,x~h,n,tvec,starttvec-miny+1,endtvec-maxy+maxt,
seqa(miny,maxy,maxt),zero_xx, zero_idx);

{b_pcce,cov_pcce,sig2_pcce,e_pcce,se_pcce,tvalue_pcce,out_pcce,ci_vec,sig_i_vec,
cov_pcce_rbst_nw,cov_pcce_hs2}=pcceNW((yname~xname~hname)',y, x, h, n,tvec,starttvec-miny+1,endtvec-maxy+maxt,
seqa(miny,maxy,maxt),cov_mg_cce[1:cols(x),1:cols(x)],b_vec_cce[.,1:cols(x)]);

xhname=xname~hname;
xhnamese={};
ccei_se={};
ii=1;
do while ii<=cols(xhname);
    xhnamese=xhnamese~(xhname[ii]~"se(NW)");
    ccei_se=ccei_se~(b_vec_cce[.,ii]~se_nw_cce[.,ii]);
    ii=ii+1;
endo;    

/** some outputs **/
outwidth 256;
output on;
"**********************************************************************************************************";
" PESARAN, M.H., (2006), ESTIMATION AND INFERENCE IN LARGE HETEROGENEOUS PANELS WITH A MULTIFACTOR 
  ERROR STRUCTURE, ECONOMETRICA, VOL74, NO.4, PP.967-1012.";
"**********************************************************************************************************";
/** some outputs **/
"++++++++++++++++ <Preliminary Information on Panel Data> ++ ++++++++++++++++++++++++++++++++++++++++++++";
anames=("Min(year)"~"Max(Year)"~"Min(Ti)"~"Max(Ti)"~"N"~"mean Ti");
$anames|(ftocv(miny~maxy~mint~maxt~n,1,0)~ftocv(meanc(tvec),1,2));
"";
"++++++++++++++++ <OLS Mean Group Estimates> ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++";
$out_mg;
"";
"   Pesaran's (2004) CD test statistic (residuals):";;cd_nt;
"     (Pesaran, M.H., (2004), General Diagnostic Tests for Cross Section Dependence in Panels, CESifo
       Working Papers No.1233)"
"";
"   * OLS Mean Group Estimator is simple cross section average of OLS estimator for each cross section unit.";
"   * se(NP) is the standard error based on non-parametric variance estimator of eq(58) in Pesaran (2006).";
"   *  t(.) is associated t-ratio."; 
"";
"++++++++++++++++ <Fixed Effects Estimates> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++";
$out_fe;
"";
"   * se(NP) is the standard error based on non-parametric variance estimator of eq(69) in Pesaran (2006)."; 
"   * se(NW) is the standard error based on Newey-West type variance estimator of eq(74) in Pesaran (2006).";
"   *  t(.) is associated t-ratio.";  
"";
"   Cross Section Averages of Estimated Heterogeneous Slops in FE Estimation";
$dname'~ftocv(meanc(ci_vec_fe),1,6);
"";
"++++++++++++++++ <Pesran's (2006) CCE Mean Group Estimates> ++++++++++++++++++++++++++++++++++++++++++++";
$out_mg_cce[1:rows(out_pcce),.];
"";
"   * CCE Mean Group Estimator is defined by eq(53).";
"   * se(NP) is the standard error based on non-parametric variance estimator of eq(58) in Pesaran (2006).";
"   *  t(.) is associated t-ratio."; 
"";
"   Cross Section Averages of Estimated Heterogeneous Slops in CCE Mean Group Estimation";
$out_mg_cce[rows(out_pcce)+1:rows(out_mg_cce),1:2];
"";
"++++++++++++++++ <Pesaran's (2006) CCE Pooled Estimates> +++++++++++++++++++++++++++++++++++++++++++++++";
$out_pcce;
"";
"   * CCE Pooled Estimator is defined by eq(65).";
"   * se(NP) is the standard error based on non-parametric variance estimator of eq(69) in Pesaran (2006)."; 
"   * se(NW) is the standard error based on Newey-West type variance estimator of eq(74) in Pesaran (2006).";
"   *  t(.) is associated t-ratio."; 
"";
"   Cross Section Averages of Estimated Heterogeneous Slops in CCE Pooled Estimation";
$hname'~ftocv(meanc(ci_vec),1,6);
"";
"--------------------------------------------------------------";
"N used for Cross Section Average (out of";;$ftocv(n,1,0);;")";
$ftocv(seqa(miny,1,maxt)~t_n,1,0);

if report==0;format /rd 15,7;output off;end;
elseif report==1;
"--------------------------------------------------------------";
"Reports on CCE Estimates of All Cross Section Units";
"";
format /rd 9,5;
a2names=("ID"~xhnamese~"Ti"~"From"~"To");
$a2names|(ftocv(idvec,1,0)~ftocv(real(ccei_se),1,3)~ftocv(tvec~starttvec~endtvec,1,0));
"";
"   * CCE Estimator for a cross section unit is defined by eq(26).";
"   * se(NW) is the standard error based on Newey-West type variance estimator of eq(50) in Pesaran (2006)."; 
endif;
output off;
format /rd 15,7;
/*************************************************************************/
/* NOTE: This code is preliminary, please do NOT distribut.             **/
/* Please report any problems you might have, to: ty228@econ.cam.ac.uk  **/
/*                                                                      **/
/* This code computes CD test statistics defined by eq. (7) in          **/
/* GENERAL DIAGNOSTIC TESTS FOR CROSS SECTION DEPENDENCE IN PANELS,     **/
/*                                        PESARAN (2004).               **/
/*                                                                      **/
/* {cd_nt,pvalue_cd_nt,meanrho,used}=cdtest(e,n,tivec,starttvec,endtvec)**/
/* [ this code allows unbalanced panel)                                 **/
/*  where                                                               **/
/*  cd_nt:  CD test statistic defined by eq. (7) in PESARAN (2004)      **/
/*  pvalue_cd_nt: p-value of CD test                                    **/
/*  meanrho: simple average of residual correlation coefficients rho_ij **/
/*              defined by eq. (3) in Pesaran (2004)                    **/
/*  used:   (used number of combinations of rho_ij)/(N(N-1)/2)          **/
/*  WITH ARGUMENTS                                                      **/
/*      e: (NT x 1 for balanced panel) stucked residual vector          **/
/*        e=(e_11,e_12,...,e_1T, e_21,e_22,...,e_2T, ... ,e_N1,e_N2,...,e_NT)' **/
/*      n: number of cross sections                                     **/
/*      tivec: (N x 1) vector of number of observations of cross        **/
/*            section unit i, T_i's                                     **/
/*            for balanced panel, tivec=T*ones(n,1);                    **/
/*            for unbalanced panel, eg., (20,20,18,17,18)' for N=5      **/
/*      starttvec:(N x 1) vector of starting year of i's                **/
/*            for balanced panel, starttvec=ones(n,1);                  **/
/*            for unbalanced panel, eg., (1971,1971,1973,1972,1971)'    **/
/*      endttvec:(N x 1) vector of end year of i's                      **/
/*            for balanced panel, endttvec=T*ones(n,1);                 **/
/*            for unbalanced panel, eg., (1996,1996,1994,1997,1980)'    **/
/*                                                                      **/
/* NOTE: When T_ij<4, rho_ij is not calculable, so need to be discarded **/
/*      where T_ij is the number of orverlapped years between i and j   **/
/*      eg. i has 1971-1980 and j has 1967-1975, T_ij=5                 **/
/*                                                                      **/
/* Takashi Yamagata, 3rd June 2005                                      **/
/*                                                                      **/
/*************************************************************************/


proc(4) = cdtest(e,n,tivec,starttvec,endtvec);

local cumtivec, T_rho, T_rho2_1, i, e_i, startt_i, endt_i, j, e_j, startt_j, endt_j;
local t_s, t_e, e_i_t, e_j_t, T_rho_ij, cd_nt, pvalue_cd_nt;
local disc,T_ij,T_ij_v,used,meanrho,rho,rho_ij;
cumtivec=0|cumsumc(tivec);
/** NOTE: When T_ij<4, rho_ij is not calculable, so need to be discarded ***/
/******** To obtain Pesaran (2004) test  (CD_nt) ******/
rho = 0;	/** for CD_nt ***/
T_rho=0;
disc=0; /** discarded pair for T_ij<4 **/
/** for corrected CD_lm ***/
	i=1;
	do while i<=n-1;
		e_i=e[cumtivec[i]+1:cumtivec[i+1]];
		startt_i=starttvec[i];
		endt_i=endtvec[i];
			j=i+1;
    	do while j<=N;

				e_j=e[cumtivec[j]+1:cumtivec[j+1]];
				startt_j=starttvec[j];
				endt_j=endtvec[j];

/*** To eliminate T_ij<4 ***/
        if startt_i<=startt_j and endt_i>=startt_j;
            T_ij=endt_i - startt_j - (endt_i-endt_j)*(endt_i>endt_j) +1;
            elseif startt_i>=startt_j and endt_j>=startt_i;
                T_ij=endt_j - startt_i - (endt_j-endt_i)*(endt_j>endt_i) +1;
            else; T_ij=0;
        endif;
        if T_ij<4;j=j+1;disc=disc+1;goto DISCARD;endif;
/***** end of the elimination procedure ****/
				t_s=maxc(startt_i|startt_j);
				t_e=minc(endt_i|endt_j);

				e_i_t = e_i[t_s-startt_i+1:t_e-startt_i+1]
                        -meanc(e_i[t_s-startt_i+1:t_e-startt_i+1]);
				e_j_t = e_j[t_s-startt_j+1:t_e-startt_j+1]
                        -meanc(e_j[t_s-startt_j+1:t_e-startt_j+1]);
				
                rho_ij=(e_i_t'e_j_t)/(sqrt(e_i_t'e_i_t)*sqrt(e_j_t'e_j_t));
				T_rho_ij = sqrt(rows(e_i_t))*rho_ij;/*rows(e_i_t)~rho_ij;*/
              
                rho=rho+rho_ij;      
				T_rho = T_rho + T_rho_ij ;   			/*  for CD_nt */

			j=j+1;
DISCARD:
			endo;
		i=i+1;
	endo;
CD_nt = sqrt(1/((n*(n-1)/2)-disc))*T_rho;
meanrho=rho/((n*(n-1)/2)-disc);

pvalue_CD_nt = 2*cdfnc(abs(CD_nt)); /** two sided!!*/
used=((n*(n-1)/2)-disc)/(n*(n-1)/2);

retp(cd_nt,pvalue_cd_nt,meanrho,used);
endp;


/*** MG estimation ***/
proc(9)=mg(yname,xname,y,x,n,tivec,starttvec,endtvec,years,zero_x,zero_id);
local namevar,cumtivec,x_mg,k,ttest05,ttest10,ttest20,i,y_i,x_i,b_i,e_i,inverse_x_x,sig_i,sig2_i;
local b_vec,sig_vec,startyear,endyear,cov_b_i,se_b_i,tvalue_b_i,e;
local estvec,mean,medi,sd,m2,m3,m4,skew,kurtosis,resultvec,out_mg;
local namev,statsname,string_resultvec,varnames, varnames2,ytoy;
local b_mg,b_dm,sig_mg,sig2_mg,cov_mg,se_mg,tvalue_mg,nameh,results_mg;
local st_results_mg,e_mg,omega_nw,lg,omega_h_i,z_i,gama0,s,gamas,se;
local mgexcel,st_st,testname,testi,testst,c,c_k;

namevar=yname $| xname;
cumtivec=0|cumsumc(tivec);
x_mg=x;
k=cols(x_mg);
inverse_x_x=zeros(cols(x_mg),cols(x_mg));
se_nw={};se={};
	i=1;
	do while i<=n;
		y_i=y[cumtivec[i]+1:cumtivec[i+1]];
		x_i=x_mg[cumtivec[i]+1:cumtivec[i+1],1:cols(x_mg)];
		b_i=pinv(x_i'x_i)*x_i'y_i;
		e_i=y_i-x_i*b_i;
		inverse_x_x = inverse_x_x + pinv(x_i'x_i); /*** For Hausman test 1 ***/
        sig_i=sqrt(e_i'e_i/(tivec[i]-k));
        if i==zero_id;sig_i=sqrt(e_i'e_i/(tivec[i]-k+1));endif;

        z_i=e_i.*x_i;      
        lg=round(4*(Tivec[i]/100)^(2/9));/*lg=2*Tivec[i]^(1/4);*//*minc(N|ceil(2*Sqrt(T)))*/
        omega_h_i=0;
    
        gama0=(z_i'z_i);gamas=0;

            s=1;
            do while s<=lg;
                gamas=(z_i[s+1:tivec[i],.])'(z_i[1:tivec[i]-s,.]);
                omega_h_i=omega_h_i + (1-s/(lg+1))*(gamas+gamas');
                s=s+1;
            endo;
/*N-W*/     omega_nw=(gama0+omega_h_i);

            cov_pcce_rbst_NW = pinv(x_i'x_i)*omega_nw*pinv(x_i'x_i);
            se_nw=se_nw|sqrt(diag(cov_pcce_rbst_NW))';

		sig2_i=sig_i^2;
            se = se|sqrt(diag(sig2_i*pinv(x_i'x_i)))';

			if i==1;
				b_vec=b_i';
				sig_vec=sig_i;
				e = y_i-x_i*b_i;
				startyear=years[starttvec[i]];
				endyear=years[endtvec[i]];
					else;
						b_vec=b_vec|(b_i');
						e = e|(y_i-x_i*b_i);
						sig_vec=sig_vec|sig_i;
						startyear=startyear|years[starttvec[i]];
						endyear=endyear|years[endtvec[i]];
			endif;
        e_mg=e;
		/*** t-test for each i ***/            
		i=i+1;
	endo;
b_mg={};
    c_k=1;
        do while c_k<=k;
            if c_k==zero_x;
                b_mg=b_mg|(sumc(b_vec[.,c_k])/(n-1));
            else;
                b_mg=b_mg|(meanc(b_vec[.,c_k]));
            endif;
        c_k=c_k+1;
        endo;

/** mg estimator **/
se_mg={};
    c_k=1;
        do while c_k<=k;
            if c_k==zero_x;
                b_vec[zero_id,c_k]=b_mg[c_k];
                se_mg=se_mg|sqrt(sumc((b_vec[.,c_k]-b_mg[c_k]).^2)/((n-1)*(n-2)));
            else;
                se_mg=se_mg|sqrt(sumc((b_vec[.,c_k]-b_mg[c_k]).^2)/((n)*(n-1)));
            endif;
        c_k=c_k+1;
        endo;

b_dm=(b_vec-b_mg');    /** row vec**/
cov_mg=b_dm'b_dm/((n)*(n-1));
if zero_x/=0;
    cov_mg[zero_x,.]=cov_mg[zero_x,.]*((n)*(n-1))/((n-1)*(n-2));
    cov_mg[.,zero_x]=cov_mg[.,zero_x]*((n)*(n-1))/((n-1)*(n-2));
endif;

cov_mg=diagrv(cov_mg,se_mg^2);

tvalue_mg=b_mg./se_mg;

/* output*/
results_mg=b_mg~se_mg~tvalue_mg;
st_results_mg=ftocv(results_mg,7,7);
nameh="coeff"~"se(NP)"~"t(NP)";

out_mg = namevar $~ (nameh $| st_results_mg);


retp(b_mg,cov_mg,e_mg,inverse_x_x,out_mg,b_vec,se_nw,se,sig_vec);
endp;


/**** Pooled CCE ****/
/* varname_cce: a (1 + k_x + k_h) x 1 vector of string names ofy, x, h
   y: NTx1 vector (please see mg.prc for ordering)
   x: NTxk_x matrix of explanatory variables (NO non-individual-specific variables)
   h: NTxk_h non-individual-specific variables (eg. intercept, etc)

   n: Number of cross section units
   tivec: N
   tivec: Nx1 vector of number of time serires for each i, i=1,...,N.
	  if balanced, put a Nx1 vector of T.
   starttvec: please put a Nx1 vector of one for balanced panel.
   endtvec: please put a Nx1 vector of T, for balanced panel.
   years   : please put a Nx1 vector of (1,2,...,T)' for balanced panel
   sig_cce: "sig_vec" from mg.prc
   cov_mg_cce: "cov_mg" from mg.prc
   b_vec_mg: "b_vec" from mg.prc


   b_pcce: pooled estimator
   cov_pcce: covariance matrix using standard FE type method
   sig2_pcce: estimate of sig2
   e_pcce: residuals
   se_pcce: standard errors based on "sig2_pcce"
   tvalue_pcce: based on "sig2_pcce"
   out_pcce: output1
   ci_vec: estimates of heterogeneous coefficients on h
   sig_i_vec: Nx1 vector of each zigma_i
   cov_pcce_rbst_h: White heteroskedasticity robust estimator
   cov_pcce_rbst_h_arellano: arellano robust variance estimator
   cov_pcce_rbst_nw: Newey West Variance Estimator
   cov_pcce_hs2: Pesaran's Non-parametric variance estimator

   * In Pesaran, cov_pcce_rbst_nw and cov_pcce_hs2 are considered and latter is recommended.

*/

proc(11)=pcceNW(varname_cce,y, x, h, n,tivec,starttvec,endtvec,years,cov_mg_cce,b_vec_mg);

local cumtivec, mx_mx, mx_y, i, y_i, x_i, h_i, m_h_i, mx_i;
local b_pcce, e_pcce,sig2_pcce,cov_pcce,se_pcce,tvalue_pcce;
local omega_h,e_pcce_i,cov_pcce_rbst_h,se_pcce_rbst_h,tvalue_pcce_rbst_h;
local omega,cov_pcce_rbst,se_pcce_rbst,tvalue_pcce_rbst,out_pcce,sig_i_vec;
local namedep,namevar_pcce,results_pcce,st_results_pcce,nameh;
local m_i,dof_i,b_mg,b_dm,sig_mg,sig2_mg,cov_mg,se_mg,tvalue_mg,ci_vec;
local results_mg,st_results_mg,out_mg,MGexcel,st_st,testname,c,testi,testst;
local varnames, namev,string_resultvec, ytoy,ttest05,ttest10,ttest20,k;
local se_ci,var_ci,tvalue_ci,namevar_h,estvec,mean,medi,sd,m2,m3,m4;
local skew,kurtosis,resultvec,statsname,varnames2;
local startyear,endyear;
local omega_h_pcce,omega_h_mgcce,omega_nw,cov_pcce_rbst_h_arellano,cov_pcce_rbst_nw;
local lg,omega_h_i,z_i,z_i_bar,gama0,gamas,s,omega_hs,cov_pcce_hs,iv_mx_mx;
local omega_hs2,cov_pcce_hs2,omega_hs3,cov_pcce_hs3,b_mean;

cumtivec=0|cumsumc(tivec);
mx_mx=zeros(cols(x),cols(x)); /** sum of (mx_i'mx_i) **/
mx_y=zeros(cols(x),1);		   /** sum of (mx_i'y_i)    **/
omega_h=zeros(cols(x),cols(x));
iv_mx_mx=zeros(cols(x),cols(x));
	i=1;
	do while i<=n;
		y_i=y[cumtivec[i]+1:cumtivec[i+1]];
			x_i=x[cumtivec[i]+1:cumtivec[i+1],.];
			h_i=h[cumtivec[i]+1:cumtivec[i+1],.];
		m_h_i=(eye(tivec[i])-h_i*pinv(h_i'h_i)*h_i');
		mx_i=m_h_i*x_i;
		mx_mx = mx_mx + mx_i'mx_i;
       /* iv_mx_mx=iv_mx_mx+(sig_cce[i]^2)*pinv(mx_i'mx_i);*/
		mx_y = mx_y + mx_i'y_i;
		
   			if i==1;
				startyear=years[starttvec[i]];
				endyear=years[endtvec[i]];
					else;
						startyear=startyear|years[starttvec[i]];
						endyear=endyear|years[endtvec[i]];
			endif;

		i=i+1;
	endo;

/** beta hat PCCE **/
b_pcce =pinv(mx_mx)*mx_y;



/** residuals & coefficients on Hi **/
	i=1;sig_i_vec=zeros(n,1);ci_vec=zeros(n,cols(h));
	do while i<=n;
		y_i=y[cumtivec[i]+1:cumtivec[i+1]];
			x_i=x[cumtivec[i]+1:cumtivec[i+1],.];
			h_i=h[cumtivec[i]+1:cumtivec[i+1],.];
		m_h_i=(eye(tivec[i])-h_i*invpd(h_i'h_i)*h_i');
        ci_vec[i,.]=(inv(h_i'h_i)*h_i'(y_i-x_i*b_pcce))';/**coeffcients on Hi**/

			if i==1;e_pcce=m_h_i*y_i - m_h_i*x_i*b_pcce;
                sig_i_vec[i]=sqrt((m_h_i*y_i - m_h_i*x_i*b_pcce)'(m_h_i*y_i - m_h_i*x_i*b_pcce)/(tivec[i]-cols(h)));

				else;e_pcce=e_pcce|(m_h_i*y_i - m_h_i*x_i*b_pcce);
                dof_i = sumc(diag(m_h_i));
                sig_i_vec[i]=
                sqrt((m_h_i*y_i - m_h_i*x_i*b_pcce)'(m_h_i*y_i - m_h_i*x_i*b_pcce)/(tivec[i]-cols(h)));
        
			endif;
		i=i+1;
	endo;
sig2_pcce=e_pcce'e_pcce/(sumc(tivec)-n*cols(h)-cols(x_i));
cov_pcce=sig2_pcce*(inv(mx_mx));
se_pcce=sqrt(diag(cov_pcce));
tvalue_pcce=b_pcce./se_pcce;

omega_nw=zeros(cols(mx_i),cols(mx_i));
omega_hs2=zeros(cols(mx_i),cols(mx_i));/* (6.54) **/
b_mean=meanc(b_vec_mg);
	i=1;
	do while i<=n;
		e_pcce_i=e_pcce[cumtivec[i]+1:cumtivec[i+1]];
			x_i=x[cumtivec[i]+1:cumtivec[i+1],.];
			h_i=h[cumtivec[i]+1:cumtivec[i+1],.];
		m_h_i=(eye(tivec[i])-h_i*invpd(h_i'h_i)*h_i');

		mx_i=m_h_i*x_i;

lg=round(4*(Tivec[i]/100)^(2/9));/*lg=2*Tivec[i]^(1/4);*//*minc(N|ceil(2*Sqrt(T)))*/
omega_h_i=0;
z_i=e_pcce_i.*mx_i;
 gama0=(z_i'z_i);

s=1;
do while s<=lg;
            gamas=(z_i[s+1:tivec[i],.])'(z_i[1:tivec[i]-s,.]);
            omega_h_i=omega_h_i + (1-s/(lg+1))*(gamas+gamas');
        s=s+1;
endo;
/*N-W*/          omega_nw=omega_nw + (gama0+omega_h_i);
                 omega_hs2=omega_hs2 
                  + (mx_i'mx_i)*(b_vec_mg[i,.]-b_mean[1:cols(mx_i)]')'
                                (b_vec_mg[i,.]-b_mean[1:cols(mx_i)]')*(mx_i'mx_i);
		i=i+1;
	endo;

cov_pcce_rbst_NW = pinv(mx_mx)*omega_nw*pinv(mx_mx);
cov_pcce_hs2 = pinv(mx_mx/n)*(omega_hs2/(n-1))*pinv(mx_mx/n)/n;

		format /rd 9,5;

		namedep=varname_cce[1];
		namevar_pcce=varname_cce[2:cols(x)+1];
        namevar_h=varname_cce[cols(x)+2:cols(varname_cce')];
		results_pcce=b_pcce~sqrt(diag(cov_pcce_hs2))~(b_pcce./sqrt(diag(cov_pcce_hs2)))
~sqrt(diag(cov_pcce_rbst_NW))~(b_pcce./sqrt(diag(cov_pcce_rbst_NW)));
		st_results_pcce=ftocv(results_pcce,7,7);	
		nameh=namedep~"coeff"~"se(NP)"~"t(NP)"~"se(NW)"~"t(NW)";
/*
endif;

*/
out_pcce= nameh|(namevar_pcce~st_results_pcce);
retp(b_pcce,cov_pcce,sig2_pcce,e_pcce,se_pcce,tvalue_pcce,out_pcce,ci_vec,sig_i_vec,
cov_pcce_rbst_nw,cov_pcce_hs2);

endp;