Announcement

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

  • Command cumulative returns?

    Hi,

    I was wondering if there is a faster way to code cumulative return that the following code:
    Code:
    webuse grunfeld, clear
    
    xtset company year
    
    gen ret = rnormal(0,1)/100
    
    gen ln_ret= ln(1+ret)
    bys company: gen sum_ln_ret = sum(ln_ret)
    gen cum_ret = exp(sum_ln_ret)-1
    Is there a Stata command to do that?

    Also, I would like to create 1,...,T variables for T years cumulative returns ahead. I have tried the following but the cumulative returns aren't correct. Also, is there a faster way to do that? Thanks!

    Code:
    webuse grunfeld, clear
    
    xtset company year
    
    gen ret = rnormal(0,1)/100
    
    xtset year company
    
    forvalues t = 1/5 {
    gen ret_F`t'=F`t'.ret
    gen ln_F`t'=ln(1+ret_F`t')
    order ln_F*
    egen cum_ln`t' = rowmean(ln_F*)
    gen cum_r`t'=exp(cum_ln`t')-1
    }
    
    drop cum_ln* ret_F* ln_F*

  • #2
    I forgot to mention that cumuative returns can be calculated the following way:
    http://www.kellogg.northwestern.edu/...ve_returns.htm

    Please help. Thanks!

    Comment


    • #3
      This may point you in the right direction. Honestly, though, I couldn't understand what you wanted in your second question, so I decided you were over-complicating the problem. If this isn't what you want, you'll need to better explain what it is that you do want.
      Code:
      webuse grunfeld, clear
      
      xtset company year
      
      set seed 42
      gen ret = rnormal(0,1)/100
      
      gen ln_ret= ln(1+ret)
      bys company: gen sum_ln_ret = sum(ln_ret)
      gen cum_ret = exp(sum_ln_ret)-1
      
      generate cuml_ret = .
      bysort company: replace cuml_ret = (1+ret)*(1+cond(_n==1,0,cuml_ret[_n-1]))-1
      
      forvalues t=1/5{
      generate F`t' = .
      bysort company: replace F`t' = cuml_ret[_n+`t']
      }
      
      list company year ret cum_ret cuml_ret F1 F2 F3 F4 F5, sepby(company) noobs
      Last edited by William Lisowski; 12 May 2016, 20:49.

      Comment


      • #4
        In the second par, I want to create T variables that represent the T future cumulative returns:
        cum ret from t=0 to t=1
        cum ret from t=0 to t=2
        .................................
        cum ret from t=0 to t=T

        Comment


        • #5
          I assume that when you ask about faster way to code, you are looking for a more compact or simpler code. Logs are used here because Stata does not have a running product function so a running sum is used instead. As William as shown, you can perform a running product using a lag. Here's another version:

          Code:
          set seed 31241
          webuse grunfeld, clear
          
          gen ret = rnormal(0,1)/100
          
          * logs are used because there isn't a cumulative product function
          by company: gen double sum_ln_ret = sum(ln(1+ret))
          gen double cum_ret = exp(sum_ln_ret)-1
          
          * cumulative returns without a running sum
          gen double cret  = ret
          by company: replace cret = (1+ret) * (1+L.cret) - 1 if _n > 1
          
          assert abs(cret - cum_ret) < 1e-15
          Note that the value of each observation depends on the computed value of the previous observation, so computational errors will accumulate and such computations should always be performed using doubles.

          As I understand it, Finance people do this because data includes returns but not prices. Since I don't do Finance things, I wrote the little example below to show that with cumulative returns, you can determine a current price starting from an original price:

          Code:
          * set the original price such that with the initial return, it
          * amounts to the id of the company
          by company: gen double original_price = company[1] / (1+ret[1])
          
          * the evolution of the price
          by company: gen double price = original_price * (1+ret)
          by company: replace price = L.price * (1+ret) if _n > 1
          
          * show that we can get to the current price using the original
          * price multiplied by the cumulative return
          by company: gen double current_price = original_price * (1+cret)
          assert abs(current_price - price) < 1e-14
          Now to address the 5 year cumulative return from the current observation, I assume that you are looking for a return that would generate the price in 5 year based on the current price. I believe this is simply, for each of the future years:
          Code:
          forvalues i = 1/5 {
              gen double cret`i' = (1+F`i'.cret) / (1+cret) - 1
          }
          You can double-check this manually using these two methods, tsegen is from SSC:
          Code:
          * double check manually
          gen double ret1y_check = (1+F1.ret) - 1
          gen double ret2y_check = (1+F1.ret) * (1+F2.ret) - 1
          gen double ret3y_check = (1+F1.ret) * (1+F2.ret) * (1+F3.ret) - 1
          gen double ret4y_check = (1+F1.ret) * (1+F2.ret) * (1+F3.ret) *(1+F4.ret) - 1
          gen double ret5y_check = (1+F1.ret) * (1+F2.ret) * (1+F3.ret) *(1+F4.ret) *(1+F5.ret) - 1
          
          * 5 year cumulative returns with respect to current obs using -tsegen-
          gen double lret1 = ln(1+ret)
          tsegen double ret5y = rowtotal(F(1/5).lret1,5)
          replace ret5y = exp(ret5y) - 1
          
          assert abs(ret5y - ret5y_check) < 1e-15 if !mi(ret5y)
          assert abs(ret5y - cret5) < 1e-15 if !mi(ret5y)
          Finally, show that we can match the price in 5 years using the current price and the computed 5 year cumulative return:
          Code:
          * match price in 5 year using current price
          gen double pricein5 = price * (1+cret5)
          gen double pricein5F5 = F5.price
          assert abs(pricein5 - pricein5F5) < 1e-14 if !mi(pricein5)

          Comment

          Working...
          X