*! Forward search regression. v.1.2, 11.06.2001 Stas Kolenikov
program define fsreg
   version 6
   #delimit ;
   syntax varlist(numeric min=2) [if] [in],
      CLEAR [Dots SAVing(str) REPLACE ID(varname) Level(int $S_level) RESiduals RSTUdent RSTAndard NRes(int 0) INITial(int 0) OBS(numlist integer) LMD(passthru) WHICH MEDian]
   ;
   #delimit cr

   if ("`residua'"~="") + ("`rstuden'"~="") + ("`rstanda'"~="") >1 {
      di in red "cannot specify more than one type of residuals"
      exit 198
   }
   local restype `residua'`rstuden'`rstanda'

   if ("`restype'"=="" & `nres'!=0) | ("`restype'"=="" & "`obs'"~="") {
      di in red "what sort of residuals?"
      exit 198
   }

   if `nres'~=0 & "`obs'"~="" {
      di in red "cannot specify the residuals and observations together"
      exit 198
   }

   marksample touse
   if "`id'"=="" {
      tempvar id
      qui g long `id'=_n
      qui compress `id'
   }
   confirm numeric var `id'
   qui keep if `touse'
   qui keep `varlist' `id'

   di in gre _n "   Forward search regression" _n

   * First piece: initial subset choice by robust regression
   * Second piece: forward inclusion with accumulating diagnostics
   * Third piece: nice graphs -- call to fsregrph

   * So, the first piece

   tempvar sm

   if "`dots'"~="" { di _n in gre "Choosing the initial subset " _c }
   Choice `varlist', gen(`sm') m(`initial') `lmd' `dots' `median'
   local m=r(m)

   if "`which'"~="" {
     local i=1
     while `i'<=`m' {
       local iid = id[`i']
       local stlist `stlist' `iid'
       local i=`i'+1
     }
     di in gre "Started with observations: " in yel "`stlist'"
   }

   if "`obs'"~=""  {
                     tokenize `obs'
                     local nres: word count `obs'
   }
   if "`nres'"~="" {
**** di in whi "`nres':"
     local k=1
     while `k'<=`nres' {
       if "`restype'"~="" { local id`k'=`id'[_N+1-`k'] }
       if "`obs'"~="" { local id`k'=``k'' }
       local resstr `resstr' _r`id`k''
****** di in whi "`resstr'"
       local k=`k'+1
     }
   }
   * some residuals or observations

   * done with the first stage. Now, cycling over the subsets

   tokenize `varlist'
   mac shift
   local k=1
   while "``k''"~="" {
     local tlist `tlist' _t`k'
     local k=`k'+1
   }
   local tlist `tlist' _t`k'
   * This is the list of the t-stats. Do not forget the constant !

   if "`saving'"=="" {
     local saving FSRegData
     local replace replace
   }
   label data "Forward search regression data"
   qui postfile FSREG _nobs _added `*' _cons `tlist' _sigma2 _scom2 _scom1 _scom05 _sco0 _sco05 _sco1 _sco2 `resstr' using `saving', `replace' every(20)
** di in whi `"POSTFILE was: FSREG _nobs _added `*' _cons `tlist' _sigma2 _scom2 _scom1 _scom05 _sco0 _sco05 _sco1 _sco2 `resstr' using `saving', `replace' "'

   * number of observations; which observation added; the list of regressors;
   * the list of the t-statistics for the regressors; the MSE;
   * the scores for the Box-Cox transformation

** set trace on
** set more off

   * the main cycle
   if "`dots'"~="" { di in gre "Adding observations starting from " in yel `m' }
   tempvar res aux eh rstud fit
   tempname eb eV
   tokenize `varlist' _cons
   mac shift
   * to get rid of the depvar
   while `m'<=_N {
      qui {
         local m1=`m'+1

         * the main regression
         reg `varlist' if `sm'
         local betas
         local tstats
         mat `eb'=e(b)
         mat `eV'=e(V)
         local k=1
         while "``k''"~="" {
           local thisb=_b[``k'']
           local betas `betas' (`thisb')
           local thist=_b[``k'']/sqrt(`eV'[`k',`k'])
           local tstats `tstats' (`thist')
           local k=`k'+1
         }
         local s2=e(rmse)^2
         estimates hold `eh'

         * now, regression with the auxiliary variables
         * we need: _scom2 _scom1 _scom05 _sco0 _sco05 _sco1 _sco2

         cap RegBC `varlist' if `sm', l(-2)
         local scom2=r(tscore)
         cap RegBC `varlist' if `sm', l(-1)
         local scom1=r(tscore)
         cap RegBC `varlist' if `sm', l(-0.5)
         local scom05=r(tscore)
         cap RegBC `varlist' if `sm', l(0)
         local sco0=r(tscore)
         cap RegBC `varlist' if `sm', l(0.5)
         local sco05=r(tscore)
         cap RegBC `varlist' if `sm', l(1)
         local sco1=r(tscore)
         cap RegBC `varlist' if `sm', l(2)
         local sco2=r(tscore)
         local scolist (`scom2') (`scom1') (`scom05') (`sco0') (`sco05') (`sco1') (`sco2')

         * the next step: the least residuals
         estimates unhold `eh'
         cap drop `res'
         predict `res', res
         replace `res'=abs(`res')
         sort `res'
         if "`nres'"~="" {
            local j=1
            local resstr

            if "`residua'"~="" {
              while `j'<=`nres' {
                sum `res' if `id'==`id`j'', meanonly
                local thisr=r(mean)
                local resstr `resstr' (`thisr')
                local j=`j'+1
              }
            }
            * if simple residuals

            if "`rstuden'"~="" {
              cap drop `rstud'
              predict `rstud', rstu
              while `j'<=`nres' {
                sum `rstud' if `id'==`id`j'', meanonly
                local thisr=abs(r(mean))
                local resstr `resstr' (`thisr')
                local j=`j'+1
              }
            }
            if "`rstanda'"~="" {
              cap drop `rstud'
              predict `rstud', rsta
              * mind the abuse of `rstud' variable!!!
              while `j'<=`nres' {
                sum `rstud' if `id'==`id`j'', meanonly
                local thisr=abs(r(mean))
                local resstr `resstr' (`thisr')
                local j=`j'+1
              }
            }
            * if studentized residuals
         }

********
*        di in whi _n "Old sm"
***      sort `id'
*        noi li `id' `res' `sm'
********

         if _N~=`m' { count if `sm'==1 in 1/`m1' }
               else { count }
******** di in whi r(N) " of " `m'
         if r(N)==`m' & `m'!=_N {
               sort `sm' in 1/`m1'
               local added=`id'[1]
         }
         else { local added=-9999 }
         * hard to tell what was added
         if `m'<_N { replace `sm'= (_n<=`m1') }

********
*        di in whi _n "New sm (added: `added' ?)"
***      sort `id'
*        noi li `id' `res' `sm'
********


******** di in whi `"POST: FSREG `m' (`added') `betas' `tstats' (`s2') `scolist' `resstr' "'
         post FSREG `m' (`added') `betas' `tstats' (`s2') `scolist' `resstr'

      }
      * end of quietly
      if "`dots'"~="" { di in gre "." _c }
      local m=`m1'
   }
   * end of the iteration
   postclose FSREG
   * done with the second stage. Now, graphing the stuff

   qui use `saving', clear
   char _dta[fsreg] "Forward search regression data"
   char _dta[start]  "`stlist'"
   if "`residua'"~="" { char _dta[res]   "simple" }
   if "`rstuden'"~="" { char _dta[res]   "studentized" }
   if "`rstanda'"~="" { char _dta[res]   "standardized" }
   local k=1
   while "``k''"~="" {
     lab var ``k'' "Coeff. of ``k''"
     lab var _t`k' "t-statistic of ``k''"
     local k=`k'+1
   }
   tokenize `varlist'
   char _dta[depvar] "`1'"
   mac shift
   char _dta[fsregl] "`*'"
   * add some stuff about the residuals!!!
   if "`nres'"~="" {
      local j=1
      while `j'<=`nres' {
         lab var _r`id`j'' "Residual in obs. no. `id`j''"
         local j=`j'+1
      }
   }

   NiceLab
   qui save, replace

   fsregrph, score

   di _n in gre "Use " in whi "fsregrph" in gre " now to produce other nice graphs."
end

pro def Choice, rclass
    syntax varlist, GEN(str) M(int) [LMD(int -1) DOTS MEDIAN]
    quietly {
     if `m'==0 {
       local m: word count `varlist'
       local m=max(20,`m',_N/10)
     }
     if `lmd'==-1 {
       * robust regression initialization
       rreg `varlist'
       tempvar res
       predict `res', r
       replace `res'=abs(`res')
       sort `res'
       noi di "..."
     }
     else {
       * random search for the least median deviation regression
       local md=1e12
       local i=1
       tempvar seed res indic obs
       g `seed' = .
       g long `indic' = .
       g long `obs' = _n
       while `i'<=`lmd' {
         if "`median'"~="" { local median q }
         `median'reg `varlist' in 1/`m'
         cap drop `res'
         predict `res' if e(sample)
         replace `res' = abs(`res')
         sort `res' `seed'
         local med = `res'[int(`m'/2)]
         if `med'<`md' { replace `indic' = e(sample) }
         local i=`i'+1
         if "`dots'"~="" & mod(`i',50)==0 { noi di in gre "." _c }
         replace `seed' = uniform()
         sort `seed'
       }
       gsort -`indic' `obs'
       noi di
     }
     * sorted so that the first observations are to enter the set
     g long `gen'=_n<=`m'
     compress `gen'
     * noi tab `indic' `gen'
     return scalar m=`m'
    }
    * end of quietly
end

pro def RegBC, rclass
   syntax varlist [if], Lambda(real)

   marksample touse
   tokenize `varlist'
   qui {
     tempvar z w
     means `1'
     local mg=r(mean_g)
     if `lambda'==0 {
        g `z'=`mg'*log(`1')
        g `w'=`z'*(.5*log(`1')-log(`mg'))
     }
     else {
        g `z'=(`1'^`lambda'-1)/(`lambda'*`mg'^(`lambda'-1))
        g `w'=(`1'^`lambda'*log(`1')-(`1'^`lambda'-1)*(1/`lambda'+log(`mg')) )/(`lambda'*`mg'^(`lambda'-1))
     }
     mac shift
   }

     reg `z' `w' `*' if `touse'
*    if _rc==2000 {
*       di in red "Error 2000 encountered!"
*       noi sum `z' `w'
*       di in whi `mg'
*    }
     tempname eb eV
     mat `eb'=e(b)
     mat `eV'=e(V)
     local t=`eb'[1,1]/sqrt(`eV'[1,1])
