Programming Tools / Procedures and Functions / Putting It All Together: An Example |
We will now develop a PROCEDURE for implementing a General LM test for serial correlation. We will start with a very simple procedure, concentrating upon getting the calculations correct, and then refine it. We need to input the following information to the procedure:
•The dependent variable
•The regressors
•The number of lags to test
To make this look as much like a RATS instruction as possible, the dependent variable should be a parameter, the regressors should come from a supplementary card, and the number of lags should be an option.
The only tricky part about our first attempt is handling the list of regressors. We need it in two places: the initial regression and the auxiliary regression. We pull it in with the EQUATION instruction, then extract that list with the %RLFROMEQN function. The regressor list functions come in very handy in writing procedures.
procedure sctest depvar
type series depvar
option integer lags 1
local equation regeqn
local vect[integer] reglist
equation regeqn depvar
linreg(equation=regeqn)
compute reglist=%rlfromeqn(regeqn)
linreg(noprint,dfc=%nreg) %resids
# reglist %resids{1 to lags}
disp "LM statistic" %trsq "Signif Level" %chisqr(%trsq,lags)
end
We should now check against the direct code to make sure the calculations are correct. After we’re sure we’re doing the calculations correctly, we can make refinements. We will make four changes:
•We will improve the output. This is a straightforward change to the DISPLAY instruction at the end of the procedure.
•We will add a PRINT option, to allow the user to suppress (with NOPRINT) the output from the first regression.
•We will have @SCTEST define the standard variables %CDSTAT and %SIGNIF.
•We will allow the user to specify a start and end range.
The last is the only difficult part of this. The range is easy to handle if we either require the user to give an explicit range, or if we always use a default range. It gets complicated when we let the user do either. This is where INQUIRE comes in. We can determine the range of the initial regression by using an INQUIRE instruction with the EQUATION option. If the user passes values to the START or END parameters, they override the values from INQUIRE. Once we have values for the range on the first regression, the auxiliary regression just starts LAGS entries farther up.
procedure sctest depvar start end
type series depvar
type integer start end
local vect[integer] reglist
local integer startl endl
local equation regeqn
option integer lags 1
option switch print 1
equation regeqn depvar
compute reglist=%rlfromeqn(regeqn)
inquire(equation=regeqn) startl<<start endl<<end
linreg(print=print,equation=regeqn) depvar startl endl
linreg(noprint,dfc=%nreg) %resids startl+lags endl
# reglist %resids{1 to lags}
compute %cdstat=%trsq , %signif=%chisqr(%trsq,lags)
disp "LM test for Serial Correlation of Order " lags
disp "Test Statistic " %trsq "Signif Level " #.###### %signif
end
Suppose we want to use the procedure to regress Y on three regressors (a constant, X1 and X2) and test the residuals for serial correlation with a lag length of 4. We can do that with the following instruction:
@sctest(lags=4) y
# constant x1 x2
An alternative handling for the range that would work here is to run the regression using START and END, then use %REGSTART() and %REGEND() to recover the range used. That allows LINREG’s standard handling of the range parameters to do the work.
linreg(print=print,equation=regeqn) depvar start end
compute startl=%regstart(),endl=%regend()
Checking Local Versus Global Declarations
When writing and testing a new procedure, you may find the instruction DEBUG(SYMBOLS) helpful. If you do DEBUG(SYMBOLS) and then compile your procedure code, RATS will report any variables that are created as global variables, or that are declared as local but aren’t actually used. For example:
debug(symbols)
source kfilter.src
produces output like this:
KFILTER, line 53 Using TIME as INTEGER
indicating that TIME is being defined as a global integer, on line 53 of the procedure.
Instruction Locations—Debugging Compiled Code
When RATS processes a compiled structure, it prefixes the actual code on each line by a pair of numbers in parentheses, which can be very helpful in debugging problems with compiled sections. (Note: these numbers normally aren’t displayed when running in interactive mode, but you can see them by using a SOURCE(ECHO) command to execute your program file.)
The first number is the structure level at the end of the previous line. The second number is the location of the instruction within the compiled section.
Consider the following example, taken from the @DFUNIT procedure:
(01.0155) inquire(series=series) startl<<start endl<<end
(01.0207) *
(01.0207) set sdiff startl+1 endl = series-series{1}
(01.0271) set strend startl+1 endl = t
If an error occurs during execution of the compiled section, the error message will include a line indicating the location of the error. For example, if you were to try to apply @DFUNIT to a series that contained no data, you would get the message:
## SR10. Missing Values And/Or SMPL Options Leave No Usable Data Points
The Error Occurred At Line 17, Location 0206 of DFUNIT
The first line in the traceback says the occurred at location 0206. That tells us the error was generated by the INQUIRE instruction, which occupies memory locations 155 through 206. The second traceback line gives the same information, but tells what line in the procedure caused it. Note that this is the line number from the start of the actual procedure or loop. Most procedure files have a header of comments at their top, but the line count used here doesn’t start until the PROCEDURE statement.
The structure level is helpful in locating block nesting errors. Consider this code from later in the procedure:
(02.1417) if lags {
(03.1432) summarize(noprint)
(03.1437) # sdiff{1 to lags}
(03.1493) compute fiddle=1.0/(1.0-%sumlc)
(03.1524) }
(02.1524) else
Suppose that we forgot the } before the ELSE. The ELSE location would be prefixed with 03, instead of 02 which is what we would expect (remember that the number prefixing a line is the level at the end of the previous line).
The SOURCE instruction includes an ECHO/NOECHO option, which controls whether or not the instructions being executed are displayed in the output window or file. When trying to debug an error, or when using a procedure for the first time, you may find it handy to use the ECHO option to see the instructions echoed to the output window.
Copyright © 2025 Thomas A. Doan