No. of Recommendations: 51
Guide to Screen Definitions

In my Screen Definitions posts, I have given the screen definitions in two forms: a URL for Jamie Gritton’s MI Backtester, and a RadiScript definition. (A few screens don’t have URL’s because they can’t be run on the backtester.) Jamie’s URLs are described at his website, http://www.backtest.org/. Following is a description of RadiScript. After that, there’s a brief discussion about the more technical aspects of screen definition.

RadiScript is a method of describing screens in detail and with precision. It was originally developed for the RadiScreen stock screener, but anyone could write a screening program which uses RadiScript definitions. Also, the near-English nature of RadiScript makes it useful for describing screens in a way that can be fairly easily read, and yet can also be run through a screener without any translation (thus verifying the accuracy of the definition).

Note: generally the URL’s have been translated into RadiScript by using a translation program, thus eliminating typographical errors. In the Screen Definitions posts, URL’s that are preceded by a semicolon (;) have been translated manually.


RadiScript

Generally, screening works by starting out with a large list of stocks. For example, you might start with the stocks covered by Value Line. Some of the screening steps keep some stocks and discard the rest. As these steps are performed, the list of stocks gets smaller. Other steps sort the current list of stocks.

RadiScript consists of keywords, column names, screen names, and formulas.

The keywords are just English words, like “Define” or “Sort”, that describe the steps to be taken or give more details for a given step.

Column names refer to the data used to evaluate the stocks, usually downloaded from Value Line, Investor’s Business Daily, Yahoo, or similar sources. In RadiScript, they are always enclosed in square brackets. This makes them easy to identify, and also resolves possible ambiguities. (For example, “Current P/E Ratio” is ambiguous and has two possible RadiScript representations. The obvious one is [Current P/E Ratio]. The non-obvious, and unlikely, one is [Current P]/[E Ratio].)

In addition to the columns from the downloaded data, a screen can specify a computed column using a formula. Once specified, these are referenced the same as columns from the download. There are also some inherent columns: [Ticker] is the stock symbol, [Rank] is the position of the stock in the current stocks list (numbered from 1 up), and [Tied Rank] is the position of the stock as a result of the last sort performed (numbered from 1 up, but with tied stocks having the same number as each other). Some screens also have [Screen Rank], [Sequence], and [Score], which will be described later.

All screen names in RadiScript are enclosed in braces. Similar to enclosing column names in brackets, this helps make screen names be quickly identifiable. As an example, the screen BETA would be written as {BETA}. Screen names are used at the beginning of a definition, when adding stocks from previously-evaluated screens (see Add), and when using the rank within a previously-evaluated screen as a column of data (see Uses).

Formulas in RadiScript are patterned after the formulas used in the popular program Microsoft Excel. In Excel, formulas are preceded by an equal sign (=). Because RadiScript definitions are often stored in Excel spreadsheets, RadiScript formulas begin with a colon (:) instead of an equal sign (otherwise, Excel would attempt to evaluate the formula). The other difference between Excel formulas and RadiScript formulas is that RadiScript formulas can contain column names (in brackets, of course). When enclosed in single brackets, a column name refers to the value for one particular stock. For example, :[Divd Yield]>5 would be ‘true’ for stocks whose dividend yield is greater than 5, and ‘false’ for stocks whose dividend yield is less than or equal to 5. When enclosed in double brackets, a column name refers to the value for all stocks currently in the stocks list. For example, :[Divd Yield]>AVERAGE([[Divd Yield]]) would be ‘true’ for stocks whose dividend yield is greater than the average of the dividend yields of all stocks in the stocks list (at the step where the formula appears).

Each line in a RadiScript definition is called a statement. Each statement begins with a keyword. Here’s a relatively simple screen definition. We’ll go through what each statement means.

Define {KEYSTONE}
Uses [Timeliness Rank] [Domicile Code] [Market Cap $ (Mil)] [Total Return 26-Week]
Deblank [Timeliness Rank] [Domicile Code] [Market Cap $ (Mil)]
Keep :[Timeliness Rank]<=2
Keep :[Domicile Code]="us"
Sort Descending [Market Cap $ (Mil)]
Top :30 PlusTies
Deblank [Total Return 26-Week]
Sort Descending [Total Return 26-Week]
; Top :10
End


Define simply indicates that this is the start of a screen definition, and tells the name of the screen being defined. In this example, the screen is KEYSTONE.

Uses lists all the columns that will be needed from the downloaded data. In this example, the screen uses Timeliness Rank (“Timeliness” is a trademark of Value Line, Inc.), Domicile Code, Market Cap, and Total Return 26-week. Additionally, the rank a stock occupied in a previously-evaluated screen can be listed as a desired column (a value of 1 will indicate the top pick, 2 indicates the second-highest pick, and so forth; stocks not picked in the screen named will be indicated by a value of zero).

