*! version 1.0.0 10jun2017 CFBaum // based on dmariano.ado 1.0.3 program define fcstats, rclass version 13 syntax varlist(ts min=2 max=3) [if] [in] [, GRAPH *] marksample touse _ts tvar panelvar `if' `in', onepanel markout `touse' `tvar' su `touse', mean if `r(N)' == 0 { error 2000 } qui tsset tempvar actual forecast vrmse vmae vmape num den en fc tempvar forecast2 vrmse2 vmae2 vmape2 num2 den2 tempname rmse mae mape theilu tempname rmse2 mae2 mape2 theilu2 tokenize `varlist' local actual `1' local forecast `2' local forecast2 `3' markout `touse' `actual' `forecast' `forecast2' qui { g double `vrmse' = sum((`forecast' - `actual')^2) if `touse' g double `vmae' = sum(abs(`forecast' -`actual')) if `touse' g double `vmape' = sum(abs(`forecast' -`actual') / `actual') if `touse' g double `num' = sum(((`forecast' - `actual') / L.`actual')^2) if `touse' g double `den' = sum((D.`actual' / L.`actual')^2) if `touse' } if "`forecast2'" != "" { qui { g double `vrmse2' = sum((`forecast2' - `actual')^2) if `touse' g double `vmae2' = sum(abs(`forecast2' -`actual')) if `touse' g double `vmape2' = sum(abs(`forecast2' -`actual') / `actual') if `touse' g double `num2' = sum(((`forecast2' - `actual') / L.`actual')^2) if `touse' g double `den2' = sum((D.`actual' / L.`actual')^2) if `touse' } } g `en' = _n * `touse' su `en', mean loc mx = r(max) su `forecast' if `touse', mean sca `rmse' = sqrt(`vrmse'[`mx'] / `r(N)') sca `mae' = `vmae'[`mx'] / `r(N)' sca `mape' = `vmape'[`mx'] / `r(N)' sca `theilu' = sqrt(`num'[`mx'] / `den'[`mx']) if "`forecast2'" != "" { sca `rmse2' = sqrt(`vrmse2'[`mx'] / `r(N)') sca `mae2' = `vmae2'[`mx'] / `r(N)' sca `mape2' = `vmape2'[`mx'] / `r(N)' sca `theilu2' = sqrt(`num2'[`mx'] / `den2'[`mx']) } di as res _n "Forecast accuracy statistics for `actual', N = `r(N)'" if "`forecast2'" == "" { di _n _col(15) "`forecast'" di "RMSE " _col(15) `rmse' di "MAE " _col(15) `mae' di "MAPE " _col(15) `mape' di "Theil's U " _col(15) `theilu' } else { di _n _col(15) "`forecast'" _col(30) "`forecast2'" di "RMSE " _col(15) `rmse' _col(30) `rmse2' di "MAE " _col(15) `mae' _col(30) `mae2' di "MAPE " _col(15) `mape' _col(30) `mape2' di "Theil's U " _col(15) `theilu' _col(30) `theilu2' } return scalar rmse = `rmse' return scalar mae = `mae' return scalar mape = `mape' return scalar theilu = `theilu' if "`forecast2'" != "" { return scalar rmse = `rmse' return scalar mae = `mae' return scalar mape = `mape' return scalar theilu = `theilu' return local forecast2 = "`forecast2'" } return local forecast = "`forecast'" return scalar N = `r(N)' return local actual = "`actual'" if "`graph'" != "" { loc leg legend(rows(1) size(small) label(1 "`actual'") label(2 "`forecast'") if "`forecast2'" != "" { loc leg `leg' label(3 "`forecast2'") } tsline `actual' `forecast' `forecast2' if `touse', `leg') `options' } end