view the stockworm user manual
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).

Group Variable Description Units Pre-ranked
accounts payable ACCOUNTS_PAYABLE money owed (payable) to suppliers for goods or services purchased on credit; these must be paid within 12 months. millions of dollars  yes
analyst ratings ANALYSTS_COVERING number of analysts covering the equity   yes
  ANALYSTS_RATING average analysts' rating 1 = strong buy, 5 = strong sell  yes
beta BETA 36 month beta (relative to S&P 500)   yes
book value TOTAL_BOOK total book value over the latest 12 months millions of dollars  yes
  BOOK book value per share dollars  yes
cash TOTAL_CASH total cash over the latest 12 months millions of dollars  yes
  CASH cash per share dollars  yes
cash flow TOTAL_CASH_FLOW total cash flow over the latest 12 months millions of dollars  yes
  TOTAL_FREE_CASH_FLOW total free cash flow over the latest 12 months millions of dollars  yes
current ratio CURRENT_RATIO mrq current assets divided by mrq current liabilities   yes
debt DEBT mrq long-term debt divided by mrq common equity   yes
  LONG_TERM_DEBT represents the amount of borrowings due after one year from the date of the balance sheet millions of dollars  yes
  SHORT_TERM_DEBT represents the amount of borrowings (principal and interest) that must be paid in the near future (usually one year). millions of dollars  yes
dividend yield DIVIDEND current dividend yield percent  yes
  DIVIDENDS_PAID total dividends paid per share over the latest 12 months (split adjusted, if necessary) dollars  yes
earnings TOTAL_EARN total earnings over the latest 12 months millions of dollars  yes
  EARN earnings per share from total operations dollars  yes
  EBIT Total Income before Interest Expenses (EBIT), equals Income after depreciation adjusted for interest income, other income, net and any special income or charges but before subtracting interest expense and taxes. millions of dollars  yes
earnings estimates EARN_THIS analysts' mean estimated earnings per share for the current year dollars  yes
  EARN_THIS_LOW analysts' lowest estimated earnings per share for the current year dollars  yes
  EARN_THIS_HIGH analysts' highest estimated earnings per share for the current year dollars  yes
  EARN_NEXT analysts' mean estimated earnings per share for the next year dollars  yes
  EARN_NEXT_LOW analysts' lowest estimated earnings per share for the next year dollars  yes
  EARN_NEXT_HIGH analysts' highest estimated earnings per share for the next year dollars  yes
earnings growth GROWTH_LAST compound annual growth rate of eps for the last 5 years percent  yes
  GROWTH_THIS estimated earnings growth for the current year percent  yes
  GROWTH_NEXT estimated earnings growth for next year percent  yes
  GROWTH_LONG long term estimated earnings growth percent  yes
employees EMPLOYEES the number of employees as indicated on the latest quarterly report employees  yes
income statements GROSS_OPERATING_PROFIT the operating revenue minus cost of goods sold. Gross profit identifies the amount available to cover other operating expenses before depreciation. millions of dollars  yes
  COST_OF_SALES all expenses directly associated with the production of goods or services the company sells (such as material and overhead) excluding depreciation, depletion, amortization, and SG&A. millions of dollars  yes
  INVENTORY_TURNOVER cost of goods sold divided by the average of inventories from the most recent two balance sheets(expressed as a ratio). It measures the velocity with which merchandise moves through a firm. ratio  yes
  RECEIVABLES_TURNOVER revenue divided by average receivables from the most recent two balance sheets (expressed as a ratio). ratio  yes
institutional ownership INSTITUTE percentage of common/preferred stock held by institutions percent  yes
market cap MARKET_CAP market capitalization = most recent price x shares outstanding millions of dollars  yes
p/e, p/b, p/s, peg P_TO_E price divided by trailing 4 quarter earnings per share   yes
  P_TO_B price divided by mrq common equity (book value) per share   yes
  P_TO_S price divided by trailing 4 quarter sales per share   yes
  PEG p/e divided by 3 year average projected growth rate   yes
price PRICE closing price dollars  yes
price to ema ratios P_TO_EMA10 price to 10 day exponential moving average   yes
  P_TO_EMA30 price to 30 day exponential moving average   yes
  P_TO_EMA50 price to 50 day exponential moving average   yes
  P_TO_EMA200 price to 200 day exponential moving average   yes
price momentum MOMENTUM_1DAY 1 day price momentum   yes
  MOMENTUM_1WEEK 1 week price momentum   yes
  MOMENTUM_2WEEKS 2 week price momentum   yes
  MOMENTUM_1MONTH 1 month price momentum   yes
  MOMENTUM_3MONTHS 3 month price momentum   yes
  MOMENTUM_6MONTHS 6 month price momentum   yes
  MOMENTUM_1YEAR 1 year price momentum   yes
quotes OPEN Opening price for the trading day, as seen on the requested date (for split adjusted open, use the expression OPEN / SPLIT_FACTOR) dollars  no
  HIGH High price for the trading day, as seen on the requested date (for split adjusted open, use the expression OPEN / SPLIT_FACTOR) dollars  no
  LOW Low price for the trading day, as seen on the requested date (for split adjusted open, use the expression OPEN / SPLIT_FACTOR) dollars  no
  CLOSE Closing price for the trading day, as seen on the requested date (for split adjusted open, use the expression OPEN / SPLIT_FACTOR) dollars  no
  VOLUME Total trading volume for the day, as seen on the requested date (for split adjusted volume, use the expression VOLUME * SPLIT_FACTOR) millions of shares  no
  SPLIT_FACTOR Cumulative split factor on the requested date   no
profit margin PROFIT 12 month net income divided by 12 month revenue percent  yes
return on assets ROA 12 month net income divided by total assets percent  yes
return on equity ROE 12 month net income divided by common equity percent  yes
sales TOTAL_SALES total sales over the latest 12 months millions of dollars  yes
  SALES sales per share dollars  yes
shares outstanding SHARES number of shares outstanding millions of shares  yes
short ratio SHORT_RATIO number of days to clear the short interest at average volume   yes
technical indicators MACD 8-17-9 moving average convergence divergence   yes
  MFI 14 day money flow index   yes
  STOC 5-3-3 stochastics   yes
  RSI 9 day relative strength index   yes
  WPR 16 day william's %r   yes
valuation VAL_EBO basic ebo valuation dollars  yes
  VAL_LEVB levered beta ebo valuation dollars  yes
  VAL_PROXY risk proxy ebo valuation dollars  yes
  VAL_PEG peg valuation dollars  yes
  VAL_PE forward p/e valuation dollars  yes
  VAL_AVERAGE average valuation dollars  yes
valuation ratios P_TO_VAL_EBO price divided by ebo valuation   yes
  P_TO_VAL_LEVB price divided by levered beta ebo valuation   yes
  P_TO_VAL_PROXY price divided by proxy ebo valuation   yes
  P_TO_VAL_PEG price divided by peg valuation   yes
  P_TO_VAL_PE price divided by forward p/e valuation   yes
  P_TO_VAL_AVERAGE price divided by average valuation   yes
volume AVG_VOLUME average three month trading volume millions of shares  yes