Deblank is followed by a list of columns. Only those stocks which have a value for all of the columns listed are kept. Any stock where one or more of the columns is blank is discarded. This is discussed in more detail in the technical section which follows.

Keep is always followed by a formula. The stocks for which the formula is ‘true’ are kept, and the stocks for which the formula is ‘false’ are discarded from the current stocks list. In the first Keep statement, the stocks having a Timeliness Rank less than or equal to 2 are kept, and of course stocks having a rank greater than 2 are discarded. Similarly, in the second Keep statement, only stocks whose Domicile Code is US are kept. Note that text comparisons are done without regard to case, so a Domicile Code of uS, Us, or us would also be kept.

Sort is followed by the keyword Descending or Ascending, and by the column to sort on. In this example, Sort Descending [Market Cap $ (Mil)], the stocks are sorted so that the stock with the highest value of Market Cap appears first in the list (at [Rank]=1), and the stock with the lowest value of Market Cap appears last. A second-level sort can also be specified. For example, Sort Descending [Market Cap $ (Mil)] Ascending [Ticker] would sort the stocks from highest to lowest value of Market Cap, and stocks having the same Market Cap as each other would be in order from lowest to highest Ticker symbol (that is, in alphabetical order). To resolve ties in the second-level sort, a third-level sort can also be specified. When there are ties at the last level of sort specified, the order of the tied stocks is indeterminate.

The Top statement keeps the number of stocks specified by the formula and discards the rest. For example, Top :5 would keep only the top five stocks ([Rank]=1 through [Rank]=5). If the keyword PlusTies is given after the formula, then any stocks that were, at the most recent sort, tied with the last stock kept will also be kept. In this example, Top :30 PlusTies following Sort Descending [Market Cap $ (Mil)], if the 31st stock has a different Market Cap than the 30th stock, only the first 30 stocks will be kept. However, if the 31st stock has the same Market Cap as the 30th stock (that is, if it was “tied” with the 30th stock in the most recent sort), it will be kept as well — and the 32nd stock will be kept if it was also tied with the 30th and 31st stock, and so on.

If the formula is either a percentage greater than 0% and less than 100%, or the equivalent factor (a decimal number greater than 0 and less than 1), then the number of stocks in the current list will be multiplied by that percentage or factor to calculate the number of stocks to keep (if the result is not an integer, it will be rounded up to the next higher integer).

A comment begins with a semi-colon (;). Comments are not actually part of the screening process, but convey useful information. In this example, ; Top :10 indicates that in some cases you will only use the top 10 stocks, but we don’t want to limit the definition to that number in all cases.

The End statement simply marks the end of the definition.


OK, let’s look at another definition:

Define {RSW}
Uses [Timeliness Rank] [Total Return 13-Week] [Total Return 26-Week] [Total Return 1-Year]
Deblank [Timeliness Rank] [Total Return 13-Week] [Total Return 26-Week] [Total Return 1-Year]
Keep :[Timeliness Rank]=1
Create [RSW] :.4*[Total Return 13-Week]+.3*[Total Return 26-Week]+.3*[Total Return 1-Year]
Sort Descending [RSW]
; Top :10
End


Again, we have the now-familiar Define, Uses, Deblank, Keep, Sort, and End statements.

The Create statement makes a new column, and specifies the formula used to fill in the data values. In this case, the newly-created column is named RSW, and it is calculated as .4*[Total Return 13-Week]+.3*[Total Return 26-Week]+.3*[Total Return 1-Year]. You’ll notice the next statement sorts the current stocks list by this new column. If the name specified for the new column matches the name of an existing column, the new column replaces the existing column.


Let’s look at a screen-of-screens (SOS) definition now. SOS’s have the additional columns [Screen Rank], [Sequence], and [Score].

Define {SOS_K}
Add {PEG13} :2 To :7 Score :10
Add {RS52WK} :4 Score :10
Add {PEGRSW} :5 Score :10
Add {KEYEPS} :7 Score :10
SOS
; Top :3
End


Because the definition doesn’t contain a Uses statement, the current stocks list for an SOS begins with no stocks.

The Add statement adds the stocks from the specified screen to the current stocks list. In this first example, Add {PEG13} :2 To :7 Score :10, the 2nd through 7th picks of the PEG13 screen are added to the current stocks list. For each stock, [Screen Rank] will be what the rank was in the original screen (2 through 7 in this example), [Sequence] will be the stock’s current position in the stock list (1 through 6 here), and [Score] will be a number that starts with the specified score and counts down by 1 for each stock (so, 10 through 5 in this example). In the second Add statement, Add {RS52WK} :4 Score :10, the keyword To was not used. This means to start at pick 1 (so :4 is the same as :1 To :4). Picks 1 through 4 from the RS52WK screen will be added below the existing stocks in the current stocks list. So, [Screen Rank] will be 1 through 4, [Sequence] will be 7 through 10, and [Score] will be 10 through 7. Note that the keyword Score can be omitted, in which case the number after To will be used as the starting Score (so in the first Add statement above, Score would be assumed to be 7, and in the second Add statement, it would be assumed to be 4).

