Announcement

Collapse
No announcement yet.
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • Get alphas and betas plus t-stat from panel estimation of the Fama French 3-Factor Model (large dataset)

    Hello,
    I have a panel data set with daily stock returns across a bunch of firms. I would like to estimate daily alphas (constant) and betas using the Fama French 3-Factor model with a rolling window of 250 days. As the rolling command in STATA takes ages, I use the -fastreg- command from Geertsema (see https://papers.ssrn.com/sol3/papers....act_id=2423171).
    I do not manage to adjust the code in that it stores standard errors or t-stats after each regression.
    Can anyone help me how to do that in STATA? The code that I use is as follows:

    **rolling window betas**
    gen mktrf_beta = .
    gen smb_beta = .
    gen hml_beta = .
    gen _cons_beta = .
    gen mktrf_beta_f = .
    gen smb_beta_f = .
    gen hml_beta_f = .
    gen _cons_beta_f = .

    local maxobs = 400000
    local window = 250

    timer clear
    timer on 1
    forvalues k = `window'/`maxobs' {
    local first = `k'-`window'+1
    local last = `k'
    if permno[`last'] == permno[`first'] {
    * if window covers same permno, then do estimation
    qui fastreg eret mktrf smb hml in `first'/`last'
    * save coefficients
    foreach x in mktrf smb hml _cons {
    qui replace `x'_beta_f = _be[`v'] in `last'
    }
    }
    }
    timer off 1
    timer list 1

    Thank you so much for your help.
    Best,
    Luce

  • #2
    Can anyone please help?

    Comment


    • #3
      Hi Luce,

      1. Please wrap your code with the code tag (the # in the text editor) so it is easier to read
      2. What exactly seems to be the problem? That you can't get the betas to be saved? do you get an error or it just never saves?

      Best,
      S

      Comment


      • #4
        Hi Sergio,
        Thank you for your reply. No, I can save betas, but I cannot save the corresponding t-stat or p-value attached to each of the betas. Can someone help me with how I can adjust my code so that I can also save the t-stat/p-values?
        The code that I use is:

        Code:
        **rolling window betas**
        gen mktrf_beta = .
        gen smb_beta = .
        gen hml_beta = .
        gen _cons_beta = .
        gen mktrf_beta_f = .
        gen smb_beta_f = .
        gen hml_beta_f = .
        gen _cons_beta_f = .
        
        local maxobs = 400000
        local window = 250
        
        timer clear
        timer on 1
        forvalues k = `window'/`maxobs' {
        local first = `k'-`window'+1
        local last = `k'
        if permno[`last'] == permno[`first'] {
        * if window covers same permno, then do estimation
        qui fastreg eret mktrf smb hml in `first'/`last'
        * save coefficients
        foreach x in mktrf smb hml _cons {
        qui replace `x'_beta_f = _be[`v'] in `last'
        }
        }
        }
        timer off 1
        timer list 1
        Best,
        Luce
        Last edited by Luce Mock; 19 Oct 2016, 09:35.

        Comment


        • #5
          To all financiers out there, I would like to point out that rangestat (from SSC) is supremely efficient at performing computations over a rolling window of time. The downside is that if you want more than just basic statistics, you have to provide the Mata code that performs the calculation on the relevant subset of data.

          Here's a complete example that shows how to perform a rolling regression over a 5 period window (including the current observation) using both a brute force approach and then using rangestat. If you expand the grunfeld data by a factor of 2,000 (yielding 400K observations), rangestat can perform the task in just over 5 seconds on my computer.

          Code:
          webuse grunfeld, clear
          
          * ------------------------ brute force approach --------------------------------
          gen double r2  = .
          gen double r2a  = .
          
          gen double mvalue_b = .
          gen double kstock_b = .
          gen double _cons_b  = .
          
          gen double mvalue_se = .
          gen double kstock_se = .
          gen double _cons_se  = .
          
          local nobs = _N
          qui forvalues i = 1/`nobs' {
          
              local first = `i'-5+1
              cap reg invest mvalue kstock if company == company[`i'] & inrange(year,year[`i']-4,year[`i'])
              replace r2 = e(r2) in `i'
              replace r2a = e(r2_a) in `i'
              replace mvalue_b = _b[mvalue] in `i'
              replace kstock_b = _b[kstock] in `i'
              replace _cons_b = _b[_cons] in `i'
              replace mvalue_se = _se[mvalue] in `i'
              replace kstock_se = _se[kstock] in `i'
              replace _cons_se = _se[_cons] in `i'
              
          }
          
          * ------------------------ using rangestat -------------------------------------
          * define a linear regression with intercept in Mata. Follows the sample code found at
          * http://blog.stata.com/2016/01/05/programming-an-estimation-command-in-stata-computing-ols-objects-in-mata/
          mata:
          mata clear
          mata set matastrict on
          real rowvector myreg(real matrix Xall)
          {
              real colvector y, b, Xy, e, e2, se
              real matrix X, XpX, XpXi, V
              real scalar n, k, ymean, tss, mss, r2, r2a
          
              y = Xall[.,1]                // dependent var is first column of Xall
              X = Xall[.,2::cols(Xall)]    // the remaining cols are the independent variables
              n = rows(X)                  // the number of observations
              X = X,J(n,1,1)               // add a constant
              
              // compute the OLS point estimates
              XpX  = quadcross(X, X)
              XpXi = invsym(XpX)
              b    = XpXi*quadcross(X, y)
              
              // compute the standard errors
              e  = y - X*b
              e2 = e:^2
              k  = cols(X)
              V  = (quadsum(e2)/(n-k))*XpXi
              se = sqrt(diagonal(V))
              
              // r2 and adjusted r2
              ymean = mean(y)
              tss   = sum((y :- ymean) :^ 2)        // total sum of squares
              mss   = sum( (X * b :- ymean)  :^ 2)  // model sum of squares    
              r2    = mss / tss
              r2a   = 1 - (1 - r2) * (n - 1) / (n - k)
          
              return(rows(X), r2, r2a, b', se')
          }
          end
          
          rangestat (myreg) invest mvalue kstock, interval(year -4 0) casewise by(company)
          rename myreg* (nobs myr2 myr2a b_mvalue b_kstock b_constant se_mvalue se_kstock se_constant)
          
          assert abs(r2 - myr2) < 1e-7 if nobs == 5
          assert abs(r2a - myr2a) < 1e-7 if nobs == 5
          assert abs(mvalue_b - b_mvalue) < 1e-7 if nobs == 5
          assert abs(kstock_b - b_kstock) < 1e-7 if nobs == 5
          assert abs(_cons_b - b_constant) < 1e-7 if nobs == 5
          assert abs(mvalue_se - se_mvalue) < 1e-7 if nobs == 5
          assert abs(kstock_se - se_kstock) < 1e-7 if nobs == 5
          assert abs(_cons_se - se_constant) < 1e-7 if nobs == 5
          Last edited by Robert Picard; 19 Oct 2016, 12:13. Reason: fixed typo in text

          Comment


          • #6
            Maybe you can get the standard error _se[..] and then calculate the P values "by hand"?

            Comment

            Working...
            X