*! Attaullah Shah; Email: attaullah.shah@imsciences.edu.pk; Support website: www.FinTechProfessor.com * Version 5.9: Feb 29, 2024: Fixed the selectindex() not found error. * Version 5.8: May 5, 2022: bug fixed in max2, max2, max4, and max5 * Version 5.7: Arpil 5, 2022: bug fixed when option window(var 0 1) was used * Version 5.6: Mar 1, 2022 : New statistic - kurtosis - added * Version 5.5: Nov 6, 2021 : Added max2, max3, max4, and max5 for finding second, third, fourth and fifth largest values. * Version 5.4: July 13, 2021 : The error 'PRODUCT(): 3201 vector required' fixed. This error would occur in the calculation of product if extended missing values were present * Version 5.3: June 14, 2021 : Bug fixed related to missing value in the rangeevar * Version 5.2: Nov 29, 2020 : Bug fix when 0 was used in the back window * Version 5.1: Sep 4, 2020 : Mutilple statistics / variables can used used now in the flexible window * Version 5.0: Adding forward window : May 22, 2020 * Version 4.6 Improves the calculation of gmean for large numbers * Version 4.5 Gmean improvement * Version 4.4 10May2018: product fuction improvement * This version supports multiple variables and multiple statistics cap prog drop asrol prog asrol, byable(onecall) sortpreserve version 11 syntax /// varlist(numeric) /// [in] [if], /// Stat(str) /// [Generate(str) /// Window(string) /// Perc(str) /// MINimum(real 0) /// by(varlist) /// XFocal(string) /// ADD (real 0) /// IGnorezero /// TYPE(str) /// ] preserve marksample touse, nov local Z : word count `stat' local V : word count `varlist' loc mult = `Z' * `V' if "`generate'"! = "" & `mult'> 1 { display as error "Option {opt g:en} is not allowed with multiple variables or statistics" exit } foreach z of local stat { if "`z'" != "mean" & "`z'" != "gmean" & "`z'" != "sd" /// & "`z'" != "sum" & "`z'" != "product" & "`z'" != "median" /// & "`z'" != "count" & "`z'" != "min" & "`z'" != "max" /// & "`z'" != "first" & "`z'" != "last" & "`z'" != "missing" /// & "`z'" != "skewness" & "`z'" != "max2" & "`z'" != "max3" /// & "`z'" != "max4" & "`z'" != "max5" & "`z'" != "kurtosis" { display as error " Incorrect statistics specified!" display as text "You have entered {cmd: `z'} in the {cmd: stat option}. However, only the following staticts are allowed with {help asrol}" dis as res "mean, gmean, sd, sum, product, median, count, min, max, first, last, missing" exit } if "`z'" != "median" & "`perc'"!="" dis as error "option {cmd: perc()} is used only when finding {cmd: percentiles with option median}, see help file {help asrol}" if "`z'" == "median" { if "`perc'" == ""{ global Q = .5 } else { confirm number `perc' global Q = `perc' } } } if "`xfocal'"=="" { local XF = 1 } else{ cap confirm numeric variable `xfocal' if _rc==0 { local varfocal "yes" } if "`xfocal'" != "focal" & "`varfocal'"!="yes"{ display as error " Option xfocal either accepts the word focal or name of an existing numeric variable" display as text "For example, you can specify xfocal option as {cmd: xfocal(focal)} or {cmd: xfocal(year)}" exit } if "`xfocal'"=="focal" { local XF = 2 } else{ local XF = 3 } } if "`type'" != "" { if !inlist("`type'", "s", "sample", "p", "population") { display as error "Option type accepts sample or population only" display as error "The default of population is used in the calculation" } else global type "`type'" } global addtofunc = `add' global ignorezero `ignorezero' if "`XF'" != "1" global XF 1 else global XF 0 if "`window'"!=""{ local nwindow : word count `window' if !inrange(`nwindow', 2, 3) { dis "" display as error "Option window must have either two arguments: rangevar and length of the rolling window, e.g., {opt window(year 10)}" dis as error " Or three arguments : rangeevar, length of the backward, and the forward windows e.g., {opt window(year -10 20)}" exit } else if `nwindow'==2 { tokenize `window' gettoken rangevar window : window gettoken bw window : window confirm number `bw' confirm numeric variable `rangevar' } else if `nwindow' == 3 { local rangevar : word 1 of `window' local bw : word 2 of `window' local fw : word 3 of `window' confirm number `bw' confirm number `fw' confirm numeric variable `rangevar' if (`bw' >= `fw') { display as error "The lower bound of the window is either equal to or less than the upper bound." display as error "Rolling window calculations are not possible when this is the case!" exit } if `fw' == 0 { loc fw loc bw = abs(`bw') } } markout `touse' `rangevar' if "`_byvars'"!="" { local by "`_byvars'" } if "`by'"=="" { tempvar by qui gen `by' = 1 } local cversion =`c(version)' tempvar __GByVars __000first __0dIf qui bysort `by' (`rangevar'): gen `__000first' = _n == 1 qui gen `__GByVars'=sum(`__000first') qui drop `__000first' qui by `by' : gen `__0dIf' = `rangevar' - `rangevar'[_n-1] loc dt = 2 cap qui assert `__0dIf' == 1 | `__0dIf' == . if _rc == 0 loc dt = 1 else { cap assert `__0dIf' == 0 if `__0dIf' < 1, fast null if _rc != 8 & _rc != 9 { loc dt = 3 tempvar touse2 qui bysort `__GByVars' `rangevar' : gen `touse2' = _n == 1 } } if "`fw'" == "" { loc bw = abs(`bw') if `mult'<=1 { if "`stat'"=="median" { if "`perc'"==""{ global Q = .5 } else { confirm number `perc' global Q = `perc' } } if "`generate'" == "" local generate "`varlist'_`stat'`bw'" loc generate = subinstr("`generate'", "-", "_", .) loc generate = subinstr("`generate'", " ", "", .) mata: asrolw( /// "`varlist'", /// "`__GByVars'" , /// "`generate'" , /// `bw', /// "`stat'", /// "`minimum'", /// "`rangevar'", /// `XF' , /// "`__0dIf'" , /// `cversion', /// "`touse'" ) cap qui label var `generate' "`stat' of `varlist' in a `bw' `fw' periods rol. wind." } else { loc windname = abs(`bw') foreach v of varlist `varlist' { foreach z of local stat { local generate "`v'_`z'`bw'" loc generate = subinstr("`generate'", "-", "_", .) loc generate = subinstr("`generate'", " ", "", .) mata: asrolw( /// "`v'", /// "`__GByVars'" , /// "`generate'" , /// `bw', /// "`z'", /// "`minimum'", /// "`rangevar'", /// `XF' , /// "`__0dIf'" , /// `cversion', /// "`touse'" ) cap qui label variable `generate' "`z' of `v' in a `bw' `fw' periods rol. wind." } } } } // If forward window else { if `mult'<=1 { if "`stat'"=="median" { if "`perc'"==""{ global Q = .5 } else { confirm number `perc' global Q = `perc' } } if "`generate'" == "" local generate "`stat'`bw'_`varlist'" loc generate = subinstr("`generate'", "-", "_", .) loc generate = subinstr("`generate'", " ", "", .) mata: asrolfw( /// "`varlist'", /// "`__GByVars'" , /// "`generate'" , /// `bw', /// `fw', /// "`stat'", /// "`minimum'", /// "`rangevar'", /// `XF' , /// "`dt'" , /// "`touse2'", /// `cversion', /// "`touse'" ) cap qui label var `generate' "`stat' of `varlist' in a `bw' `fw' periods rol. wind." } // if forward window and multi else { foreach v of varlist `varlist' { foreach z of local stat { local generate "`v'_`z'`bw'_`fw'" loc generate = subinstr("`generate'", "-", "_", .) loc generate = subinstr("`generate'", " ", "", .) mata: asrolfw( /// "`v'", /// "`__GByVars'" , /// "`generate'" , /// `bw', /// `fw', /// "`z'", /// "`minimum'", /// "`rangevar'", /// `XF' , /// "`dt'" , /// "`touse2'", /// `cversion', /// "`touse'" ) cap qui label variable `generate' "`z' of `v' in a `bw' `fw' periods rol. wind." } } } } } // End window else { local bw = 0 tempvar GByVars dup first n dif if "`_byvars'"!="" { local by "`_byvars'" } if "`by'"!="" { if `XF'==3 { local rangevar "`xfocal'" } gen `n'=_n bysort `by' (`rangevar' `n'): gen `first' = _n == 1 qui gen `GByVars' = sum(`first') drop `first' `n' } if "`by'"=="" { tempvar GByVars qui gen `GByVars' = 1 if `XF'==3 { local rangevar "`xfocal'" sort `GByVars' `rangevar' } } if `mult' <= 1 { if "`generate'" == "" local generate "`varlist'_`stat'" mata: asrolnw( /// "`varlist'", /// "`GByVars'" , /// "`generate'" , /// "`stat'", /// `minimum', /// "`rangevar'", /// `XF' , /// "`touse'" /// ) capture quietly label variable `generate' "`stat' of `varlist'" } else{ foreach v of varlist `varlist' { foreach z of local stat { local generate "`z'_`v'" mata: asrolnw( /// "`v'", /// "`GByVars'" , /// "`generate'" , /// "`z'", /// `minimum', /// "`rangevar'", /// `XF' , /// "`touse'" /// ) capture quietly label variable `generate' "`z' of `v'" } } } } restore, not if `mult' <= 1 { if "`dt'" == "3" & `XF' != 2 { qui bys `__GByVars' `rangevar': replace `generate' =`generate'[1] } } else { foreach v of varlist `varlist' { foreach z of local stat { loc generate "`v'_`z'`bw'" loc generate = subinstr("`generate'", "-", "_", .) loc generate = subinstr("`generate'", " ", "", .) qui bys `__GByVars' `rangevar': replace `generate' =`generate'[1] } } } global type end