The SOS statement performs the screen-of-screens selection. A formula can be specified which discards stocks that appear on fewer screens than the number specified. For each stock, the sum of the [Score] column for all appearances of that stock is computed as [Total Score]. Next, only the first appearance of each stock is kept (based on the ticker symbol). Finally, the stocks are sorted descending by [Total Score] and secondarily sorted ascending by the [Sequence].


Now, let’s look at an overlap screen.

Define {OVER_RS}
Add {RS13WK} :30
Add {RS26WK} :30
Overlap
Pad :30 {RS13WK} :30 {RS26WK} :30
; Top :5
End


An overlap screen has two Add statements (and no Uses statement). In this example, picks 1 through 30 are added to the current stocks list from the screens RS13WK and RS26WK.

The Overlap statement first keeps only stocks which appear in both screens (determined by ticker symbol). Next, the sum of the [Screen Rank] column from both screens is calculated for each stock in a column named [Combo]. The larger of the two [Screen Rank]’s is calculated in a column named [Max]. Then, the stocks from the second screen are discarded. Finally, the remaining stocks are sorted ascending by [Max], ascending by [Combo], ascending by [Screen Rank].

Pad first has a formula indicating the desired number of stocks (30 in this example). Then one or two screens are listed to add stocks from, along with the number of stocks to consider from each screen. Stocks are added alternately from the two screens (or, just from the one screen) until the current stocks list has the desired number of stocks (or until the specified number of stocks have been considered from the screens). Only stocks not already appearing in the current stocks list are added. So in this example, if the Overlap produces fewer than 30 picks, the Pad statement will check pick #1 from RS13WK, then pick #1 from RS26WK, then pick #2 from RS13WK, and so on, adding the pick if it isn’t already in the current stocks list.


There are a few remaining miscellaneous statements in RadiScript:

AddNoPad is the same as Add, but it adds only stocks that did not result from a Pad statement.

GoTo is used to skip to a different place in the definition. For example, Goto Restart will skip to the statement following the statement Label Restart (wherever that may be in the definition).

Label specifies a label which can be branched to with the GoTo statement.

If has a formula, and the following statement is skipped if the formula is false (zero). Example: If :[TickerCount]<10 followed by Goto Restart will continue at the statement following Label Restart if fewer than 10 stocks are in the current stocks list.

IfExists has a column name, and the following statement is skipped if the column doesn’t exist in the screen’s present results. Example: IfExists [IBD A/D RTG] followed by Create [IBD A/D RTG] :LEFT([IBD A/D RTG],1) will strip off all characters except the leftmost one in the [IBD A/D RTG] column, if that column is used by the screen.

Else skips the following statement unless the formula in the most recent If statement was false. For example:
If :[Period]<=26
Sort Descending [Total Return 26-Week]
Else
Sort Descending [Total Return 1-Year]

If the variable Period is less than or equal to 26, the stocks will be sorted by [Total Return 26-Week], but if the variable Period is greater than 26, the stocks will be sorted by [Total Return 1-Year].

Replace finds a particular value in a column and replaces it with another value. Example: Replace [Financial Strength] :"B" With :3 will replace all occurrences of B (or b) in the Financial Strength column with the number 3 (it will not replace B++ to be 3++). The statement Replace [Financial Strength] Blank With :3 would replace all blanks in that column with the number 3.

Set creates a variable or changes the value of an existing variable. Example: Set [Counter] :[Counter]+1 adds one to the value of the variable Counter.

Stop is the same as End, but End is used only at the very end of a definition.

Unique begins with the keyword First or Last, and then a column name. Only one stock with a given value is kept. For example, Unique First [Ticker] will discard any stocks where the ticker symbol duplicates the ticker symbol of another stock in the current stocks list. Only the first stock (or last stock, if Last is specified) of any duplicates is kept.


Global rules

In addition to the statements listed for each screen, there are “global” statements that apply to all screens. After any Uses statement the statement Keep :[Ticker]>”@” is to be performed. This removes stocks where the ticker symbol begins with a digit. And before the End statement, the statement Sort Ascending [Tied Rank] Ascending [Ticker] is to be performed. This breaks any ties from the last sort in the screen definition using the ticker symbol (in alphabetical order).