*     di in whi "Lambda = " `lambda' "; t-score = " `t' "; geom. mean = " `mg'
*     sum `z' `w'
   return scalar tscore= `t'
end

pro def NiceLab

   lab var _nobs "Number of observations"
   lab var _added "The observation added at this step"
   qui mvdecode _added , mv(-9999)
   lab var _sigma2 "MSE residuals squared"
   lab var _scom2 "Score test for lambda=-2"
   lab var _scom1 "Score test for lambda=-1"
   lab var _scom05 "Score test for lambda=-0.5"
   lab var _sco0 "Score test for lambda=0"
   lab var _sco05 "Score test for lambda=0.5"
   lab var _sco1 "Score test for lambda=1"
   lab var _sco2 "Score test for lambda=2"

   qui {
      g str2 _labm2="-2"
      replace _labm2="." in 2/-2

      g str2 _labm1="-1"
      replace _labm1="." in 2/-2

      g str4 _labm05="-0.5"
      replace _labm05="." in 2/-2

      g str1 _lab0="0"
      replace _lab0="." in 2/-2

      g str1 _lab2="2"
      replace _lab2="." in 2/-2

      g str1 _lab1="1"
      replace _lab1="." in 2/-2

      g str3 _lab05="0.5"
      replace _lab05="." in 2/-2

      unab labl : _lab*
      tokenize `labl'
      while "`1'"~="" {
          lab var `1' "Labels for graphs"
          mac shift
      }
   }
end