![]()
Contents
Data Coverage
Navigation
Home
Stock Analysis
My Portfolios
Investing Tools
Rule Sets
Custom Expressions
Autoinvestor Strategies
Autoinvestor Simulations
Screeners
Trading Signals
Community
Stockworm provides you with a custom expression syntax which provides you with a highly configurable way to isolate stocks which match your investing criteria. The custom expressions can be used in screeners and strategies to either remove undesirable stocks from a list or to sort a list of stocks, based your custom criteria. Here are some examples of custom filters along with an explanation of each filter:
- INSTITUTE > AVG(INSTITUTE) - institutional ownership is greater than the market average institutional ownership.
- EARN > EARN[60] - earnings per share is greater than earnings per share 60 trading days ago (approximately 1 quarter)
- VAL_AVERAGE > 2 * PRICE - the average value for this stock is greater than two times the last closing price (the stock is very undervalued)
- INSTITUTE > AVG(INSTITUTE) AND VAL_AVERAGE > 2 * PRICE - a combination of the above-mentioned institutional ownership and valuation filters.
- P_TO_E/P_TO_EMA50 - This is a composite expression which effectively creates a new ratio: the 50 day exponential moving average over price divided by earnings. This new expression might be used to sort stocks, similar to sorting by the price-to-earnings ratio except in this case the 50 day moving average would slow the day-to-day change of this ratio. To be perfectly clear, here's the math: price/earnings/(price/ema50(price)) = ema50(price)/earnings = 'slowed' price to earnings.
As shown above, a custom filter is composed of:
- Variables (e.g. INSTITUTE = percent institutional ownership; EARN = earnings per share). For a full list of variables, please see the section below.
- Functions can be applied to modify the value of the variables.
- Operators are the glue which binds the functions/variables together.
The following sections describe in detail all of the operators, functions, and variables which are available when composing custom filters.
Sorting versus Filtering
One subtopic which needs at least brief attention is the issue of whether the custom expression can be used for sorting (as with 'custom sort' rules in screeners or strategies) or as a filter (as with 'custom filter' rules in screeners and strategies). The answer is that the same expression can be used in either capacity -- the result of the expression is treated differently, depending on the context. If a custom expression is used as a:
- sorting expression - the expression is evaluated and the numeric value of the expression is sorted high to low, low to high, or median to extremes, as you specify.
- filter expression - the expression is evaluated and if the numerical value of result is 1 (representing 'true'), the stock is kept and otherwise the stock is removed from the list.
Note: it is important to understand that logical operators such as > or 'AND' return the numerical value of 1 when true and 0 when false. You can use this fact to develop some complex sorting routines. For example, if you want to use a different sorting expression for stocks which distribute dividends versus those that do not distribute dividends, your sort expression could be (DIVIDEND > 0) * DIVIDEND_SORT_EXPRESSION + (DIVIDEND = 0) * NON_DIVIDEND_SORT_EXPRESSION.
Normalization and sorting on multiple expressions
Sometimes you might wish to simultaneously sort on multiple sub expressions which have different magnitudes such as
a comparison between market cap and price-to-earnings. In this case, you would most likely want to 'normalize' the sub-expressions
to
make their values comparable. Let's say that you have a custom expression:
A+B
and you want to combine this with another expression to create a composite sort:
C+D
To combine the expressions, you would choose one of the available normalization functions (see 'functions', below).
As an example, let's apply linear normalization:
NORMALIZE_LINEAR(A+B) + NORMALIZE_LINEAR(C+D)
This expression would represent a combination of the first expression, normalized from 0 (lowest value) to 1 (greatest value) with the second expression normalized in a likewise fashion. Thus you have a 'multi-sort' of two different custom expressions without any worry about differing scales for the expressions.
Next, let's say that you want to double the weighting on the second expression. You would simply multiply the second expression
by two:
NORMALIZE_LINEAR(A+B) + 2 * NORMALIZE_LINEAR(C+D)
Or ... let's say that you want "A+B" to be sorted high to low and "C+D" low to high. In this case, you would
multiply the second equation by minus one to reverse the sort:
NORMALIZE_LINEAR(A+B) - NORMALIZE_LINEAR(C+D)
You can add as many different normalized expressions to your custom sort as you wish and thus this is an incredibly powerful tool for combining different expressions into a single sorting command!
Functions
Functions are provided to perform potentially complex operations on variables. For example, the 'AVG' function will yield the average value of a given expression across all stocks in the Stockworm database. Functions can operate on complex expressions. For example, the expression 'AVG((VAL_PE + VAL_EBO)/2)' computes the average across all stocks of the forward p/e value plus the ebo value divided by two. A complete description of each function is provided below.
| Functions | Usage |
| ABS(EXPRESSION) | Calculates the absolute value of the expression. |
| AVG(EXPRESSION) | Calculates the average value of the expression across all stocks in the database. Example: AVG(ROE) would return the average return on equity for all stocks in the Stockworm database. |
| AVG_BY_INDUSTRY(EXPRESSION) | Calculates the average value of the expression for each industry in our database. The screener will then only return stocks which belong to an industry which satisfies the statement in the expert filter. Example: AVG_BY_INDUSTRY(ROE) would return the average return on equity for each industry in the Stockworm database and AVG_BY_INDUSTRY(ROE) > 10 would only return stocks from industries which have an average ROE greater than 10%. |
| MEDIAN_BY_INDUSTRY(EXPRESSION) | Calculates the median value of the expression for each industry in our database. See AVG_BY_INDUSTRY for a usage example. |
| MEDIAN_IN_LIST(EXPRESSION) | Calculates the median value of the expression across the stocks which are currently in the list of stocks generated by the rules. See MAX_IN_LIST for a usage example. |
| MAX(EXPRESSION) | Calculates the maximum value of the expression across all stocks in the database. Example: MAX(ROE) would return the maximum return on equity for all stocks in the Stockworm database. |
| MAX_IN_LIST(EXPRESSION) | This function computes the maximum value of the expression across the stocks which are currently in the list of stocks generated by the open rules. So, MAX(ROE) would return the maximum return on equity for all stocks in the Stockworm database while MAX_IN_LIST(ROE) would be the maximum roe value in the current list of stocks generated by the open rules. |
| MIN(EXPRESSION) | Calculates the minimum value of the expression across all stocks in the database. Example: MIN(ROE) would return the minimum return on equity for all stocks in the Stockworm database. |
| MIN_IN_LIST(EXPRESSION) | When used in the autoinvestor, this function computes the minimum value of the expression across the stocks which are currently in the list of stocks generated by the open rules. So, MIN(ROE) would return the minimum return on equity for all stocks in the Stockworm database while MIN_IN_LIST(ROE) would be the minimum roe value in the current list of stocks generated by the open rules. |
| MEDIAN(EXPRESSION) | Calculates the median value of the expression across all stocks in the database. Example: MEDIAN(ROE) would return the median return on equity for all stocks in the Stockworm database. |
| NORMALIZE(EXPRESSION) | Normalize values of the expression as: (EXPRESSION - AVG(EXPRESSION))/ STD(EXPRESSION) |
| NORMALIZE_BY_INDUSTRY(EXPRESSION) | Normalize values of the expression as: (EXPRESSION - AVG_BY_INDUSTRY(EXPRESSION))/ STD_BY_INDUSTRY(EXPRESSION) where AVG_BY_INDUSTRY and AVG_BY_INDUSTRY represent the Average and Standard deviation valuations of the respective stock's industry. |
| NORMALIZE_LINEAR(EXPRESSION) | Normalize the expression by sorting all values of the expression from low to high and then assigning normalized values from 0 (lowest in sorted list) to 1 (highest in sorted list). If a particular value is repeated, then it will be normalized to the same value. |
| NORMALIZE_LINEAR_BY_INDUSTRY(EXPRESSION) | Normalize the expression by sorting all values of the expression from low to high within each industry and then assigning normalized values from 0 (lowest in each sorted industry list) to 1 (highest in each sorted industry list). If a particular value is repeated within an industry, then it will be normalized to the same value. |
| PATCH(EXPRESSION1, EXPRESSION2) | The PATCH expression is used to replace missing data in EXPRESSION1 with the respective value in EXPRESSION2, thereby 'patching' the data. For example, if you have an expression which involves earnings estimates but you don't want to exclude a stock which does not have estimates data, you could use the expression 'PATCH(EARN_THIS, 0)'. The result of this expression would be the earnings estimates for this year or the value of '0' if the estimates are unavailable. |
| RANK_OF_INDUSTRY_AVG(EXPRESSION) | Calculates the average value of the expression for each industry in our database and then ranks each industry starting from 1 (the highest industry average of the expression) through the number of industries in the database (the lowest industry average of the expression). The screener will then only return stocks which belong to an industry which satisfies the statement in the expert filter. Example: RANK_OF_INDUSTRY_AVG(ROE) <= 3 would only return stocks from industries which have the top 3 average ROE. |
| RANK_OF_INDUSTRY_MEDIAN(EXPRESSION) | Calculates the median value of the expression for each industry in our database and then ranks each industry starting from 1 (the highest industry median of the expression) through the number of industries in the database (the lowest industry median of the expression). See RANK_OF_INDUSTRY_AVG for a usage example. |
| SQRT(EXPRESSION) | Calculates the square root of the expression. |
| STD(EXPRESSION) | Calculates the standard deviation of the expression across all stocks in the database. Example: STD(ROE) would return the standard deviation of return on equity for all stocks in the Stockworm database. |
| STD_BY_INDUSTRY(EXPRESSION) | Calculates the standard deviation of the expression across all stocks withing the respective stock's industry. Example: STD_BY_INDUSTRY(ROE) would return the standard deviation of return on equity for each stock's respective industry in the Stockworm database. |
Operators
Operators are formula elements which are subcategorized into arithmetic operators (+, -, *, etc.), logical operators (A > B, A AND B, etc.), and the shift operator (A[B]). All of the Stockworm formula operators are listed and described below. The list appears in the order in which these expressions will be evaluated, in the absence of parenthesis to explicitly enforce ordering.
| Expressions | Usage |
| A OR B | 'OR' is a logical operator which evaluates whether at least one of the arguments in the expression 'A OR B' is true. Example: VAL_EBO > PRICE OR VAL_PEG > PRICE (true if either ebo value > closing price or peg value > closing price). |
| A AND B | 'AND' is a logical operator which evaluates whether or not both arguments in the expression 'A AND B' are true. Example: VAL_EBO > PRICE AND VAL_PEG > PRICE (true if both ebo value > closing price and peg value > closing price). |
| A = B A <> B |
Equal to and not equal to are also logical operators. Equal to (=) is true when two expressions are equal (e.g. PRICE = BOOK is true only if price is identically equal to the book value per share) while not equal to (<>) is true for non-equality. |
| A < B A <= B A > B A >= B |
These logical operators compare the value of two expressions. Less than (<) is true when the first expression is less than the second expression and less than or equal to (<=) is true when the first expression is less than or equal to the second expression. Greater than (>) and greater than or equal to (>=) are evaluated in a similar fashion. |
| A + B A - B |
The arithmetic operator plus (+) adds the first expression to the second expression. The arithmetic operator minus (-) subtracts the second expression from the first expression. Example: The expression 'BOOK - CASH' would give the book value per share less the cash per share. |
| A * B A / B |
The arithmetic operator times (*) multiplies the first expression by the second expression while the division arithmetic operator (/) divides the first expression by the second expression. Example: The expression 'GROWTH_NEXT/GROWTH_THIS' yields the ratio of the estimated earnings growth for next year in comparison with the estimated earnings growth for the current year. |
| - A | The arithmetic operator minus (-), when applied to a single argument, gives the negative value of this argument. This operation is equivalent to multiplying the argument by -1. |
| NOT A | The logical operator NOT will convert 'true' values to 'false' and vice versa. Example: The expression 'NOT(PRICE> 5)' will be true when the closing price is not greater than 5 (PRICE <= 5 is an equivalent statement). |
| A[B] | The offset operator ([]) is used to denote past values of a given expression, in trading days. For example, 'VAL_AVERAGE[20]' refers to the average value 20 trading days ago (approximately 1 calendar month). VAL_AVERAGE[0], which is the average valuation 0 trading days ago, is equivalent to VAL_AVERAGE. Note that there are approximately: 5 trading days/week; 21 trading days/month, 63 trading days/quarter and 252 trading days/year. |
Variables
The custom filter provides you with a rich variety of fundamental variables. All of these variables are listed below based upon the screener group to which the respective variable belongs. To add a variable to your custom filter, simply find the appropriate text description in the table below (e.g. "number of analysts covering the equity") and then use the variable name in your filter, exactly as shown in the table (e.g. "ANALYSTS_COVERING").
Pre-ranking is the process by which a variable is ranked for each stock on each trading day by its relative position within the market as a whole and within its respective industry. These rankings are then stored in the database for rapid sorting or filtering. Pre-ranked variables are available in the pull-down lists for 'sort stocks', 'sort stocks - multi', and 'filter stocks' rules. Variables which are not pre-ranked are only available for use in rules which use custom expressions (e.g. 'sort stocks - custom', 'filter stocks - custom' rules).
|