The IBD screens have global statements done after the Keep :[Ticker]>”@”. They are IfExists [IBD A/D RTG] and Create [IBD A/D RTG] :LEFT([IBD A/D RTG],1) which checks to see if the screen uses [IBD A/D RTG] and if it does, modifies the [IBD A/D RTG] data to include only the first character of the original data. This is done because the screens were designed when IBD’s Accumulation/Distribution rating had only a single letter (A, B, C, etc.), and IBD has subsequently changed the rating to include a plus/minus (A+, A, A-, B+, etc.).

And finally, any stock which results in a division by zero must be discarded. For example, if a screen includes the statement Create [PEG] :[Current P/E Ratio]/[Proj EPS Growth Rate], then any stock with a Projected EPS Growth Rate of zero would have to be discarded at that statement.


More on Excel formulas

Some screen definitions make use of Excel functions.

AND uses a number of arguments in parenthesis separated by commas. If all the arguments are true (non-zero), then the result is true (one). If one or more of the arguments is false (zero), then the result is false (zero). For example:
Keep :AND([Current P/E Ratio]<>0,[Current P/E Ratio]<100)
will keep stocks where the P/E is non-zero and less than 100; any stock with a P/E equal to zero or greater than or equal to 100 is discarded.

The OR function is similar. The result of OR is true (one) if one or more of its arguments is true (non-zero), and it is false (zero) if all of its arguments are false (zero). For example:
Keep :OR([EPS Growth 5-Year]>0,[Proj EPS Growth Rate]>0)
will keep stocks where either the EPS Growth 5-Year is greater than zero or the Proj EPS Growth Rate is greater than zero; a stock is discarded if both values are <= zero.

As just described, Excel formulas count zero as false and non-zero as true, and formulas that evaluate to true or false have a value of zero for false and one for true.

The AVERAGE function computes the average of its arguments by summing them and dividing by the number of arguments.

COUNTIF counts the number of times the second argument appears in the data specified by the first argument. For example:
Create [Appearances] :COUNTIF([[Ticker]],[Ticker])
sets Appearances to the number of times the ticker symbol occurs in the list of all ticker symbols (within the current stocks list).

The LEFT function gives the leftmost characters of the first argument. The second argument tells how many characters. For example, LEFT("Hi there",4) is the same as "Hi t".

Another thing that’s important to know about Excel formulas is the operator precedence. Mostly all you need to know is formulas are done left to right, except multiply or divide is done before add or subtract. So A-B+C*D/E is the same as (A-B)+((C*D)/E). Further information on operator precedence (and on other functions) can be found in Excel’s Help or in many books about Excel.


Technical aspects of screen definition

Ideally, screen definitions will be done so precisely that anyone following the definition will arrive at the same screen picks (given the same downloaded data). When using automated processes, it is necessary to avoid things that are implementation-dependant in the definition. It’s also necessary to avoid steps that have indeterminate results, unless subsequent steps resolve that problem.

Broadly speaking, downloaded data has three types of data: numbers, text, and blanks. Blanks may be literally blank in the data, or may be N/A, N/M, -----, Unreported, or similar entries. Problems arise when formulas are applied to text or blanks, or when operations are performed on a mixture of two or more of these data types.

To illustrate, consider sorting. The numbers 1 through 12 sort ascending as 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12. Notice that 2 comes before 10 (bear with me a moment). However, those numbers as text sort ascending as 1, 10, 11, 12, 2, 3, 4, 5, 6, 7, 8, 9. Notice that in this case, 2 comes after 10. If you don’t know whether the data was intended to be numbers or text, the results can vary depending on the person or program that’s doing the sort — in other words, the results are implementation-dependant.

Here are some rules that have been generally agreed upon to avoid these problems.

1. Do not perform sorts where the data in a given column is a combination of numbers, text, and/or blanks. Avoid sorting blank values by discarding stocks with blanks (in the columns to be sorted) immediately before the sort.

2. Avoid sorting on text values when the sort sequence isn’t obvious. For example, sorting single letters from A to Z is pretty obvious, but special characters like the Yen symbol or the symbol for 1/4 may sort differently in different implementations. Similarly, it’s unknown how a lower-case letter will sort compared to an upper-case letter.

3. Perform arithmetic operations only on numbers. Avoid arithmetic operations on blanks, for example, by discarding stocks with blanks (in any columns used in the calculation) immediately before evaluating each formula.

4. Discard stocks that would result in a division by zero.


Phil
Print the post  

Announcements

What was Your Dumbest Investment?
Share it with us -- and learn from others' stories of flubs.
When Life Gives You Lemons
We all have had hardships and made poor decisions. The important thing is how we respond and grow. Read the story of a Fool who started from nothing, and looks to gain everything.
Contact Us
Contact Customer Service and other Fool departments here.
Work for Fools?
Winner of the Washingtonian great places to work, and Glassdoor #1 Company to Work For 2015! Have access to all of TMF's online and email products for FREE, and be paid for your contributions to TMF! Click the link and start your Fool career.