Announcement

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

  • Carhart Model: Calculating the betas

    Hi there,

    I am desperately looking for a way to estimate the alpha and the betas of the carhart 4 factor model.
    I need a code which makes a regression between the return of a stock and 4 global factors influencing the whole market. These correlation coefficients of the estimation window are the betas to calculate the expected return in the event window. My data set contains more than 1000 different stocks, and looks like following:

    days return of the stock mktrf smb hml umd intercept b_mktrf b_smb b_hml b_umd
    -200 0.012 0.0012 0.054 0.065 0.007 ? ? ? ? ?
    -199 .. ... ... .. ..
    ...
    -52
    ...
    0
    1
    2
    ..
    I need to estimate the "?" now. The Estimation Window is always <-51 and >-200, the event window 0,1.
    I have tried various way, but always failed, this is my closest try, but STATA just does not come to an end calculating:
    sort group_id date
    by group_id : gen datenum=_n
    by group_id: gen dif= date- ceo_turnover_date
    by group_id: gen dif1= ((dif)^2)^0.5
    by group_id : egen min_dif1=min(dif1)
    by group_id : gen target=datenum if dif1==min_dif1
    egen td=min(target), by( group_id )
    gen dif2=datenum-td
    by group_id : gen event_window=1 if dif2>=-2 & dif2<=2 & ret!=. & vwretd!=.
    egen count_event_obs=count(event_window), by( group_id )
    by group_id : gen estimation_window=1 if dif2<-51 & dif2>=-200 & ret!=. & vwretd!=.
    egen count_est_obs=count(estimation_window), by( group_id )
    replace event_window=0 if event_window==.
    replace estimation_window=0 if estimation_window==.
    drop if count_event_obs < 5
    drop if count_est_obs < 149
    gen alpha = .
    gen b_mktrf = .
    gen b_smb = .
    gen b_hml = .
    gen b_umd = .
    gen return_minus_rf= ret-rf
    gen predicted_return=.
    egen id_estimation=group(group_id)
    sort group_id date
    sum id_estimation
    rename return_minus_rf excess_return_interlcompany

    qui forval p = 1/`=_N' {
    l id_estimation group_id if id_estimation==`p' & dif2==0
    capture bygroup: reg excess_return_interlcompany mktrf smb hml umd if id_estimation ==`p' & estimation_window==1
    capture replace alpha = _b[_cons] in `p'
    capture replace b_mktrf = _b[mktrf] in `p'
    capture replace b_smb = _b[smb] in `p'
    capture replace b_hml = _b[hml] in `p'
    capture replace b_umd = _b[umd] in `p'
    }


    Is anyone able to offer me any help?

  • #2
    I'm not in finance so I don't know what it means to estimate a Carhat 4 factor model but your code seems very similar to one used by the "Princeton" method for Event Studies with Stata. I'm not a fan of their approach as it relies on old merge syntax and is overly complicated as I have pointed out in a previous post.

    It's difficult to present a more efficient approach without a workable data example. Here's code to create a demonstration dataset that has the same structure as the one described in #1:
    Code:
    clear
    set seed 4313
    set obs 1000
    gen group_id = _n
    gen ceo_turnover_date = runiformint(mdy(1,1,2000),mdy(1,1,2015))
    format %tdDayDDmonCCYY ceo_turnover_date
    expand 500
    bysort group_id: gen date = ceo_turnover_date -300 + _n
    format %tdDayDDmonCCYY date
    drop if inlist(dow(date),0,6) | inlist(dow(ceo_turnover_date),0,6)
    foreach v in ret mktrf smb hml umd rf {
        gen `v' = runiform()
    }
    isid group_id date, sort
    save "dataex.dta", replace
    This data example uses daily dates with trading days occurring from Mon-Fri. This type of data would be best handled using Stata's business calendars (help bcal) but to avoid straying away too far from the "Princeton" method, I'll do what they do and assume that no trading days are missing in the data. This means that for the purpose of identifying the observations within the event and estimation windows, all you need to know is the observation counter for the event day (in this case on the ceo_turnover_date) within each by-group. You can then use rangestat (from SSC) to perform the regressions (one regression per by-group). Finally, you use the coefficients to calculate predicted returns over the event window observations.
    Code:
    use "dataex.dta", clear
    
    * use a simple counter for trading days (assume no missing trading days)
    by group_id: gen day = _n
    
    * create event and estimation window identifiers
    by group_id : egen event_day = total(day * (ceo_turnover_date == date))
    by group_id : gen evt_window = inrange(day, event_day-2, event_day+2)
    by group_id : gen est_window  = inrange(day, event_day-200, event_day-52)
    
    * regressions using estimation window observations
    gen ret2use = ret - rf if est_window
    rangestat (reg) ret2use mktrf smb hml umd, interval(group_id 0 0)
    drop if reg_nobs < 149
    
    * predicted returns for event window observations
    gen p_return = b_mktrf * mktrf + ///
        b_smb * smb + b_hml * hml + b_umd * umd + b_cons if evt_window
    by group_id: egen ewcount = count(p_return)
    drop if ewcount < 5

    Comment


    • #3
      Here's a slightly slower but perhaps more intuitive way of doing the same using runby (from SSC) to process each by-group:
      Code:
      clear all
      use "dataex.dta"
      
      * use a simple counter for trading days (assume no missing trading days)
      by group_id: gen day = _n
      
      * create event and estimation window identifiers
      by group_id : egen event_day = total(day * (ceo_turnover_date == date))
      by group_id : gen evt_window = inrange(day, event_day-2, event_day+2)
      by group_id : gen est_window  = inrange(day, event_day-200, event_day-52)
      
      gen ret2use = ret - rf
      program doit
          reg ret2use mktrf smb hml umd if est_window
          if e(N) == 149 predict event_ret if evt_window, xb
      end
      runby doit, by(group_id)

      Comment

      Working...
      X