Announcement

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

  • #31
    The "optimization" of lambda is carried out by trying out different values of lambda and retaining the results that give the lowest value of HRMSE among those values tried. But lambda is a continuous variable. The code shown considers as possible values of lambda 0.78, 0.79, 0.80, ..., 0.95, 0.96, 0.97. Values of lambda between those numbers are not considered. So when the calculation concludes, say, that 0.83 is the optimal value of lambda, we cannot exclude the possibility that the actual optimal value is .0833 or .08275169 or something like that, because those values were not considered. All we can say is that to within a precision of 0.01, 0.83 turned out best. If you need more precision on lambda than that, we would have to try a series of values that increased more slowly than 0.01 at each step. For example, in principle, it is possible to try lambda values of 0.780, 0.781, 0.782, 0.783, ..., 0.967, 0.968, 0.969, 0.097. This will give a value of lambda with a precision of 0.001. But it also involves 10 times as much calculation, which means the code runs 10 times slower. You can make this trade-off between precision and speed any way you like. (Including, you could go in the other direction: if a precision of 0.1 were sufficient, we could just do 0.7, 0.8, 0.9, and the result would be less precise but obtained in about 1/3 as much time.) The precision depends on just how fine-grained (difference between successive trial values of lambda) the analysis is.

    The direct definition of sigma2 is the mean value of (rt - rt_mean)2. Given that the calculation of sigma2 is done many times in this code, using the -egen, sd()- function would make the code very slow. So I am using a recursive algorithm for calculating variances, Welford's algorithm. (Actually, a slight variation on Welford's algorithm that improves its numerical stability). I put in the comment naming it because, if you are not familiar with Welford's algorithm, you could look at it and have no idea what those lines of code are doing--it isn't immediately obvious. I wanted you to know that that was a calculation of the variance over the window. If you want to read more about different approaches to calculating variances, the Wikipedia article (https://en.wikipedia.org/wiki/Algori...ating_variance) is good. It does include the formulas for Welford's algorithm, and you will recognize that my code is an implementation of those.

    Comment


    • #32
      Thanks for this explanation. I ran the code on a file with data on about 850 stock_id's over 2002 to 2022. The code took about 21 hours to generate the output.

      Comment


      • #33
        I'm not surprised. The use of these moving windows makes this a very long computation. Not only does each single observation have to be treated separately, but the calculations to be performed for each observation (assuming it has a complete window of preceding months) involves a lot of work as well, with an already iterative calculation of ewma repeated for 20 different values of lambda.

        Comment


        • #34
          I have a small query. In #29, for getting ewma_idio, if i want to do regression on ert and emkt instead of rt and mkt, where i need to change the code? ert and emkt is nothing but ert = rt - rf and emkt = mkt - rf.

          Moreover, before running #29, i would have have run #5 and would like to retain variables like rt_sd, rt_skewness, rt_kurtosis, beta, idiovol, idskew and coskew alongwith other main data variables and out put of #29 in the file.

          ​​​​​​
          Last edited by Sartaj Hussain; 17 Jan 2023, 13:05.

          Comment


          • #35
            I think this will do it:
            Code:
            capture program drop one_window
            program define one_window
                local best_lambda .
                local best_hrmse_sq .
                local best_ewma_idio .
                if _N == window[1] {
                    gsort -mdate
                    //  CALCULATE RUNNING VARIANCE BY WELFORD'S ALGORITHM
                    gen double M1 = rt in 1
                    replace M1 = M1[_n-1] + (rt - M1[_n-1])/_n in 2/L
                    gen double M2 = 0 in 1
                    replace M2 = M2[_n-1] + (rt - M1[_n-1])*(rt - M1) in 2/L
                    gen double sigma_sq = cond(_n == 1, 0, M2/(_n-1))
                    drop M1 M2
                    //  LOOP OVER VALUES OF LAMBDA CALCULATING EWMA IDIO
                    //  AND SAVING ONE WITH SMALLEST "RMSE"
                    gen double rt_demeaned_sq = .
                    gen double wt = .
                    gen double weighted_rt_demeaned_sq = .
                    gen double ewma_rt = .
                    gen double weighted_resid_sq = .
                    gen double ewma_idio = .
                    gen double hrmse_sq = .
                    forvalues ilambda = 78/97 {
                        local lambda = `ilambda'/100
                        summ rt, meanonly
                        replace rt_demeaned_sq = (rt-`r(mean)')^2
                        replace wt = 1-`lambda' in 1
                        replace wt = `lambda'*wt[_n-1] in 2/L
                        replace weighted_rt_demeaned_sq = wt*rt_demeaned_sq
                        replace ewma_rt = sum(weighted_rt_demeaned_sq)
                        quietly regress ert emkt
                        predict resid, resid
                        replace weighted_resid_sq = wt*resid^2
                        replace ewma_idio = sum(weighted_resid_sq)
                        replace hrmse_sq = sum((1-sigma_sq/ewma_idio)^2)/_n
                        drop resid
                        if hrmse_sq[_N] < `best_hrmse_sq' {
                            local best_lambda = `lambda'
                            local best_hrmse_sq = hrmse_sq[_N]
                            local best_ewma_idio = ewma_idio[_N]
                        }
                    }
                    keep in L
                    keep stock_id stock date mdate rt mkt ert emkt ewma_* sigma_sq
                    foreach v of varlist date mdate rt mkt ert emkt {
                        replace `v' = current_`v'
                    }
                    foreach v of varlist rt_sd rt_skewness rt_kurtosis beta idiovol ///
                        idskew coskew {
                            gen `v' = current_`v'
                    }
                    gen lambda = `best_lambda'
                    replace ewma_idio = `best_ewma_idio'
                    gen hrmse = sqrt(`best_hrmse_sq')
                }
                exit
            end
            
            gen mdate = mofd(date)
            format mdate %tm
            
            local window 36
            gen window = `window'
            
            gen ert = rt - rf
            gen emkt = mkt - rf
            
            rangerun one_window, by(stock_id) interval(mdate -`window' -1) sprefix(current_)
            Note: I am assuming that you still want to calculate ewma_rt from demeaned rt, not demeaned ert. Only the calculation of ewma_idio is changed to use ert and emkt.

            As I do not have an example data set that includes this new variable rf, this code is not tested. But given the sample nature of the changes made, I think it should work properly when used with the appropriate data.

            Comment


            • #36
              Thanks. Just needed a bit clarification. In the #35, what does "quietly" do and what is the function of current_`v' particulary in below mentioned part.

              Code:
              foreach v of varlist rt_sd rt_skewness rt_kurtosis beta idiovol ///            idskew coskew {                gen `v' = current_`v'        }
              Last edited by Sartaj Hussain; 17 Jan 2023, 20:58.

              Comment


              • #37
                The -quietly- tells Stata not to show the output of the command that follows it. Actually, it isn't needed there, because -rangerun- automatically suppresses all the output from program one_window. The reason it's there is that while I was developing program one_window, I ran -rangerun- with an option, -verbose-, that caused it to allow the output of program one_window to appear. But I didn't need to see the regression output, so I put -quietly- in front of that so I would see everything else, but not that. I meant to take it out, but forgot to. It does no harm leaving it there, but it also does no good. Indeed, it does nothing at all.

                The current_`v' part of the code is needed because, for any given observation that we are doing the calculations on, -rangerun- actually works only with the 36 preceding observations: the current observation is not part of the window. But that means that the values of rt_sd, rt_skewness, etc. that correspond to the current observation for which ewma_idio, etc. are being calculated, are not in the data in the window. Notice that the -rangerun- command specifies an option -prefix(current_)-. That option tells -rangerun- before it selects the observations in the window, to save the values of all the variables in the current observation as scalars whose names are the variable names, prefixed by current_. So current_rt_sd means the value of rt_sd in the current observation. The output produced by -rangerun- is taken from the final observation in the window. In that observation, the variables rt_sd, rt_skewness, etc. were dropped (because they are not included in the -keep- statement. So the loop generates new variables rt_sd etc. and populates them with the values from the current observation of the original data.

                The end result is that the final accumulated results after -rangerun- include the correct values of rt_sd, rt_skewness, etc. associated with the correct stock_id, mdate, rt, etc. from the original data, and also associated with the values of ewma_idio and sigma_sq calculated using the data in the preceding 36 observations.

                Yes, it's a bit roundabout, but it's the only way to blend information from the current observation with results calculated from the window when the window does not itself contain the current observation.
                Last edited by Clyde Schechter; 17 Jan 2023, 22:19.

                Comment


                • #38
                  Please check #35. I ran it. However, it did not save any ewma measures. Additionally it just generated window, ert and emkt.
                  Last edited by Sartaj Hussain; 18 Jan 2023, 18:19.

                  Comment


                  • #39
                    Sorry. I see the mistake.

                    Code:
                    capture program drop one_window
                    program define one_window
                        local best_lambda .
                        local best_hrmse_sq .
                        local best_ewma_idio .
                        if _N == window[1] {
                            display "Entered Calculation"
                            gsort -mdate
                            //  CALCULATE RUNNING VARIANCE BY WELFORD'S ALGORITHM
                            gen double M1 = rt in 1
                            replace M1 = M1[_n-1] + (rt - M1[_n-1])/_n in 2/L
                            gen double M2 = 0 in 1
                            replace M2 = M2[_n-1] + (rt - M1[_n-1])*(rt - M1) in 2/L
                            gen double sigma_sq = cond(_n == 1, 0, M2/(_n-1))
                            drop M1 M2
                            //  LOOP OVER VALUES OF LAMBDA CALCULATING EWMA IDIO
                            //  AND SAVING ONE WITH SMALLEST "RMSE"
                            gen double rt_demeaned_sq = .
                            gen double wt = .
                            gen double weighted_rt_demeaned_sq = .
                            gen double ewma_rt = .
                            gen double weighted_resid_sq = .
                            gen double ewma_idio = .
                            gen double hrmse_sq = .
                            forvalues ilambda = 78/97 {
                                local lambda = `ilambda'/100
                                summ rt, meanonly
                                replace rt_demeaned_sq = (rt-`r(mean)')^2
                                replace wt = 1-`lambda' in 1
                                replace wt = `lambda'*wt[_n-1] in 2/L
                                replace weighted_rt_demeaned_sq = wt*rt_demeaned_sq
                                replace ewma_rt = sum(weighted_rt_demeaned_sq)
                                quietly regress ert emkt
                                predict resid, resid
                                replace weighted_resid_sq = wt*resid^2
                                replace ewma_idio = sum(weighted_resid_sq)
                                replace hrmse_sq = sum((1-sigma_sq/ewma_idio)^2)/_n
                                drop resid
                                if hrmse_sq[_N] < `best_hrmse_sq' {
                                    local best_lambda = `lambda'
                                    local best_hrmse_sq = hrmse_sq[_N]
                                    local best_ewma_idio = ewma_idio[_N]
                                }
                            }
                            keep in L
                            keep stock_id stock date mdate rt mkt ert emkt ewma_* sigma_sq
                            foreach v of varlist date mdate rt mkt ert emkt {
                                replace `v' = current_`v'
                            }
                            foreach v in rt_sd rt_skewness rt_kurtosis beta idiovol ///
                                idskew coskew {
                                    gen `v' = current_`v'
                            }
                            gen lambda = `best_lambda'
                            replace ewma_idio = `best_ewma_idio'
                            gen hrmse = sqrt(`best_hrmse_sq')
                        }
                        exit
                    end
                    
                    gen mdate = mofd(date) // REMOVE THIS COMMAND IF mdate ALREADY EXISTS
                    format mdate %tm
                    
                    local window 36
                    gen window = `window'
                    
                    gen ert = rt - rf
                    gen emkt = mkt - rf
                    
                    rangerun one_window, by(stock_id) interval(mdate -`window' -1) sprefix(current_)
                    will get you your results.

                    Comment


                    • #40
                      Thanks! It works very well. But one thing i want to put is that i compare results of rt_sd produced by #5 and sigma_sq produced by #39. I suppose they should have been similar. Why are the two different.

                      Comment


                      • #41
                        I suppose they should have been similar.
                        No, they should not. rt_sd is a standard deviation, sigma_sq is the variance. So sigma_sq should equal (rt_sd)2. And if you check this in the results of the code you will see that, at least to float precision (6 significant figures), that is true:
                        Code:
                        . * Example generated by -dataex. For more info, type help dataex
                        . clear
                        
                        . input float stock_id str54 stock int date float(rt mkt)
                        
                              stock_id                                                   stock      date         rt        mkt
                          1. 1 "3M India Ltd."         15310    -.0887372  -.03955433
                          2. 1 "3M India Ltd."         15341  -.026404494  .021463245
                          3. 1 "3M India Ltd."         15372    .04250817   .07242663
                          4. 1 "3M India Ltd."         15400      .149262  -.02732929
                          5. 1 "3M India Ltd."         15431   .008990207  -.04528218
                          6. 1 "3M India Ltd."         15461   -.10039777   -.0853004
                          7. 1 "3M India Ltd."         15492   .008666431  .002052819
                          8. 1 "3M India Ltd."         15522    .05207785    -.118447
                          9. 1 "3M India Ltd."         15553    .05333333    .0436935
                         10. 1 "3M India Ltd."         15584  -.003164557  -.04591998
                         11. 1 "3M India Ltd."         15614   .003174603 -.012602217
                         12. 1 "3M India Ltd."         15645  -.008227848   .04842421
                         13. 1 "3M India Ltd."         15675  -.034620292   .04941667
                         14. 1 "3M India Ltd."         15706  -.022806147 -.033169586
                         15. 1 "3M India Ltd."         15737   -.06308135  .009157823
                         16. 1 "3M India Ltd."         15765   -.13267148   -.0782898
                         17. 1 "3M India Ltd."         15796     .1862643 -.010596635
                         18. 1 "3M India Ltd."         15826    .10526316   .09825777
                         19. 1 "3M India Ltd."         15857    .06095238   .06033916
                         20. 1 "3M India Ltd."         15887  .0041891085   .04996381
                         21. 1 "3M India Ltd."         15918    .10250298     .136254
                         22. 1 "3M India Ltd."         15949    .11783784  .003297209
                         23. 1 "3M India Ltd."         15979   .003384913   .06014735
                         24. 1 "3M India Ltd."         16010     .2060241    .0712712
                         25. 1 "3M India Ltd."         16040    .03886114   .18632157
                         26. 1 "3M India Ltd."         16071    -.2037696  -.07444008
                         27. 1 "3M India Ltd."         16102   -.02415459  .006037154
                         28. 1 "3M India Ltd."         16131    .02722772  .007745117
                         29. 1 "3M India Ltd."         16162     .1827711  .008075608
                         30. 1 "3M India Ltd."         16192   -.17327085   -.1837298
                         31. 1 "3M India Ltd."         16223    .06653524   .05848542
                         32. 1 "3M India Ltd."         16253   .016751386   .05154314
                         33. 1 "3M India Ltd."         16284    .03397341 -.002812333
                         34. 1 "3M India Ltd."         16315     .1354945   .09279332
                         35. 1 "3M India Ltd."         16345   -.04432401  .005587839
                         36. 1 "3M India Ltd."         16376   .067341775   .07218837
                         37. 1 "3M India Ltd."         16406     .0975332    .0309204
                         38. 1 "3M India Ltd."         16437  -.006310512 -.030511327
                         39. 2 "3P Land Holdings Ltd." 15310   -.04444445  -.03955433
                         40. 2 "3P Land Holdings Ltd." 15341  -.011627907  .021463245
                         41. 2 "3P Land Holdings Ltd." 15372     .2235294   .07242663
                         42. 2 "3P Land Holdings Ltd." 15400   -.09615385  -.02732929
                         43. 2 "3P Land Holdings Ltd." 15431   -.28723404  -.04528218
                         44. 2 "3P Land Holdings Ltd." 15461     .9701493   -.0853004
                         45. 2 "3P Land Holdings Ltd." 15492    .25757575  .002052819
                         46. 2 "3P Land Holdings Ltd." 15522    -.1566265    -.118447
                         47. 2 "3P Land Holdings Ltd." 15553    -.3214286    .0436935
                         48. 2 "3P Land Holdings Ltd." 15584   -.15789473  -.04591998
                         49. 2 "3P Land Holdings Ltd." 15614            0 -.012602217
                         50. 2 "3P Land Holdings Ltd." 15645            0   .04842421
                         51. 2 "3P Land Holdings Ltd." 15675         .125   .04941667
                         52. 2 "3P Land Holdings Ltd." 15706   -.12777779 -.033169586
                         53. 2 "3P Land Holdings Ltd." 15737     .2101911  .009157823
                         54. 2 "3P Land Holdings Ltd." 15765    -.2105263   -.0782898
                         55. 2 "3P Land Holdings Ltd." 15796    .13333334 -.010596635
                         56. 2 "3P Land Holdings Ltd." 15826    -.1117647   .09825777
                         57. 2 "3P Land Holdings Ltd." 15857     .3642384   .06033916
                         58. 2 "3P Land Holdings Ltd." 15887   -.05339806   .04996381
                         59. 2 "3P Land Holdings Ltd." 15918    .11794872     .136254
                         60. 2 "3P Land Holdings Ltd." 15949    -.0825688  .003297209
                         61. 2 "3P Land Holdings Ltd." 15979         -.19   .06014735
                         62. 2 "3P Land Holdings Ltd." 16010     .4691358    .0712712
                         63. 2 "3P Land Holdings Ltd." 16040    .25210086   .18632157
                         64. 2 "3P Land Holdings Ltd." 16071    -.3389262  -.07444008
                         65. 2 "3P Land Holdings Ltd." 16102    .11675127  .006037154
                         66. 2 "3P Land Holdings Ltd." 16131     .0909091  .007745117
                         67. 2 "3P Land Holdings Ltd." 16162   -.06666667  .008075608
                         68. 2 "3P Land Holdings Ltd." 16192          .25   -.1837298
                         69. 2 "3P Land Holdings Ltd." 16223   -.14285715   .05848542
                         70. 2 "3P Land Holdings Ltd." 16253    .15833333   .05154314
                         71. 2 "3P Land Holdings Ltd." 16284    .26258993 -.002812333
                         72. 2 "3P Land Holdings Ltd." 16315    .36182335   .09279332
                         73. 2 "3P Land Holdings Ltd." 16345    .10878661  .005587839
                         74. 2 "3P Land Holdings Ltd." 16376    .10377359   .07218837
                         75. 2 "3P Land Holdings Ltd." 16406    .14529915    .0309204
                         76. 2 "3P Land Holdings Ltd." 16437   -.19701493 -.030511327
                         77. 3 "A B B India Ltd."      15310  -.004149378  -.03955433
                         78. 3 "A B B India Ltd."      15341    .09068628  .021463245
                         79. 3 "A B B India Ltd."      15372      .154382   .07242663
                         80. 3 "A B B India Ltd."      15400    .03387191  -.02732929
                         81. 3 "A B B India Ltd."      15431   .002824327  -.04528218
                         82. 3 "A B B India Ltd."      15461   -.07641757   -.0853004
                         83. 3 "A B B India Ltd."      15492    .09270177  .002052819
                         84. 3 "A B B India Ltd."      15522   .031069767    -.118447
                         85. 3 "A B B India Ltd."      15553    .01930711    .0436935
                         86. 3 "A B B India Ltd."      15584   -.00495663  -.04591998
                         87. 3 "A B B India Ltd."      15614   -.14659314 -.012602217
                         88. 3 "A B B India Ltd."      15645 -.0002084636   .04842421
                         89. 3 "A B B India Ltd."      15675   .036905754   .04941667
                         90. 3 "A B B India Ltd."      15706    .12306455 -.033169586
                         91. 3 "A B B India Ltd."      15737    .14753805  .009157823
                         92. 3 "A B B India Ltd."      15765    -.1015759   -.0782898
                         93. 3 "A B B India Ltd."      15796    .07033692 -.010596635
                         94. 3 "A B B India Ltd."      15826    .11487912   .09825777
                         95. 3 "A B B India Ltd."      15857    .07335177   .06033916
                         96. 3 "A B B India Ltd."      15887   .028338984   .04996381
                         97. 3 "A B B India Ltd."      15918     .2542194     .136254
                         98. 3 "A B B India Ltd."      15949   .003153911  .003297209
                         99. 3 "A B B India Ltd."      15979    .09955984   .06014735
                        100. 3 "A B B India Ltd."      16010   .010293557    .0712712
                        101. end
                        
                        . format %td date
                        
                        .
                        . gen mdate = mofd(date)
                        
                        . format mdate %tm
                        
                        .
                        .
                        . rangestat (count) rt (sd) rt (skewness) rt (kurtosis) rt, by(stock_id) interval(mdate -36 -1)
                        
                        . foreach v of varlist rt_sd rt_skewness rt_kurtosis {
                          2.     replace `v' = . if rt_count < 36
                          3. }
                        (90 real changes made, 90 to missing)
                        (90 real changes made, 90 to missing)
                        (90 real changes made, 90 to missing)
                        
                        . drop rt_count
                        
                        .
                        . rangestat (reg) rt mkt, by(stock_id) interval(mdate -36 -1)
                        
                        . gen residual = rt - b_mkt*mkt - b_cons
                        (9 missing values generated)
                        
                        . rename b_mkt beta
                        
                        . drop reg_r2 reg_adj_r2 *_cons se_* b_cons
                        
                        . rangestat (sd) idiovol = residual (skewness) idskew = residual, ///
                        >     by(stock_id) interval(mdate -36 -1)
                        
                        . foreach v of varlist beta idiovol idskew {
                          2.     replace `v' = . if reg_nobs < 36
                          3. }
                        (87 real changes made, 87 to missing)
                        (81 real changes made, 81 to missing)
                        (81 real changes made, 81 to missing)
                        
                        . drop residual reg_nobs
                        
                        .     
                        . gen mkt_sq = mkt*mkt
                        
                        . rangestat (reg) rt mkt mkt_sq, by(stock_id) interval(mdate -36 -1)
                        
                        . rename b_mkt_sq coskew
                        
                        . replace coskew = . if reg_nobs < 36
                        (84 real changes made, 84 to missing)
                        
                        . drop b_mkt b_cons se_* reg_* mkt_sq
                        
                        .
                        . capture program drop one_window
                        
                        . program define one_window
                          1.     local best_lambda .
                          2.     local best_hrmse_sq .
                          3.     local best_ewma_idio .
                          4.     if _N == window[1] {
                          5.         display "Entered Calculation"
                          6.         gsort -mdate
                          7.         //  CALCULATE RUNNING VARIANCE BY WELFORD'S ALGORITHM
                        .         gen double M1 = rt in 1
                          8.         replace M1 = M1[_n-1] + (rt - M1[_n-1])/_n in 2/L
                          9.         gen double M2 = 0 in 1
                         10.         replace M2 = M2[_n-1] + (rt - M1[_n-1])*(rt - M1) in 2/L
                         11.         gen double sigma_sq = cond(_n == 1, 0, M2/(_n-1))
                         12.         drop M1 M2
                         13.         //  LOOP OVER VALUES OF LAMBDA CALCULATING EWMA IDIO
                        .         //  AND SAVING ONE WITH SMALLEST "RMSE"
                        .         gen double rt_demeaned_sq = .
                         14.         gen double wt = .
                         15.         gen double weighted_rt_demeaned_sq = .
                         16.         gen double ewma_rt = .
                         17.         gen double weighted_resid_sq = .
                         18.         gen double ewma_idio = .
                         19.         gen double hrmse_sq = .
                         20.         forvalues ilambda = 78/97 {
                         21.             local lambda = `ilambda'/100
                         22.             summ rt, meanonly
                         23.             replace rt_demeaned_sq = (rt-`r(mean)')^2
                         24.             replace wt = 1-`lambda' in 1
                         25.             replace wt = `lambda'*wt[_n-1] in 2/L
                         26.             replace weighted_rt_demeaned_sq = wt*rt_demeaned_sq
                         27.             replace ewma_rt = sum(weighted_rt_demeaned_sq)
                         28.             quietly regress ert emkt
                         29.             predict resid, resid
                         30.             replace weighted_resid_sq = wt*resid^2
                         31.             replace ewma_idio = sum(weighted_resid_sq)
                         32.             replace hrmse_sq = sum((1-sigma_sq/ewma_idio)^2)/_n
                         33.             drop resid
                         34.             if hrmse_sq[_N] < `best_hrmse_sq' {
                         35.                 local best_lambda = `lambda'
                         36.                 local best_hrmse_sq = hrmse_sq[_N]
                         37.                 local best_ewma_idio = ewma_idio[_N]
                         38.             }
                         39.         }
                         40.         keep in L
                         41.         keep stock_id stock date mdate rt mkt ert emkt ewma_* sigma_sq
                         42.         foreach v of varlist date mdate rt mkt ert emkt {
                         43.             replace `v' = current_`v'
                         44.         }
                         45.         foreach v in rt_sd rt_skewness rt_kurtosis beta idiovol ///
                        >             idskew coskew {
                         46.                 gen `v' = current_`v'
                         47.         }
                         48.         gen lambda = `best_lambda'
                         49.         replace ewma_idio = `best_ewma_idio'
                         50.         gen hrmse = sqrt(`best_hrmse_sq')
                         51.     }
                         52.     exit
                         53. end
                        
                        .
                        .
                        . local window 36
                        
                        . gen window = `window'
                        
                        .
                        . gen rf = rnormal(0, 0.01)
                        
                        .
                        . gen ert = rt - rf
                        
                        . gen emkt = mkt - rf
                        
                        .
                        . rangerun one_window, by(stock_id) interval(mdate -`window' -1) sprefix(current_)
                          (using rangestat version 1.1.1)
                        
                        .
                        . assert float(rt_sd^2) == float(sigma_sq)
                        
                        .
                        Note: I don't have an example data set from you that contains a variable rf, so I just stuck in some random numbers so I could run this code.

                        Comment


                        • #42
                          Yes, you are right. I had wrongly defined in #25 as

                          Where the numerator, i.e. sigma squared t is the realised volatility, which is standard deviation of the rt and the denominator, i.e. sigma hat squared t is the ewma volatility of rt. For a given month, we minimise HRMSE subject to:
                          But you have specified rightly for calculation of hrmse. Right?

                          Comment


                          • #43
                            Good question. You have correctly quoted the wording from #25. However, it is bizarre to use the notation sigma squared t to refer to the standard deviation itself. I had taken this to simply be inaccurate use of language and wrote the code on the assumption that in the formula, which appeared to be pasted from some reference, the numerator referred to the variance, not the standard deviation. It is easy enough to make the change to standard deviation. You have only to replace sigma_sq by sqrt(sigma_sq) in -replace hrmse_sq = sum((1-sigma_sq/ewma_idio)^2)/_n.

                            But before you do that, I strongly urge you to double check what the correct expression is. Not only is it strange to use the sigma squared notation to refer to a standard deviation, but the ratio of a standard deviation to what is both denoted as a variance (sigma hat squared) and calculated similarly to a variance (as a weighted sum of squared residuals) in an expression like that is also mathematically anomalous and I cannot see any way to assign a meaning to it under that interpretation. I would be astonished to learn that the formula truly places the standard deviation, not the variance, there.

                            Comment


                            • #44
                              This is one of the codes we used in past. As I understand, it groups rt of stocks into value-weighted and equal-weighted deciles based on previous fiscal year value of beta. In this case, the fiscal year runs through July to June. Further, value-weighted returns for a decile are generated using immediate past month mcap value.

                              Code:
                              xtset stock_id mdate
                              gen int ref_month = mofd(dofy(yofd(dofm(mdate-6))))+5
                              format ref_month %tm
                              rangestat (max) lagged_beta = beta, by(stock_id)interval(mdate ref_month ref_month)
                              gen lagged_mcap = L1.mcap
                              by mdate, sort: egen beta_decile = xtile (lagged_beta), nq(10)
                              
                              capture program drop one_weighted_return
                              program define one_weighted_return
                                  if !missing(beta_decile){
                                      egen numerator = total(lagged_mcap*rt)
                                      egen denominator = total(lagged_mcap)
                                      gen vw_mean_rt = numerator/denominator
                                      egen ew_mean_rt = mean(rt)
                                  }
                                  exit
                              end
                              
                              runby one_weighted_return, by(mdate beta_decile)
                              
                              keep mdate beta_decile *_mean_rt
                              drop if missing(beta_decile, vw_mean_rt, ew_mean_rt) // THIS COMMAND SHOULD PREVENT THE RESHAPE ERROR
                              
                              by mdate *_decile, sort: gen stock_count = _N
                              by mdate beta_decile, sort: keep if _n == 1
                              
                              gen str32 group = "beta_d" + string(beta_d) + "_"
                              drop *_decile
                              reshape wide  @stock_count  ew_mean_@rt vw_mean_@rt, i(mdate) j(group) string
                              Now I need some changes to this code as follows:

                              Variant 1 (Yearly sorts)
                              The fiscal year should be defined as January to December and stocks be grouped into deciles following previous fiscal December month value of beta. The value-weighted returns for a decile should be generated using previous fiscal year December mcap value. This process should repeat every year and likewise till the end.

                              Variant 2 (Half yearly sorts)
                              The fiscal year is defined variant 1 but stocks to be grouped into deciles following previous fiscal year December month beta for next six months till June, then from July onwards till December following current fiscal year June end beta. The value-weighted returns for a decile should also revise mcap values, January to June – previous fiscal year December month mcap and July to December, current fiscal year June month mcap. This process should repeat every half year and likewise till the end.

                              Variant 3 (Quarter yearly sorts)
                              Same as Variant 2 but values of beta and mcap should change every three months. Say for January month, groupings should be on previous fiscal year December beta and for April month on current fiscal year March beta and so on till the end. For value-weighted rt’s of deciles, weights should also revise three monthly like beta for grouping.

                              Variant 4 (Monthly yearly sorts)
                              Same as Variant 2 but values of beta and mcap should change every month months for making of decile groups. Say January month, groupings should be on previous fiscal year December beta, for February month, on current fiscal year January beta and so on. Weighting of value-weighted deciles for each month be on previous month mcap and so on till end.

                              The following needs to be included in each variant:

                              In each of these variants, for each decile (both equal and value), mean value of beta, mean value of rt and its corresponding Newey and west (1987) adjusted t-statistics using 5 lags. The mean rt is to be obtained by regressing each deciles’ rt’s on constant only.

                              Example Data:

                              Code:
                              * Example generated by -dataex-. For more info, type help dataex
                              clear
                              input float stock_id str54 stock int date float(mdate ert) double(beta mcap)
                              1 "3M India Ltd."         15310 503   -.09458616 .  300.78
                              1 "3M India Ltd."         15341 504  -.031701893 .  292.84
                              1 "3M India Ltd."         15372 505    .03747085 .  305.28
                              1 "3M India Ltd."         15400 506    .14428975 .  350.85
                              1 "3M India Ltd."         15431 507  .0040179635 .     354
                              1 "3M India Ltd."         15461 508   -.10572764 .  318.46
                              1 "3M India Ltd."         15492 509  .0036941874 .  321.22
                              1 "3M India Ltd."         15522 510    .04736606 .  337.95
                              1 "3M India Ltd."         15553 511    .04865415 .  355.98
                              1 "3M India Ltd."         15584 512  -.007843738 .  354.85
                              1 "3M India Ltd."         15614 513  -.001308996 .  355.98
                              1 "3M India Ltd."         15645 514   -.01238505 .  353.05
                              1 "3M India Ltd."         15675 515   -.03907128 .  340.82
                              1 "3M India Ltd."         15706 516   -.02738759 .  333.05
                              1 "3M India Ltd."         15737 517   -.06779314 .  312.04
                              1 "3M India Ltd."         15765 518   -.13744837 .  270.64
                              1 "3M India Ltd."         15796 519    .18256493 .  321.05
                              1 "3M India Ltd."         15826 520     .1013674 .  354.85
                              1 "3M India Ltd."         15857 521    .05692584 .  376.48
                              1 "3M India Ltd."         15887 522  .0003260844 .  378.06
                              1 "3M India Ltd."         15918 523    .09863996 .  416.81
                              1 "3M India Ltd."         15949 524    .11410566 .  465.92
                              1 "3M India Ltd."         15979 525  -.000641624 .   467.5
                              1 "3M India Ltd."         16010 526    .20255393 .  563.82
                              1 "3M India Ltd."         16040 527   .035390977 .  585.73
                              2 "3P Land Holdings Ltd." 15310 503    -.0502934 .     3.1
                              2 "3P Land Holdings Ltd." 15341 504  -.016925305 .    3.06
                              2 "3P Land Holdings Ltd." 15372 505     .2184921 .    3.74
                              2 "3P Land Holdings Ltd." 15400 506    -.1011261 .    3.38
                              2 "3P Land Holdings Ltd." 15431 507    -.2922063 .    2.41
                              2 "3P Land Holdings Ltd." 15461 508     .9648194 .    4.75
                              2 "3P Land Holdings Ltd." 15492 509     .2526035 .    5.98
                              2 "3P Land Holdings Ltd." 15522 510    -.1613383 .    5.04
                              2 "3P Land Holdings Ltd." 15553 511    -.3261077 .    3.42
                              2 "3P Land Holdings Ltd." 15584 512    -.1625739 .    2.88
                              2 "3P Land Holdings Ltd." 15614 513  -.004483599 .    2.88
                              2 "3P Land Holdings Ltd." 15645 514  -.004157201 .    2.88
                              2 "3P Land Holdings Ltd." 15675 515      .120549 .    3.24
                              2 "3P Land Holdings Ltd." 15706 516   -.13235922 .    2.83
                              2 "3P Land Holdings Ltd." 15737 517     .2054793 .    3.42
                              2 "3P Land Holdings Ltd." 15765 518    -.2153032 .     2.7
                              2 "3P Land Holdings Ltd." 15796 519    .12963396 .    3.06
                              2 "3P Land Holdings Ltd." 15826 520   -.11566047 .    2.72
                              2 "3P Land Holdings Ltd." 15857 521     .3602119 .    3.71
                              2 "3P Land Holdings Ltd." 15887 522   -.05726108 .    3.51
                              2 "3P Land Holdings Ltd." 15918 523     .1140857 .    3.92
                              2 "3P Land Holdings Ltd." 15949 524     -.086301 .     3.6
                              2 "3P Land Holdings Ltd." 15979 525   -.19402653 .    2.92
                              2 "3P Land Holdings Ltd." 16010 526     .4656656 .    4.28
                              2 "3P Land Holdings Ltd." 16040 527     .2486307 .    5.36
                              3 "A B B India Ltd."      15310 503  -.009998336 .  864.59
                              3 "A B B India Ltd."      15341 504    .08538888 .  942.99
                              3 "A B B India Ltd."      15372 505     .1493447 . 1088.57
                              3 "A B B India Ltd."      15400 506    .02889967 . 1125.45
                              3 "A B B India Ltd."      15431 507 -.0021479162 . 1128.62
                              3 "A B B India Ltd."      15461 508   -.08174744 . 1042.38
                              3 "A B B India Ltd."      15492 509    .08772953 . 1139.01
                              3 "A B B India Ltd."      15522 510   .026357977 .  1174.4
                              3 "A B B India Ltd."      15553 511   .014627928 . 1197.07
                              3 "A B B India Ltd."      15584 512   -.00963581 . 1191.14
                              3 "A B B India Ltd."      15614 513   -.15107673 . 1016.52
                              3 "A B B India Ltd."      15645 514 -.0043656644 . 1016.31
                              3 "A B B India Ltd."      15675 515   .032454766 . 1053.82
                              3 "A B B India Ltd."      15706 516     .1184831 . 1183.51
                              3 "A B B India Ltd."      15737 517    .14282626 . 1358.12
                              3 "A B B India Ltd."      15765 518    -.1063528 . 1220.17
                              3 "A B B India Ltd."      15796 519   .066637546 . 1305.99
                              3 "A B B India Ltd."      15826 520    .11098335 . 1456.02
                              3 "A B B India Ltd."      15857 521    .06932523 . 1562.82
                              3 "A B B India Ltd."      15887 522    .02447596 . 1607.11
                              3 "A B B India Ltd."      15918 523    .25035638 . 2015.67
                              3 "A B B India Ltd."      15949 524 -.0005782682 . 2022.03
                              3 "A B B India Ltd."      15979 525     .0955333 . 2223.34
                              3 "A B B India Ltd."      16010 526   .006823394 . 2246.23
                              3 "A B B India Ltd."      16040 527    .26775625 . 2855.47
                              4 "A B C India Ltd."      15310 503   -.15839133 .     2.5
                              4 "A B C India Ltd."      15341 504    -.2052974 .       2
                              4 "A B C India Ltd."      15372 505    -.2425373 .    1.53
                              4 "A B C India Ltd."      15400 506     .7983065 .    2.75
                              4 "A B C India Ltd."      15431 507   -.28679043 .    1.98
                              4 "A B C India Ltd."      15461 508    .08327773 .    2.15
                              4 "A B C India Ltd."      15492 509     .2508417 .     2.7
                              4 "A B C India Ltd."      15522 510   -.07878587 .     2.5
                              4 "A B C India Ltd."      15553 511    .01532082 .    2.55
                              4 "A B C India Ltd."      15584 512   -.12232624 .    2.25
                              4 "A B C India Ltd."      15614 513     .1955164 .     2.7
                              4 "A B C India Ltd."      15645 514   -.24489795 .    2.05
                              4 "A B C India Ltd."      15675 515    .09310998 .    2.25
                              4 "A B C India Ltd."      15706 516    -.1823592 .    1.85
                              4 "A B C India Ltd."      15737 517    .10339632 .    2.05
                              4 "A B C India Ltd."      15765 518    -.1755086 .     1.7
                              4 "A B C India Ltd."      15796 519    .05512415 .     1.8
                              4 "A B C India Ltd."      15826 520     .3155487 .    2.38
                              4 "A B C India Ltd."      15857 521    .23807873 .    2.95
                              4 "A B C India Ltd."      15887 522   -.18691386 .    2.41
                              4 "A B C India Ltd."      15918 523     .3260125 .    3.21
                              4 "A B C India Ltd."      15949 524   -.07861517 .    2.97
                              4 "A B C India Ltd."      15979 525    -.0849709 .    2.73
                              4 "A B C India Ltd."      16010 526    .06075002 .     2.9
                              4 "A B C India Ltd."      16040 527    1.3327367 .    6.78
                              end
                              format %td date
                              format %tm mdate


                              Last edited by Sartaj Hussain; 20 Jan 2023, 11:09.

                              Comment


                              • #45
                                In order to develop these variants, I will need example data to which they can be applied. The example data shown in #44 has all missing values for beta, so it is impossible to group anything on quantiles of beta.

                                Also, the original code uses a variable, rt, for return. Your current example has no such variable. Should I use ert in place of rt?

                                Finally, it would be helpful to have data covering five or more different stock_id's to develop these. (-dataex- is not limited to 100 observations; that is just the default. By specifying the -count()- option you can have -dataex- produce a different number of observations in the example.)

                                Comment

                                Working...
                                X